use gix_object::{Tree, TreeRef, TreeRefIter, WriteTo, bstr::ByteSlice, tree, tree::EntryRef}; use crate::{fixture_oid, tree_fixture}; #[test] fn empty() -> crate::Result { let tree_ref = TreeRef::from_bytes(&[], gix_testtools::object_hash())?; assert_eq!( tree_ref, TreeRef { entries: vec![] }, "empty trees are valid despite usually rare in the wild" ); let mut buf = Vec::new(); tree_ref.write_to(&mut buf)?; assert!(buf.is_empty()); buf.clear(); Tree::from(tree_ref).write_to(&mut buf)?; assert!(buf.is_empty()); Ok(()) } #[test] fn everything() -> crate::Result { let fixture = tree_fixture("everything.tree")?; let hash_kind = crate::fixture_hash_kind(); let tree_ref = TreeRef::from_bytes(&fixture, hash_kind)?; assert_eq!( tree_ref, TreeRef { entries: vec![ EntryRef { mode: tree::EntryKind::BlobExecutable.into(), filename: b"exe".as_bstr(), oid: &fixture_oid("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, EntryRef { mode: tree::EntryKind::Blob.into(), filename: b"file".as_bstr(), oid: &fixture_oid("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, EntryRef { mode: tree::EntryKind::Commit.into(), filename: b"grit-submodule".as_bstr(), oid: &fixture_oid("b2d1b5d684bdfda5f922b466cc13d4ce2d635cf8") }, EntryRef { mode: tree::EntryKind::Tree.into(), filename: b"subdir".as_bstr(), oid: &fixture_oid("4d5fcadc293a348e88f777dc0920f11e7d71441c") }, EntryRef { mode: tree::EntryKind::Link.into(), filename: b"symlink".as_bstr(), oid: &fixture_oid("1a010b1c0f081b2e8901d55307a15c29ff30af0e") } ] } ); Ok(()) } #[test] fn invalid() { let fixture = tree_fixture("definitely-special.tree").expect("fixture is valid"); let partial_tree = &fixture[..fixture.len() / 2]; let hash_kind = crate::fixture_hash_kind(); assert!(TreeRef::from_bytes(partial_tree, hash_kind).is_err()); assert!( TreeRefIter::from_bytes(partial_tree, hash_kind) .take_while(Result::is_ok) .count() > 0, "we can decode some entries before failing" ); } #[test] fn fuzzed() { assert!( gix_object::TreeRef::from_bytes(b"2", gix_testtools::object_hash()).is_err(), "fail, but don't crash" ); } #[test] fn fuzz_artifact_inputs_can_be_parsed_without_panicking() { for path in crate::fuzz_artifact_paths("fuzz_tree") { let input = std::fs::read(path).expect("artifact is readable"); _ = TreeRef::from_bytes(&input, gix_hash::Kind::Sha1); _ = TreeRef::from_bytes(&input, gix_hash::Kind::Sha256); } } #[test] fn special_trees() -> crate::Result { let hash_kind = crate::fixture_hash_kind(); for (name, expected_entry_count) in [ ("maybe-special", 160), ("definitely-special", 19), ("special-1", 5), ("special-2", 18), ("special-3", 5), ("special-4", 18), ("special-5", 17), ] { let fixture = tree_fixture(&format!("{name}.tree"))?; let actual = TreeRef::from_bytes(&fixture, hash_kind)?; assert_eq!(actual.entries.len(), expected_entry_count, "{name}"); assert_eq!( TreeRefIter::from_bytes(&fixture, hash_kind).map(Result::unwrap).count(), expected_entry_count, "{name}" ); // Show we can roundtrip let mut buf: Vec = Default::default(); actual.write_to(&mut buf).expect("Failed to write bytes to buffer"); assert_eq!(buf, fixture); } Ok(()) }