• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pythonbrad / afrim / 6632683999

24 Oct 2023 09:19PM UTC coverage: 98.234% (-0.4%) from 98.585%
6632683999

push

github

web-flow
feat(preprocessor): implement inhibit mode (#111)

140 of 140 new or added lines in 2 files covered. (100.0%)

1391 of 1416 relevant lines covered (98.23%)

65.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.06
/engine/preprocessor/src/lib.rs
1
//! Preprocessor of keyboard events for an input method.
2
//!
3
//! Example
4
//!
5
//! ```rust
6
//! use afrim_preprocessor::{utils, Command, Preprocessor};
7
//! use keyboard_types::{
8
//!     webdriver::{self, Event},
9
//!     Key::*,
10
//! };
11
//! use std::collections::VecDeque;
12
//!
13
//! // We build initiate our preprocessor
14
//! let data = utils::load_data("cc ç");
15
//! let map = utils::build_map(data);
16
//! let mut preprocessor = Preprocessor::new(map, 8);
17
//!
18
//! // We trigger a sequence
19
//! webdriver::send_keys("cc")
20
//!     .into_iter()
21
//!     .for_each(|e| {
22
//!         match e {
23
//!             Event::Keyboard(e) => preprocessor.process(e),
24
//!             _ => unimplemented!(),
25
//!         };
26
//!     });
27
//!
28
//! // We got the generated command
29
//! let mut expecteds = VecDeque::from(vec![
30
//!     Command::Pause,
31
//!     Command::KeyClick(Backspace),
32
//!     #[cfg(feature = "inhibit")]
33
//!     Command::Resume,
34
//!     #[cfg(feature = "inhibit")]
35
//!     Command::Pause,
36
//!     Command::KeyClick(Backspace),
37
//!     Command::CommitText("ç".to_owned()),
38
//!     Command::Resume,
39
//! ]);
40
//!
41
//! while let Some(command) = preprocessor.pop_stack() {
42
//!     assert_eq!(command, expecteds.pop_front().unwrap());
43
//! }
44
//! ```
45

46
#![deny(missing_docs)]
47

48
mod message;
49

50
pub use crate::message::Command;
51
pub use afrim_memory::utils;
52
use afrim_memory::{Cursor, Node};
53
pub use keyboard_types::{Key, KeyState, KeyboardEvent};
54
use std::collections::VecDeque;
55

56
/// The main structure of the preprocessor.
57
#[derive(Debug)]
58
pub struct Preprocessor {
59
    cursor: Cursor,
60
    stack: VecDeque<Command>,
61
}
62

63
impl Preprocessor {
64
    /// Initiate a new preprocessor.
65
    pub fn new(map: Node, buffer_size: usize) -> Self {
7✔
66
        let cursor = Cursor::new(map, buffer_size);
7✔
67
        let stack = VecDeque::with_capacity(15);
7✔
68

7✔
69
        Self { cursor, stack }
7✔
70
    }
7✔
71

72
    /// Cancel the previous operation.
73
    /// NB: The inhibit feature don't manage the rollback
74
    #[cfg(not(feature = "inhibit"))]
75
    fn rollback(&mut self) -> bool {
76
        self.stack.push_back(Command::KeyRelease(Key::Backspace));
77

78
        if let Some(out) = self.cursor.undo() {
79
            (1..out.chars().count())
80
                .for_each(|_| self.stack.push_back(Command::KeyClick(Key::Backspace)));
81

82
            // Clear the remaining code
83
            while let (None, 1.., ..) = self.cursor.state() {
84
                self.cursor.undo();
85
            }
86

87
            if let (Some(_in), ..) = self.cursor.state() {
88
                self.stack.push_back(Command::CommitText(_in));
89
            }
90

91
            true
92
        } else {
93
            false
94
        }
95
    }
96

97
    /// Process the key event.
98
    pub fn process(&mut self, event: KeyboardEvent) -> (bool, bool) {
693✔
99
        let (mut changed, mut committed) = (false, false);
693✔
100

693✔
101
        match (event.state, event.key) {
693✔
102
            (KeyState::Down, Key::Backspace) => {
57✔
103
                #[cfg(not(feature = "inhibit"))]
57✔
104
                {
57✔
105
                    self.pause();
57✔
106
                    committed = self.rollback();
57✔
107
                    self.resume();
57✔
108
                }
57✔
109
                #[cfg(feature = "inhibit")]
57✔
110
                self.cursor.clear();
57✔
111
                changed = true;
57✔
112
            }
57✔
113
            (KeyState::Down, Key::Character(character))
183✔
114
                if character
183✔
115
                    .chars()
183✔
116
                    .next()
183✔
117
                    .map(|e| e.is_alphanumeric() || e.is_ascii_punctuation())
183✔
118
                    .unwrap_or(false) =>
183✔
119
            {
183✔
120
                #[cfg(feature = "inhibit")]
183✔
121
                self.pause();
183✔
122
                #[cfg(feature = "inhibit")]
183✔
123
                self.stack.push_back(Command::KeyClick(Key::Backspace));
183✔
124

183✔
125
                let character = character.chars().next().unwrap();
183✔
126

127
                if let Some(_in) = self.cursor.hit(character) {
183✔
128
                    #[cfg(not(feature = "inhibit"))]
129
                    self.pause();
130
                    let mut prev_cursor = self.cursor.clone();
73✔
131
                    prev_cursor.undo();
73✔
132
                    #[cfg(not(feature = "inhibit"))]
133
                    self.stack.push_back(Command::KeyClick(Key::Backspace));
134

135
                    // Remove the remaining code
136
                    while let (None, 1.., ..) = prev_cursor.state() {
138✔
137
                        prev_cursor.undo();
65✔
138
                        #[cfg(not(feature = "inhibit"))]
65✔
139
                        self.stack.push_back(Command::KeyClick(Key::Backspace));
65✔
140
                    }
65✔
141

142
                    if let (Some(out), ..) = prev_cursor.state() {
73✔
143
                        (0..out.chars().count())
28✔
144
                            .for_each(|_| self.stack.push_back(Command::KeyClick(Key::Backspace)))
32✔
145
                    }
45✔
146

147
                    self.stack.push_back(Command::CommitText(_in));
73✔
148
                    #[cfg(not(feature = "inhibit"))]
73✔
149
                    self.resume();
73✔
150
                    committed = true;
73✔
151
                };
110✔
152

153
                #[cfg(feature = "inhibit")]
154
                self.resume();
183✔
155
                changed = true;
183✔
156
            }
157
            (KeyState::Down, Key::Shift | Key::CapsLock) => (),
13✔
158
            (KeyState::Down, _) => {
21✔
159
                self.cursor.clear();
21✔
160
                changed = true;
21✔
161
            }
21✔
162
            _ => (),
419✔
163
        };
164

165
        (changed, committed)
693✔
166
    }
693✔
167

168
    /// Commit a text.
169
    pub fn commit(&mut self, text: &str) {
13✔
170
        self.pause();
13✔
171

13✔
172
        #[cfg(not(feature = "inhibit"))]
13✔
173
        while !self.cursor.is_empty() {
13✔
174
            self.stack.push_back(Command::KeyPress(Key::Backspace));
13✔
175
            self.rollback();
13✔
176
        }
13✔
177
        #[cfg(feature = "inhibit")]
13✔
178
        self.cursor.clear();
13✔
179
        self.stack.push_back(Command::CommitText(text.to_owned()));
13✔
180
        self.resume();
13✔
181
        // We clear the buffer
13✔
182
        self.cursor.clear();
13✔
183
    }
13✔
184

185
    /// Pause the keyboard event listerner.
186
    fn pause(&mut self) {
196✔
187
        self.stack.push_back(Command::Pause);
196✔
188
    }
196✔
189

190
    /// Resume the keyboard event listener.
191
    fn resume(&mut self) {
196✔
192
        self.stack.push_back(Command::Resume);
196✔
193
    }
196✔
194

195
    /// Return the sequence present in the memory.
196
    pub fn get_input(&self) -> String {
212✔
197
        self.cursor
212✔
198
            .to_sequence()
212✔
199
            .into_iter()
212✔
200
            .filter(|c| *c != '\0')
1,434✔
201
            .collect::<String>()
212✔
202
    }
212✔
203

204
    /// Return the next command to be executed.
205
    pub fn pop_stack(&mut self) -> Option<Command> {
1,321✔
206
        self.stack.pop_front()
1,321✔
207
    }
1,321✔
208

209
    /// Clear the stack.
210
    pub fn clear_stack(&mut self) {
1✔
211
        self.stack.clear();
1✔
212
    }
1✔
213
}
214

215
#[cfg(test)]
216
mod tests {
217
    use crate::message::Command;
218
    use crate::utils;
219
    use crate::Preprocessor;
220
    use keyboard_types::{
221
        webdriver::{self, Event},
222
        Key::*,
223
    };
224
    use std::collections::VecDeque;
225

226
    #[test]
1✔
227
    fn test_process() {
1✔
228
        let data = utils::load_data("ccced ç\ncc ç");
1✔
229
        let map = utils::build_map(data);
1✔
230
        let mut preprocessor = Preprocessor::new(map, 8);
1✔
231
        webdriver::send_keys("ccced").into_iter().for_each(|e| {
10✔
232
            match e {
10✔
233
                Event::Keyboard(e) => preprocessor.process(e),
10✔
234
                _ => unimplemented!(),
×
235
            };
236
        });
10✔
237
        let mut expecteds = VecDeque::from(vec![
1✔
238
            // c c
1✔
239
            Command::Pause,
1✔
240
            Command::KeyClick(Backspace),
1✔
241
            #[cfg(feature = "inhibit")]
1✔
242
            Command::Resume,
1✔
243
            #[cfg(feature = "inhibit")]
1✔
244
            Command::Pause,
1✔
245
            Command::KeyClick(Backspace),
1✔
246
            Command::CommitText("ç".to_owned()),
1✔
247
            Command::Resume,
1✔
248
            // c e d
1✔
249
            Command::Pause,
1✔
250
            Command::KeyClick(Backspace),
1✔
251
            #[cfg(feature = "inhibit")]
1✔
252
            Command::Resume,
1✔
253
            #[cfg(feature = "inhibit")]
1✔
254
            Command::Pause,
1✔
255
            Command::KeyClick(Backspace),
1✔
256
            #[cfg(feature = "inhibit")]
1✔
257
            Command::Resume,
1✔
258
            #[cfg(feature = "inhibit")]
1✔
259
            Command::Pause,
1✔
260
            Command::KeyClick(Backspace),
1✔
261
            Command::KeyClick(Backspace),
1✔
262
            Command::CommitText("ç".to_owned()),
1✔
263
            Command::Resume,
1✔
264
        ]);
1✔
265

266
        while let Some(command) = preprocessor.pop_stack() {
19✔
267
            assert_eq!(command, expecteds.pop_front().unwrap());
18✔
268
        }
269
    }
1✔
270

271
    #[test]
1✔
272
    fn test_commit() {
1✔
273
        use afrim_memory::Node;
1✔
274
        use keyboard_types::KeyboardEvent;
1✔
275

1✔
276
        let mut preprocessor = Preprocessor::new(Node::default(), 8);
1✔
277
        preprocessor.process(KeyboardEvent {
1✔
278
            key: Character("a".to_owned()),
1✔
279
            ..Default::default()
1✔
280
        });
1✔
281
        preprocessor.commit("word");
1✔
282

1✔
283
        let mut expecteds = VecDeque::from(vec![
1✔
284
            Command::Pause,
1✔
285
            #[cfg(feature = "inhibit")]
1✔
286
            Command::KeyClick(Backspace),
1✔
287
            #[cfg(feature = "inhibit")]
1✔
288
            Command::Resume,
1✔
289
            #[cfg(feature = "inhibit")]
1✔
290
            Command::Pause,
1✔
291
            #[cfg(not(feature = "inhibit"))]
1✔
292
            Command::KeyPress(Backspace),
1✔
293
            #[cfg(not(feature = "inhibit"))]
1✔
294
            Command::KeyRelease(Backspace),
1✔
295
            Command::CommitText("word".to_owned()),
1✔
296
            Command::Resume,
1✔
297
        ]);
1✔
298

299
        while let Some(command) = preprocessor.pop_stack() {
7✔
300
            assert_eq!(command, expecteds.pop_front().unwrap());
6✔
301
        }
302
    }
1✔
303

304
    #[test]
1✔
305
    fn test_rollback() {
1✔
306
        use keyboard_types::KeyboardEvent;
1✔
307

1✔
308
        let data = utils::load_data("ccced ç\ncc ç");
1✔
309
        let map = utils::build_map(data);
1✔
310
        let mut preprocessor = Preprocessor::new(map, 8);
1✔
311
        let backspace_event = KeyboardEvent {
1✔
312
            key: Backspace,
1✔
313
            ..Default::default()
1✔
314
        };
1✔
315

1✔
316
        webdriver::send_keys("ccced").into_iter().for_each(|e| {
10✔
317
            match e {
10✔
318
                Event::Keyboard(e) => preprocessor.process(e),
10✔
319
                _ => unimplemented!(),
×
320
            };
321
        });
10✔
322

1✔
323
        preprocessor.clear_stack();
1✔
324
        assert_eq!(preprocessor.get_input(), "ccced".to_owned());
1✔
325
        preprocessor.process(backspace_event.clone());
1✔
326
        #[cfg(not(feature = "inhibit"))]
1✔
327
        assert_eq!(preprocessor.get_input(), "cc".to_owned());
1✔
328
        #[cfg(not(feature = "inhibit"))]
1✔
329
        preprocessor.process(backspace_event);
1✔
330
        assert_eq!(preprocessor.get_input(), "".to_owned());
1✔
331

332
        let mut expecteds = VecDeque::from(vec![
1✔
333
            Command::Pause,
1✔
334
            #[cfg(not(feature = "inhibit"))]
1✔
335
            Command::KeyRelease(Backspace),
1✔
336
            Command::CommitText("ç".to_owned()),
1✔
337
            Command::Resume,
1✔
338
            #[cfg(not(feature = "inhibit"))]
1✔
339
            Command::Pause,
1✔
340
            #[cfg(not(feature = "inhibit"))]
1✔
341
            Command::KeyRelease(Backspace),
1✔
342
            #[cfg(not(feature = "inhibit"))]
1✔
343
            Command::Resume,
1✔
344
        ]);
1✔
345

346
        while let Some(command) = preprocessor.pop_stack() {
1✔
347
            assert_eq!(command, expecteds.pop_front().unwrap());
×
348
        }
349
    }
1✔
350

351
    #[test]
1✔
352
    fn test_advanced() {
1✔
353
        use std::fs;
1✔
354

1✔
355
        let data = fs::read_to_string("./data/sample.txt").unwrap();
1✔
356
        let data = utils::load_data(&data);
1✔
357
        let map = utils::build_map(data);
1✔
358
        let mut preprocessor = Preprocessor::new(map, 64);
1✔
359

1✔
360
        webdriver::send_keys(
1✔
361
            "u\u{E003}uu\u{E003}uc_ceduuaf3afafaff3uu3\
1✔
362
            \u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}\u{E003}"
1✔
363
        ).into_iter().for_each(|e| {
80✔
364
            match e {
80✔
365
                Event::Keyboard(e) => preprocessor.process(e),
80✔
366
                _ => unimplemented!(),
×
367
            };
368
        });
80✔
369

1✔
370
        let mut expecteds = VecDeque::from(vec![
1✔
371
            // Process
1✔
372
            // u backspace
1✔
373
            Command::Pause,
1✔
374
            #[cfg(feature = "inhibit")]
1✔
375
            Command::KeyClick(Backspace),
1✔
376
            #[cfg(feature = "inhibit")]
1✔
377
            Command::Resume,
1✔
378
            #[cfg(not(feature = "inhibit"))]
1✔
379
            Command::KeyRelease(Backspace),
1✔
380
            #[cfg(not(feature = "inhibit"))]
1✔
381
            Command::Resume,
1✔
382
            // u u backspace
1✔
383
            Command::Pause,
1✔
384
            Command::KeyClick(Backspace),
1✔
385
            #[cfg(feature = "inhibit")]
1✔
386
            Command::Resume,
1✔
387
            #[cfg(feature = "inhibit")]
1✔
388
            Command::Pause,
1✔
389
            Command::KeyClick(Backspace),
1✔
390
            Command::CommitText("ʉ".to_owned()),
1✔
391
            Command::Resume,
1✔
392
            #[cfg(not(feature = "inhibit"))]
1✔
393
            Command::Pause,
1✔
394
            #[cfg(not(feature = "inhibit"))]
1✔
395
            Command::KeyRelease(Backspace),
1✔
396
            #[cfg(not(feature = "inhibit"))]
1✔
397
            Command::Resume,
1✔
398
            // u
1✔
399
            #[cfg(feature = "inhibit")]
1✔
400
            Command::Pause,
1✔
401
            #[cfg(feature = "inhibit")]
1✔
402
            Command::KeyClick(Backspace),
1✔
403
            #[cfg(feature = "inhibit")]
1✔
404
            Command::Resume,
1✔
405
            // c _
1✔
406
            Command::Pause,
1✔
407
            Command::KeyClick(Backspace),
1✔
408
            #[cfg(feature = "inhibit")]
1✔
409
            Command::Resume,
1✔
410
            #[cfg(feature = "inhibit")]
1✔
411
            Command::Pause,
1✔
412
            Command::KeyClick(Backspace),
1✔
413
            Command::CommitText("ç".to_owned()),
1✔
414
            Command::Resume,
1✔
415
            // c e d
1✔
416
            Command::Pause,
1✔
417
            Command::KeyClick(Backspace),
1✔
418
            #[cfg(feature = "inhibit")]
1✔
419
            Command::Resume,
1✔
420
            #[cfg(feature = "inhibit")]
1✔
421
            Command::Pause,
1✔
422
            Command::KeyClick(Backspace),
1✔
423
            #[cfg(feature = "inhibit")]
1✔
424
            Command::Resume,
1✔
425
            #[cfg(feature = "inhibit")]
1✔
426
            Command::Pause,
1✔
427
            Command::KeyClick(Backspace),
1✔
428
            Command::KeyClick(Backspace),
1✔
429
            Command::CommitText("ç".to_owned()),
1✔
430
            Command::Resume,
1✔
431
            // u u
1✔
432
            Command::Pause,
1✔
433
            Command::KeyClick(Backspace),
1✔
434
            #[cfg(feature = "inhibit")]
1✔
435
            Command::Resume,
1✔
436
            #[cfg(feature = "inhibit")]
1✔
437
            Command::Pause,
1✔
438
            Command::KeyClick(Backspace),
1✔
439
            Command::CommitText("ʉ".to_owned()),
1✔
440
            Command::Resume,
1✔
441
            // a f 3
1✔
442
            Command::Pause,
1✔
443
            Command::KeyClick(Backspace),
1✔
444
            #[cfg(feature = "inhibit")]
1✔
445
            Command::Resume,
1✔
446
            #[cfg(feature = "inhibit")]
1✔
447
            Command::Pause,
1✔
448
            Command::KeyClick(Backspace),
1✔
449
            #[cfg(feature = "inhibit")]
1✔
450
            Command::Resume,
1✔
451
            #[cfg(feature = "inhibit")]
1✔
452
            Command::Pause,
1✔
453
            Command::KeyClick(Backspace),
1✔
454
            Command::KeyClick(Backspace),
1✔
455
            Command::CommitText("ʉ\u{304}ɑ\u{304}".to_owned()),
1✔
456
            Command::Resume,
1✔
457
            // a f
1✔
458
            Command::Pause,
1✔
459
            Command::KeyClick(Backspace),
1✔
460
            #[cfg(feature = "inhibit")]
1✔
461
            Command::Resume,
1✔
462
            #[cfg(feature = "inhibit")]
1✔
463
            Command::Pause,
1✔
464
            Command::KeyClick(Backspace),
1✔
465
            Command::CommitText("ɑ".to_owned()),
1✔
466
            Command::Resume,
1✔
467
            // a f
1✔
468
            Command::Pause,
1✔
469
            Command::KeyClick(Backspace),
1✔
470
            #[cfg(feature = "inhibit")]
1✔
471
            Command::Resume,
1✔
472
            #[cfg(feature = "inhibit")]
1✔
473
            Command::Pause,
1✔
474
            Command::KeyClick(Backspace),
1✔
475
            Command::CommitText("ɑ".to_owned()),
1✔
476
            Command::Resume,
1✔
477
            // a f
1✔
478
            Command::Pause,
1✔
479
            Command::KeyClick(Backspace),
1✔
480
            #[cfg(feature = "inhibit")]
1✔
481
            Command::Resume,
1✔
482
            #[cfg(feature = "inhibit")]
1✔
483
            Command::Pause,
1✔
484
            Command::KeyClick(Backspace),
1✔
485
            Command::CommitText("ɑ".to_owned()),
1✔
486
            Command::Resume,
1✔
487
            // f
1✔
488
            Command::Pause,
1✔
489
            Command::KeyClick(Backspace),
1✔
490
            Command::KeyClick(Backspace),
1✔
491
            Command::CommitText("ɑɑ".to_owned()),
1✔
492
            Command::Resume,
1✔
493
            // 3
1✔
494
            Command::Pause,
1✔
495
            Command::KeyClick(Backspace),
1✔
496
            Command::KeyClick(Backspace),
1✔
497
            Command::KeyClick(Backspace),
1✔
498
            Command::CommitText("ɑ\u{304}ɑ\u{304}".to_owned()),
1✔
499
            Command::Resume,
1✔
500
            // uu
1✔
501
            Command::Pause,
1✔
502
            Command::KeyClick(Backspace),
1✔
503
            #[cfg(feature = "inhibit")]
1✔
504
            Command::Resume,
1✔
505
            #[cfg(feature = "inhibit")]
1✔
506
            Command::Pause,
1✔
507
            Command::KeyClick(Backspace),
1✔
508
            Command::CommitText("ʉ".to_owned()),
1✔
509
            Command::Resume,
1✔
510
            // 3
1✔
511
            Command::Pause,
1✔
512
            Command::KeyClick(Backspace),
1✔
513
            Command::KeyClick(Backspace),
1✔
514
            Command::CommitText("ʉ\u{304}".to_owned()),
1✔
515
            Command::Resume,
1✔
516
            // Rollback
1✔
517
            Command::Pause,
1✔
518
            Command::KeyRelease(Backspace),
1✔
519
            Command::KeyClick(Backspace),
1✔
520
            Command::CommitText("ʉ".to_owned()),
1✔
521
            Command::Resume,
1✔
522
            Command::Pause,
1✔
523
            Command::KeyRelease(Backspace),
1✔
524
            Command::Resume,
1✔
525
            Command::Pause,
1✔
526
            Command::KeyRelease(Backspace),
1✔
527
            Command::KeyClick(Backspace),
1✔
528
            Command::KeyClick(Backspace),
1✔
529
            Command::KeyClick(Backspace),
1✔
530
            Command::CommitText("ɑɑ".to_owned()),
1✔
531
            Command::Resume,
1✔
532
            Command::Pause,
1✔
533
            Command::KeyRelease(Backspace),
1✔
534
            Command::KeyClick(Backspace),
1✔
535
            Command::CommitText("ɑ".to_owned()),
1✔
536
            Command::Resume,
1✔
537
            Command::Pause,
1✔
538
            Command::KeyRelease(Backspace),
1✔
539
            Command::Resume,
1✔
540
            Command::Pause,
1✔
541
            Command::KeyRelease(Backspace),
1✔
542
            Command::Resume,
1✔
543
            Command::Pause,
1✔
544
            Command::KeyRelease(Backspace),
1✔
545
            Command::Resume,
1✔
546
            Command::Pause,
1✔
547
            Command::KeyRelease(Backspace),
1✔
548
            Command::KeyClick(Backspace),
1✔
549
            Command::KeyClick(Backspace),
1✔
550
            Command::KeyClick(Backspace),
1✔
551
            Command::CommitText("ʉ".to_owned()),
1✔
552
            Command::Resume,
1✔
553
            Command::Pause,
1✔
554
            Command::KeyRelease(Backspace),
1✔
555
            Command::Resume,
1✔
556
            Command::Pause,
1✔
557
            Command::KeyRelease(Backspace),
1✔
558
            Command::CommitText("ç".to_owned()),
1✔
559
            Command::Resume,
1✔
560
            Command::Pause,
1✔
561
            Command::KeyRelease(Backspace),
1✔
562
            Command::Resume,
1✔
563
            Command::Pause,
1✔
564
            Command::KeyRelease(Backspace),
1✔
565
            Command::Resume,
1✔
566
        ]);
1✔
567

568
        while let Some(command) = preprocessor.pop_stack() {
94✔
569
            assert_eq!(command, expecteds.pop_front().unwrap());
93✔
570
        }
571
    }
1✔
572
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc