Mercurial > hg > mercurial
view mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutTest.java @ 1068:2d8aab94494f Lakhnau-2020.2.x release-86063
TW-70693
author | victory.bedrosova |
---|---|
date | Thu, 18 Mar 2021 18:30:34 +0100 |
parents | 10dc26b32c35 |
children |
line wrap: on
line source
/* * Copyright 2000-2018 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.buildServer.buildTriggers.vcs.mercurial; import jetbrains.buildServer.TestInternalProperties; import jetbrains.buildServer.agent.*; import jetbrains.buildServer.agent.vcs.AgentCheckoutAbility; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandSettingsForRootImpl; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.CommandlineViaFileWrapperWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ExtensionsWeaver; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory; import jetbrains.buildServer.buildTriggers.vcs.mercurial.ext.MercurialExtensionManager; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.TestFor; import jetbrains.buildServer.vcs.*; import jetbrains.buildServer.vcs.impl.VcsRootImpl; import org.hamcrest.CoreMatchers; import org.jetbrains.annotations.NotNull; import org.jmock.Expectations; import org.jmock.Mockery; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.*; import static java.util.Arrays.asList; import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.text.StringContains.containsString; /** * @author Pavel.Sher * Date: 30.07.2008 */ @Test public class AgentSideCheckoutTest extends BaseMercurialPatchTestCase { final static String HG_PATH_REFERENCE = "%" + HgDetector.AGENT_HG_PATH_PROPERTY + "%"; private MercurialAgentSideVcsSupport myVcsSupport; private File myWorkDir; private File myMirrorsRootDir; private Mockery myContext; private BuildProgressLogger myLogger; private int myBuildCounter = 0; @Override @BeforeMethod protected void setUp() throws Exception { super.setUp(); TestInternalProperties.init(); myContext = new Mockery(); myMirrorsRootDir = myTempFiles.createTempDir(); final BuildAgentConfiguration agentConfig = myContext.mock(BuildAgentConfiguration.class); myContext.checking(new Expectations() {{ allowing(agentConfig).getCacheDirectory("mercurial"); will(returnValue(myMirrorsRootDir)); allowing(agentConfig).getTempDirectory(); will(returnValue(myTempFiles.createTempDir())); allowing(agentConfig).getParametersResolver(); will(returnValue(new HgPathResolver())); }}); final AgentPluginConfigImpl pluginConfig = new AgentPluginConfigImpl(agentConfig); myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig, new MirrorManagerImpl(pluginConfig), new AgentRepoFactory(pluginConfig, new CommandSettingsForRootImpl(new TestCommandSettingsFactory(), new ExtensionsWeaver(), new CommandlineViaFileWrapperWeaver()), new AgentHgPathProvider(agentConfig)), new MercurialExtensionManager()); myLogger = myContext.mock(FlowLogger.class); myContext.checking(new Expectations() {{ allowing(myLogger).message(with(any(String.class))); allowing(myLogger).getFlowLogger(with(any(String.class))); will(returnValue(myLogger)); allowing(myLogger).activityStarted(with(any(String.class)), with(any(String.class))); allowing(myLogger).activityFinished(with(any(String.class)), with(any(String.class))); allowing(myLogger).getFlowLogger(with(any(String.class))); will(returnValue(myLogger)); }}); myWorkDir = myTempFiles.createTempDir(); } public void should_work_when_path_to_hg_is_property() throws Exception { VcsRootImpl root = new VcsRootBuilder() .withUrl(copyRepository(myTempFiles, simpleRepo()).getAbsolutePath()) .withHgPath(HG_PATH_REFERENCE).build(); testUpdate(root, "b06a290a363b", "cleanPatch1/after", new IncludeRule(".", ".", null)); } public void auto_checkout_when_hg_client_not_found() throws Exception { VcsRootImpl root = new VcsRootBuilder().withUrl(copyRepository(myTempFiles, simpleRepo()).getAbsolutePath()).withHgPath("invalid_hg_path").build(); AgentCheckoutAbility agentCheckoutAbility = myVcsSupport.canCheckout(root, CheckoutRules.DEFAULT, myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++)); assertThat(agentCheckoutAbility.getCanNotCheckoutReason().getType(), CoreMatchers.equalTo(AgentCanNotCheckoutReason.NO_VCS_CLIENT)); } public void auto_checkout_when_unsupported_include_rule_is_used() throws Exception { VcsRootImpl root = createVcsRoot(simpleRepo()); AgentCheckoutAbility agentCheckoutAbility = myVcsSupport.canCheckout(root, new CheckoutRules("+:subdir=>subdir2"), myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++)); assertThat(agentCheckoutAbility.getCanNotCheckoutReason().getType(), CoreMatchers.equalTo(AgentCanNotCheckoutReason.NOT_SUPPORTED_CHECKOUT_RULES)); assertThat(agentCheckoutAbility.getCanNotCheckoutReason().getDetails(), containsString("Invalid include rule: subdir=>subdir2")); } @DataProvider public static Object[][] severalRootsSetups() throws Exception { return new Object[][]{ new Object[]{new Setup() .setShouldFail(true) }, new Object[]{new Setup() .setCheckoutRules1("+:.=>dir") .setCheckoutRules2("+:.=>dir") .setShouldFail(true) }, new Object[]{new Setup() .setCheckoutRules1("+:.=>dir1") .setCheckoutRules2("+:.=>dir2\n+:.=>dir1") .setShouldFail(true) }, new Object[]{new Setup() .setCheckoutRules2("+:.=>dir1") .setCheckoutRules2("+:.=>dir2") .setShouldFail(false) } }; } @TestFor(issues = "TW-49811") @Test(dataProvider = "severalRootsSetups") public void auto_checkout_many_roots(@NotNull Setup setup) throws Exception { VcsRootImpl root1 = new VcsRootBuilder().withId(1).withUrl("http://some.org/repo1").build(); VcsRootImpl root2 = new VcsRootBuilder().withId(2).withUrl("http://some.org/repo2").build(); CheckoutRules rules1 = new CheckoutRules(setup.getCheckoutRules1()); CheckoutRules rules2 = new CheckoutRules(setup.getCheckoutRules2()); AgentRunningBuild build = myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++); myContext.checking(new Expectations() {{ allowing(build).getVcsRootEntries(); will(returnValue(asList(new VcsRootEntry(root1, rules1), new VcsRootEntry(root2, rules2)))); }}); AgentCheckoutAbility canCheckout1 = myVcsSupport.canCheckout(root1, rules1, build); AgentCheckoutAbility canCheckout2 = myVcsSupport.canCheckout(root2, rules2, build); if (setup.isShouldFail()) { assertThat(canCheckout1.getCanNotCheckoutReason().getDetails(), CoreMatchers.equalTo( "Cannot checkout VCS root '" + root1.getName() + "' into the same directory as VCS root '" + root2.getName() + "'")); assertThat(canCheckout2.getCanNotCheckoutReason().getDetails(), CoreMatchers.equalTo( "Cannot checkout VCS root '" + root2.getName() + "' into the same directory as VCS root '" + root1.getName() + "'")); } else { assertNull(canCheckout1.getCanNotCheckoutReason()); assertNull(canCheckout2.getCanNotCheckoutReason()); } } @TestFor(issues = "TW-49811") public void auto_checkout_many_roots_ignore_broken() throws Exception { //root1 and root2 have intersecting checkout dir (dir1), but //root2 also has an unsupported checkout rule; we should ignore //root2 during canCheckout() call for root1 VcsRootImpl root1 = new VcsRootBuilder().withId(1).withUrl("http://some.org/repo1").build(); VcsRootImpl root2 = new VcsRootBuilder().withId(2).withUrl("http://some.org/repo2").build(); CheckoutRules rules1 = new CheckoutRules("+:.=>dir1"); CheckoutRules rules2 = new CheckoutRules("+:.=>dir1\n+:dir2=>dir3"); AgentRunningBuild build = myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++); myContext.checking(new Expectations() {{ allowing(build).getVcsRootEntries(); will(returnValue(asList(new VcsRootEntry(root1, rules1), new VcsRootEntry(root2, rules2)))); }}); AgentCheckoutAbility canCheckout1 = myVcsSupport.canCheckout(root1, rules1, build); AgentCheckoutAbility canCheckout2 = myVcsSupport.canCheckout(root2, rules2, build); assertNull(canCheckout1.getCanNotCheckoutReason()); assertThat(canCheckout2.getCanNotCheckoutReason().getType(), CoreMatchers.equalTo(AgentCanNotCheckoutReason.NOT_SUPPORTED_CHECKOUT_RULES)); assertThat(canCheckout2.getCanNotCheckoutReason().getDetails(), containsString("Invalid include rule: dir2=>dir3")); } public void checkout_on_agent() throws IOException, VcsException { testUpdate(createVcsRoot(simpleRepo()), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule(".", ".", null)); } public void checkout_on_agent_include_rule_with_mapping() throws IOException, VcsException { testUpdate(createVcsRoot(simpleRepo()), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule("+:.", "subdir", null)); } @TestFor(issues = "TW-19761") public void include_subdir_is_not_supported() throws Exception { try { testUpdate(createVcsRoot(simpleRepo()), "4:b06a290a363b", "cleanPatch1/after", new IncludeRule("+:subdir", ".", null)); fail("should fail"); } catch (VcsException e) { assertTrue(e.getMessage().contains("Invalid include rule")); } } private void testUpdate(final VcsRoot vcsRoot, String version, String expected, final IncludeRule includeRule) throws VcsException, IOException { File workDir = doUpdate(vcsRoot, version, includeRule); checkWorkingDir(expected, workDir); } private void checkWorkingDir(final String expected, final File workDir) throws IOException { FileUtil.delete(new File(workDir, ".hg")); checkDirectoriesAreEqual(new File(getTestDataPath(), expected), workDir); } private File doUpdate(@NotNull final VcsRoot root, @NotNull final String version, int timeoutSeconds) throws Exception { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<File> future = executor.submit(() -> doUpdate(root, version)); executor.shutdown(); executor.awaitTermination(timeoutSeconds, TimeUnit.SECONDS); if (!future.isDone()) fail("Update failed due to timeout"); return future.get(); } protected File doUpdate(@NotNull VcsRoot root, @NotNull String version) throws VcsException { return doUpdate(root, version, IncludeRule.createDefaultInstance()); } private File doUpdate(final VcsRoot vcsRoot, final String version, final IncludeRule includeRule) throws VcsException { return doUpdate(vcsRoot, version, includeRule, false); } private File doUpdate(final VcsRoot vcsRoot, final String version, final IncludeRule includeRule, boolean useLocalMirrors) throws VcsException { File actualWorkDir = new File(myWorkDir, includeRule.getTo()); final Map<String, String> sharedConfigParameters = new HashMap<>(); sharedConfigParameters.put("teamcity.hg.use.local.mirrors", String.valueOf(useLocalMirrors)); final AgentRunningBuild build = myContext.mock(AgentRunningBuild.class, "build" + myBuildCounter++); myContext.checking(new Expectations() {{ allowing(build).getBuildLogger(); will(returnValue(myLogger)); allowing(build).getSharedConfigParameters(); will(returnValue(sharedConfigParameters)); }}); myVcsSupport.getUpdater(vcsRoot, new CheckoutRules(""), version, myWorkDir, build, false).process(includeRule, actualWorkDir); File hgDir = new File(actualWorkDir, ".hg"); assertTrue(hgDir.isDirectory()); return actualWorkDir; } public void checkout_on_agent_from_branch() throws IOException, VcsException { testUpdate(createVcsRoot(simpleRepo(), "test_branch"), "7:376dcf05cd2a", "patch3/after", new IncludeRule(".", ".", null)); } public void update_on_agent() throws IOException, VcsException { VcsRoot vcsRoot = createVcsRoot(simpleRepo()); doUpdate(vcsRoot, "3:9522278aa38d", new IncludeRule(".", ".", null)); File workDir = doUpdate(vcsRoot, "4:b06a290a363b", new IncludeRule(".", ".", null)); checkWorkingDir("patch1/after", workDir); } public void update_on_agent_with_include_rule() throws IOException, VcsException { VcsRoot vcsRoot = createVcsRoot(simpleRepo()); doUpdate(vcsRoot, "3:9522278aa38d", new IncludeRule(".", "subdir", null)); File workDir = doUpdate(vcsRoot, "4:b06a290a363b", new IncludeRule(".", "subdir", null)); checkWorkingDir("patch1/after", workDir); } public void update_on_agent_from_branch() throws IOException, VcsException { VcsRoot vcsRoot = createVcsRoot(simpleRepo(), "test_branch"); doUpdate(vcsRoot, "7:376dcf05cd2a", new IncludeRule(".", ".", null)); File workDir = doUpdate(vcsRoot, "8:04c3ae4c6312", new IncludeRule(".", ".", null)); checkWorkingDir("patch4/after", workDir); } public void by_default_local_mirror_not_created() throws IOException, VcsException { List<File> mirrors = FileUtil.getSubDirectories(myMirrorsRootDir); assertTrue(mirrors.isEmpty()); VcsRoot root = createVcsRoot(simpleRepo()); doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null)); mirrors = FileUtil.getSubDirectories(myMirrorsRootDir); //though some dirs are created - they are empty => there were no clones into local mirrors for (File mirror : mirrors) { assertTrue(FileUtil.getSubDirectories(mirror).isEmpty()); } } public void local_mirror_is_created() throws IOException, VcsException { List<File> mirrors = FileUtil.getSubDirectories(myMirrorsRootDir); assertTrue(mirrors.isEmpty()); VcsRoot root = createVcsRoot(simpleRepo()); doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null), true); mirrors = FileUtil.getSubDirectories(myMirrorsRootDir); assertEquals(1, mirrors.size()); File mirror = mirrors.get(0); File dotHg = new File(mirror, ".hg"); assertTrue(dotHg.exists()); File hgrc = new File(dotHg, "hgrc"); String hgrcContent = FileUtil.readText(hgrc); assertTrue(hgrcContent.contains("default = " + root.getProperty(Constants.REPOSITORY_PROP))); } private void new_repository_is_cloned_from_local_mirror() throws IOException, VcsException { VcsRoot root = createVcsRoot(simpleRepo()); File workingDir = doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null), true); File mirrorDir = FileUtil.getSubDirectories(myMirrorsRootDir).get(0); File hgrc = new File(workingDir, ".hg" + File.separator + "hgrc"); String hgrcContent = FileUtil.readText(hgrc); assertTrue(hgrcContent.contains("default = " + mirrorDir.getCanonicalPath())); } private void repository_cloned_from_remote_start_cloning_from_local_mirror() throws IOException, VcsException { VcsRoot root = createVcsRoot(simpleRepo()); //clone from remote repository File workingDir = doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null)); String hgrcContent = FileUtil.readText(new File(workingDir, ".hg" + File.separator + "hgrc")); File workingDir2 = doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null), true); File newMirrorDir = FileUtil.getSubDirectories(myMirrorsRootDir).get(0); String hgrcContent2 = FileUtil.readText(new File(workingDir2, ".hg" + File.separator + "hgrc")); assertFalse(hgrcContent2.equals(hgrcContent));//repository settings are changed assertTrue(hgrcContent2.contains("default = " + newMirrorDir.getCanonicalPath()));//now it clones from local mirror } private void repository_cloned_from_local_mirror_start_cloning_from_remote() throws IOException, VcsException { VcsRoot root = createVcsRoot(simpleRepo()); //clone from remote repository File workingDir = doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null), true); String hgrcContent = FileUtil.readText(new File(workingDir, ".hg" + File.separator + "hgrc")); File newMirrorDir = FileUtil.getSubDirectories(myMirrorsRootDir).get(0); assertTrue(hgrcContent.contains("default = " + newMirrorDir.getCanonicalPath()));//now it clones from local mirror File workingDir2 = doUpdate(root, "3:9522278aa38d", new IncludeRule(".", ".", null)); String hgrcContent2 = FileUtil.readText(new File(workingDir2, ".hg" + File.separator + "hgrc")); assertFalse(hgrcContent2.equals(hgrcContent));//repository settings are changed assertTrue(hgrcContent2.contains("default = " + root.getProperty(Constants.REPOSITORY_PROP)));//now it clones from remote } /** * TW-15984 */ public void should_be_able_to_clone_into_non_empty_dir() throws IOException, VcsException { VcsRoot vcsRoot = createVcsRoot(simpleRepo()); doUpdate(vcsRoot, "3:9522278aa38d", new IncludeRule(".", "subdir", null)); doUpdate(vcsRoot, "4:b06a290a363b", new IncludeRule(".", ".", null)); } public void cloned_repo_should_contains_default_parameter_in_hgrc() throws VcsException, IOException { VcsRoot root = createVcsRoot(simpleRepo()); File workingDir = doUpdate(root, "4:b06a290a363b", new IncludeRule(".", ".", null)); File hgrc = new File(workingDir, ".hg" + File.separator + "hgrc"); String hgrcContent = FileUtil.readText(hgrc); assertTrue(hgrcContent.contains("default = " + root.getProperty(Constants.REPOSITORY_PROP))); } @TestFor(issues = "TW-19703") public void should_work_when_repository_is_locked() throws Exception{ VcsRootImpl root = new VcsRootBuilder() .withUrl(copyRepository(myTempFiles, simpleRepo()).getAbsolutePath()) .withHgPath(HG_PATH_REFERENCE).build(); File workingDir = doUpdate(root, "4:b06a290a363b"); lockRepository(workingDir); doUpdate(root, "6:b9deb9a1c6f4", 10); lockWorkingDir(workingDir); doUpdate(root, "10:9c6a6b4aede0", 10); } private void lockRepository(@NotNull File workingDir) { File lock = new File(workingDir, ".hg" + File.separator + "store" + File.separator + "lock"); FileUtil.writeFile(lock, ""); } private void lockWorkingDir(@NotNull File workingDir) { File lock = new File(workingDir, ".hg" + File.separator + "wlock"); FileUtil.writeFile(lock, ""); } protected String getTestDataPath() { return "mercurial-tests/testData"; } private static class Setup { private String myCheckoutRules1 = CheckoutRules.DEFAULT.getAsString(); private String myCheckoutRules2 = CheckoutRules.DEFAULT.getAsString(); private boolean myShouldFail; @NotNull public String getCheckoutRules1() { return myCheckoutRules1; } @NotNull public Setup setCheckoutRules1(@NotNull String checkoutRules1) { myCheckoutRules1 = checkoutRules1; return this; } @NotNull public String getCheckoutRules2() { return myCheckoutRules2; } @NotNull public Setup setCheckoutRules2(@NotNull String checkoutRules2) { myCheckoutRules2 = checkoutRules2; return this; } public boolean isShouldFail() { return myShouldFail; } @NotNull public Setup setShouldFail(boolean shouldFail) { myShouldFail = shouldFail; return this; } @Override public String toString() { return "rules1: '" + myCheckoutRules1 + "', rules2: '" + myCheckoutRules2 + "'"; } } }