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