| /******************************************************************************* |
| * Copyright (c) 2013, 2016 Tasktop Technologies and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.gerrit.core.remote; |
| |
| import static org.hamcrest.Matchers.greaterThan; |
| import static org.hamcrest.Matchers.is; |
| import static org.hamcrest.Matchers.notNullValue; |
| import static org.hamcrest.Matchers.sameInstance; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.math.BigInteger; |
| import java.net.Proxy; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.Date; |
| import java.util.Random; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.eclipse.jgit.api.CommitCommand; |
| import org.eclipse.jgit.api.Git; |
| import org.eclipse.jgit.lib.ObjectId; |
| import org.eclipse.jgit.revwalk.RevCommit; |
| import org.eclipse.jgit.revwalk.RevWalk; |
| import org.eclipse.mylyn.commons.net.IProxyProvider; |
| import org.eclipse.mylyn.commons.net.WebLocation; |
| import org.eclipse.mylyn.commons.net.WebUtil; |
| import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials; |
| import org.eclipse.mylyn.commons.sdk.util.CommonTestUtil.PrivilegeLevel; |
| import org.eclipse.mylyn.gerrit.tests.support.GerritFixture; |
| import org.eclipse.mylyn.gerrit.tests.support.GerritHarness; |
| import org.eclipse.mylyn.gerrit.tests.support.GerritProject.CommitResult; |
| import org.eclipse.mylyn.internal.gerrit.core.client.GerritChange; |
| import org.eclipse.mylyn.internal.gerrit.core.client.GerritClient; |
| import org.eclipse.mylyn.internal.gerrit.core.client.GerritException; |
| import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; |
| import org.eclipse.mylyn.reviews.core.model.IRepository; |
| import org.eclipse.mylyn.reviews.core.model.IReview; |
| import org.eclipse.mylyn.reviews.core.model.IReviewItemSet; |
| import org.eclipse.mylyn.reviews.core.spi.remote.JobRemoteService; |
| import org.eclipse.mylyn.reviews.core.spi.remote.emf.RemoteEmfConsumer; |
| import org.eclipse.mylyn.tasks.core.TaskRepository; |
| |
| class ReviewHarness { |
| |
| private static final Pattern SHORT_ID_PATTERN = Pattern.compile("(\\d+).*", Pattern.DOTALL); |
| |
| //The maximum difference between two dates to account for clock skew between test machines |
| private static final long CREATION_TIME_DELTA = 30 * 60 * 1000; //30 Minutes |
| |
| private static final String DEFAULT_TEST_FILE = "testFile1.txt"; |
| |
| private TestRemoteObserver<IRepository, IReview, String, Date> listener; |
| |
| private RemoteEmfConsumer<IRepository, IReview, String, GerritChange, String, Date> consumer; |
| |
| private String shortId; |
| |
| private String commitId; |
| |
| private String changeId; |
| |
| private final Git git; |
| |
| private final GerritClient client; |
| |
| private GerritClient adminClient; |
| |
| private final GerritRemoteFactoryProvider provider; |
| |
| private final TaskRepository taskRepository; |
| |
| private final GerritHarness gerritHarness; |
| |
| ReviewHarness() throws Exception { |
| this.changeId = generateChangeId(); |
| gerritHarness = GerritFixture.current().harness(); |
| git = gerritHarness.project().getGitProject(PrivilegeLevel.USER); |
| |
| taskRepository = GerritFixture.current().singleRepository(); |
| client = gerritHarness.client(PrivilegeLevel.USER); |
| |
| provider = new GerritRemoteFactoryProvider(client); |
| provider.setService(new JobRemoteService()); |
| provider.setDataLocator(new TestDataLocator()); |
| } |
| |
| static String generateChangeId() throws NoSuchAlgorithmException { |
| byte[] bytes = new byte[22]; |
| new Random().nextBytes(bytes); |
| return "I" + new BigInteger(bytes).toString(16).replace("-", "").substring(0, 40); |
| } |
| |
| ReviewHarness duplicate() throws Exception { |
| ReviewHarness reviewHarness = new ReviewHarness(); |
| reviewHarness.changeId = this.changeId; |
| return reviewHarness; |
| } |
| |
| void retrieve() { |
| consumer.retrieve(false); |
| listener.waitForResponse(); |
| } |
| |
| void init() throws Exception { |
| init("HEAD:refs/for/master", PrivilegeLevel.USER, DEFAULT_TEST_FILE, true); |
| } |
| |
| void init(String refSpec, PrivilegeLevel privilegeLevel, String fileName, boolean wait) throws Exception { |
| provider.open(); |
| assertThat(getRepository().getReviews().size(), is(0)); |
| pushFileToReview(refSpec, privilegeLevel, fileName); |
| listener = new TestRemoteObserver<IRepository, IReview, String, Date>(provider.getReviewFactory()); |
| |
| consumer = provider.getReviewFactory().getConsumerForRemoteKey(getRepository(), getShortId()); |
| consumer.setAsynchronous(false); |
| consumer.addObserver(listener); |
| if (!wait) { |
| return; |
| } |
| retrieve(); |
| assertThat(getRepository().getReviews().size(), is(1)); |
| IReview review = getRepository().getReviews().get(0); |
| IReview reviewDirect = provider.open(getShortId()); |
| assertThat(review, sameInstance(reviewDirect)); |
| assertThat(review, notNullValue()); |
| assertThat(review.getId(), is(getShortId())); |
| assertThat(review.getKey(), is(changeId)); |
| assertThat(review.getSubject(), is("Test Change " + changeId)); |
| assertThat(review.getOwner().getDisplayName(), is("tests")); |
| assertIsRecent(review.getCreationDate()); |
| } |
| |
| public void pushFileToReview(String refSpec, PrivilegeLevel privilegeLevel) throws Exception { |
| pushFileToReview(refSpec, privilegeLevel, DEFAULT_TEST_FILE); |
| } |
| |
| public void pushFileToReview(String refSpec, PrivilegeLevel privilegeLevel, String fileName) throws Exception { |
| CommitCommand command = createCommitCommand(changeId); |
| addFile(fileName); |
| CommitResult result = commitAndPush(command, refSpec, privilegeLevel); |
| shortId = parseShortId(result.push.getMessages()); |
| commitId = result.commit.getId().toString(); |
| assertThat("Bad Push: " + result.push.getMessages(), getShortId().length(), greaterThan(0)); |
| } |
| |
| static String parseShortId(String messages) { |
| String tail = StringUtils.trimToEmpty(StringUtils.substringAfterLast(messages, "/")); |
| Matcher m = SHORT_ID_PATTERN.matcher(tail); |
| if (m.matches()) { |
| return m.group(1); |
| } |
| fail("ShortId could not be parsed from \"" + tail + "\". Messages was: " + messages); |
| return null; |
| } |
| |
| void assertIsRecent(Date date) { |
| long timeDelta = System.currentTimeMillis() - date.getTime(); |
| assertThat("Creation delta out of range : " + timeDelta + " ms", |
| timeDelta > -CREATION_TIME_DELTA && timeDelta < CREATION_TIME_DELTA, is(true)); |
| } |
| |
| public void dispose() throws GerritException { |
| if (listener != null) { |
| consumer.removeObserver(listener); |
| } |
| if (consumer != null) { |
| consumer.release(); |
| } |
| gerritHarness.dispose(); |
| } |
| |
| CommitCommand createCommitCommand() { |
| return createCommitCommand(changeId).setAmend(true); |
| } |
| |
| CommitCommand createCommitCommand(String changeId) { |
| return git.commit().setAll(true).setMessage("Test Change " + changeId + "\n\nChange-Id: " + changeId); |
| } |
| |
| void addFile(String fileName) throws Exception { |
| gerritHarness.project().addFile(fileName); |
| } |
| |
| void addFile(String fileName, String text) throws Exception { |
| gerritHarness.project().addFile(fileName, text); |
| } |
| |
| void addFile(String fileName, File file) throws Exception { |
| gerritHarness.project().addFile(fileName, file); |
| } |
| |
| void removeFile(String fileName) throws Exception { |
| gerritHarness.project().removeFile(fileName); |
| } |
| |
| CommitResult commitAndPush(CommitCommand command) throws Exception { |
| return gerritHarness.project().commitAndPush(command); |
| } |
| |
| CommitResult commitAndPush(CommitCommand command, String refSpec, PrivilegeLevel privilegeLevel) throws Exception { |
| return gerritHarness.project().commitAndPush(command, refSpec, privilegeLevel); |
| } |
| |
| void checkoutPatchSet(int number) throws Exception { |
| IReviewItemSet patchSet = getReview().getSets().get(0); |
| ObjectId ref = git.getRepository().resolve(patchSet.getRevision()); |
| RevWalk walker = new RevWalk(git.getRepository()); |
| RevCommit targetCommit = walker.parseCommit(ref); |
| |
| //make sure to checkout the correct commit |
| assertThat(targetCommit.toString(), is(commitId)); |
| |
| git.checkout() |
| .setCreateBranch(true) |
| .setName("change" + "/" + getReview().getId() + "/" + number) |
| .setStartPoint(targetCommit) |
| .call(); |
| } |
| |
| GerritClient getClient() { |
| return client; |
| } |
| |
| GerritClient getAdminClient() { |
| if (adminClient == null) { |
| UserCredentials credentials = GerritFixture.current().getCredentials(PrivilegeLevel.ADMIN); |
| |
| WebLocation location = new WebLocation(GerritFixture.current().getRepositoryUrl(), |
| credentials.getUserName(), credentials.getPassword(), new IProxyProvider() { |
| public Proxy getProxyForHost(String host, String proxyType) { |
| return WebUtil.getProxyForUrl(GerritFixture.current().getRepositoryUrl()); |
| } |
| }); |
| |
| TaskRepository repository = TasksUiPlugin.getRepositoryManager() |
| .getRepository(GerritFixture.current().getRepositoryUrl()); |
| adminClient = GerritClient.create(repository, location); |
| } |
| return adminClient; |
| } |
| |
| IReview getReview() { |
| return consumer.getModelObject(); |
| } |
| |
| IRepository getRepository() { |
| return provider.getRoot(); |
| } |
| |
| public TaskRepository getTaskRepository() { |
| return taskRepository; |
| } |
| |
| String getShortId() { |
| return shortId; |
| } |
| |
| GerritRemoteFactoryProvider getProvider() { |
| return provider; |
| } |
| } |