TEAMCITY-GIT-CR-7 TW-56415 Improve tests, don't retry after GitExecTimeout
authorVladislav Rassokhin <vladislav.rassokhin@jetbrains.com>
Fri, 17 Aug 2018 11:55:07 +0000 (14:55 +0300)
committerVladislav Rassokhin <vladislav.rassokhin@jetbrains.com>
Fri, 17 Aug 2018 12:03:48 +0000 (15:03 +0300)
git-agent/src/jetbrains/buildServer/buildTriggers/vcs/git/agent/UpdaterWithMirror.java
git-tests/src/jetbrains/buildServer/buildTriggers/vcs/git/tests/AgentVcsSupportTest.java

index b50207a3011eda02a0972dc3ab29e1e554439d52..f24f8821b799829c46f3c8619d76adae8f35ebdc 100644 (file)
@@ -23,7 +23,6 @@ import jetbrains.buildServer.buildTriggers.vcs.git.GitUtils;
 import jetbrains.buildServer.buildTriggers.vcs.git.MirrorManager;
 import jetbrains.buildServer.buildTriggers.vcs.git.agent.errors.GitExecTimeout;
 import jetbrains.buildServer.util.StringUtil;
-import jetbrains.buildServer.util.ThreadUtil;
 import jetbrains.buildServer.vcs.CheckoutRules;
 import jetbrains.buildServer.vcs.VcsException;
 import jetbrains.buildServer.vcs.VcsRoot;
@@ -161,12 +160,18 @@ public class UpdaterWithMirror extends UpdaterImpl {
         try {
           fetch(repositoryDir, refspec, false);
           break;
+        } catch (GitExecTimeout e) {
+          throw e;
         } catch (VcsException e) {
           // Throw exception after latest attempt
           if (i == retryTimeouts.length) throw e;
           int wait = retryTimeouts[i];
           LOG.warnAndDebugDetails("Failed to fetch mirror, will retry after " + wait + " seconds.", e);
-          ThreadUtil.sleep(wait * 1000);
+          try {
+            Thread.sleep(wait * 1000);
+          } catch (InterruptedException e1) {
+            throw new VcsException("Failed to fetch mirror", e1);
+          }
         }
       }
     } catch (VcsException e) {
index 270d8ba550bf86ea05f0554b00b72d9ee43be91a..71c247c3efd029a3ffa4fdb151f1b53644c2da1b 100644 (file)
@@ -679,12 +679,12 @@ public class AgentVcsSupportTest {
     copyRepository(updatedRepo, remoteRepo);
 
 
-    //make first fetch in local mirror to fail:
+    //make first two fetches in local mirror to fail:
     AtomicInteger invocationCount = new AtomicInteger(0);
     loggingFactory.addCallback(FetchCommand.class.getName() + ".call", new GitCommandProxyCallback() {
       @Override
       public void call(final Method method, final Object[] args) throws VcsException {
-        if (invocationCount.getAndIncrement() == 0)
+        if (invocationCount.getAndIncrement() <= 1)
           throw new VcsException("TEST ERROR");
       }
     });
@@ -696,11 +696,70 @@ public class AgentVcsSupportTest {
     VcsRootImpl root2 = vcsRoot().withAgentGitPath(getGitPath()).withBranch("refs/heads/personal").withFetchUrl(GitUtils.toURL(remoteRepo)).build();
     AgentRunningBuild build = runningBuild()
       .useLocalMirrors(true)
-      .sharedConfigParams("teamcity.git.fetchMirrorRetryTimeouts", "0")
+      .sharedConfigParams("teamcity.git.fetchMirrorRetryTimeouts", "0,0")
+      .build();
+    myVcsSupport.updateSources(root2, CheckoutRules.DEFAULT, "d47dda159b27b9a8c4cee4ce98e4435eb5b17168", myCheckoutDir, build, false);
+    File mirrorAfterBuild = myBuilder.getMirrorManager().getMirrorDir(GitUtils.toURL(remoteRepo));
+    then(mirrorAfterBuild).isEqualTo(mirror);//repository was not remapped to another dir
+  }
+
+  @TestFor(issues = "TW-56415")
+  public void should_not_retry_fetch_mirror_for_exec_timeout() throws Exception {
+    MockFS fs = new MockFS();
+    LoggingGitMetaFactory loggingFactory = new LoggingGitMetaFactory();
+    myVcsSupport = myBuilder.setGitMetaFactory(loggingFactory).setFS(fs).build();
+
+    File repo = dataFile("repo_for_fetch.1");
+    File remoteRepo = myTempFiles.createTempDir();
+    copyRepository(repo, remoteRepo);
+
+    //run build to prepare mirror
+    VcsRootImpl root = vcsRoot().withAgentGitPath(getGitPath()).withFetchUrl(GitUtils.toURL(remoteRepo)).build();
+    myVcsSupport
+      .updateSources(root, CheckoutRules.DEFAULT, "add81050184d3c818560bdd8839f50024c188586", myCheckoutDir, createRunningBuild(true),
+                     false);
+
+    //update remote repo: add personal branch
+    delete(remoteRepo);
+    File updatedRepo = dataFile("repo_for_fetch.2.personal");
+    copyRepository(updatedRepo, remoteRepo);
+
+    //make first two fetches in local mirror to fail:
+    loggingFactory.addCallback(FetchCommand.class.getName() + ".call", new GitCommandProxyCallback() {
+      volatile boolean thrown = false;
+
+      @Override
+      public void call(final Method method, final Object[] args) throws VcsException {
+        if (!thrown) {
+          thrown = true;
+          throw new GitExecTimeout();
+        }
+        fail("Should not try to fetch again");
+      }
+    });
+    File mirror = myBuilder.getMirrorManager().getMirrorDir(GitUtils.toURL(remoteRepo));
+
+    //try to fetch unknown branch, first fetch fails with exec timeout, repo would be remapped
+    VcsRootImpl root2 =
+      vcsRoot().withAgentGitPath(getGitPath()).withBranch("refs/heads/personal").withFetchUrl(GitUtils.toURL(remoteRepo)).build();
+    AgentRunningBuild build = runningBuild()
+      .useLocalMirrors(true)
+      .sharedConfigParams("teamcity.git.fetchMirrorRetryTimeouts", "0,0")
       .build();
+
+    try {
+      myVcsSupport.updateSources(root2, CheckoutRules.DEFAULT, "d47dda159b27b9a8c4cee4ce98e4435eb5b17168", myCheckoutDir, build, false);
+      fail("GitExecTimeout exception expected");
+    } catch (GitExecTimeout ignored) {
+    }
+
+    //try again, should succeed without remapping, means previous code has not changed mirror directory
+    loggingFactory.addCallback(FetchCommand.class.getName() + ".call", (method, args) -> {
+    });
     myVcsSupport.updateSources(root2, CheckoutRules.DEFAULT, "d47dda159b27b9a8c4cee4ce98e4435eb5b17168", myCheckoutDir, build, false);
+
     File mirrorAfterBuild = myBuilder.getMirrorManager().getMirrorDir(GitUtils.toURL(remoteRepo));
-    then(mirrorAfterBuild).isEqualTo(mirror);//repository was remapped to another dir
+    then(mirrorAfterBuild).isEqualTo(mirror);//repository was not remapped to another dir
   }