comparison test/org/tmatesoft/hg/test/TestHistory.java @ 521:59e555c85da0

Cover ChangesetTreeHandler with various followRename, followAncestry and direction
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 26 Dec 2012 17:51:07 +0100
parents 1ee452f31187
children 2103388d4010
comparison
equal deleted inserted replaced
520:1ee452f31187 521:59e555c85da0
22 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.assertTrue;
23 23
24 import java.util.ArrayList; 24 import java.util.ArrayList;
25 import java.util.Collections; 25 import java.util.Collections;
26 import java.util.Comparator; 26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.Iterator; 27 import java.util.Iterator;
29 import java.util.LinkedList; 28 import java.util.LinkedList;
30 import java.util.List; 29 import java.util.List;
31 import java.util.Map;
32 30
33 import org.junit.Assert; 31 import org.junit.Assert;
34 import org.junit.Rule; 32 import org.junit.Rule;
35 import org.junit.Test; 33 import org.junit.Test;
36 import org.tmatesoft.hg.core.HgCallbackTargetException; 34 import org.tmatesoft.hg.core.HgCallbackTargetException;
109 changelogParser.reset(); 107 changelogParser.reset();
110 eh.run("hg", "log", "--debug", "--follow", f.toString()); 108 eh.run("hg", "log", "--debug", "--follow", f.toString());
111 109
112 CollectWithRenameHandler h = new CollectWithRenameHandler(); 110 CollectWithRenameHandler h = new CollectWithRenameHandler();
113 new HgLogCommand(repo).file(f, true).execute(h); 111 new HgLogCommand(repo).file(f, true).execute(h);
114 errorCollector.assertEquals(1, h.renames.size()); 112 errorCollector.assertEquals(1, h.rh.renames.size());
115 HgFileRevision from = h.renames.get(0).first(); 113 HgFileRevision from = h.rh.renames.get(0).first();
116 boolean fromMatched = "src/com/tmate/hgkit/console/Remote.java".equals(from.getPath().toString()); 114 boolean fromMatched = "src/com/tmate/hgkit/console/Remote.java".equals(from.getPath().toString());
117 String what = "hg log - FOLLOW FILE HISTORY"; 115 String what = "hg log - FOLLOW FILE HISTORY";
118 errorCollector.checkThat(what + "#copyReported ", h.copyReported, is(true)); 116 errorCollector.checkThat(what + "#copyReported ", h.rh.copyReported, is(true));
119 errorCollector.checkThat(what + "#copyFromMatched", fromMatched, is(true)); 117 errorCollector.checkThat(what + "#copyFromMatched", fromMatched, is(true));
120 // 118 //
121 // cmdline always gives in changesets in order from newest (bigger rev number) to oldest. 119 // cmdline always gives in changesets in order from newest (bigger rev number) to oldest.
122 // LogCommand does other way round, from oldest to newest, follewed by revisions of copy source, if any 120 // LogCommand does other way round, from oldest to newest, follewed by revisions of copy source, if any
123 // (apparently older than oldest of the copy target). Hence need to sort Java results according to rev numbers 121 // (apparently older than oldest of the copy target). Hence need to sort Java results according to rev numbers
139 137
140 TreeCollectHandler h = new TreeCollectHandler(false); 138 TreeCollectHandler h = new TreeCollectHandler(false);
141 new HgLogCommand(repo).file(fname, false).execute(h); 139 new HgLogCommand(repo).file(fname, false).execute(h);
142 // since we use TreeCollectHandler with natural order (older to newer), shall reverse console result in report() 140 // since we use TreeCollectHandler with natural order (older to newer), shall reverse console result in report()
143 report("execute with HgChangesetTreeHandler(follow == false)", h.getResult(), true); 141 report("execute with HgChangesetTreeHandler(follow == false)", h.getResult(), true);
144 }
145
146 @Test
147 public void testChangesetTreeFollowRenameAndAncestry() throws Exception {
148 repo = Configuration.get().find("log-follow");
149 final String fname = "file1_b";
150 assertTrue("[sanity]", repo.getFileNode(fname).exists());
151 eh.run("hg", "log", "--debug", "--follow", fname, "--cwd", repo.getLocation());
152
153 final Map<Path,Path> renames = new HashMap<Path, Path>();
154 TreeCollectHandler h = new TreeCollectHandler(true);
155 h.attachAdapter(HgFileRenameHandlerMixin.class, new HgFileRenameHandlerMixin() {
156
157 public void copy(HgFileRevision from, HgFileRevision to) throws HgCallbackTargetException {
158 renames.put(from.getPath(), to.getPath());
159 }
160 });
161 h.checkPrevInParents = true;
162 new HgLogCommand(repo).file(fname, true, true).execute(h);
163
164 assertEquals(1, h.getAdapterUse(HgFileRenameHandlerMixin.class));
165
166 report("execute with HgChangesetTreeHandler(follow == true)", h.getResult(), false);
167
168 assertEquals(1, renames.size());
169 assertEquals(Path.create(fname), renames.get(Path.create("file1_a")));
170 } 142 }
171 143
172 /** 144 /**
173 * Few tests to check newly introduced followAncestry parameter to HgLogCommand: 145 * Few tests to check newly introduced followAncestry parameter to HgLogCommand:
174 * followRename: true, followAncestry: false 146 * followRename: true, followAncestry: false
186 // sequentially gives follow rename semantics without ancestry 158 // sequentially gives follow rename semantics without ancestry
187 eh.run("hg", "log", "--debug", fname2, fname1, "--cwd", repo.getLocation()); 159 eh.run("hg", "log", "--debug", fname2, fname1, "--cwd", repo.getLocation());
188 160
189 CollectWithRenameHandler h = new CollectWithRenameHandler(); 161 CollectWithRenameHandler h = new CollectWithRenameHandler();
190 new HgLogCommand(repo).file(fname2, true, false).execute(h); 162 new HgLogCommand(repo).file(fname2, true, false).execute(h);
191 errorCollector.assertEquals(1, h.renames.size()); 163 errorCollector.assertEquals(1, h.rh.renames.size());
192 Pair<HgFileRevision, HgFileRevision> rename = h.renames.get(0); 164 Pair<HgFileRevision, HgFileRevision> rename = h.rh.renames.get(0);
193 errorCollector.assertEquals(fname1, rename.first().getPath().toString()); 165 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
194 errorCollector.assertEquals(fname2, rename.second().getPath().toString()); 166 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
195 // Ensure rename info came in the right moment 167 // Ensure rename info came in the right moment
196 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size()); 168 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size());
197 // Command iterates old to new, rename comes after last fname1 revision. Since we don't follow 169 // Command iterates old to new, rename comes after last fname1 revision. Since we don't follow
202 // 174 //
203 // Direction 175 // Direction
204 h = new CollectWithRenameHandler(); 176 h = new CollectWithRenameHandler();
205 new HgLogCommand(repo).file(fname2, true, false).debugSwitch1().execute(h); 177 new HgLogCommand(repo).file(fname2, true, false).debugSwitch1().execute(h);
206 // Identical rename shall be reported, at the same moment 178 // Identical rename shall be reported, at the same moment
207 errorCollector.assertEquals(1, h.renames.size()); 179 errorCollector.assertEquals(1, h.rh.renames.size());
208 rename = h.renames.get(0); 180 rename = h.rh.renames.get(0);
209 errorCollector.assertEquals(fname1, rename.first().getPath().toString()); 181 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
210 errorCollector.assertEquals(fname2, rename.second().getPath().toString()); 182 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
211 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size()); 183 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size());
212 // new to old, recently reported would be the very first revision fname2 pops up 184 // new to old, recently reported would be the very first revision fname2 pops up
213 String firstRevOfFname2 = "27e7a69373b74d42e75f3211e56510ff17d01370"; 185 String firstRevOfFname2 = "27e7a69373b74d42e75f3211e56510ff17d01370";
214 errorCollector.assertEquals(firstRevOfFname2, h.lastChangesetReportedAtRename.get(0).getNodeid().toString()); 186 errorCollector.assertEquals(firstRevOfFname2, h.lastChangesetReportedAtRename.get(0).getNodeid().toString());
215 report("HgChangesetHandler(renames: true, ancestry:false)", h.getChanges(), false); 187 report("HgChangesetHandler(renames: true, ancestry:false)", h.getChanges(), false);
216 // 188 //
217 // TODO TreeChangeHandler 189 // TreeChangeHandler - in #testChangesetTreeFollowRenamesNotAncestry
190 }
191
192 @Test
193 public void testChangesetTreeFollowRenamesNotAncestry() throws Exception {
194 repo = Configuration.get().find("log-follow");
195 final String fname1 = "file1_a";
196 final String fname2 = "file1_b";
197 assertTrue("[sanity]", repo.getFileNode(fname2).exists());
198 // no --follow, but two names we know have been the same file (fname1 renamed to fname2)
199 // sequentially gives follow rename semantics without ancestry
200 eh.run("hg", "log", "--debug", fname2, fname1, "--cwd", repo.getLocation());
201
202 TreeCollectHandler h = new TreeCollectHandler(true);
203 RenameCollector rh = new RenameCollector(h);
204 // can't check that prev revision is in parent because there are forks in
205 // file history (e.g. rev2 and rev3 (that comes next) both have rev0 as their parent
206 // and followAncestry is false
207 // h.checkPrevInParents = true;
208 new HgLogCommand(repo).file(fname2, true, false).execute(h);
209 errorCollector.assertEquals(1, rh.renames.size());
210 Pair<HgFileRevision, HgFileRevision> rename = rh.renames.get(0);
211 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
212 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
213 report("HgChangesetTreeHandler(renames: true, ancestry:false)", h.getResult(), false);
214
215 // Direction
216 h = new TreeCollectHandler(false);
217 rh = new RenameCollector(h);
218 // h.checkPrevInChildren = true; see above
219 new HgLogCommand(repo).file(fname2, true, false).debugSwitch1().execute(h);
220 errorCollector.assertEquals(1, rh.renames.size());
221 rename = rh.renames.get(0);
222 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
223 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
224 report("HgChangesetTreeHandler(renames: true, ancestry:false)", h.getResult(), false);
218 } 225 }
219 226
220 @Test 227 @Test
221 public void testFollowAncestryNotRenames() throws Exception { 228 public void testFollowAncestryNotRenames() throws Exception {
222 repo = Configuration.get().find("log-follow"); 229 repo = Configuration.get().find("log-follow");
223 final String fname2 = "file1_b"; 230 final String fname2 = "file1_b";
224 assertTrue("[sanity]", repo.getFileNode(fname2).exists()); 231 assertTrue("[sanity]", repo.getFileNode(fname2).exists());
232 final List<Record> fname2Follow = getAncestryWithoutRenamesFromCmdline(fname2);
233
234 CollectWithRenameHandler h = new CollectWithRenameHandler();
235 new HgLogCommand(repo).file(fname2, false, true).execute(h);
236 errorCollector.assertEquals(0, h.rh.renames.size());
237 report("HgChangesetHandler(renames: false, ancestry:true)", h.getChanges(), fname2Follow, true, errorCollector);
238 //
239 // Direction
240 h = new CollectWithRenameHandler();
241 new HgLogCommand(repo).file(fname2, false, true).debugSwitch1().execute(h);
242 report("HgChangesetHandler(renames: false, ancestry:true)", h.getChanges(), fname2Follow, false/*!!!*/, errorCollector);
243 //
244 // TreeChangeHandler - in #testChangesetTreeFollowAncestryNotRenames
245 }
246
247 @Test
248 public void testChangesetTreeFollowAncestryNotRenames() throws Exception {
249 repo = Configuration.get().find("log-follow");
250 final String fname2 = "file1_b";
251 final List<Record> fname2Follow = getAncestryWithoutRenamesFromCmdline(fname2);
252
253 TreeCollectHandler h = new TreeCollectHandler(false);
254 RenameCollector rh = new RenameCollector(h);
255 h.checkPrevInParents = true;
256 new HgLogCommand(repo).file(fname2, false, true).execute(h);
257 errorCollector.assertEquals(0, rh.renames.size());
258 report("HgChangesetTreeHandler(renames: false, ancestry:true)", h.getResult(), fname2Follow, true, errorCollector);
259
260 // Direction
261 h = new TreeCollectHandler(false);
262 rh = new RenameCollector(h);
263 h.checkPrevInChildren = true;
264 new HgLogCommand(repo).file(fname2, false, true).debugSwitch1().execute(h);
265 report("HgChangesetTreeHandler(renames: false, ancestry:true)", h.getResult(), fname2Follow, false, errorCollector);
266 }
267
268
269 private List<Record> getAncestryWithoutRenamesFromCmdline(String fname2) throws Exception {
225 // to get "followed" history of fname2 only (without fname1 origin), 270 // to get "followed" history of fname2 only (without fname1 origin),
226 // get the complete history and keep there only elements that match fname2 own history 271 // get the complete history and keep there only elements that match fname2 own history
227 eh.run("hg", "log", "--debug", "--follow", fname2, "--cwd", repo.getLocation()); 272 eh.run("hg", "log", "--debug", "--follow", fname2, "--cwd", repo.getLocation());
228 final List<Record> fname2Follow = new LinkedList<LogOutputParser.Record>(changelogParser.getResult()); 273 final List<Record> fname2Follow = new LinkedList<LogOutputParser.Record>(changelogParser.getResult());
229 changelogParser.reset(); 274 changelogParser.reset();
241 } 286 }
242 if (!belongsToSoleFname2History) { 287 if (!belongsToSoleFname2History) {
243 it.remove(); 288 it.remove();
244 } 289 }
245 } 290 }
246 CollectWithRenameHandler h = new CollectWithRenameHandler(); 291 return fname2Follow;
247 new HgLogCommand(repo).file(fname2, false, true).execute(h);
248 errorCollector.assertEquals(0, h.renames.size());
249 report("HgChangesetHandler(renames: false, ancestry:true)", h.getChanges(), fname2Follow, true, errorCollector);
250 //
251 // Direction
252 h = new CollectWithRenameHandler();
253 new HgLogCommand(repo).file(fname2, false, true).debugSwitch1().execute(h);
254 report("HgChangesetHandler(renames: false, ancestry:true)", h.getChanges(), fname2Follow, false/*!!!*/, errorCollector);
255 //
256 // TODO TreeChangeHandler
257 } 292 }
258 293
259 /** 294 /**
260 * output identical to that of "hg log --follow" 295 * output identical to that of "hg log --follow"
261 */ 296 */
267 assertTrue("[sanity]", repo.getFileNode(fname2).exists()); 302 assertTrue("[sanity]", repo.getFileNode(fname2).exists());
268 eh.run("hg", "log", "--debug", "--follow", fname2, "--cwd", repo.getLocation()); 303 eh.run("hg", "log", "--debug", "--follow", fname2, "--cwd", repo.getLocation());
269 304
270 CollectWithRenameHandler h = new CollectWithRenameHandler(); 305 CollectWithRenameHandler h = new CollectWithRenameHandler();
271 new HgLogCommand(repo).file(fname2, true, true).execute(h); 306 new HgLogCommand(repo).file(fname2, true, true).execute(h);
272 errorCollector.assertEquals(1, h.renames.size()); 307 errorCollector.assertEquals(1, h.rh.renames.size());
273 Pair<HgFileRevision, HgFileRevision> rename = h.renames.get(0); 308 Pair<HgFileRevision, HgFileRevision> rename = h.rh.renames.get(0);
274 errorCollector.assertEquals(fname1, rename.first().getPath().toString()); 309 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
275 errorCollector.assertEquals(fname2, rename.second().getPath().toString()); 310 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
276 // Ensure rename info came in the right moment 311 // Ensure rename info came in the right moment
277 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size()); 312 errorCollector.assertEquals(1, h.lastChangesetReportedAtRename.size());
278 String fname1BranchRevision = "6e668ff2940acb250c8627843f8116166fe5d5cd"; 313 String fname1BranchRevision = "6e668ff2940acb250c8627843f8116166fe5d5cd";
282 // 317 //
283 // Switch direction and compare, order shall match that from console 318 // Switch direction and compare, order shall match that from console
284 h = new CollectWithRenameHandler(); 319 h = new CollectWithRenameHandler();
285 new HgLogCommand(repo).file(fname2, true, true).debugSwitch1().execute(h); 320 new HgLogCommand(repo).file(fname2, true, true).debugSwitch1().execute(h);
286 // Identical rename event shall be reported 321 // Identical rename event shall be reported
287 errorCollector.assertEquals(1, h.renames.size()); 322 errorCollector.assertEquals(1, h.rh.renames.size());
288 rename = h.renames.get(0); 323 rename = h.rh.renames.get(0);
289 errorCollector.assertEquals(fname1, rename.first().getPath().toString()); 324 errorCollector.assertEquals(fname1, rename.first().getPath().toString());
290 errorCollector.assertEquals(fname2, rename.second().getPath().toString()); 325 errorCollector.assertEquals(fname2, rename.second().getPath().toString());
291 // new to old, recently reported would be the very first revision fname2 pops up 326 // new to old, recently reported would be the very first revision fname2 pops up
292 String firstRevOfFname2 = "27e7a69373b74d42e75f3211e56510ff17d01370"; 327 String firstRevOfFname2 = "27e7a69373b74d42e75f3211e56510ff17d01370";
293 errorCollector.assertEquals(firstRevOfFname2, h.lastChangesetReportedAtRename.get(0).getNodeid().toString()); 328 errorCollector.assertEquals(firstRevOfFname2, h.lastChangesetReportedAtRename.get(0).getNodeid().toString());
294 report("HgChangesetHandler(renames: true, ancestry:true)", h.getChanges(), false /*do not reorder console results !!!*/); 329 report("HgChangesetHandler(renames: true, ancestry:true)", h.getChanges(), false /*do not reorder console results !!!*/);
295 // 330 //
296 // TreeChangeHandler in #testChangesetTreeFollowRenameAndAncestry 331 // TreeChangeHandler in #testChangesetTreeFollowRenameAndAncestry
332 }
333
334 @Test
335 public void testChangesetTreeFollowRenameAndAncestry() throws Exception {
336 repo = Configuration.get().find("log-follow");
337 final String fname = "file1_b";
338 assertTrue("[sanity]", repo.getFileNode(fname).exists());
339 eh.run("hg", "log", "--debug", "--follow", fname, "--cwd", repo.getLocation());
340
341 TreeCollectHandler h = new TreeCollectHandler(true);
342 RenameCollector rh = new RenameCollector(h);
343 h.checkPrevInParents = true;
344 new HgLogCommand(repo).file(fname, true, true).execute(h);
345
346 assertEquals(1, h.getAdapterUse(HgFileRenameHandlerMixin.class));
347
348 report("execute with HgChangesetTreeHandler(follow == true)", h.getResult(), false);
349
350 assertEquals(1, rh.renames.size());
351 assertEquals(Path.create(fname), rh.renames.get(0).second().getPath());
297 } 352 }
298 353
299 /** 354 /**
300 * @see TestAuxUtilities#testChangelogCancelSupport() 355 * @see TestAuxUtilities#testChangelogCancelSupport()
301 */ 356 */
494 //// 549 ////
495 550
496 private final class TreeCollectHandler extends AdapterPlug implements HgChangesetTreeHandler { 551 private final class TreeCollectHandler extends AdapterPlug implements HgChangesetTreeHandler {
497 private final LinkedList<HgChangeset> cmdResult = new LinkedList<HgChangeset>(); 552 private final LinkedList<HgChangeset> cmdResult = new LinkedList<HgChangeset>();
498 private final boolean reverseResult; 553 private final boolean reverseResult;
499 boolean checkPrevInChildren = false; 554 boolean checkPrevInChildren = false; // true when iterating new to old
500 boolean checkPrevInParents = false; 555 boolean checkPrevInParents = false; // true when iterating old to new
501 556
502 public TreeCollectHandler(boolean _reverseResult) { 557 public TreeCollectHandler(boolean _reverseResult) {
503 this.reverseResult = _reverseResult; 558 this.reverseResult = _reverseResult;
504 } 559 }
505 560
544 } 599 }
545 } 600 }
546 } 601 }
547 602
548 private static class CollectWithRenameHandler extends CollectHandler implements HgChangesetHandler.WithCopyHistory { 603 private static class CollectWithRenameHandler extends CollectHandler implements HgChangesetHandler.WithCopyHistory {
549 public boolean copyReported = false; 604 public final RenameCollector rh = new RenameCollector();
550 public List<Pair<HgFileRevision, HgFileRevision>> renames = new LinkedList<Pair<HgFileRevision,HgFileRevision>>(); 605 public List<HgChangeset> lastChangesetReportedAtRename = new LinkedList<HgChangeset>();
551 public List<HgChangeset> lastChangesetReportedAtRename = new LinkedList<HgChangeset>(); 606
552 607 public void copy(HgFileRevision from, HgFileRevision to) throws HgCallbackTargetException {
553 public void copy(HgFileRevision from, HgFileRevision to) {
554 copyReported = true;
555 Assert.assertTrue("Renames couldn't be reported prior to any change", getChanges().size() > 0); 608 Assert.assertTrue("Renames couldn't be reported prior to any change", getChanges().size() > 0);
556 HgChangeset lastKnown = getChanges().get(getChanges().size() - 1); 609 HgChangeset lastKnown = getChanges().get(getChanges().size() - 1);
557 lastChangesetReportedAtRename.add(lastKnown); 610 lastChangesetReportedAtRename.add(lastKnown);
611 rh.copy(from, to);
612 }
613 };
614
615 private static class RenameCollector implements HgFileRenameHandlerMixin {
616 public boolean copyReported = false;
617 public List<Pair<HgFileRevision, HgFileRevision>> renames = new LinkedList<Pair<HgFileRevision,HgFileRevision>>();
618
619 public RenameCollector() {
620 }
621
622 public RenameCollector(AdapterPlug ap) {
623 ap.attachAdapter(HgFileRenameHandlerMixin.class, this);
624 }
625
626 public void copy(HgFileRevision from, HgFileRevision to) {
627 copyReported = true;
558 renames.add(new Pair<HgFileRevision, HgFileRevision>(from, to)); 628 renames.add(new Pair<HgFileRevision, HgFileRevision>(from, to));
559 } 629 }
560 }; 630 }
561 } 631 }