tikhomirov@70: /* tikhomirov@70: * Copyright (c) 2011 TMate Software Ltd tikhomirov@70: * tikhomirov@70: * This program is free software; you can redistribute it and/or modify tikhomirov@70: * it under the terms of the GNU General Public License as published by tikhomirov@70: * the Free Software Foundation; version 2 of the License. tikhomirov@70: * tikhomirov@70: * This program is distributed in the hope that it will be useful, tikhomirov@70: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@70: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@70: * GNU General Public License for more details. tikhomirov@70: * tikhomirov@70: * For information on how to redistribute this software under tikhomirov@70: * the terms of a license other than GNU General Public License tikhomirov@102: * contact TMate Software at support@hg4j.com tikhomirov@70: */ tikhomirov@70: package org.tmatesoft.hg.test; tikhomirov@70: tikhomirov@103: import static org.hamcrest.CoreMatchers.equalTo; tikhomirov@103: import static org.hamcrest.CoreMatchers.is; tikhomirov@147: import static org.junit.Assert.assertTrue; tikhomirov@103: tikhomirov@70: import java.util.Collections; tikhomirov@103: import java.util.Comparator; tikhomirov@70: import java.util.Iterator; tikhomirov@103: import java.util.LinkedList; tikhomirov@70: import java.util.List; tikhomirov@70: tikhomirov@103: import org.junit.Rule; tikhomirov@101: import org.junit.Test; tikhomirov@129: import org.tmatesoft.hg.core.HgChangeset; tikhomirov@131: import org.tmatesoft.hg.core.HgLogCommand; tikhomirov@131: import org.tmatesoft.hg.core.HgLogCommand.CollectHandler; tikhomirov@131: import org.tmatesoft.hg.core.HgLogCommand.FileHistoryHandler; tikhomirov@131: import org.tmatesoft.hg.core.HgLogCommand.FileRevision; tikhomirov@101: import org.tmatesoft.hg.repo.HgLookup; tikhomirov@74: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@70: import org.tmatesoft.hg.test.LogOutputParser.Record; tikhomirov@133: import org.tmatesoft.hg.util.Path; tikhomirov@70: tikhomirov@70: tikhomirov@70: /** tikhomirov@70: * tikhomirov@70: * @author Artem Tikhomirov tikhomirov@70: * @author TMate Software Ltd. tikhomirov@70: */ tikhomirov@70: public class TestHistory { tikhomirov@70: tikhomirov@103: @Rule tikhomirov@103: public ErrorCollectorExt errorCollector = new ErrorCollectorExt(); tikhomirov@103: tikhomirov@147: private HgRepository repo; tikhomirov@147: private final ExecHelper eh; tikhomirov@70: private LogOutputParser changelogParser; tikhomirov@70: tikhomirov@103: public static void main(String[] args) throws Throwable { tikhomirov@101: TestHistory th = new TestHistory(); tikhomirov@70: th.testCompleteLog(); tikhomirov@82: th.testFollowHistory(); tikhomirov@103: th.errorCollector.verify(); tikhomirov@147: // th.testPerformance(); tikhomirov@147: th.testOriginalTestLogRepo(); tikhomirov@147: th.testUsernames(); tikhomirov@147: th.testBranches(); tikhomirov@147: // tikhomirov@147: th.errorCollector.verify(); tikhomirov@70: } tikhomirov@101: tikhomirov@101: public TestHistory() throws Exception { tikhomirov@101: this(new HgLookup().detectFromWorkingDir()); tikhomirov@101: } tikhomirov@70: tikhomirov@101: private TestHistory(HgRepository hgRepo) { tikhomirov@70: repo = hgRepo; tikhomirov@70: eh = new ExecHelper(changelogParser = new LogOutputParser(true), null); tikhomirov@147: tikhomirov@70: } tikhomirov@70: tikhomirov@101: @Test tikhomirov@70: public void testCompleteLog() throws Exception { tikhomirov@70: changelogParser.reset(); tikhomirov@70: eh.run("hg", "log", "--debug"); tikhomirov@131: List r = new HgLogCommand(repo).execute(); tikhomirov@82: report("hg log - COMPLETE REPO HISTORY", r, true); tikhomirov@82: } tikhomirov@82: tikhomirov@101: @Test tikhomirov@82: public void testFollowHistory() throws Exception { tikhomirov@82: final Path f = Path.create("cmdline/org/tmatesoft/hg/console/Remote.java"); tikhomirov@82: try { tikhomirov@82: if (repo.getFileNode(f).exists()) { // FIXME getFileNode shall not fail with IAE tikhomirov@82: changelogParser.reset(); tikhomirov@82: eh.run("hg", "log", "--debug", "--follow", f.toString()); tikhomirov@82: tikhomirov@82: class H extends CollectHandler implements FileHistoryHandler { tikhomirov@82: boolean copyReported = false; tikhomirov@82: boolean fromMatched = false; tikhomirov@82: public void copy(FileRevision from, FileRevision to) { tikhomirov@82: copyReported = true; tikhomirov@82: fromMatched = "src/com/tmate/hgkit/console/Remote.java".equals(from.getPath().toString()); tikhomirov@82: } tikhomirov@82: }; tikhomirov@82: H h = new H(); tikhomirov@131: new HgLogCommand(repo).file(f, true).execute(h); tikhomirov@103: String what = "hg log - FOLLOW FILE HISTORY"; tikhomirov@103: errorCollector.checkThat(what + "#copyReported ", h.copyReported, is(true)); tikhomirov@103: errorCollector.checkThat(what + "#copyFromMatched", h.fromMatched, is(true)); tikhomirov@103: // tikhomirov@103: // cmdline always gives in changesets in order from newest (bigger rev number) to oldest. tikhomirov@103: // LogCommand does other way round, from oldest to newest, follewed by revisions of copy source, if any tikhomirov@103: // (apparently older than oldest of the copy target). Hence need to sort Java results according to rev numbers tikhomirov@129: final LinkedList sorted = new LinkedList(h.getChanges()); tikhomirov@129: Collections.sort(sorted, new Comparator() { tikhomirov@129: public int compare(HgChangeset cs1, HgChangeset cs2) { tikhomirov@103: return cs1.getRevision() < cs2.getRevision() ? 1 : -1; tikhomirov@103: } tikhomirov@103: }); tikhomirov@103: report(what, sorted, false); tikhomirov@82: } tikhomirov@82: } catch (IllegalArgumentException ex) { tikhomirov@82: System.out.println("Can't test file history with follow because need to query specific file with history"); tikhomirov@82: } tikhomirov@70: } tikhomirov@70: tikhomirov@129: private void report(String what, List r, boolean reverseConsoleResults) { tikhomirov@70: final List consoleResult = changelogParser.getResult(); tikhomirov@82: if (reverseConsoleResults) { tikhomirov@82: Collections.reverse(consoleResult); tikhomirov@82: } tikhomirov@147: Iterator consoleResultItr = consoleResult.iterator(); tikhomirov@129: for (HgChangeset cs : r) { tikhomirov@147: Record cr = consoleResultItr.next(); tikhomirov@70: int x = cs.getRevision() == cr.changesetIndex ? 0x1 : 0; tikhomirov@70: x |= cs.getDate().equals(cr.date) ? 0x2 : 0; tikhomirov@70: x |= cs.getNodeid().toString().equals(cr.changesetNodeid) ? 0x4 : 0; tikhomirov@70: x |= cs.getUser().equals(cr.user) ? 0x8 : 0; tikhomirov@70: x |= cs.getComment().equals(cr.description) ? 0x10 : 0; tikhomirov@147: errorCollector.checkThat(String.format(what + ". Error in %d hg4j rev comparing to %d cmdline's.", cs.getRevision(), cr.changesetIndex), x, equalTo(0x1f)); tikhomirov@70: consoleResultItr.remove(); tikhomirov@70: } tikhomirov@103: errorCollector.checkThat(what + ". Insufficient results from Java ", consoleResultItr.hasNext(), equalTo(false)); tikhomirov@70: } tikhomirov@100: tikhomirov@100: public void testPerformance() throws Exception { tikhomirov@100: final int runs = 10; tikhomirov@100: final long start1 = System.currentTimeMillis(); tikhomirov@100: for (int i = 0; i < runs; i++) { tikhomirov@100: changelogParser.reset(); tikhomirov@100: eh.run("hg", "log", "--debug"); tikhomirov@100: } tikhomirov@100: final long start2 = System.currentTimeMillis(); tikhomirov@100: for (int i = 0; i < runs; i++) { tikhomirov@131: new HgLogCommand(repo).execute(); tikhomirov@100: } tikhomirov@100: final long end = System.currentTimeMillis(); tikhomirov@100: System.out.printf("'hg log --debug', %d runs: Native client total %d (%d per run), Java client %d (%d)\n", runs, start2-start1, (start2-start1)/runs, end-start2, (end-start2)/runs); tikhomirov@100: } tikhomirov@147: tikhomirov@147: @Test tikhomirov@147: public void testOriginalTestLogRepo() throws Exception { tikhomirov@147: repo = Configuration.get().find("log-1"); tikhomirov@147: HgLogCommand cmd = new HgLogCommand(repo); tikhomirov@147: // funny enough, but hg log -vf a -R c:\temp\hg\test-log\a doesn't work, while --cwd works fine tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "a", "--cwd", repo.getLocation()); tikhomirov@147: report("log a", cmd.file("a", false).execute(), true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-f", "a", "--cwd", repo.getLocation()); tikhomirov@147: List r = cmd.file("a", true).execute(); tikhomirov@147: report("log -f a", r, true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-f", "e", "--cwd", repo.getLocation()); tikhomirov@147: report("log -f e", cmd.file("e", true).execute(), false /*#1, below*/); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "dir/b", "--cwd", repo.getLocation()); tikhomirov@147: report("log dir/b", cmd.file("dir/b", false).execute(), true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-f", "dir/b", "--cwd", repo.getLocation()); tikhomirov@147: report("log -f dir/b", cmd.file("dir/b", true).execute(), false /*#1, below*/); tikhomirov@147: /* tikhomirov@147: * #1: false works because presently commands dispatches history of the queried file, and then history tikhomirov@147: * of it's origin. With history comprising of renames only, this effectively gives reversed (newest to oldest) tikhomirov@147: * order of revisions. tikhomirov@147: */ tikhomirov@147: } tikhomirov@147: tikhomirov@147: @Test tikhomirov@147: public void testUsernames() throws Exception { tikhomirov@147: repo = Configuration.get().find("log-users"); tikhomirov@147: final String user1 = "User One "; tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-u", user1, "--cwd", repo.getLocation()); tikhomirov@147: report("log -u " + user1, new HgLogCommand(repo).user(user1).execute(), true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-u", "user1", "-u", "user2", "--cwd", repo.getLocation()); tikhomirov@147: report("log -u user1 -u user2", new HgLogCommand(repo).user("user1").user("user2").execute(), true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-u", "user3", "--cwd", repo.getLocation()); tikhomirov@147: report("log -u user3", new HgLogCommand(repo).user("user3").execute(), true); tikhomirov@147: } tikhomirov@147: tikhomirov@147: @Test tikhomirov@147: public void testBranches() throws Exception { tikhomirov@147: repo = Configuration.get().find("log-branches"); tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-b", "default", "--cwd", repo.getLocation()); tikhomirov@147: report("log -b default" , new HgLogCommand(repo).branch("default").execute(), true); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-b", "test", "--cwd", repo.getLocation()); tikhomirov@147: report("log -b test" , new HgLogCommand(repo).branch("test").execute(), true); tikhomirov@147: // tikhomirov@147: assertTrue("log -b dummy shall yeild empty result", new HgLogCommand(repo).branch("dummy").execute().isEmpty()); tikhomirov@147: // tikhomirov@147: changelogParser.reset(); tikhomirov@147: eh.run("hg", "log", "--debug", "-b", "default", "-b", "test", "--cwd", repo.getLocation()); tikhomirov@147: report("log -b default -b test" , new HgLogCommand(repo).branch("default").branch("test").execute(), true); tikhomirov@147: } tikhomirov@70: }