crates/forge/ents-forge/tests/round_trip.rs
round_trip.rshistorycomment on this file
| 1 | //! Property-based round-trip test for `meta-ref.typed-tree`: struct → tree |
| 2 | //! → struct must be identity over an unenumerable input space (arbitrary |
| 3 | //! strings, arbitrary-length collections) — the shape |
| 4 | //! `git-ents-engineering` calls out for `proptest` rather than a fixed |
| 5 | //! `rstest` table. [`Issue`] is exercised directly, as the richest entity |
| 6 | //! this crate owns (ported from `ents-model`'s own `tests/round_trip.rs` |
| 7 | //! when [`Issue`] moved here; [`ents_model::Member`] stays covered by that |
| 8 | //! crate's own analogous test). |
| 9 | |
| 10 | #![allow(clippy::expect_used, reason = "integration test")] |
| 11 | |
| 12 | use ents_forge::Issue; |
| 13 | use ents_model::MemberId; |
| 14 | use facet_git_tree::{deserialize, serialize}; |
| 15 | use proptest::prelude::*; |
| 16 | |
| 17 | fn member_id() -> impl Strategy<Value = MemberId> { |
| 18 | any::<String>().prop_map(MemberId::new) |
| 19 | } |
| 20 | |
| 21 | proptest! { |
| 22 | #![proptest_config(ProptestConfig::with_cases(64))] |
| 23 | |
| 24 | // @relation(meta-ref.typed-tree, model.issue, scope=function, role=Verifies) |
| 25 | #[test] |
| 26 | fn issue_round_trips_for_any_fields_and_collection_lengths( |
| 27 | title in any::<String>(), |
| 28 | body in any::<String>(), |
| 29 | state in any::<String>(), |
| 30 | assignees in prop::collection::vec(member_id(), 0..8), |
| 31 | labels in prop::collection::vec(any::<String>(), 0..8), |
| 32 | ) { |
| 33 | let issue = Issue { title, body, state, assignees, labels }; |
| 34 | let (id, store) = serialize(&issue).expect("serialize"); |
| 35 | let back: Issue = deserialize(&id, &store).expect("deserialize"); |
| 36 | prop_assert_eq!(back, issue); |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | proptest! { |
| 41 | #![proptest_config(ProptestConfig::with_cases(64))] |
| 42 | |
| 43 | // @relation(meta-ref.typed-tree, model.comment, scope=function, role=Verifies) |
| 44 | #[test] |
| 45 | fn comment_round_trips_for_any_fields( |
| 46 | body in any::<String>(), |
| 47 | state in any::<String>(), |
| 48 | context in proptest::option::of(any::<String>()), |
| 49 | parent in proptest::option::of(any::<String>()), |
| 50 | anchored in any::<bool>(), |
| 51 | ) { |
| 52 | use ents_forge::comment::Comment; |
| 53 | use facet_git_tree::{ObjectStore, RawTree}; |
| 54 | use gix_object::Write as _; |
| 55 | |
| 56 | let store = ObjectStore::default(); |
| 57 | let anchor = anchored.then(|| { |
| 58 | let tree = gix_object::Tree { entries: vec![] }; |
| 59 | RawTree::new(store.write(&tree).expect("tree")) |
| 60 | }); |
| 61 | let comment = Comment { body, state, anchor, context, parent }; |
| 62 | let root = facet_git_tree::serialize_into(&comment, &store).expect("serialize"); |
| 63 | let back: Comment = facet_git_tree::deserialize(&root, &store).expect("deserialize"); |
| 64 | prop_assert_eq!(back, comment); |
| 65 | } |
| 66 | } |