package hudson.plugins.mercurial;
import hudson.FilePath;
import hudson.model.FreeStyleProject;
import hudson.model.ParametersAction;
import hudson.model.StringParameterValue;
import hudson.scm.ChangeLogSet;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import org.jvnet.hudson.test.Bug;
public class MercurialSCMTest extends MercurialTestCase {
private File repo;
protected String hgInstallation = null; // see DebugFlagTest
protected @Override void setUp() throws Exception {
super.setUp();
repo = createTmpDir();
}
public void testBasicOps() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, null, null, null, false, false));
hg(repo, "init");
touchAndCommit(repo, "a");
buildAndCheck(p,"a"); // this tests the clone op
touchAndCommit(repo, "b");
buildAndCheck(p,"b"); // this tests the update op
}
@Bug(4281)
public void testBranches() throws Exception {
hg(repo, "init");
touchAndCommit(repo, "init");
hg(repo, "tag", "init");
touchAndCommit(repo, "default-1");
hg(repo, "update", "--clean", "init");
hg(repo, "branch", "b");
touchAndCommit(repo, "b-1");
FreeStyleProject p = createFreeStyleProject();
// Clone off b.
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), "b", null, null, null, false, false));
buildAndCheck(p, "b-1");
hg(repo, "update", "--clean", "default");
touchAndCommit(repo, "default-2");
// Changes in default should be ignored.
assertFalse(pollSCMChanges(p));
hg(repo, "update", "--clean", "b");
touchAndCommit(repo, "b-2");
// But changes in b should be pulled.
assertTrue(pollSCMChanges(p));
buildAndCheck(p, "b-2");
// Switch to default branch with an existing workspace.
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, null, null, null, false, false));
// Should now consider preexisting changesets in default to be poll triggers.
assertTrue(pollSCMChanges(p));
// Should switch working copy to default branch.
buildAndCheck(p, "default-2");
touchAndCommit(repo, "b-3");
// Changes in other branch should be ignored.
assertFalse(pollSCMChanges(p));
}
@Bug(1099)
public void testPollingLimitedToModules() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, "dir1 dir2", null, null, false, false));
hg(repo, "init");
touchAndCommit(repo, "dir1/f");
buildAndCheck(p, "dir1/f");
touchAndCommit(repo, "dir2/f");
assertTrue(pollSCMChanges(p));
buildAndCheck(p, "dir2/f");
touchAndCommit(repo, "dir3/f");
assertFalse(pollSCMChanges(p));
// No support for partial checkouts yet, so workspace will contain everything.
buildAndCheck(p, "dir3/f");
// HUDSON-4972: do not pay attention to merges
// (reproduce using the pathological scenario, since reproducing the actual scenario
// where merge gives meaningless file list is not so easy)
hg(repo, "update", "0");
touchAndCommit(repo, "dir4/f");
hg(repo, "merge");
new FilePath(repo).child("dir2/f").write("stuff", "UTF-8");
hg(repo, "commit", "--message", "merged");
assertFalse(pollSCMChanges(p));
buildAndCheck(p, "dir4/f");
}
@Bug(6337)
public void testPollingLimitedToModules2() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, "dir1", null, null, false, false));
hg(repo, "init");
touchAndCommit(repo, "starter");
pollSCMChanges(p);
buildAndCheck(p, "starter");
touchAndCommit(repo, "dir2/f");
assertFalse(pollSCMChanges(p));
touchAndCommit(repo, "dir1/f");
assertTrue(pollSCMChanges(p));
buildAndCheck(p, "dir1/f");
}
@Bug(4702)
public void testChangelogLimitedToModules() throws Exception {
FreeStyleProject p = createFreeStyleProject();
// Control case: no modules specified.
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, null, null, null, false, false));
hg(repo, "init");
touchAndCommit(repo, "dir1/f1");
p.scheduleBuild2(0).get();
touchAndCommit(repo, "dir2/f1");
Iterator<? extends ChangeLogSet.Entry> it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
ChangeLogSet.Entry entry = it.next();
assertEquals(Collections.singleton("dir2/f1"), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, "dir1 extra", null, null, false, false));
// dir2/f2 change should be ignored.
touchAndCommit(repo, "dir1/f2");
touchAndCommit(repo, "dir2/f2");
it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
entry = it.next();
assertEquals(Collections.singleton("dir1/f2"), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
// First commit should match (because at least one file does) but not second.
touchAndCommit(repo, "dir2/f3", "dir1/f3");
touchAndCommit(repo, "dir2/f4", "dir2/f5");
it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
entry = it.next();
assertEquals(new HashSet<String>(Arrays.asList("dir1/f3", "dir2/f3")), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
// Any module in the list can trigger an inclusion.
touchAndCommit(repo, "extra/f1");
it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
entry = it.next();
assertEquals(Collections.singleton("extra/f1"), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
}
@Bug(4271)
public void testParameterizedBuildsBranch() throws Exception {
hg(repo, "init");
touchAndCommit(repo, "trunk");
hg(repo, "update", "null");
hg(repo, "branch", "b");
touchAndCommit(repo, "variant");
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), "${BRANCH}", null, null, null, false, false));
// This is not how a real parameterized build runs, but using ParametersDefinitionProperty just looks untestable:
String log = buildAndCheck(p, "variant", new ParametersAction(new StringParameterValue("BRANCH", "b")));
assertTrue(log, log.contains("--rev b"));
assertFalse(log, log.contains("--rev ${BRANCH}"));
touchAndCommit(repo, "further-variant");
assertTrue(pollSCMChanges(p));
buildAndCheck(p, "further-variant", new ParametersAction(new StringParameterValue("BRANCH", "b")));
}
@Bug(6517)
public void testFileListOmittedForMerges() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, null, null, null, false, false));
hg(repo, "init");
touchAndCommit(repo, "f1");
p.scheduleBuild2(0).get();
hg(repo, "up", "null");
touchAndCommit(repo, "f2");
hg(repo, "merge");
hg(repo, "commit", "--message", "merge");
Iterator<? extends ChangeLogSet.Entry> it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
ChangeLogSet.Entry entry = it.next();
assertTrue(((MercurialChangeSet) entry).isMerge());
assertEquals(Collections.emptySet(), new HashSet<String>(entry.getAffectedPaths()));
assertTrue(it.hasNext());
entry = it.next();
assertFalse(((MercurialChangeSet) entry).isMerge());
assertEquals(Collections.singleton("f2"), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
}
@Bug(3602)
public void testSubdirectoryCheckout() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, null, "repo", null, false, false));
hg(repo, "init");
touchAndCommit(repo, "f1");
buildAndCheck(p, "repo/f1");
touchAndCommit(repo, "f2");
buildAndCheck(p, "repo/f2");
touchAndCommit(repo, "f3");
Iterator<? extends ChangeLogSet.Entry> it = p.scheduleBuild2(0).get().getChangeSet().iterator();
assertTrue(it.hasNext());
ChangeLogSet.Entry entry = it.next();
assertEquals(Collections.singleton("f3"), new HashSet<String>(entry.getAffectedPaths()));
assertFalse(it.hasNext());
}
/* XXX the following will pass, but canUpdate is not going to work without further changes:
public void testParameterizedBuildsSource() throws Exception {
p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, "${REPO}", null, null, null, false, false));
buildAndCheck(p, "trunk", new ParametersAction(new StringParameterValue("REPO", repo.getPath())));
String hgrc = p.getSomeWorkspace().child(".hg/hgrc").readToString();
assertTrue(hgrc.contains(repo.getPath()));
}
*/
/* XXX not yet supported; not sure how to expand var in MercurialSCM.createChangeLogParser:
public void testParameterizedBuildsModules() throws Exception {
hg(repo, "init");
touchAndCommit(repo, "trunk", "dir1/f", "dir2/f");
FreeStyleProject p = createFreeStyleProject();
p.setScm(new MercurialSCM(hgInstallation, repo.getPath(), null, "${MODULES}", null, false, false));
buildAndCheck(p, "dir1/f", new ParametersAction(new StringParameterValue("MODULES", "dir2")));
hg(repo, "update", "default");
touchAndCommit(repo, "dir1/g");
assertFalse(pollSCMChanges(p));
touchAndCommit(repo, "dir2/g");
assertTrue(pollSCMChanges(p));
}
*/
}