-
Notifications
You must be signed in to change notification settings - Fork 0
7966: impl Stream for std::collections::*
#77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
566e3a1
fe4c140
23c97cc
ab596f1
de158ac
236154d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| use std::collections::BTreeSet; | ||
| use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; | ||
|
|
||
| use tokio_stream::{self as stream, StreamExt}; | ||
| use tokio_test::{assert_pending, assert_ready, assert_ready_err, assert_ready_ok, task}; | ||
|
|
@@ -63,6 +63,48 @@ async fn collect_vec_items() { | |
| assert_eq!(vec![1, 2], coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_vecdeque_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<VecDeque<i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(1).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(2).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(VecDeque::from([1, 2]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_linkedlist_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<LinkedList<i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(1).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(2).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(LinkedList::from([1, 2]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_btreeset_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
|
|
@@ -84,6 +126,90 @@ async fn collect_btreeset_items() { | |
| assert_eq!(BTreeSet::from([1, 2]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_btreemap_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<BTreeMap<i32, i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send((3, 4)).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send((1, 2)).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(BTreeMap::from([(1, 2), (3, 4)]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_hashset_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<HashSet<i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(1).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(2).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(HashSet::from([1, 2]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_hashmap_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<HashMap<i32, i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send((1, 2)).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send((3, 4)).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(HashMap::from([(1, 2), (3, 4)]), coll); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn collect_binaryheap_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
| let mut fut = task::spawn(rx.collect::<BinaryHeap<i32>>()); | ||
|
|
||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(2).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| tx.send(1).unwrap(); | ||
| assert!(fut.is_woken()); | ||
| assert_pending!(fut.poll()); | ||
|
|
||
| drop(tx); | ||
| assert!(fut.is_woken()); | ||
| let coll = assert_ready!(fut.poll()); | ||
| assert_eq!(vec![1, 2], coll.into_sorted_vec()); | ||
| } | ||
|
Comment on lines
+130
to
+211
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned for the other new tests, there is significant code duplication here. Using a macro would greatly improve the maintainability of these tests. Here is an example of how such a macro could look and be used: macro_rules! test_collect {
($name:ident, $ty:ty, $items:expr, $expected:expr) => {
#[tokio::test]
async fn $name() {
let (tx, rx) = mpsc::unbounded_channel_stream();
let mut fut = task::spawn(rx.collect::<$ty>());
assert_pending!(fut.poll());
for item in $items {
tx.send(item).unwrap();
assert!(fut.is_woken());
assert_pending!(fut.poll());
}
drop(tx);
assert!(fut.is_woken());
let coll = assert_ready!(fut.poll());
assert_eq!($expected, coll);
}
};
}
// Usage:
test_collect!(
collect_btreemap_items,
BTreeMap<i32, i32>,
vec![(3, 4), (1, 2)],
BTreeMap::from([(1, 2), (3, 4)])
);Tests with special assertion logic, like for
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. value:good-to-have; category:bug; feedback: The Gemini AI reviewer is correct! There is a lot of duplicated logic that could be extracted into a macro and reused for all collection types. This would prevent fixing/improving the same thing multiple times. |
||
|
|
||
| #[tokio::test] | ||
| async fn collect_string_items() { | ||
| let (tx, rx) = mpsc::unbounded_channel_stream(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new tests for
VecDequeandLinkedListare very similar and contain a lot of boilerplate, a pattern that is repeated for the other collections added in this PR. To improve maintainability and reduce this duplication, consider using a macro to generate the test cases.This would make the test suite more concise and easier to extend. I've added a similar comment on the other block of new tests with a concrete example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value:good-to-have; category:bug; feedback: The Gemini AI reviewer is correct! There is a lot of duplicated logic that could be extracted into a macro and reused for all collection types. This would prevent fixing/improving the same thing multiple times.