Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
Improve COB stream tests
Merged fintohaps opened 8 months ago

This patch contains two fixes to the COB stream tests:

  • Use the fixture repository to ensure there is a name and email set for making commits
  • Add each previous cob::Entry as the tip of the next one, to ensure they form a Git history.
1 file changed +100 -28 1d7478cd a670b6e6
modified crates/radicle/src/cob/stream.rs
@@ -173,11 +173,11 @@ mod tests {
    use nonempty::NonEmpty;
    use serde_json as json;

-
    use crate::cob;
    use crate::cob::change::Storage as _;
    use crate::crypto::test::signer::MockSigner;
    use crate::test::arbitrary;
    use crate::test::arbitrary::gen;
+
    use crate::{cob, test};

    use super::*;

@@ -190,35 +190,49 @@ mod tests {
        let n = gen::<u8>(1).clamp(1, 10);
        let mut entries = Vec::with_capacity(n.into());

+
        let mut parent = None;
        for _ in 0..n {
-
            // Number of actions in this bop
+
            // Number of actions in this op
            let m = gen::<u8>(1).clamp(1, 3);
-
            let contents = NonEmpty::collect((0..m).map(|_| {
-
                json::to_vec(&json!({
-
                    "test": arbitrary::alphanumeric(1),
-
                }))
-
                .unwrap()
-
            }))
-
            .unwrap();
-
            let entry = repo
-
                .store(
-
                    None,
-
                    vec![],
-
                    signer,
-
                    cob::change::Template {
-
                        type_name: typename(),
-
                        tips: vec![],
-
                        message: "Test Op Stream".to_string(),
-
                        embeds: vec![],
-
                        contents,
-
                    },
-
                )
-
                .unwrap();
+
            let contents = create_contents((0..m).map(|_| arbitrary::alphanumeric(1)));
+
            let entry = create_entry(repo, signer, contents, parent);
+
            parent = Some(entry.id);
            entries.push(entry);
        }
        entries
    }

+
    fn create_contents(values: impl Iterator<Item = String>) -> NonEmpty<Vec<u8>> {
+
        NonEmpty::collect(values.map(|value| {
+
            json::to_vec(&json!({
+
                "test": value,
+
            }))
+
            .unwrap()
+
        }))
+
        .unwrap()
+
    }
+

+
    fn create_entry(
+
        repo: &git2::Repository,
+
        signer: &MockSigner,
+
        contents: NonEmpty<Vec<u8>>,
+
        parent: Option<Oid>,
+
    ) -> cob::Entry {
+
        repo.store(
+
            None,
+
            parent.into_iter().collect(),
+
            signer,
+
            cob::change::Template {
+
                type_name: typename(),
+
                tips: vec![],
+
                message: "Test Op Stream".to_string(),
+
                embeds: vec![],
+
                contents,
+
            },
+
        )
+
        .unwrap()
+
    }
+

    /// all === from(root)
    fn prop_all_from<S>(stream: &S)
    where
@@ -309,14 +323,14 @@ mod tests {
                .cloned()
                .collect::<BTreeSet<_>>(),
            from_until_s,
-
            "from: {from_s:?}\nuntil: {until_s:?}"
+
            "\nfrom_until: {from_until_s:?}\nfrom: {from_s:?}\nuntil: {until_s:?}"
        )
    }

    #[test]
    fn test_all_from() {
        let tmp = tempfile::tempdir().unwrap();
-
        let repo = git2::Repository::init(tmp.path()).unwrap();
+
        let (repo, _) = test::fixtures::repository(tmp.path());
        let signer = MockSigner::default();
        let ops = gen_ops(&repo, &signer);
        let history = CobRange {
@@ -330,7 +344,7 @@ mod tests {
    #[test]
    fn test_all_until() {
        let tmp = tempfile::tempdir().unwrap();
-
        let repo = git2::Repository::init(tmp.path()).unwrap();
+
        let (repo, _) = test::fixtures::repository(tmp.path());
        let signer = MockSigner::default();
        let ops = gen_ops(&repo, &signer);
        let tip = ops.last().unwrap().id;
@@ -345,7 +359,7 @@ mod tests {
    #[test]
    fn test_all_from_until() {
        let tmp = tempfile::tempdir().unwrap();
-
        let repo = git2::Repository::init(tmp.path()).unwrap();
+
        let (repo, _) = test::fixtures::repository(tmp.path());
        let signer = MockSigner::default();
        let ops = gen_ops(&repo, &signer);
        let tip = ops.last().unwrap().id;
@@ -360,7 +374,7 @@ mod tests {
    #[test]
    fn test_from_until() {
        let tmp = tempfile::tempdir().unwrap();
-
        let repo = git2::Repository::init(tmp.path()).unwrap();
+
        let (repo, _) = test::fixtures::repository(tmp.path());
        let signer = MockSigner::default();
        let ops = gen_ops(&repo, &signer);
        let history = CobRange {
@@ -379,4 +393,62 @@ mod tests {
        let stream = Stream::<json::Value>::new(&repo, history, typename());
        prop_from_until(&stream, from, until)
    }
+

+
    #[test]
+
    fn test_regression_from_until() {
+
        let tmp = tempfile::tempdir().unwrap();
+
        let (repo, _) = test::fixtures::repository(tmp.path());
+
        let signer = MockSigner::default();
+
        // Set up 3 entries that make up the COB history
+
        let op1 = create_entry(
+
            &repo,
+
            &signer,
+
            create_contents(std::iter::once("hello".to_string())),
+
            None,
+
        );
+
        let op2 = create_entry(
+
            &repo,
+
            &signer,
+
            create_contents(std::iter::once("radicle".to_string())),
+
            Some(op1.id),
+
        );
+
        let op3 = create_entry(
+
            &repo,
+
            &signer,
+
            create_contents(std::iter::once("world".to_string())),
+
            Some(op2.id),
+
        );
+

+
        // The history spans from the 1st op to the last
+
        let history = CobRange {
+
            root: op1.id,
+
            until: op3.id.into(),
+
        };
+
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        eprintln!("Op 1: {}", op1.id);
+
        eprintln!("Op 2: {}", op2.id);
+
        eprintln!("Op 3: {}", op3.id);
+

+
        // "since" the root operation should include all operations
+
        assert_eq!(
+
            stream
+
                .since(op1.id)
+
                .unwrap()
+
                .map(|op| op.unwrap().id)
+
                .collect::<BTreeSet<_>>(),
+
            [op1.id, op2.id, op3.id]
+
                .into_iter()
+
                .collect::<BTreeSet<_>>()
+
        );
+
        // "until" the second operation should only include up to the second operation
+
        assert_eq!(
+
            stream
+
                .until(op2.id)
+
                .unwrap()
+
                .map(|op| op.unwrap().id)
+
                .collect::<BTreeSet<_>>(),
+
            [op1.id, op2.id].into_iter().collect::<BTreeSet<_>>()
+
        );
+
        prop_from_until(&stream, op1.id, op2.id);
+
    }
}