|
21 | 21 | import java.util.HashSet; |
22 | 22 | import java.util.LinkedList; |
23 | 23 | import java.util.List; |
| 24 | +import java.util.NoSuchElementException; |
24 | 25 | import java.util.Random; |
25 | 26 |
|
26 | 27 | import junit.framework.TestCase; |
@@ -1457,13 +1458,72 @@ private int compareUnsigned(byte[] left, byte[] right) |
1457 | 1458 | } |
1458 | 1459 |
|
1459 | 1460 | /** |
1460 | | - * A reduced hash tree over a large number of data objects. This reaches both sorted lists - |
| 1461 | + * toList() sorts a copy, so the list handed back belongs to the caller and the accessors can |
| 1462 | + * be interleaved with add() in any order. getFirst() answers without sorting at all. |
| 1463 | + */ |
| 1464 | + public void testSortedHashListAccessors() |
| 1465 | + { |
| 1466 | + SortedHashList list = new SortedHashList(); |
| 1467 | + |
| 1468 | + assertEquals(0, list.size()); |
| 1469 | + assertTrue(list.toList().isEmpty()); |
| 1470 | + |
| 1471 | + try |
| 1472 | + { |
| 1473 | + list.getFirst(); |
| 1474 | + fail("no exception on empty list"); |
| 1475 | + } |
| 1476 | + catch (NoSuchElementException e) |
| 1477 | + { |
| 1478 | + // expected - as LinkedList.getFirst() did |
| 1479 | + } |
| 1480 | + |
| 1481 | + byte[] three = Hex.decode("03"); |
| 1482 | + byte[] oneA = Hex.decode("01"); |
| 1483 | + byte[] two = Hex.decode("02"); |
| 1484 | + byte[] oneB = Hex.decode("01"); |
| 1485 | + |
| 1486 | + byte[][] values = new byte[][]{three, oneA, two, oneB}; |
| 1487 | + for (int i = 0; i != values.length; i++) |
| 1488 | + { |
| 1489 | + list.add(values[i]); |
| 1490 | + } |
| 1491 | + |
| 1492 | + List<byte[]> first = list.toList(); |
| 1493 | + |
| 1494 | + assertEquals(4, first.size()); |
| 1495 | + // equal hashes come back in the order they were added in |
| 1496 | + assertTrue(oneA == first.get(0)); |
| 1497 | + assertTrue(oneB == first.get(1)); |
| 1498 | + assertTrue(two == first.get(2)); |
| 1499 | + assertTrue(three == first.get(3)); |
| 1500 | + assertTrue(oneA == list.getFirst()); |
| 1501 | + |
| 1502 | + // the caller owns the list returned, and the one before it |
| 1503 | + first.clear(); |
| 1504 | + |
| 1505 | + List<byte[]> second = list.toList(); |
| 1506 | + |
| 1507 | + assertEquals(4, list.size()); |
| 1508 | + assertEquals(4, second.size()); |
| 1509 | + assertTrue(oneA == second.get(0)); |
| 1510 | + |
| 1511 | + byte[] zero = Hex.decode("00"); |
| 1512 | + |
| 1513 | + list.add(zero); |
| 1514 | + |
| 1515 | + assertEquals(5, list.size()); |
| 1516 | + assertTrue(zero == list.getFirst()); |
| 1517 | + assertTrue(zero == list.toList().get(0)); |
| 1518 | + } |
| 1519 | + |
| 1520 | + /** |
| 1521 | + * A reduced hash tree over a large number of data objects, reaching both sorted lists - |
1461 | 1522 | * SortedIndexedHashList from ERSArchiveTimeStampGenerator.getPartialHashtrees(), and |
1462 | | - * SortedHashList from BinaryTreeRootCalculator.computeRootHash() - and took about 2.5 |
1463 | | - * seconds for these 2,000 objects when the insertion point was found by walking a |
1464 | | - * LinkedList, rising by roughly a factor of eight per doubling (10,000 objects took 347 |
1465 | | - * seconds). The root is also checked to be independent of the order the objects were added |
1466 | | - * in, which is what the sorting is there for. |
| 1523 | + * SortedHashList from BinaryTreeRootCalculator.computeRootHash(). Finding each insertion |
| 1524 | + * point by walking a LinkedList made this cubic in the number of data objects; the root is |
| 1525 | + * also checked to be independent of the order the objects were added in, which is what the |
| 1526 | + * sorting is there for. |
1467 | 1527 | */ |
1468 | 1528 | public void testLargeDataObjectSet() |
1469 | 1529 | throws Exception |
|
0 commit comments