comparison tests/test-stabletailgraph.t @ 50426:f0d2b18f0274

stabletailgraph: implement stable-tail sort This adds the computation of the "stable-tail sort", an incremental node sorting method. It is a stepping stone for the implementation of faster label discovery (for example for obs markers) and more caching.
author pacien <pacien.trangirard@pacien.net>
date Thu, 30 Mar 2023 22:22:44 +0200
parents
children 1e31eda9c845
comparison
equal deleted inserted replaced
50425:9fa3cda7449e 50426:f0d2b18f0274
1 ====================================
2 Test for the stabletailgraph package
3 ====================================
4
5 This test file contains a bunch of small test graphs with some minimal yet
6 non-trivial structure, on which the various stable-tail graph and stable-tail
7 sort functions are tested.
8
9 Each case consists of the creation of the interesting graph structure, followed
10 by a check, for each noteworthy node, of:
11 - the stable-tail sort output.
12
13 In the ASCII art of the diagrams, the side of the exclusive part which is
14 followed in priority is denoted with "<" or ">" if it is on the left or right
15 respectively.
16
17 The intermediary linear parts in the example graph are there to force the
18 exclusive part choice (made on a min rank condition).
19
20
21 Setup
22 =====
23
24 Enable the rank computation to test sorting based on the rank.
25
26 $ cat << EOF >> $HGRCPATH
27 > [format]
28 > exp-use-changelog-v2=enable-unstable-format-and-corrupt-my-data
29 >
30 > [alias]
31 > test-sts = debug::stable-tail-sort -T '{tags},'
32 > test-log = log --graph -T '{tags} rank={_fast_rank}'
33 > EOF
34
35
36 Example 1: single merge node
37 ============================
38
39 A base case with one branchpoint "b" and one merge node "e".
40
41 The exclusive part, starting with the lowest-ranking parent "c" of "e",
42 appears first in stable-tail sort of "e" and "f".
43
44 # f
45 # |
46 # e
47 # |
48 # --<--
49 # | |
50 # c d
51 # | |
52 # --+-- <- at this point, the sort of "e" is done consuming its
53 # | exclusive part [c] and jumps back to its other parent "d"
54 # b
55 # |
56 # a
57
58 $ hg init example-1
59 $ cd example-1
60 $ hg debugbuilddag '.:a*a:b*b:c<b+2:d*c/d:e*e:f.'
61 $ hg test-log
62 o tip rank=8
63 |
64 o f rank=7
65 |
66 o e rank=6
67 |\
68 | o d rank=4
69 | |
70 | o rank=3
71 | |
72 o | c rank=3
73 |/
74 o b rank=2
75 |
76 o a rank=1
77
78
79 Check the sort of the base linear case.
80
81 $ hg test-sts c
82 c,b,a, (no-eol)
83
84 Check the stable-tail sort of "e": "c" should come before "d".
85
86 $ hg test-sts e
87 e,c,d,*,b,a, (no-eol) (glob)
88
89 Check that the linear descendant of the merge inherits its sort properly.
90
91 $ hg test-sts f
92 f,e,c,d,*,b,a, (no-eol) (glob)
93
94 $ cd ..
95
96
97 Example 2: nested exclusive parts, without specific leap
98 ========================================================
99
100 "g" is a merge node whose exclusive part contains a merge node "e".
101 We check that the stable-tail sort recurses properly by delegating.
102
103 Notice that parts of the sort of "e" is an infix of the sort of "g".
104 This is an expected property of the sort.
105
106 # g
107 # |
108 # ---<---
109 # | |
110 # e | <- while processing the sort in the exclusive part of "g"
111 # | | we recursively process the exclusive part of "e"
112 # --<-- f
113 # | | |
114 # c d |
115 # | | |
116 # --+-- |
117 # | |
118 # b |
119 # | |
120 # ---+--- <- done with excl(g), jump to "f"
121 # |
122 # a
123
124 $ hg init example-2
125 $ cd example-2
126 $ hg debugbuilddag '.:a*a:b*b:c<b+2:d*c/d:e<a+6:f*e/f:g.'
127 $ hg test-log
128 o tip rank=14
129 |
130 o g rank=13
131 |\
132 | o f rank=7
133 | |
134 | o rank=6
135 | |
136 | o rank=5
137 | |
138 | o rank=4
139 | |
140 | o rank=3
141 | |
142 | o rank=2
143 | |
144 o | e rank=6
145 |\ \
146 | o | d rank=4
147 | | |
148 | o | rank=3
149 | | |
150 o | | c rank=3
151 |/ /
152 o / b rank=2
153 |/
154 o a rank=1
155
156 Display the sort of "e" for reference
157
158 $ hg test-sts e
159 e,c,d,*,b,a, (no-eol) (glob)
160
161 Check the correctness of the sort of "g",
162 and that a part of the sort of "e" appears as an infix.
163
164 $ hg test-sts g
165 g,e,c,d,*,b,f,*,a, (no-eol) (glob)
166
167 $ cd ..
168
169
170 Example 3: shadowing of a final leap
171 ====================================
172
173 We have a merge "f" whose exclusive part contains a merge "d".
174
175 The inherited parent of "d" is not in the exclusive part of "f".
176 At the end of the exclusive part of "d",
177 the leap to "c" is shadowed by the leap to "e", i.e. the inherited part to "f".
178
179 Notice that emitting "c" before "e" would break the reverse topological
180 ordering.
181
182 # f
183 # |
184 # ---<---
185 # | |
186 # d |
187 # | e
188 # --<-- |
189 # | | |
190 # | +----
191 # b |
192 # | c
193 # | |
194 # --+-- <- at this point, jumping to "e", not the shadowed "c"
195 # |
196 # a
197
198 $ hg init example-3
199 $ cd example-3
200 $ hg debugbuilddag '.:a*a:b<a+2:c*b/c:d<c+3:e*d/e:f.'
201 $ hg test-log
202 o tip rank=10
203 |
204 o f rank=9
205 |\
206 | o e rank=6
207 | |
208 | o rank=5
209 | |
210 | o rank=4
211 | |
212 o | d rank=5
213 |\|
214 | o c rank=3
215 | |
216 | o rank=2
217 | |
218 o | b rank=2
219 |/
220 o a rank=1
221
222
223 Display the sort of "d" for reference:
224
225 $ hg test-sts d
226 d,b,c,*,a, (no-eol) (glob)
227
228 Check that we leap from "b" directly to "e" (shadowing the leap to "c"),
229 and that "c" is then emitted after "e" (its descendant).
230
231 $ hg test-sts f
232 f,d,b,e,*,c,*,a, (no-eol) (glob)
233
234 $ cd ..
235
236
237 Example 4: skipping over nested exclusive part (entirely)
238 =========================================================
239
240 We have a merge "f" whose exclusive part contains a merge "d".
241
242 The exclusive part of "d" is not in the exclusive part of "f".
243 However, some of the inherited part of "d" is part of the exclusive part of "f"
244 and needs to be iterated over before leaping to the inherited part of "f".
245
246 The sort of "d" is partially reused for the ordering of the exclusive part of
247 "f". However the reused part is not contiguous in the sort of "d".
248
249 # f
250 # |
251 # ---<---
252 # | |
253 # d |
254 # | e
255 # -->-- | <- in the sort of "f", we need to skip "c" and leap to the
256 # | | | inherited part of "d"
257 # | +----
258 # b |
259 # | c
260 # | |
261 # --+--
262 # |
263 # a
264
265 $ hg init example-4
266 $ cd example-4
267 $ hg debugbuilddag '.:a*a+1:b<a+1:c*b/c:d<c+4:e*d/e:f.'
268 $ hg test-log
269 o tip rank=11
270 |
271 o f rank=10
272 |\
273 | o e rank=6
274 | |
275 | o rank=5
276 | |
277 | o rank=4
278 | |
279 | o rank=3
280 | |
281 o | d rank=5
282 |\|
283 | o c rank=2
284 | |
285 o | b rank=3
286 | |
287 o | rank=2
288 |/
289 o a rank=1
290
291
292 Display the sort of "d" for reference:
293
294 $ hg test-sts d
295 d,c,b,*,a, (no-eol) (glob)
296
297 Chack that sort "f" leaps from "d" to "b":
298
299 $ hg test-sts f
300 f,d,b,*,e,*,c,a, (no-eol) (glob)
301
302 $ cd ..
303
304
305 Example 5: skipping over nested exclusive part (partially)
306 ==========================================================
307
308 We have a merge "f" whose exclusive part contains a merge "d".
309
310 Similar to example 4, but the exclusive part of "d" is only partially
311 contained in the inherited part of "f".
312 So, we need to leap in the middle of the exclusive part of "d".
313
314 # f
315 # |
316 # ---<---
317 # | |
318 # d |
319 # | e
320 # -->-- |
321 # | | |
322 # | g |
323 # | | |
324 # | +---- <- in the sort of "f", leaping from "g" to "b"
325 # b |
326 # | c
327 # | |
328 # --+--
329 # |
330 # a
331
332 $ hg init example-5
333 $ cd example-5
334 $ hg debugbuilddag '.:a*a+2:b<a+1:c+1:g*b/g:d<c+6:e*d/e:f.'
335 $ hg test-log
336 o tip rank=15
337 |
338 o f rank=14
339 |\
340 | o e rank=8
341 | |
342 | o rank=7
343 | |
344 | o rank=6
345 | |
346 | o rank=5
347 | |
348 | o rank=4
349 | |
350 | o rank=3
351 | |
352 o | d rank=7
353 |\ \
354 | o | g rank=3
355 | |/
356 | o c rank=2
357 | |
358 o | b rank=4
359 | |
360 o | rank=3
361 | |
362 o | rank=2
363 |/
364 o a rank=1
365
366
367 Display the sort of "d" for reference:
368
369 $ hg test-sts d
370 d,g,c,b,*,a, (no-eol) (glob)
371
372 Check that sort "f" leaps from "g" to "b":
373
374 $ hg test-sts f
375 f,d,g,b,*,e,*,c,a, (no-eol) (glob)
376
377 $ cd ..
378
379
380 Example 6: merge in the inherited part
381 ======================================
382
383 Variant of example 2, but with a merge ("f") in the inherited part of "g".
384
385 "g" is a merge node whose inherited part contains a merge node "f".
386 We check that the stable-tail sort delegates properly after the exclusive part.
387
388 # g
389 # |
390 # ---<---
391 # | |
392 # d f
393 # | |
394 # | ---<---
395 # | | |
396 # | e c
397 # | | |
398 # ---+ | <- at this point, we're done (for good) with the exclusive
399 # | | part of "g"
400 # b |
401 # | |
402 # ---+---
403 # |
404 # a
405
406 $ hg init example-6
407 $ cd example-6
408 $ hg debugbuilddag '.:a*a:b<a+3:c*b:d*b:e*e/c:f*d/f:g.'
409 $ hg test-log
410 o tip rank=10
411 |
412 o g rank=9
413 |\
414 | o f rank=7
415 | |\
416 | | o e rank=3
417 | | |
418 o---+ d rank=3
419 / /
420 o | c rank=4
421 | |
422 o | rank=3
423 | |
424 o | rank=2
425 | |
426 | o b rank=2
427 |/
428 o a rank=1
429
430
431 Display the sort of "f" for reference:
432
433 $ hg test-sts f
434 f,e,b,c,*,a, (no-eol) (glob)
435
436 Check that the sort of "g" delegates to the sort of "f" after processing its
437 exclusive part of "g":
438
439 $ hg test-sts g
440 g,d,f,e,b,c,*,a, (no-eol) (glob)
441
442 $ cd ..
443
444
445 Example 7: postponed iteration of common exclusive ancestors
446 ============================================================
447
448 Sibling merges "j" and "k", with partially shared exclusive parts.
449
450 When considering the sort of "l", the iteration over this shared part cannot
451 happen when iterating over excl(j) and has to be postponed to excl(k).
452
453 # l
454 # |
455 # ----<----
456 # | |
457 # j k
458 # | |
459 # -->-- --<--
460 # | | | |
461 # g e h i
462 # | | | |
463 # | --+-- | <- at this point, for the sort of "l", the iteration on
464 # f | | the end of excl(j) is postponed to the iteration of
465 # | d | excl(k)
466 # | | |
467 # | c |
468 # | | |
469 # ---+--- |
470 # | |
471 # b |
472 # | |
473 # ----+-----
474 # |
475 # a
476
477 $ hg init example-7
478 $ cd example-7
479 $ hg debugbuilddag \
480 > '.:a*a:b*b:c*c:d*d:e*b:f<f+3:g<d+2:h<a+6:i*e/g:j*h/i:k*j/k:l.'
481 $ hg test-log
482 o tip rank=21
483 |
484 o l rank=20
485 |\
486 | o k rank=13
487 | |\
488 o \ \ j rank=10
489 |\ \ \
490 | | | o i rank=7
491 | | | |
492 | | | o rank=6
493 | | | |
494 | | | o rank=5
495 | | | |
496 | | | o rank=4
497 | | | |
498 | | | o rank=3
499 | | | |
500 | | | o rank=2
501 | | | |
502 | | o | h rank=6
503 | | | |
504 | | o | rank=5
505 | | | |
506 | o | | g rank=6
507 | | | |
508 | o | | rank=5
509 | | | |
510 | o | | rank=4
511 | | | |
512 | o | | f rank=3
513 | | | |
514 o---+ | e rank=5
515 / / /
516 | o | d rank=4
517 | | |
518 | o | c rank=3
519 |/ /
520 o / b rank=2
521 |/
522 o a rank=1
523
524
525 Display the sort of "j" for reference:
526
527 $ hg test-sts j
528 j,e,d,c,g,*,f,b,a, (no-eol) (glob)
529
530 Display the sort of "k" for reference:
531
532 $ hg test-sts k
533 k,h,*,d,c,b,i,*,a, (no-eol) (glob)
534
535 Check that the common part of excl(j) and excl(k) is iterated over after "k":
536
537 $ hg test-sts l
538 l,j,e,g,*,f,k,h,*,d,c,b,i,*,a, (no-eol) (glob)
539
540 $ cd ..
541
542
543 Example 8: postponed iteration of common ancestors between parts
544 ================================================================
545
546 Sibling merges "g" and "i", with some part shared between the inherited part
547 of "g" and the exclusive part of "i".
548
549 When considering the sort of "j", the iteration over this shared part cannot
550 happen when iterating over inherited(g) and has to be postponed to excl(i).
551
552 # j
553 # |
554 # ----<----
555 # | |
556 # g i
557 # | |
558 # --<-- --<--
559 # | | | |
560 # c f | h
561 # | | | |
562 # | --+-- | <- at this point, for the sort of "j", the iteration
563 # | | | on the end of inherited(g) is postponed to the
564 # | e | iteration of excl(k)
565 # | | |
566 # ---+--- |
567 # b |
568 # | |
569 # ----+-----
570 # |
571 # a
572
573 $ hg init example-8
574 $ cd example-8
575 $ hg debugbuilddag '.:a*a:b*b:c*b:d*d:e*e:f*c/f:g<a+5:h*e/h:i*g/i:j.'
576 $ hg test-log
577 o tip rank=15
578 |
579 o j rank=14
580 |\
581 | o i rank=10
582 | |\
583 | | o h rank=6
584 | | |
585 | | o rank=5
586 | | |
587 | | o rank=4
588 | | |
589 | | o rank=3
590 | | |
591 | | o rank=2
592 | | |
593 o | | g rank=7
594 |\ \ \
595 | o | | f rank=5
596 | |/ /
597 | o | e rank=4
598 | | |
599 | o | d rank=3
600 | | |
601 o | | c rank=3
602 |/ /
603 o / b rank=2
604 |/
605 o a rank=1
606
607
608 Display the sort of "g" for reference:
609
610 $ hg test-sts g
611 g,c,f,e,d,b,a, (no-eol)
612
613 Display the sort of "i" for reference:
614
615 $ hg test-sts i
616 i,e,d,b,h,*,a, (no-eol) (glob)
617
618 Check that the common part of inherited(g) and excl(k) is iterated over after
619 "i":
620
621 $ hg test-sts j
622 j,g,c,f,i,e,d,b,h,*,a, (no-eol) (glob)
623
624 $ cd ..
625
626
627 Example 9: postponed iteration of common ancestors between both parts
628 =====================================================================
629
630 This is a combination of example 7 and 8 at the same time.
631 Both excl(i) and excl(j) share a common part.
632 Same with inherited(i) and inherited(j).
633
634 We test that the walk on the common ancestors in both cases is properly
635 postponed when considering sort(k).
636
637 # k
638 # |
639 # ----<----
640 # | |
641 # i j
642 # | |
643 # --<-- --<--
644 # | | | |
645 # c f g h
646 # | | | |
647 # | e | |
648 # | | | |
649 # +--]|[--- | <- rest of excl(i) postponed to excl(j)
650 # | | |
651 # b ----+---- <- rest of inherited(i) postponed to inherited(j)
652 # | |
653 # | d
654 # | |
655 # ----+----
656 # |
657 # a
658
659 $ hg init example-9
660 $ cd example-9
661 $ hg debugbuilddag '.:a*a:b*b:c*a:d*d:e*e:f<b+2:g<d+3:h*c/f:i*g/h:j*i/j:k.'
662 $ hg test-log
663 o tip rank=15
664 |
665 o k rank=14
666 |\
667 | o j rank=9
668 | |\
669 o \ \ i rank=7
670 |\ \ \
671 | | | o h rank=5
672 | | | |
673 | | | o rank=4
674 | | | |
675 | | | o rank=3
676 | | | |
677 | | o | g rank=4
678 | | | |
679 | | o | rank=3
680 | | | |
681 | o | | f rank=4
682 | | | |
683 | o---+ e rank=3
684 | / /
685 | | o d rank=2
686 | | |
687 o | | c rank=3
688 |/ /
689 o / b rank=2
690 |/
691 o a rank=1
692
693
694 Display sort(i) for reference:
695
696 $ hg test-sts i
697 i,c,b,f,e,d,a, (no-eol)
698
699 Display sort(j) for reference:
700
701 $ hg test-sts j
702 j,g,*,b,h,*,d,a, (no-eol) (glob)
703
704 Check that the end of excl(i) is postponed to excl(j), the end of inherited(i)
705 is postponed to inherited(j) in sort(k):
706
707 $ hg test-sts k
708 k,i,c,f,e,j,g,*,b,h,*,d,a, (no-eol) (glob)
709
710 $ cd ..