1use crate::descriptor::EventDescriptor;
6use crate::events::{EventStream, EventStreamError, event_name};
7use crate::matcher::EventMatcher;
8use anyhow::{Error, format_err};
9use futures::StreamExt;
10
11#[derive(Clone)]
14pub enum Ordering {
15 Ordered,
16 Unordered,
17}
18
19#[derive(Clone, PartialEq)]
22pub enum Contains {
23 All,
24 Subset,
25}
26
27#[derive(Clone)]
28pub struct EventSequence {
29 groups: Vec<EventGroup>,
30}
31
32impl EventSequence {
33 pub fn new() -> Self {
34 Self { groups: vec![] }
35 }
36
37 pub fn then(self, matcher: EventMatcher) -> Self {
38 self.all_of(vec![matcher], Ordering::Ordered)
39 }
40
41 pub fn all_of(mut self, events: Vec<EventMatcher>, ordering: Ordering) -> Self {
46 self.groups.push(EventGroup::new(events, ordering, Contains::All));
47 self
48 }
49
50 pub fn has_subset(mut self, events: Vec<EventMatcher>, ordering: Ordering) -> Self {
56 self.groups.push(EventGroup::new(events, ordering, Contains::Subset));
57 self
58 }
59
60 pub async fn expect(self, event_stream: EventStream) -> Result<(), Error> {
62 self.expect_and_giveback(event_stream).await.map(|_| ())
63 }
64
65 pub async fn expect_and_giveback(
68 mut self,
69 mut event_stream: EventStream,
70 ) -> Result<EventStream, Error> {
71 while !self.groups.is_empty() {
72 match event_stream.next().await {
73 None => return Err(EventStreamError::StreamClosed.into()),
74 Some(event) => {
75 let actual_event = EventDescriptor::try_from(&event)?;
76 let _ = self.next(&actual_event)?;
77 }
78 }
79 }
80 Ok(event_stream)
81 }
82
83 pub fn is_empty(&self) -> bool {
84 self.groups.is_empty()
85 }
86
87 pub fn event_names(&self) -> Result<Vec<String>, Error> {
88 let mut event_names = vec![];
89 for group in &self.groups {
90 let mut group_event_names = group.event_names()?;
91 event_names.append(&mut group_event_names);
92 }
93 event_names.dedup();
94 Ok(event_names)
95 }
96
97 pub fn next(&mut self, event: &EventDescriptor) -> Result<(), Error> {
108 loop {
109 if self.groups.is_empty() {
110 return Ok(());
111 }
112 let group = &mut self.groups[0];
113 if group.next(event)? {
114 if group.is_empty() {
115 self.groups.remove(0);
116 }
117 return Ok(());
118 }
119 self.groups.remove(0);
120 }
121 }
122}
123
124#[derive(Clone)]
125pub struct EventGroup {
126 events: Vec<EventMatcher>,
127 ordering: Ordering,
128 contains: Contains,
129}
130
131impl EventGroup {
132 pub fn new(events: Vec<EventMatcher>, ordering: Ordering, contains: Contains) -> Self {
133 Self { events, ordering, contains }
134 }
135
136 pub fn is_empty(&self) -> bool {
137 self.events.is_empty()
138 }
139
140 pub fn event_names(&self) -> Result<Vec<String>, Error> {
141 let mut event_names = vec![];
142 for event in &self.events {
143 if let Some(event_type) = &event.event_type {
144 event_names.push(event_name(&event_type.value()));
145 } else {
146 return Err(format_err!("No event name or type set for matcher {:?}", event));
147 }
148 }
149 event_names.dedup();
150 Ok(event_names)
151 }
152
153 pub fn next(&mut self, event: &EventDescriptor) -> Result<bool, Error> {
165 if self.events.is_empty() {
166 return Ok(Contains::Subset == self.contains);
167 }
168 match self.ordering {
169 Ordering::Ordered => {
170 let matches = self.events.get(0).unwrap().matches(event);
171 if matches.is_ok() {
172 self.events.remove(0);
173 Ok(true)
174 } else {
175 match self.contains {
178 Contains::All => Err(Error::new(matches.unwrap_err())),
179 Contains::Subset => Ok(true),
180 }
181 }
182 }
183 Ordering::Unordered => {
184 if let Some((index, _)) = self
185 .events
186 .iter()
187 .enumerate()
188 .find(|&matcher| matcher.1.matches(&event).is_ok())
189 {
190 self.events.remove(index);
191 Ok(true)
192 } else {
193 match self.contains {
194 Contains::All => Err(format_err!("Failed to find event: {:?}", event)),
195 Contains::Subset => Ok(true),
196 }
197 }
198 }
199 }
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::events::{Event, Started};
207 use fidl_fuchsia_component as fcomponent;
208 use futures::StreamExt;
209
210 async fn run_server(
211 events: Vec<fcomponent::Event>,
212 mut server: fcomponent::EventStreamRequestStream,
213 ) {
214 let (tx, mut rx) = futures::channel::mpsc::unbounded();
215 for event in events {
216 tx.unbounded_send(event).unwrap();
217 }
218 drop(tx);
222 while let Some(Ok(request)) = server.next().await {
223 match request {
224 fcomponent::EventStreamRequest::GetNext { responder } => {
225 if let Some(event) = rx.next().await {
226 responder.send(vec![event]).unwrap();
227 } else {
228 return;
229 }
230 }
231 fcomponent::EventStreamRequest::WaitForReady { responder } => {
232 responder.send().unwrap()
233 }
234 }
235 }
236 }
237
238 async fn make_event_stream(
239 events: Vec<fcomponent::Event>,
240 ) -> Result<(EventStream, fuchsia_async::Task<()>), Error> {
241 let (proxy, server) = fidl::endpoints::create_proxy::<fcomponent::EventStreamMarker>();
242 Ok((
243 EventStream::new(proxy),
244 fuchsia_async::Task::spawn(run_server(events, server.into_stream())),
245 ))
246 }
247
248 fn make_event<M: Into<String>>(moniker: M) -> fcomponent::Event {
250 fcomponent::Event {
251 header: Some(fcomponent::EventHeader {
252 event_type: Some(fcomponent::EventType::Started),
253 moniker: Some(moniker.into()),
254 ..Default::default()
255 }),
256 payload: Some(fcomponent::EventPayload::Started(fcomponent::StartedPayload::default())),
257 ..Default::default()
258 }
259 }
260
261 fn make_matcher<M: Into<String>>(moniker: M) -> EventMatcher {
263 EventMatcher::ok().r#type(Started::TYPE).moniker(moniker)
264 }
265
266 #[fuchsia::test]
267 async fn event_sequence_empty() {
268 let (event_stream, _server) =
269 make_event_stream(vec![]).await.expect("failed to make event stream");
270 EventSequence::new()
271 .expect(event_stream)
272 .await
273 .expect("event sequence did not match expected");
274 }
275
276 #[fuchsia::test]
277 async fn event_sequence_then() {
278 let moniker = "./foo:0";
279 let (event_stream, _server) = make_event_stream(vec![make_event(moniker)])
280 .await
281 .expect("failed to make event stream");
282 EventSequence::new()
283 .then(make_matcher(moniker))
284 .expect(event_stream)
285 .await
286 .expect("event sequence did not match expected");
287 }
288
289 #[fuchsia::test]
290 async fn event_sequence_all_of_ordered_ok() {
291 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
292 let events = monikers.iter().copied().map(make_event).collect();
293 let matchers = monikers.iter().copied().map(make_matcher).collect();
294
295 let (event_stream, _server) =
296 make_event_stream(events).await.expect("failed to make event stream");
297 EventSequence::new()
298 .all_of(matchers, Ordering::Ordered)
299 .expect(event_stream)
300 .await
301 .expect("event sequence did not match expected");
302 }
303
304 #[fuchsia::test]
305 async fn event_sequence_all_of_ordered_fail_order() {
306 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
307 let events = monikers.iter().rev().copied().map(make_event).collect();
309 let matchers = monikers.iter().copied().map(make_matcher).collect();
310
311 let (event_stream, _server) =
312 make_event_stream(events).await.expect("failed to make event stream");
313 assert!(
314 EventSequence::new()
315 .all_of(matchers, Ordering::Ordered)
316 .expect(event_stream)
317 .await
318 .is_err()
319 );
320 }
321
322 #[fuchsia::test]
323 async fn event_sequence_all_of_ordered_fail_missing_event() {
324 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
325 let events = monikers.iter().skip(1).copied().map(make_event).collect();
327 let matchers = monikers.iter().copied().map(make_matcher).collect();
328
329 let (event_stream, _server) =
330 make_event_stream(events).await.expect("failed to make event stream");
331 assert!(
332 EventSequence::new()
333 .all_of(matchers, Ordering::Ordered)
334 .expect(event_stream)
335 .await
336 .is_err()
337 );
338 }
339
340 #[fuchsia::test]
341 async fn event_sequence_all_of_ordered_fail_missing_matcher() {
342 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
343 let events = monikers.iter().copied().map(make_event).collect();
344 let matchers = monikers.iter().skip(1).copied().map(make_matcher).collect();
346
347 let (event_stream, _server) =
348 make_event_stream(events).await.expect("failed to make event stream");
349 assert!(
350 EventSequence::new()
351 .all_of(matchers, Ordering::Ordered)
352 .expect(event_stream)
353 .await
354 .is_err()
355 );
356 }
357
358 #[fuchsia::test]
359 async fn event_sequence_all_of_unordered_ok_reversed() {
360 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
361 let events = monikers.iter().rev().copied().map(make_event).collect();
363 let matchers = monikers.iter().copied().map(make_matcher).collect();
364
365 let (event_stream, _server) =
366 make_event_stream(events).await.expect("failed to make event stream");
367 EventSequence::new()
368 .all_of(matchers, Ordering::Unordered)
369 .expect(event_stream)
370 .await
371 .expect("event sequence did not match expected");
372 }
373
374 #[fuchsia::test]
375 async fn event_sequence_has_subset_ordered_ok() {
376 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
377 let events = monikers.iter().copied().map(make_event).collect();
378 let matchers = monikers.iter().skip(1).copied().map(make_matcher).collect();
380
381 let (event_stream, _server) =
382 make_event_stream(events).await.expect("failed to make event stream");
383 EventSequence::new()
384 .has_subset(matchers, Ordering::Ordered)
385 .expect(event_stream)
386 .await
387 .expect("event sequence did not match expected");
388 }
389
390 #[fuchsia::test]
391 async fn event_sequence_has_subset_ordered_missing_event() {
392 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
393 let events = monikers.iter().skip(2).copied().map(make_event).collect();
395 let matchers = monikers.iter().skip(1).copied().map(make_matcher).collect();
397
398 let (event_stream, _server) =
400 make_event_stream(events).await.expect("failed to make event stream");
401 assert!(
402 EventSequence::new()
403 .has_subset(matchers, Ordering::Ordered)
404 .expect(event_stream)
405 .await
406 .is_err()
407 );
408 }
409
410 #[fuchsia::test]
411 async fn event_sequence_has_subset_unordered_ok_reversed() {
412 let monikers = vec!["./foo:0", "./bar:0", "./baz:0"];
413 let events = monikers.iter().rev().copied().map(make_event).collect();
415 let matchers = monikers.iter().skip(1).copied().map(make_matcher).collect();
417
418 let (event_stream, _server) =
419 make_event_stream(events).await.expect("failed to make event stream");
420 EventSequence::new()
421 .has_subset(matchers, Ordering::Unordered)
422 .expect(event_stream)
423 .await
424 .expect("event sequence did not match expected");
425 }
426}