summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/transport/mod.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/transport/mod.rs b/src/transport/mod.rs
index c3db962..35e3499 100644
--- a/src/transport/mod.rs
+++ b/src/transport/mod.rs
@@ -328,3 +328,40 @@ pub trait Transport: Send + Sync {
/// Asynchronously monitors for fatal network client or sub-process failures.
async fn wait_for_exit(&self) -> std::io::Result<std::process::ExitStatus>;
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::testrand::for_seeds;
+
+ /// Two summaries are equal exactly when the heads are, in any order, whichever form
+ /// (listed or digest) each took.
+ #[test]
+ fn heads_summary_equality_is_set_equality() {
+ for_seeds(300, |rng| {
+ let n = rng.between(0, 2 * MAX_LISTED_HEADS + 2);
+ let heads: Vec<ChangeHash> = (0..n).map(|_| ChangeHash(rng.bytes32())).collect();
+ let summary = HeadsSummary::of(heads.clone());
+ assert_eq!(summary.heads().is_some(), n <= MAX_LISTED_HEADS);
+
+ let mut shuffled = heads.clone();
+ rng.shuffle(&mut shuffled);
+ assert_eq!(summary, HeadsSummary::of(shuffled));
+ assert_eq!(summary, HeadsSummary::Digest(summary.digest()));
+
+ let mut other = heads.clone();
+ match rng.below(3) {
+ 1 if !other.is_empty() => {
+ let i = rng.below(other.len());
+ other.remove(i);
+ }
+ 2 if !other.is_empty() => {
+ let i = rng.below(other.len());
+ other[i] = ChangeHash(rng.bytes32());
+ }
+ _ => other.push(ChangeHash(rng.bytes32())),
+ }
+ assert_ne!(summary, HeadsSummary::of(other));
+ });
+ }
+}