Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions relay-server/src/managed/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,27 @@ impl<T: Counted> Managed<T> {
other.accept(|o| f(s, o, records));
})
}
/// Zips two managed instances into one managed tuple.
///
/// The returned instance uses the metadata from `first`. `second` is accepted, transferring
/// outcome responsibility to the merged instance.
pub fn zip<S>(first: Self, second: Managed<S>) -> Managed<(T, S)>
where
S: Counted,
{
debug_assert_eq!(
first.scoping(),
second.scoping(),
"cannot zip Managed values with different metadata"
);
first.map(|first, records| {
for (category, quantity) in second.quantities() {
records.modify_by(category, quantity as isize);
}
let second = second.accept(|second| second);
(first, second)
})
Comment thread
cursor[bot] marked this conversation as resolved.
}

/// Splits [`Self`] into two other [`Managed`] items.
///
Expand Down Expand Up @@ -1134,6 +1155,8 @@ where
mod tests {
use super::*;

use relay_base_schema::project::ProjectId;

struct CountedVec(Vec<u32>);

impl Counted for CountedVec {
Expand Down Expand Up @@ -1177,6 +1200,43 @@ mod tests {
handle_b.assert_no_outcomes();
}

#[test]
fn test_zip_into_tuple() {
let (a, mut handle_a) = Managed::for_test(CountedVec(vec![1, 2])).build();
let (b, mut handle_b) = Managed::for_test(CountedValue(3)).build();

let z = Managed::zip(a, b);

assert_eq!((z.as_ref().0).0, vec![1, 2]);
Comment thread
Dav1dde marked this conversation as resolved.
assert_eq!((z.as_ref().1).0, 3);
drop(z);
handle_a.assert_internal_outcome(DataCategory::Error, 2);
handle_a.assert_internal_outcome(DataCategory::Error, 1);
handle_b.assert_no_outcomes();
}

#[test]
fn test_zip_rejects_different_metadata() {
let (a, mut handle_a) = Managed::for_test(CountedVec(vec![1, 2])).build();
let (b, mut handle_b) = Managed::for_test(CountedValue(3))
.scoping(Scoping {
project_id: ProjectId::new(45),
..a.scoping()
})
.build();

let result = std::panic::catch_unwind(move || {
Managed::zip(a, b);
});

assert!(
result.is_err(),
"cannot zip Managed values with different metadata"
);
handle_a.assert_internal_outcome(DataCategory::Error, 2);
handle_b.assert_internal_outcome(DataCategory::Error, 1);
}

#[test]
fn test_merge_mismatched_records_should_panic() {
let (mut a, mut handle_a) = Managed::for_test(CountedVec(vec![1, 2])).build();
Expand Down
6 changes: 6 additions & 0 deletions relay-server/src/managed/managed/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ impl<T> ManagedTestBuilder<T> {
}
}

/// Sets the scoping of the managed test instance.
pub fn scoping(mut self, scoping: Scoping) -> Self {
self.scoping = scoping;
self
}

/// Creates a new [`Managed`] instance and a [`ManagedTestHandle`] to assert outcomes.
pub fn build(self) -> (Managed<T>, ManagedTestHandle)
where
Expand Down
Loading