##// END OF EJS Templates
rust-dirstatemap: add unit tests...
Raphaël Gomès -
r50017:e7b74bb6 default
parent child Browse files
Show More
@@ -1433,3 +1433,417 b' impl OwningDirstateMap {'
1433 1433 }))
1434 1434 }
1435 1435 }
1436 #[cfg(test)]
1437 mod tests {
1438 use super::*;
1439
1440 /// Shortcut to return tracked descendants of a path.
1441 /// Panics if the path does not exist.
1442 fn tracked_descendants(map: &OwningDirstateMap, path: &[u8]) -> u32 {
1443 let path = dbg!(HgPath::new(path));
1444 let node = map.get_map().get_node(path);
1445 node.unwrap().unwrap().tracked_descendants_count()
1446 }
1447
1448 /// Shortcut to return descendants with an entry.
1449 /// Panics if the path does not exist.
1450 fn descendants_with_an_entry(map: &OwningDirstateMap, path: &[u8]) -> u32 {
1451 let path = dbg!(HgPath::new(path));
1452 let node = map.get_map().get_node(path);
1453 node.unwrap().unwrap().descendants_with_entry_count()
1454 }
1455
1456 fn assert_does_not_exist(map: &OwningDirstateMap, path: &[u8]) {
1457 let path = dbg!(HgPath::new(path));
1458 let node = map.get_map().get_node(path);
1459 assert!(node.unwrap().is_none());
1460 }
1461
1462 /// Shortcut for path creation in tests
1463 fn p(b: &[u8]) -> &HgPath {
1464 HgPath::new(b)
1465 }
1466
1467 /// Test the very simple case a single tracked file
1468 #[test]
1469 fn test_tracked_descendants_simple() -> Result<(), DirstateError> {
1470 let mut map = OwningDirstateMap::new_empty(vec![]);
1471 assert_eq!(map.len(), 0);
1472
1473 map.set_tracked(p(b"some/nested/path"))?;
1474
1475 assert_eq!(map.len(), 1);
1476 assert_eq!(tracked_descendants(&map, b"some"), 1);
1477 assert_eq!(tracked_descendants(&map, b"some/nested"), 1);
1478 assert_eq!(tracked_descendants(&map, b"some/nested/path"), 0);
1479
1480 map.set_untracked(p(b"some/nested/path"))?;
1481 assert_eq!(map.len(), 0);
1482 assert!(map.get_map().get_node(p(b"some"))?.is_none());
1483
1484 Ok(())
1485 }
1486
1487 /// Test the simple case of all tracked, but multiple files
1488 #[test]
1489 fn test_tracked_descendants_multiple() -> Result<(), DirstateError> {
1490 let mut map = OwningDirstateMap::new_empty(vec![]);
1491
1492 map.set_tracked(p(b"some/nested/path"))?;
1493 map.set_tracked(p(b"some/nested/file"))?;
1494 // one layer without any files to test deletion cascade
1495 map.set_tracked(p(b"some/other/nested/path"))?;
1496 map.set_tracked(p(b"root_file"))?;
1497 map.set_tracked(p(b"some/file"))?;
1498 map.set_tracked(p(b"some/file2"))?;
1499 map.set_tracked(p(b"some/file3"))?;
1500
1501 assert_eq!(map.len(), 7);
1502 assert_eq!(tracked_descendants(&map, b"some"), 6);
1503 assert_eq!(tracked_descendants(&map, b"some/nested"), 2);
1504 assert_eq!(tracked_descendants(&map, b"some/other"), 1);
1505 assert_eq!(tracked_descendants(&map, b"some/other/nested"), 1);
1506 assert_eq!(tracked_descendants(&map, b"some/nested/path"), 0);
1507
1508 map.set_untracked(p(b"some/nested/path"))?;
1509 assert_eq!(map.len(), 6);
1510 assert_eq!(tracked_descendants(&map, b"some"), 5);
1511 assert_eq!(tracked_descendants(&map, b"some/nested"), 1);
1512 assert_eq!(tracked_descendants(&map, b"some/other"), 1);
1513 assert_eq!(tracked_descendants(&map, b"some/other/nested"), 1);
1514
1515 map.set_untracked(p(b"some/nested/file"))?;
1516 assert_eq!(map.len(), 5);
1517 assert_eq!(tracked_descendants(&map, b"some"), 4);
1518 assert_eq!(tracked_descendants(&map, b"some/other"), 1);
1519 assert_eq!(tracked_descendants(&map, b"some/other/nested"), 1);
1520 assert_does_not_exist(&map, b"some_nested");
1521
1522 map.set_untracked(p(b"some/other/nested/path"))?;
1523 assert_eq!(map.len(), 4);
1524 assert_eq!(tracked_descendants(&map, b"some"), 3);
1525 assert_does_not_exist(&map, b"some/other");
1526
1527 map.set_untracked(p(b"root_file"))?;
1528 assert_eq!(map.len(), 3);
1529 assert_eq!(tracked_descendants(&map, b"some"), 3);
1530 assert_does_not_exist(&map, b"root_file");
1531
1532 map.set_untracked(p(b"some/file"))?;
1533 assert_eq!(map.len(), 2);
1534 assert_eq!(tracked_descendants(&map, b"some"), 2);
1535 assert_does_not_exist(&map, b"some/file");
1536
1537 map.set_untracked(p(b"some/file2"))?;
1538 assert_eq!(map.len(), 1);
1539 assert_eq!(tracked_descendants(&map, b"some"), 1);
1540 assert_does_not_exist(&map, b"some/file2");
1541
1542 map.set_untracked(p(b"some/file3"))?;
1543 assert_eq!(map.len(), 0);
1544 assert_does_not_exist(&map, b"some/file3");
1545
1546 Ok(())
1547 }
1548
1549 /// Check with a mix of tracked and non-tracked items
1550 #[test]
1551 fn test_tracked_descendants_different() -> Result<(), DirstateError> {
1552 let mut map = OwningDirstateMap::new_empty(vec![]);
1553
1554 // A file that was just added
1555 map.set_tracked(p(b"some/nested/path"))?;
1556 // This has no information, the dirstate should ignore it
1557 map.reset_state(p(b"some/file"), false, false, false, false, None)?;
1558 assert_does_not_exist(&map, b"some/file");
1559
1560 // A file that was removed
1561 map.reset_state(
1562 p(b"some/nested/file"),
1563 false,
1564 true,
1565 false,
1566 false,
1567 None,
1568 )?;
1569 assert!(!map.get(p(b"some/nested/file"))?.unwrap().tracked());
1570 // Only present in p2
1571 map.reset_state(p(b"some/file3"), false, false, true, false, None)?;
1572 assert!(!map.get(p(b"some/file3"))?.unwrap().tracked());
1573 // A file that was merged
1574 map.reset_state(p(b"root_file"), true, true, true, false, None)?;
1575 assert!(map.get(p(b"root_file"))?.unwrap().tracked());
1576 // A file that is added, with info from p2
1577 // XXX is that actually possible?
1578 map.reset_state(p(b"some/file2"), true, false, true, false, None)?;
1579 assert!(map.get(p(b"some/file2"))?.unwrap().tracked());
1580 // A clean file
1581 // One layer without any files to test deletion cascade
1582 map.reset_state(
1583 p(b"some/other/nested/path"),
1584 true,
1585 true,
1586 false,
1587 false,
1588 None,
1589 )?;
1590 assert!(map.get(p(b"some/other/nested/path"))?.unwrap().tracked());
1591
1592 assert_eq!(map.len(), 6);
1593 assert_eq!(tracked_descendants(&map, b"some"), 3);
1594 assert_eq!(descendants_with_an_entry(&map, b"some"), 5);
1595 assert_eq!(tracked_descendants(&map, b"some/other/nested"), 1);
1596 assert_eq!(descendants_with_an_entry(&map, b"some/other/nested"), 1);
1597 assert_eq!(tracked_descendants(&map, b"some/other/nested/path"), 0);
1598 assert_eq!(
1599 descendants_with_an_entry(&map, b"some/other/nested/path"),
1600 0
1601 );
1602 assert_eq!(tracked_descendants(&map, b"some/nested"), 1);
1603 assert_eq!(descendants_with_an_entry(&map, b"some/nested"), 2);
1604
1605 // might as well check this
1606 map.set_untracked(p(b"path/does/not/exist"))?;
1607 assert_eq!(map.len(), 6);
1608
1609 map.set_untracked(p(b"some/other/nested/path"))?;
1610 // It is set untracked but not deleted since it held other information
1611 assert_eq!(map.len(), 6);
1612 assert_eq!(tracked_descendants(&map, b"some"), 2);
1613 assert_eq!(descendants_with_an_entry(&map, b"some"), 5);
1614 assert_eq!(descendants_with_an_entry(&map, b"some/other"), 1);
1615 assert_eq!(descendants_with_an_entry(&map, b"some/other/nested"), 1);
1616 assert_eq!(tracked_descendants(&map, b"some/nested"), 1);
1617 assert_eq!(descendants_with_an_entry(&map, b"some/nested"), 2);
1618
1619 map.set_untracked(p(b"some/nested/path"))?;
1620 // It is set untracked *and* deleted since it was only added
1621 assert_eq!(map.len(), 5);
1622 assert_eq!(tracked_descendants(&map, b"some"), 1);
1623 assert_eq!(descendants_with_an_entry(&map, b"some"), 4);
1624 assert_eq!(tracked_descendants(&map, b"some/nested"), 0);
1625 assert_eq!(descendants_with_an_entry(&map, b"some/nested"), 1);
1626 assert_does_not_exist(&map, b"some/nested/path");
1627
1628 map.set_untracked(p(b"root_file"))?;
1629 // Untracked but not deleted
1630 assert_eq!(map.len(), 5);
1631 assert!(map.get(p(b"root_file"))?.is_some());
1632
1633 map.set_untracked(p(b"some/file2"))?;
1634 assert_eq!(map.len(), 5);
1635 assert_eq!(tracked_descendants(&map, b"some"), 0);
1636 assert!(map.get(p(b"some/file2"))?.is_some());
1637
1638 map.set_untracked(p(b"some/file3"))?;
1639 assert_eq!(map.len(), 5);
1640 assert_eq!(tracked_descendants(&map, b"some"), 0);
1641 assert!(map.get(p(b"some/file3"))?.is_some());
1642
1643 Ok(())
1644 }
1645
1646 /// Check that copies counter is correctly updated
1647 #[test]
1648 fn test_copy_source() -> Result<(), DirstateError> {
1649 let mut map = OwningDirstateMap::new_empty(vec![]);
1650
1651 // Clean file
1652 map.reset_state(p(b"files/clean"), true, true, false, false, None)?;
1653 // Merged file
1654 map.reset_state(p(b"files/from_p2"), true, true, true, false, None)?;
1655 // Removed file
1656 map.reset_state(p(b"removed"), false, true, false, false, None)?;
1657 // Added file
1658 map.reset_state(p(b"files/added"), true, false, false, false, None)?;
1659 // Add copy
1660 map.copy_map_insert(p(b"files/clean"), p(b"clean_copy_source"))?;
1661 assert_eq!(map.copy_map_len(), 1);
1662
1663 // Copy override
1664 map.copy_map_insert(p(b"files/clean"), p(b"other_clean_copy_source"))?;
1665 assert_eq!(map.copy_map_len(), 1);
1666
1667 // Multiple copies
1668 map.copy_map_insert(p(b"removed"), p(b"removed_copy_source"))?;
1669 assert_eq!(map.copy_map_len(), 2);
1670
1671 map.copy_map_insert(p(b"files/added"), p(b"added_copy_source"))?;
1672 assert_eq!(map.copy_map_len(), 3);
1673
1674 // Added, so the entry is completely removed
1675 map.set_untracked(p(b"files/added"))?;
1676 assert_does_not_exist(&map, b"files/added");
1677 assert_eq!(map.copy_map_len(), 2);
1678
1679 // Removed, so the entry is kept around, so is its copy
1680 map.set_untracked(p(b"removed"))?;
1681 assert!(map.get(p(b"removed"))?.is_some());
1682 assert_eq!(map.copy_map_len(), 2);
1683
1684 // Clean, so the entry is kept around, but not its copy
1685 map.set_untracked(p(b"files/clean"))?;
1686 assert!(map.get(p(b"files/clean"))?.is_some());
1687 assert_eq!(map.copy_map_len(), 1);
1688
1689 map.copy_map_insert(p(b"files/from_p2"), p(b"from_p2_copy_source"))?;
1690 assert_eq!(map.copy_map_len(), 2);
1691
1692 // Info from p2, so its copy source info is kept around
1693 map.set_untracked(p(b"files/from_p2"))?;
1694 assert!(map.get(p(b"files/from_p2"))?.is_some());
1695 assert_eq!(map.copy_map_len(), 2);
1696
1697 Ok(())
1698 }
1699
1700 /// Test with "on disk" data. For the sake of this test, the "on disk" data
1701 /// does not actually come from the disk, but it's opaque to the code being
1702 /// tested.
1703 #[test]
1704 fn test_on_disk() -> Result<(), DirstateError> {
1705 // First let's create some data to put "on disk"
1706 let mut map = OwningDirstateMap::new_empty(vec![]);
1707
1708 // A file that was just added
1709 map.set_tracked(p(b"some/nested/added"))?;
1710 map.copy_map_insert(p(b"some/nested/added"), p(b"added_copy_source"))?;
1711
1712 // A file that was removed
1713 map.reset_state(
1714 p(b"some/nested/removed"),
1715 false,
1716 true,
1717 false,
1718 false,
1719 None,
1720 )?;
1721 // Only present in p2
1722 map.reset_state(
1723 p(b"other/p2_info_only"),
1724 false,
1725 false,
1726 true,
1727 false,
1728 None,
1729 )?;
1730 map.copy_map_insert(
1731 p(b"other/p2_info_only"),
1732 p(b"other/p2_info_copy_source"),
1733 )?;
1734 // A file that was merged
1735 map.reset_state(p(b"merged"), true, true, true, false, None)?;
1736 // A file that is added, with info from p2
1737 // XXX is that actually possible?
1738 map.reset_state(
1739 p(b"other/added_with_p2"),
1740 true,
1741 false,
1742 true,
1743 false,
1744 None,
1745 )?;
1746 // One layer without any files to test deletion cascade
1747 // A clean file
1748 map.reset_state(
1749 p(b"some/other/nested/clean"),
1750 true,
1751 true,
1752 false,
1753 false,
1754 None,
1755 )?;
1756
1757 let (packed, metadata, _should_append) = map.pack_v2(false)?;
1758 let packed_len = packed.len();
1759 assert!(packed_len > 0);
1760
1761 // Recreate "from disk"
1762 let mut map = OwningDirstateMap::new_v2(
1763 packed,
1764 packed_len,
1765 metadata.as_bytes(),
1766 )?;
1767
1768 // Check that everything is accounted for
1769 assert!(map.contains_key(p(b"some/nested/added"))?);
1770 assert!(map.contains_key(p(b"some/nested/removed"))?);
1771 assert!(map.contains_key(p(b"merged"))?);
1772 assert!(map.contains_key(p(b"other/p2_info_only"))?);
1773 assert!(map.contains_key(p(b"other/added_with_p2"))?);
1774 assert!(map.contains_key(p(b"some/other/nested/clean"))?);
1775 assert_eq!(
1776 map.copy_map_get(p(b"some/nested/added"))?,
1777 Some(p(b"added_copy_source"))
1778 );
1779 assert_eq!(
1780 map.copy_map_get(p(b"other/p2_info_only"))?,
1781 Some(p(b"other/p2_info_copy_source"))
1782 );
1783 assert_eq!(tracked_descendants(&map, b"some"), 2);
1784 assert_eq!(descendants_with_an_entry(&map, b"some"), 3);
1785 assert_eq!(tracked_descendants(&map, b"other"), 1);
1786 assert_eq!(descendants_with_an_entry(&map, b"other"), 2);
1787 assert_eq!(tracked_descendants(&map, b"some/other"), 1);
1788 assert_eq!(descendants_with_an_entry(&map, b"some/other"), 1);
1789 assert_eq!(tracked_descendants(&map, b"some/other/nested"), 1);
1790 assert_eq!(descendants_with_an_entry(&map, b"some/other/nested"), 1);
1791 assert_eq!(tracked_descendants(&map, b"some/nested"), 1);
1792 assert_eq!(descendants_with_an_entry(&map, b"some/nested"), 2);
1793 assert_eq!(map.len(), 6);
1794 assert_eq!(map.get_map().unreachable_bytes, 0);
1795 assert_eq!(map.copy_map_len(), 2);
1796
1797 // Shouldn't change anything since it's already not tracked
1798 map.set_untracked(p(b"some/nested/removed"))?;
1799 assert_eq!(map.get_map().unreachable_bytes, 0);
1800
1801 match map.get_map().root {
1802 ChildNodes::InMemory(_) => {
1803 panic!("root should not have been mutated")
1804 }
1805 _ => (),
1806 }
1807 // We haven't mutated enough (nothing, actually), we should still be in
1808 // the append strategy
1809 assert!(map.get_map().write_should_append());
1810
1811 // But this mutates the structure, so there should be unreachable_bytes
1812 assert!(map.set_untracked(p(b"some/nested/added"))?);
1813 let unreachable_bytes = map.get_map().unreachable_bytes;
1814 assert!(unreachable_bytes > 0);
1815
1816 match map.get_map().root {
1817 ChildNodes::OnDisk(_) => panic!("root should have been mutated"),
1818 _ => (),
1819 }
1820
1821 // This should not mutate the structure either, since `root` has
1822 // already been mutated along with its direct children.
1823 map.set_untracked(p(b"merged"))?;
1824 assert_eq!(map.get_map().unreachable_bytes, unreachable_bytes);
1825
1826 match map.get_map().get_node(p(b"other/added_with_p2"))?.unwrap() {
1827 NodeRef::InMemory(_, _) => {
1828 panic!("'other/added_with_p2' should not have been mutated")
1829 }
1830 _ => (),
1831 }
1832 // But this should, since it's in a different path
1833 // than `<root>some/nested/add`
1834 map.set_untracked(p(b"other/added_with_p2"))?;
1835 assert!(map.get_map().unreachable_bytes > unreachable_bytes);
1836
1837 match map.get_map().get_node(p(b"other/added_with_p2"))?.unwrap() {
1838 NodeRef::OnDisk(_) => {
1839 panic!("'other/added_with_p2' should have been mutated")
1840 }
1841 _ => (),
1842 }
1843
1844 // We have rewritten most of the tree, we should create a new file
1845 assert!(!map.get_map().write_should_append());
1846
1847 Ok(())
1848 }
1849 }
General Comments 0
You need to be logged in to leave comments. Login now