view mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/AgentSideCheckoutWithSharedMirrorsTest.java @ 976:7bf4d943d5bb

Update copyright
author pavel.sher
date Mon, 22 Jan 2018 11:39:20 +0100
parents 6b5e83970a26
children 10dc26b32c35
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.agent.AgentRunningBuild;
import jetbrains.buildServer.agent.BuildAgentConfiguration;
import jetbrains.buildServer.agent.BuildProgressLogger;
import jetbrains.buildServer.agent.FlowLogger;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
import jetbrains.buildServer.buildTriggers.vcs.mercurial.ext.MercurialExtensionManager;
import jetbrains.buildServer.util.FileUtil;
import jetbrains.buildServer.util.TestFor;
import jetbrains.buildServer.vcs.CheckoutRules;
import jetbrains.buildServer.vcs.IncludeRule;
import jetbrains.buildServer.vcs.VcsException;
import jetbrains.buildServer.vcs.VcsRoot;
import jetbrains.buildServer.vcs.impl.VcsRootImpl;
import org.jetbrains.annotations.NotNull;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
import static jetbrains.buildServer.util.Util.map;

@Test
public class AgentSideCheckoutWithSharedMirrorsTest extends BaseMercurialPatchTestCase {

  private MirrorManager myMirrorManager;
  private File myOriginalRepositoriesParentDir;
  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();

    myOriginalRepositoriesParentDir = myTempFiles.createTempDir();
    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);
    myMirrorManager = new MirrorManagerImpl(pluginConfig);
    myVcsSupport = new MercurialAgentSideVcsSupport(pluginConfig,
            myMirrorManager,
            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).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 working_dir_store_should_be_empty() throws Exception {
    VcsRoot root = createVcsRoot(simpleRepo());
    String version = "4:b06a290a363b";
    update(root, version);
    File workingDirStore = new File(new File(myWorkDir, ".hg"), "store");
    assertTrue(!workingDirStore.exists() || listFiles(workingDirStore).length == 0);
    checkWorkingDir("patch1/after", myWorkDir);
  }


  public void subrepos_store_should_be_empty() throws Exception {
    File myR1Dir = copy(new File("mercurial-tests/testData/subrepos/r1"));
    copy(new File("mercurial-tests/testData/subrepos/r2"));
    copy(new File("mercurial-tests/testData/subrepos/r3"));
    VcsRootImpl root = vcsRoot().withUrl(myR1Dir.getAbsolutePath()).build();
    update(root, "34017377d9c3");

    File subrepoStore = new File(new File(new File(myWorkDir, "r2"), ".hg"), "store");
    assertTrue(!subrepoStore.exists() || listFiles(subrepoStore).length == 0);
  }


  public void turn_off_sharing() throws Exception {
    File myR1Dir = copy(new File("mercurial-tests/testData/subrepos/r1"));
    copy(new File("mercurial-tests/testData/subrepos/r2"));
    copy(new File("mercurial-tests/testData/subrepos/r3"));
    VcsRootImpl root = vcsRoot().withUrl(myR1Dir.getAbsolutePath()).build();
    update(root, "34017377d9c3");

    update(root, "34017377d9c3", false);
    File workingDirSharedPath = new File(new File(myWorkDir, ".hg"), "sharedpath");
    File subrepoSharedPath = new File(new File(new File(myWorkDir, "r2"), ".hg"), "sharedpath");
    File workingDirStore = new File(new File(myWorkDir, ".hg"), "store");
    File subrepoStore = new File(new File(new File(myWorkDir, "r2"), ".hg"), "store");

    assertFalse(workingDirSharedPath.exists());
    assertFalse(subrepoSharedPath.exists());
    assertTrue(listFiles(workingDirStore).length > 0);
    assertTrue(listFiles(subrepoStore).length > 0);
  }


  @TestFor(issues = "TW-39482")
  @RequiredHgVersion(min = "2.4")
  @Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "installedHgVersion")
  public void should_recover_from_abandoned_transaction(@NotNull HgVersion _) throws Exception {
    File remoteRepo = myTempFiles.createTempDir();
    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/1"), remoteRepo);
    VcsRootImpl root = vcsRoot().withUrl(remoteRepo).build();

    //checkout sources, so that shared mirror is created
    update(root, "5:e052c89b1159");

    //make next pull fail
    File mirror = myMirrorManager.getMirrorDir(new HgVcsRoot(root).getRepository());
    FileUtil.writeFile(new File(new File(new File(mirror, ".hg"), "store"), "journal"), "", "UTF-8");

    //update remote repo so that next build requires pull
    FileUtil.delete(remoteRepo);
    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/2"), remoteRepo);

    //run build which require pull
    update(root, "6:7597a4da7195");
  }


  @NotNull
  private File[] listFiles(@NotNull File dir) {
    File[] files = dir.listFiles();
    if (files == null)
      return new File[0];
    return files;
  }


  private void update(@NotNull VcsRoot root, @NotNull String version) throws VcsException {
    update(root, version, true);
  }

  private void update(@NotNull VcsRoot root, @NotNull String version, boolean share) throws VcsException {
    AgentRunningBuild build = createBuild(share);
    myVcsSupport.getUpdater(root, CheckoutRules.DEFAULT, version, myWorkDir, build, false)
            .process(IncludeRule.createDefaultInstance(), myWorkDir);
  }


  private void checkWorkingDir(final String expected, final File workDir) throws IOException {
    FileUtil.delete(new File(workDir, ".hg"));
    checkDirectoriesAreEqual(new File(getTestDataPath(), expected), workDir);
  }


  private AgentRunningBuild createBuild(boolean share) {
    final Map<String, String> sharedConfigParameters = map("teamcity.hg.use.local.mirrors", "true", "teamcity.hg.shareLocalMirrors", String.valueOf(share));
    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));
    }});
    return build;
  }

  protected String getTestDataPath() {
    return "mercurial-tests/testData";
  }

  private File copy(@NotNull File originalRepositoryDir) throws IOException {
    String dirName = originalRepositoryDir.getName();
    File copyDir = new File(myOriginalRepositoriesParentDir, dirName);
    FileUtil.copyDir(originalRepositoryDir, copyDir);
    if (new File(copyDir, "hg").isDirectory()) {
      FileUtil.rename(new File(copyDir, "hg"), new File(copyDir, ".hg"));
    }
    return copyDir;
  }
}