2 * Copyright (C) 2007 Robin Rosenberg
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.jgit
.lib
;
19 import java
.io
.StringWriter
;
20 import java
.util
.Arrays
;
21 import java
.util
.Comparator
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
25 import junit
.framework
.TestCase
;
27 import org
.spearce
.jgit
.lib
.TopologicalSorter
.Edge
;
28 import org
.spearce
.jgit
.lib
.TopologicalSorter
.Lane
;
30 public class LaneTest
extends TestCase
{
32 TopologicalSorter
<Data
> counter
= new TopologicalSorter
<Data
>(
33 new Comparator
<Data
>() {
34 public int compare(Data o1
, Data o2
) {
35 return o1
.compareTo(o2
);
39 class Data
implements Comparable
<Data
> {
44 Data(String name
, int n
) {
49 public int compareTo(Data o
) {
55 return name
.compareTo(o
.name
);
59 public String
toString() {
60 return name
+ "(" + n
+ ")";
64 public void testLayout() {
66 * This is th test input. A list of nodes. The number is a weight that
67 * is used when the output order cannot be determined conclusively from
68 * the order of the nodes. Think of the number as a date in a git
69 * commit. The elements are sorted by weight (the number in parentheses)
70 * when the topological order is non defined.
72 * a(1) - b(3) - c(7) - d(10) - e(21) - f(3) - g(1) - h(1) - i(1) - j(1) -
74 * k(3) - l(2) - m(11) - n(4) - o(5) - p(5) - q(5)
119 Data a
= new Data("a", 1);
120 Data b
= new Data("b", 3);
121 Data c
= new Data("c", 7);
122 Data d
= new Data("d", 10);
123 Data e
= new Data("e", 21);
124 Data f
= new Data("f", 3);
125 Data g
= new Data("g", 1);
126 Data h
= new Data("h", 1);
127 Data i
= new Data("i", 1);
128 Data j
= new Data("j", 1);
129 Data k
= new Data("k", 3);
130 Data l
= new Data("l", 2);
131 Data m
= new Data("m", 11);
132 Data n
= new Data("n", 4);
133 Data o
= new Data("o", 5);
134 Data p
= new Data("p", 5);
135 Data q
= new Data("q", 5);
136 Data x
= new Data("x", 6);
137 Data y
= new Data("y", 5);
138 Data z
= new Data("z", 5);
140 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
141 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, c
));
142 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
143 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
, e
));
144 counter
.put(new TopologicalSorter
.Edge
<Data
>(e
, f
));
145 counter
.put(new TopologicalSorter
.Edge
<Data
>(f
, g
));
146 counter
.put(new TopologicalSorter
.Edge
<Data
>(g
, h
));
147 counter
.put(new TopologicalSorter
.Edge
<Data
>(h
, i
));
148 counter
.put(new TopologicalSorter
.Edge
<Data
>(i
, j
));
149 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, k
));
150 counter
.put(new TopologicalSorter
.Edge
<Data
>(k
, l
));
151 counter
.put(new TopologicalSorter
.Edge
<Data
>(l
, m
));
152 counter
.put(new TopologicalSorter
.Edge
<Data
>(m
, n
));
153 counter
.put(new TopologicalSorter
.Edge
<Data
>(n
, o
));
154 counter
.put(new TopologicalSorter
.Edge
<Data
>(o
, p
));
155 counter
.put(new TopologicalSorter
.Edge
<Data
>(p
, q
));
156 counter
.put(new TopologicalSorter
.Edge
<Data
>(q
, i
));
157 counter
.put(new TopologicalSorter
.Edge
<Data
>(m
, x
));
158 counter
.put(new TopologicalSorter
.Edge
<Data
>(x
, y
));
159 counter
.put(new TopologicalSorter
.Edge
<Data
>(y
, z
));
160 counter
.put(new TopologicalSorter
.Edge
<Data
>(z
, p
));
161 counter
.put(new TopologicalSorter
.Edge
<Data
>(l
, e
));
163 String road
= drawAsAscii(counter
);
164 String road2
= drawAsAscii(counter
);
166 assertEquals(road
, road2
);
173 "d>>>>>>>|>>>>>>>\\\n" +
174 " m>>>>>>>|>>>>>>>\\\n" +
179 " /<<<<<<<|<<<<<<<z\n" +
190 for(Data xx
: counter
.getEntries()) {
191 Lane lj
= counter
.lane
.get(xx
);
192 System
.out
.println(":"+xx
+ ", lane "+ lj
+ "{" + (lj
.startsAt
!=null ? counter
.lane
.get(lj
.startsAt
).getNumber() : -1) + "," + counter
.lane
.get(lj
.endsAt
).getNumber()+"}");
194 for (TopologicalSorter
<Data
>.Lane li
: counter
.lane
.values()) {
195 System
.out
.println("L "+li
);
200 Iterator
<Data
> di
= counter
.getEntries().iterator();
201 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("a",da
.name
); assertEquals(0, la
.getNumber());
202 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("b",da
.name
); assertEquals(0, la
.getNumber());
203 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("k",da
.name
); assertEquals(1, la
.getNumber());
204 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("l",da
.name
); assertEquals(1, la
.getNumber());
205 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("c",da
.name
); assertEquals(0, la
.getNumber());
206 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("d",da
.name
); assertEquals(0, la
.getNumber());
207 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("m",da
.name
); assertEquals(1, la
.getNumber());
208 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("n",da
.name
); assertEquals(1, la
.getNumber());
209 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("o",da
.name
); assertEquals(1, la
.getNumber());
210 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("x",da
.name
); assertEquals(3, la
.getNumber());
211 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("y",da
.name
); assertEquals(3, la
.getNumber());
212 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("z",da
.name
); assertEquals(3, la
.getNumber());
213 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("p",da
.name
); assertEquals(1, la
.getNumber());
214 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("q",da
.name
); assertEquals(1, la
.getNumber());
215 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("e",da
.name
); assertEquals(2, la
.getNumber());
216 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("f",da
.name
); assertEquals(2, la
.getNumber());
217 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("g",da
.name
); assertEquals(2, la
.getNumber());
218 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("h",da
.name
); assertEquals(2, la
.getNumber());
219 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("i",da
.name
); assertEquals(1, la
.getNumber());
220 da
=di
.next(); la
=counter
.lane
.get(da
); assertEquals("j",da
.name
); assertEquals(1, la
.getNumber());
221 assertFalse(di
.hasNext());
224 public void testZeroNodes() {
225 String road
= drawAsAscii(counter
);
226 String road2
= drawAsAscii(counter
);
227 assertEquals(road
,road2
);
233 public void testOneNode() {
234 Data a
= new Data("a", 5);
237 String road
= drawAsAscii(counter
);
238 String road2
= drawAsAscii(counter
);
239 assertEquals(road
,road2
);
245 public void testTwoNodes() {
246 Data a
= new Data("a", 5);
247 Data b
= new Data("b", 4);
251 String road
= drawAsAscii(counter
);
252 String road2
= drawAsAscii(counter
);
253 assertEquals(road
,road2
);
260 public void testOneInTwoOut() {
261 Data a
= new Data("a", 5);
262 Data b
= new Data("b", 4);
263 Data c
= new Data("c", 3);
265 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
266 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, c
));
267 String road
= drawAsAscii(counter
);
268 String road2
= drawAsAscii(counter
);
269 assertEquals(road
,road2
);
277 public void testTwoInOneOut() {
278 Data a
= new Data("a", 5);
279 Data b
= new Data("b", 4);
280 Data c
= new Data("c", 3);
282 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, a
));
283 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, a
));
284 String road
= drawAsAscii(counter
);
285 String road2
= drawAsAscii(counter
);
286 assertEquals(road
,road2
);
294 public void testTwoLanesWithFourNode_variant1() {
295 Data a
= new Data("a", 5);
296 Data b
= new Data("b", 4);
297 Data c
= new Data("c", 3);
298 Data d
= new Data("d", 2);
300 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
301 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
302 String road
= drawAsAscii(counter
);
303 String road2
= drawAsAscii(counter
);
304 assertEquals(road
,road2
);
313 public void testTwoLanesWithFourNode_variant2() {
314 Data a
= new Data("a", 3);
315 Data b
= new Data("b", 2);
316 Data c
= new Data("c", 5);
317 Data d
= new Data("d", 4);
319 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
320 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
321 String road
= drawAsAscii(counter
);
322 String road2
= drawAsAscii(counter
);
323 assertEquals(road
,road2
);
332 public void testTwoLanesWithFourNode_variant3() {
333 Data a
= new Data("a", 3);
334 Data b
= new Data("b", 4);
335 Data c
= new Data("c", 2);
336 Data d
= new Data("d", 5);
338 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
339 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
340 String road
= drawAsAscii(counter
);
341 String road2
= drawAsAscii(counter
);
342 assertEquals(road
,road2
);
351 public void testTwoLanesWithFourNode_variant4() {
352 Data a
= new Data("a", 3);
353 Data b
= new Data("b", 5);
354 Data c
= new Data("c", 2);
355 Data d
= new Data("d", 4);
357 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
358 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
359 String road
= drawAsAscii(counter
);
360 String road2
= drawAsAscii(counter
);
361 assertEquals(road
,road2
);
370 public void testDiamond() {
371 Data a
= new Data("a", 3);
372 Data b
= new Data("b", 4);
373 Data c
= new Data("c", 2);
374 Data d
= new Data("d", 5);
376 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
377 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, c
));
378 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, d
));
379 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
380 String road
= drawAsAscii(counter
);
381 String road2
= drawAsAscii(counter
);
382 assertEquals(road
,road2
);
391 public void testAllDirections() {
392 Data a
= new Data("a",1);
393 Data b
= new Data("b",2);
394 Data c
= new Data("c",5);
395 Data d
= new Data("d",4);
396 Data e
= new Data("e",3);
397 Data f
= new Data("f",6);
398 Data g
= new Data("g",7);
399 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
,b
));
400 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
,c
));
401 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
,d
));
402 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
,d
));
403 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
,c
));
404 counter
.put(new TopologicalSorter
.Edge
<Data
>(e
,d
));
405 counter
.put(new TopologicalSorter
.Edge
<Data
>(e
,g
));
406 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
,g
));
407 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
,f
));
408 String road
= drawAsAscii(counter
);
409 String road2
= drawAsAscii(counter
);
410 assertEquals(road
,road2
);
415 "/<<<<<<<d>>>>>>>\\\n"+
422 public void testAllPossibleWithFour() {
423 Data a
= new Data("a", 1);
424 Data b
= new Data("b", 2);
425 Data c
= new Data("c", 3);
426 Data d
= new Data("d", 4);
428 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
429 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, c
));
430 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, d
));
431 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, c
));
432 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, d
));
433 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
434 String road
= drawAsAscii(counter
);
435 String road2
= drawAsAscii(counter
);
436 assertEquals(road
,road2
);
438 "a>>>>>>>\\>>>>>>>\\\n"+
439 "b>>>>>>>\\>>>>>>>\\\n"+
445 public void testAllPossibleWithFive() {
446 Data a
= new Data("a", 1);
447 Data b
= new Data("b", 2);
448 Data c
= new Data("c", 3);
449 Data d
= new Data("d", 4);
450 Data e
= new Data("e", 5);
452 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
453 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, c
));
454 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, d
));
455 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, e
));
456 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, c
));
457 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, d
));
458 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, e
));
459 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
460 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, e
));
461 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
, e
));
462 String road
= drawAsAscii(counter
);
463 String road2
= drawAsAscii(counter
);
464 assertEquals(road
,road2
);
466 "a>>>>>>>\\>>>>>>>\\>>>>>>>\\\n"+
467 "b>>>>>>>\\>>>>>>>\\>>>>>>>\\\n"+
468 " c>>>>>>>\\>>>>>>>\\\n"+
474 public void testAllPossibleWithFiveLessSome() {
475 Data a
= new Data("a", 1);
476 Data b
= new Data("b", 2);
477 Data c
= new Data("c", 3);
478 Data d
= new Data("d", 4);
479 Data e
= new Data("e", 5);
481 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, b
));
482 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, c
));
483 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, d
));
484 counter
.put(new TopologicalSorter
.Edge
<Data
>(a
, e
));
485 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, c
));
486 counter
.put(new TopologicalSorter
.Edge
<Data
>(b
, e
));
487 counter
.put(new TopologicalSorter
.Edge
<Data
>(c
, d
));
488 counter
.put(new TopologicalSorter
.Edge
<Data
>(d
, e
));
489 String road
= drawAsAscii(counter
);
490 String road2
= drawAsAscii(counter
);
491 assertEquals(road
,road2
);
493 "a>>>>>>>\\>>>>>>>\\>>>>>>>\\\n"+
494 "b>>>>>>>\\>>>>>>>|>>>>>>>\\\n"+
501 @SuppressWarnings("boxing")
502 private String
drawAsAscii(TopologicalSorter
<Data
> counter
) {
503 StringWriter w
= new StringWriter();
504 List
<Data
> entries
= counter
.getEntries();
505 for (int i
=0; i
<entries
.size(); ++i
) {
506 Data xx
= entries
.get(i
);
507 Integer io
= counter
.getInternalPosition(xx
);
508 // System.out.print("Now at item "+xx+ " at "+io);
509 Lane lane
= counter
.lane
.get(xx
);
511 char[] points
= new char[counter
.currentLanes
.size()];
512 char[] horiz
= new char[counter
.currentLanes
.size()-1];
513 Arrays
.fill(points
,' ');
515 List
<Edge
<Data
>> px
= counter
.getEdgeFrom(xx
);
516 for (TopologicalSorter
<Data
>.Lane li
: counter
.currentLanes
) {
517 Integer iost
= counter
.getInternalPosition(li
.startsAt
);
518 Integer ioen
= counter
.getInternalPosition(li
.endsAt
);
524 if (iost
!= null && io
> iost
&& (ioen
== null || io
< ioen
)) {
525 points
[li
.getNumber()] = '|';
527 // branch out to parent
529 // \>>>>>>>>>>o o<<<<<<<<<</
531 for (int j
=0; j
<px
.size(); ++j
) {
532 Data p
= px
.get(j
).to
;
533 Lane pl
= counter
.getLane(p
);
534 if (li
== pl
&& lane
!= li
) {
535 int fromn
= lane
.getNumber();
536 int ton
= pl
.getNumber();
539 for (int k
=fromn
; k
<ton
; ++k
) {
544 for (int k
=fromn
-1; k
>=ton
; --k
) {
551 // merge, SAME (unless we get really smart)
553 points
[lane
.getNumber()] = xx
.name
.charAt(0);
554 int m
= points
.length
;
555 while (m
> 0 && points
[m
-1] == ' ')
557 for (int ii
=0; ii
<m
-1; ++ii
) {
561 for (int jj
=0; jj
<7; ++jj
)
567 w
.write(points
[m
-1]);
570 System
.out
.println(w
);