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

Vest / aoc-rust / 4005027531

pending completion
4005027531

Pull #19

github

GitHub
Merge 74f46dcbf into 0e0e3157b
Pull Request #19: Updated versions

2556 of 3992 branches covered (64.03%)

Branch coverage included in aggregate %.

1560 of 1560 new or added lines in 44 files covered. (100.0%)

5981 of 6247 relevant lines covered (95.74%)

624811.64 hits per line

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

80.5
/adv2015/src/day7.rs
1
use std::collections::HashMap;
318✔
2
use std::fmt;
3
use std::fmt::Formatter;
4

5
pub fn count_input_a(input: &str) -> u16 {
2✔
6
    let mut bobby = BobbyInterpreter::new();
2✔
7
    bobby.interpret(String::from(input));
2✔
8

9
    bobby.evaluate(&String::from("a")).unwrap_or_default()
2✔
10
}
2✔
11

12
pub fn count_input_a_override(input: &str) -> u16 {
2✔
13
    let mut bobby = BobbyInterpreter::new();
2✔
14
    bobby.interpret(String::from(input));
2✔
15

16
    let value_for_b = bobby.evaluate(&String::from("a")).unwrap();
2✔
17
    bobby
2✔
18
        .evaluate_override_signal(&String::from("a"), &String::from("b"), value_for_b)
2✔
19
        .unwrap_or_default()
20
}
2✔
21

22
struct NextToken(Token, usize);
23

24
#[derive(Clone, Debug)]
1!
25
enum Token {
26
    // value 0-65535
27
    Signal(u16),
1✔
28
    Wire(String),
×
29
    And,
30
    Or,
31
    LeftShift,
32
    RightShift,
33
    Not,
34
    Assign,
35
    EOF,
36
}
37

38
#[derive(Copy, Clone)]
14✔
39
enum Operation {
40
    And,
41
    Or,
42
    LShift,
43
    RShift,
44
    Not,
45
}
46

47
#[derive(Clone)]
35✔
48
enum RValue {
49
    Const(u16),
14✔
50
    Var(String),
21✔
51
}
52

53
#[derive(Clone)]
×
54
enum LValue {
55
    Var(String),
×
56
}
57

58
#[derive(Clone)]
27!
59
enum Command {
60
    Result(RValue),
13✔
61

62
    // A op B
63
    Binary(RValue, Operation, RValue),
8✔
64

65
    // x A
66
    Unary(Operation, RValue),
6✔
67
}
68

69
#[derive(Clone)]
×
70
enum Expression {
71
    NOP,
72
    // From - To
73
    Assign(Command, LValue),
×
74
}
75

76
struct Lexer {
77
    input: String,
78
    current_pos: usize,
79
}
80

81
struct Parser {
82
    lexer: Lexer,
83
    parsing: bool,
84
}
85

86
struct BobbyInterpreter {
87
    parser: Parser,
88
    tree: HashMap<String, Command>,
89
    cache: HashMap<String, u16>,
90
}
91

92
impl Lexer {
93
    fn new(input: String) -> Lexer {
37✔
94
        Lexer {
37✔
95
            input,
37✔
96
            current_pos: 0usize,
97
        }
98
    }
37✔
99

100
    fn next_token(&mut self) -> Token {
242✔
101
        let next_token = get_token(self.input.as_str(), self.current_pos);
242✔
102
        self.current_pos = next_token.1;
242✔
103

104
        next_token.0
242✔
105
    }
242✔
106
}
107

108
impl Token {
109
    fn parse_token(input: &str) -> Token {
269✔
110
        match input {
111
            "AND" => return Token::And,
269✔
112
            "OR" => return Token::Or,
258✔
113
            "LSHIFT" => return Token::LeftShift,
251✔
114
            "RSHIFT" => return Token::RightShift,
245✔
115
            "NOT" => return Token::Not,
236✔
116
            "->" => return Token::Assign,
226✔
117
            str_value => {
164✔
118
                if str_value.is_empty() {
164✔
119
                    return Token::EOF;
17✔
120
                }
121

122
                if let Ok(value) = str_value.parse::<u16>() {
147✔
123
                    Token::Signal(value)
42✔
124
                } else {
125
                    Token::Wire(String::from(str_value))
105✔
126
                }
127
            }
128
        }
129
    }
269✔
130
}
131

132
impl fmt::Display for Token {
133
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14✔
134
        match self {
14!
135
            Token::Signal(u) => f.write_fmt(format_args!("{}", u)),
2✔
136
            Token::Wire(s) => f.write_str(s.as_str()),
1✔
137
            Token::And => f.write_str("and"),
2✔
138
            Token::Or => f.write_str("or"),
2✔
139
            Token::LeftShift => f.write_str("lshift"),
2✔
140
            Token::RightShift => f.write_str("rshift"),
2✔
141
            Token::Not => f.write_str("not"),
1✔
142
            Token::Assign => f.write_str("->"),
1✔
143
            Token::EOF => f.write_str("eof"),
1✔
144
        }
145
    }
14✔
146
}
147

148
fn get_token(input: &str, from: usize) -> NextToken {
269✔
149
    let mut word = String::with_capacity(7);
269✔
150
    let chars = input.chars();
269✔
151

152
    for (i, c) in chars.enumerate() {
13,314✔
153
        if i < from {
13,263✔
154
            continue;
155
        }
156

157
        match c {
158
            // whitespace, but we have a word in the buffer
159
            _ if c.is_whitespace() && !word.is_empty() => {
1,516✔
160
                return NextToken(Token::parse_token(word.as_str()), i);
218✔
161
            }
162

163
            // skip whitespace
164
            _ if c.is_whitespace() && word.is_empty() => {
1,298!
165
                continue;
166
            }
167

168
            // any letter
169
            _ => {
170
                word.push(c);
475✔
171
            }
172
        }
173
    }
174

175
    return NextToken(Token::parse_token(word.as_str()), input.chars().count());
51✔
176
}
269✔
177

178
impl Parser {
179
    fn new(input: String) -> Parser {
35✔
180
        Parser {
35✔
181
            lexer: Lexer::new(input),
35✔
182
            parsing: true,
183
        }
184
    }
35✔
185

186
    fn next_operation(&mut self) -> Expression {
58✔
187
        if !self.parsing {
58✔
188
            return Expression::NOP;
1✔
189
        }
190

191
        let mut commands: Vec<Token> = Vec::new();
57✔
192

193
        while self.parsing {
189✔
194
            match self.lexer.next_token() {
170✔
195
                Token::EOF => self.parsing = false,
16✔
196

197
                Token::Assign => {
198
                    if commands.is_empty() {
61✔
199
                        println!("Error in parsing, there were no commands before the assignment");
1✔
200
                        self.parsing = false;
1✔
201
                    } else {
202
                        let token = self.lexer.next_token();
49✔
203
                        if let Token::Wire(target) = token {
49✔
204
                            if commands.len() == 1 {
48✔
205
                                if let Some(lvalue) = lvalue_from_one(&commands) {
17✔
206
                                    return Expression::Assign(
16✔
207
                                        Command::Result(lvalue),
16✔
208
                                        LValue::Var(target),
16✔
209
                                    );
210
                                }
211
                            } else if commands.len() == 2 {
32✔
212
                                if let Some(lvalue) = lvalue_from_two(&commands) {
8✔
213
                                    return Expression::Assign(lvalue, LValue::Var(target));
6✔
214
                                }
215
                            } else if commands.len() == 3 {
26✔
216
                                if let Some(lvalue) = lvalue_from_three(&commands) {
22✔
217
                                    return Expression::Assign(lvalue, LValue::Var(target));
16✔
218
                                }
219
                            } else {
6✔
220
                                println!("Cannot parse tokens to a command. The size of the vector is {}:", commands.len());
1✔
221
                                for c in &commands {
5✔
222
                                    print!("{} ", c);
4✔
223
                                }
224
                                println!();
1✔
225
                                self.parsing = false;
1✔
226
                            }
227
                        } else {
10✔
228
                            println!("Unexpected token, expected a wire, but got {}", token);
1✔
229
                            self.parsing = false;
1✔
230
                        }
231
                    }
49!
232
                }
233

234
                token => commands.push(token),
104✔
235
            }
236
        }
170✔
237
        return Expression::NOP;
19✔
238
    }
58✔
239
}
240

241
impl Iterator for Parser {
242
    type Item = Expression;
243

244
    fn next(&mut self) -> Option<Self::Item> {
31✔
245
        match self.next_operation() {
31✔
246
            Expression::NOP => None,
7✔
247
            result => Some(result),
24✔
248
        }
249
    }
31✔
250
}
251

252
fn lvalue_from_one(commands: &Vec<Token>) -> Option<RValue> {
17✔
253
    assert_eq!(commands.len(), 1);
17!
254
    let lvalue = &commands[0];
17✔
255
    if let Token::Wire(s) = lvalue {
17✔
256
        Some(RValue::Var(s.clone()))
2✔
257
    } else if let Token::Signal(v) = lvalue {
15✔
258
        Some(RValue::Const(v.clone()))
14✔
259
    } else {
260
        None
1✔
261
    }
262
}
17✔
263

264
fn lvalue_from_two(commands: &Vec<Token>) -> Option<Command> {
8✔
265
    assert_eq!(commands.len(), 2);
8!
266
    // NOT x
267
    let op = &commands[0];
8✔
268
    let lvalue = &commands[1];
8✔
269

270
    if let (Token::Not, Token::Wire(s)) = (op, lvalue) {
8!
271
        return Some(Command::Unary(Operation::Not, RValue::Var(s.clone())));
6✔
272
    }
273
    None
2✔
274
}
8✔
275

276
fn lvalue_from_three(commands: &Vec<Token>) -> Option<Command> {
22✔
277
    assert_eq!(commands.len(), 3);
22!
278
    // x op Y
279
    let lvalue1 = &commands[0];
22✔
280
    let op = &commands[1];
22✔
281
    let lvalue2 = &commands[2];
22✔
282

283
    match op {
22✔
284
        Token::And => {
285
            if let (Token::Wire(s1), Token::Wire(s2)) = (lvalue1, lvalue2) {
8!
286
                Some(Command::Binary(
6✔
287
                    RValue::Var(s1.clone()),
6✔
288
                    Operation::And,
6✔
289
                    RValue::Var(s2.clone()),
6✔
290
                ))
291
            } else if let (Token::Signal(u1), Token::Wire(s2)) = (lvalue1, lvalue2) {
2!
292
                Some(Command::Binary(
1✔
293
                    RValue::Const(u1.clone()),
1✔
294
                    Operation::And,
1✔
295
                    RValue::Var(s2.clone()),
1✔
296
                ))
297
            } else {
298
                None
1✔
299
            }
300
        }
301
        Token::Or => {
302
            if let (Token::Wire(s1), Token::Wire(s2)) = (lvalue1, lvalue2) {
4!
303
                Some(Command::Binary(
3✔
304
                    RValue::Var(s1.clone()),
3✔
305
                    Operation::Or,
3✔
306
                    RValue::Var(s2.clone()),
3✔
307
                ))
308
            } else {
309
                None
1✔
310
            }
311
        }
312
        Token::LeftShift => {
313
            if let (Token::Wire(ls1), Token::Signal(u1)) = (lvalue1, lvalue2) {
4!
314
                Some(Command::Binary(
3✔
315
                    RValue::Var(ls1.clone()),
3✔
316
                    Operation::LShift,
3✔
317
                    RValue::Const(u1.clone()),
3✔
318
                ))
319
            } else {
320
                None
1✔
321
            }
322
        }
323
        Token::RightShift => {
324
            if let (Token::Wire(rs1), Token::Signal(u1)) = (lvalue1, lvalue2) {
5!
325
                Some(Command::Binary(
3✔
326
                    RValue::Var(rs1.clone()),
3✔
327
                    Operation::RShift,
3✔
328
                    RValue::Const(u1.clone()),
3✔
329
                ))
330
            } else {
331
                None
2✔
332
            }
333
        }
334
        _ => None,
1✔
335
    }
336
}
22✔
337

338
impl fmt::Display for Expression {
339
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2✔
340
        match self {
2✔
341
            Expression::NOP => f.write_str("NOP"),
1✔
342
            Expression::Assign(_, _) => f.write_str("Assign"),
1✔
343
        }
344
    }
2✔
345
}
346

347
impl fmt::Display for LValue {
348
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2✔
349
        match self {
350
            LValue::Var(name) => f.write_str(name),
2✔
351
        }
352
    }
2✔
353
}
354

355
impl fmt::Display for RValue {
356
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16✔
357
        match self {
16✔
358
            RValue::Const(c) => f.write_fmt(format_args!("{}", c)),
7✔
359
            RValue::Var(v) => f.write_fmt(format_args!("{}", v)),
9✔
360
        }
361
    }
16✔
362
}
363

364
impl fmt::Display for Operation {
365
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6✔
366
        f.write_str(match self {
12!
367
            Operation::And => "&",
1✔
368
            Operation::Or => "|",
1✔
369
            Operation::LShift => "<<",
1✔
370
            Operation::RShift => ">>",
1✔
371
            Operation::Not => "!",
2✔
372
        })
373
    }
6✔
374
}
375

376
impl fmt::Display for Command {
377
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
12✔
378
        match self {
12!
379
            Command::Result(lvalue) => f.write_fmt(format_args!("{}", lvalue)),
6✔
380
            Command::Binary(lvalue1, op, lvalue2) => {
4✔
381
                f.write_fmt(format_args!("{} {} {}", lvalue1, op, lvalue2))
4✔
382
            }
383
            Command::Unary(op, lvalue) => f.write_fmt(format_args!("{} {}", op, lvalue)),
2✔
384
        }
385
    }
12✔
386
}
387

388
impl BobbyInterpreter {
389
    fn new() -> BobbyInterpreter {
7✔
390
        BobbyInterpreter {
7✔
391
            parser: Parser::new(String::from("")),
7✔
392
            tree: HashMap::new(),
7✔
393
            cache: HashMap::new(),
7✔
394
        }
395
    }
7✔
396

397
    fn interpret(&mut self, input: String) {
7✔
398
        self.parser = Parser::new(input);
7✔
399
        self.tree.clear();
7✔
400
        self.cache.clear();
7✔
401

402
        while let Some(e) = self.parser.next() {
31✔
403
            match e {
24!
404
                Expression::Assign(c, r) => {
24✔
405
                    let LValue::Var(var_name) = r;
24✔
406
                    self.tree.insert(var_name, c);
24✔
407
                }
408
                Expression::NOP => {}
409
            };
410
        }
411
    }
7✔
412

413
    #[allow(dead_code)]
414
    fn print_ast(&self) {
2✔
415
        println!("Print AST:");
2✔
416
        for i in self.tree.iter() {
12✔
417
            println!("{} = {}", i.0, i.1);
10✔
418
        }
419
    }
2✔
420

421
    fn evaluate(&mut self, wire: &String) -> Option<u16> {
37✔
422
        // Read from cache, if the value exists there
423
        if let Some(&cached_value) = self.cache.get(wire) {
37✔
424
            return Some(cached_value);
9✔
425
        }
426

427
        let next_command = self.tree.get(&wire.clone());
28✔
428
        if next_command.is_none() {
28✔
429
            eprintln!("Wire '{}' doesn't have a command", wire);
1✔
430
            return None;
1✔
431
        }
432

433
        let result = match next_command.unwrap().clone() {
27!
434
            Command::Result(lvalue) => match lvalue {
13✔
435
                RValue::Const(c) => Some(c.clone()),
12✔
436
                RValue::Var(w) => self.evaluate(&w),
1✔
437
            },
438
            Command::Unary(op, lvalue) => {
6✔
439
                // There is only one Unary operation, for more you can add "match"
440
                if let Operation::Not = op {
6!
441
                    match lvalue {
6!
442
                        RValue::Const(c) => Some(!c.clone()),
×
443
                        RValue::Var(w) => Some(!self.evaluate(&w).unwrap()),
6✔
444
                    }
445
                } else {
446
                    None
×
447
                }
448
            }
6!
449
            Command::Binary(l1, op, l2) => {
8✔
450
                let lvalue1 = match l1 {
8!
451
                    RValue::Const(c) => c.clone(),
×
452
                    RValue::Var(w) => self.evaluate(&w).unwrap(),
8✔
453
                };
454

455
                let lvalue2 = match l2 {
8✔
456
                    RValue::Const(c) => c.clone(),
2✔
457
                    RValue::Var(w) => self.evaluate(&w).unwrap(),
6✔
458
                };
459

460
                match op {
8!
461
                    Operation::And => Some(lvalue1 & lvalue2),
5✔
462
                    Operation::Or => Some(lvalue1 | lvalue2),
1✔
463
                    Operation::LShift => Some(lvalue1 << lvalue2),
1✔
464
                    Operation::RShift => Some(lvalue1 >> lvalue2),
1✔
465
                    _ => None,
×
466
                }
467
            }
468
        };
469

470
        if let Some(u) = result {
27!
471
            self.cache.insert(wire.clone(), u);
27✔
472
        }
473

474
        result
27✔
475
    }
37✔
476

477
    fn evaluate_override_signal(
2✔
478
        &mut self,
479
        wire: &String,
480
        new_wire: &String,
481
        new_value: u16,
482
    ) -> Option<u16> {
483
        self.cache.clear();
2✔
484
        self.tree.insert(
2✔
485
            (*new_wire).clone(),
2✔
486
            Command::Result(RValue::Const(new_value)),
2✔
487
        );
2✔
488

489
        self.evaluate(wire)
2✔
490
    }
2✔
491
}
492

493
#[cfg(test)]
494
mod tests {
495
    use super::*;
496
    use std::{cmp, fmt};
497

498
    impl fmt::Debug for NextToken {
499
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1✔
500
            f.debug_tuple("NextToken")
2✔
501
                .field(&self.0)
502
                .field(&self.1)
1✔
503
                .finish()
504
        }
1✔
505
    }
506

507
    impl fmt::Debug for RValue {
508
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2✔
509
            match self {
2✔
510
                RValue::Const(c) => f.write_fmt(format_args!("{}", c)),
1✔
511
                RValue::Var(v) => f.write_fmt(format_args!("{}", v)),
1✔
512
            }
513
        }
2✔
514
    }
515

516
    impl fmt::Debug for Expression {
517
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3✔
518
            match self {
3✔
519
                Expression::NOP => f.write_str("NOP"),
1✔
520
                Expression::Assign(command, rvalue) => {
2✔
521
                    f.write_fmt(format_args!("{} = {}", rvalue, command))
2✔
522
                }
523
            }
524
        }
3✔
525
    }
526

527
    impl cmp::PartialEq for RValue {
528
        fn eq(&self, other: &Self) -> bool {
11✔
529
            match (self, other) {
11!
530
                (RValue::Const(c1), RValue::Const(c2)) if c1 == c2 => true,
3!
531
                (RValue::Var(w1), RValue::Var(w2)) if w1 == w2 => true,
8!
532
                _ => false,
×
533
            }
534
        }
11✔
535
    }
536

537
    impl cmp::PartialEq for Expression {
538
        fn eq(&self, other: &Self) -> bool {
20✔
539
            match (self, other) {
20!
540
                (Expression::NOP, Expression::NOP) => true,
13✔
541
                (Expression::Assign(c1, r1), Expression::Assign(c2, r2))
7✔
542
                    if c1 == c2 && r1 == r2 =>
7!
543
                {
544
                    true
7✔
545
                }
7✔
546
                _ => false,
×
547
            }
548
        }
20✔
549
    }
550

551
    impl cmp::PartialEq for Command {
552
        fn eq(&self, other: &Self) -> bool {
7✔
553
            match (self, other) {
7!
554
                (Command::Result(l1), Command::Result(l2)) if l1 == l2 => true,
2!
555
                (Command::Binary(l11, op1, l12), Command::Binary(l21, op2, l22))
4✔
556
                    if l11 == l21 && op1 == op2 && l12 == l22 =>
4!
557
                {
558
                    true
4✔
559
                }
4✔
560
                (Command::Unary(op1, l1), Command::Unary(op2, l2)) if op1 == op2 && l1 == l2 => {
1!
561
                    true
1✔
562
                }
1✔
563
                _ => false,
×
564
            }
565
        }
7✔
566
    }
567

568
    impl cmp::PartialEq for NextToken {
569
        fn eq(&self, other: &Self) -> bool {
27✔
570
            self.0 == other.0 && self.1 == other.1
27!
571
        }
27✔
572
    }
573

574
    impl cmp::PartialEq for LValue {
575
        fn eq(&self, other: &Self) -> bool {
7✔
576
            match (self, other) {
7✔
577
                (LValue::Var(r1), LValue::Var(r2)) if r1 == r2 => true,
7!
578
                _ => false,
×
579
            }
580
        }
7✔
581
    }
582

583
    impl cmp::PartialEq for Operation {
584
        fn eq(&self, other: &Self) -> bool {
5✔
585
            match (self, other) {
5!
586
                (Operation::And, Operation::And) => true,
1✔
587
                (Operation::Or, Operation::Or) => true,
1✔
588
                (Operation::LShift, Operation::LShift) => true,
1✔
589
                (Operation::RShift, Operation::RShift) => true,
1✔
590
                (Operation::Not, Operation::Not) => true,
1✔
591
                _ => false,
×
592
            }
593
        }
5✔
594
    }
595

596
    impl cmp::PartialEq for Token {
597
        fn eq(&self, other: &Self) -> bool {
50✔
598
            match (self, other) {
50!
599
                (Token::Signal(x1), Token::Signal(x2)) if x1 == x2 => true,
7!
600
                (Token::Wire(s1), Token::Wire(s2)) if s1 == s2 => true,
23!
601
                (Token::And, Token::And) => true,
2✔
602
                (Token::Or, Token::Or) => true,
2✔
603
                (Token::LeftShift, Token::LeftShift) => true,
1✔
604
                (Token::RightShift, Token::RightShift) => true,
1✔
605
                (Token::Not, Token::Not) => true,
1✔
606
                (Token::Assign, Token::Assign) => true,
12✔
607
                (Token::EOF, Token::EOF) => true,
1✔
608
                _ => false,
×
609
            }
610
        }
50✔
611
    }
612

613
    #[test]
614
    fn test_get_token_assign() {
2✔
615
        let input = "123 -> x";
1✔
616
        assert_eq!(
1✔
617
            get_token(input, 0),
1!
618
            NextToken(Token::Signal(123), 3),
619
            "Unexpected Token"
620
        );
621
        assert_eq!(
1✔
622
            get_token(input, 3),
1!
623
            NextToken(Token::Assign, 6),
624
            "Unexpected Token"
625
        );
626
        assert_eq!(
1✔
627
            get_token(input, 6),
1✔
628
            NextToken(Token::Wire(String::from("x")), input.len()),
1!
629
            "Unexpected Token"
630
        );
631
    }
2✔
632

633
    #[test]
634
    fn test_get_token_and() {
2✔
635
        let input = "x AND y -> d";
1✔
636
        assert_eq!(
1✔
637
            get_token(input, 0),
1✔
638
            NextToken(Token::Wire(String::from("x")), 1),
1!
639
            "Unexpected Token"
640
        );
641
        assert_eq!(
1✔
642
            get_token(input, 1),
1!
643
            NextToken(Token::And, 5),
644
            "Unexpected Token"
645
        );
646
        assert_eq!(
1✔
647
            get_token(input, 5),
1✔
648
            NextToken(Token::Wire(String::from("y")), 7),
1!
649
            "Unexpected Token"
650
        );
651
        assert_eq!(
1✔
652
            get_token(input, 7),
1!
653
            NextToken(Token::Assign, 10),
654
            "Unexpected Token"
655
        );
656
        assert_eq!(
1✔
657
            get_token(input, 10),
1✔
658
            NextToken(Token::Wire(String::from("d")), input.len()),
1!
659
            "Unexpected Token"
660
        );
661
    }
2✔
662

663
    #[test]
664
    fn test_get_token_or() {
2✔
665
        let input = "x OR y -> e";
1✔
666
        assert_eq!(
1✔
667
            get_token(input, 0),
1✔
668
            NextToken(Token::Wire(String::from("x")), 1),
1!
669
            "Unexpected Token"
670
        );
671
        assert_eq!(
1✔
672
            get_token(input, 1),
1!
673
            NextToken(Token::Or, 4),
674
            "Unexpected Token"
675
        );
676
        assert_eq!(
1✔
677
            get_token(input, 4),
1✔
678
            NextToken(Token::Wire(String::from("y")), 6),
1!
679
            "Unexpected Token"
680
        );
681
        assert_eq!(
1✔
682
            get_token(input, 6),
1!
683
            NextToken(Token::Assign, 9),
684
            "Unexpected Token"
685
        );
686
        assert_eq!(
1✔
687
            get_token(input, 9),
1✔
688
            NextToken(Token::Wire(String::from("e")), input.len()),
1!
689
            "Unexpected Token"
690
        );
691
    }
2✔
692

693
    #[test]
694
    fn test_get_token_lshift() {
2✔
695
        let input = "x LSHIFT 2 -> f";
1✔
696
        assert_eq!(
1✔
697
            get_token(input, 0),
1✔
698
            NextToken(Token::Wire(String::from("x")), 1),
1!
699
            "Unexpected Token"
700
        );
701
        assert_eq!(
1✔
702
            get_token(input, 1),
1!
703
            NextToken(Token::LeftShift, 8),
704
            "Unexpected Token"
705
        );
706
        assert_eq!(
1✔
707
            get_token(input, 8),
1!
708
            NextToken(Token::Signal(2), 10),
709
            "Unexpected Token"
710
        );
711
        assert_eq!(
1✔
712
            get_token(input, 10),
1!
713
            NextToken(Token::Assign, 13),
714
            "Unexpected Token"
715
        );
716
        assert_eq!(
1✔
717
            get_token(input, 13),
1✔
718
            NextToken(Token::Wire(String::from("f")), input.len()),
1!
719
            "Unexpected Token"
720
        );
721
    }
2✔
722

723
    #[test]
724
    fn test_get_token_rshift() {
2✔
725
        let input = "y RSHIFT 2 -> g";
1✔
726
        assert_eq!(
1✔
727
            get_token(input, 0),
1✔
728
            NextToken(Token::Wire(String::from("y")), 1),
1!
729
            "Unexpected Token"
730
        );
731
        assert_eq!(
1✔
732
            get_token(input, 1),
1!
733
            NextToken(Token::RightShift, 8),
734
            "Unexpected Token"
735
        );
736
        assert_eq!(
1✔
737
            get_token(input, 8),
1!
738
            NextToken(Token::Signal(2), 10),
739
            "Unexpected Token"
740
        );
741
        assert_eq!(
1✔
742
            get_token(input, 10),
1!
743
            NextToken(Token::Assign, 13),
744
            "Unexpected Token"
745
        );
746
        assert_eq!(
1✔
747
            get_token(input, 13),
1✔
748
            NextToken(Token::Wire(String::from("g")), input.len()),
1!
749
            "Unexpected Token"
750
        );
751
    }
2✔
752

753
    #[test]
754
    fn test_get_token_not() {
2✔
755
        let input = "NOT x -> h";
1✔
756
        assert_eq!(
1✔
757
            get_token(input, 0),
1!
758
            NextToken(Token::Not, 3),
759
            "Unexpected Token"
760
        );
761
        assert_eq!(
1✔
762
            get_token(input, 3),
1✔
763
            NextToken(Token::Wire(String::from("x")), 5),
1!
764
            "Unexpected Token"
765
        );
766
        assert_eq!(
1✔
767
            get_token(input, 5),
1!
768
            NextToken(Token::Assign, 8),
769
            "Unexpected Token"
770
        );
771
        assert_eq!(
1✔
772
            get_token(input, 8),
1✔
773
            NextToken(Token::Wire(String::from("h")), input.len()),
1!
774
            "Unexpected Token"
775
        );
776
    }
2✔
777

778
    #[test]
779
    fn test_lexer() {
2✔
780
        let mut lexer = Lexer::new(String::from(
1✔
781
            "123 -> x\r\n456 -> y\r\nx AND y -> d\r\nx OR y -> e",
782
        ));
783
        assert_eq!(lexer.next_token(), Token::Signal(123), "Unexpected Token");
1!
784
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
785
        assert_eq!(
1✔
786
            lexer.next_token(),
1✔
787
            Token::Wire(String::from("x")),
1!
788
            "Unexpected Token"
789
        );
790

791
        assert_eq!(lexer.next_token(), Token::Signal(456), "Unexpected Token");
1!
792
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
793
        assert_eq!(
1✔
794
            lexer.next_token(),
1✔
795
            Token::Wire(String::from("y")),
1!
796
            "Unexpected Token"
797
        );
798

799
        assert_eq!(
1✔
800
            lexer.next_token(),
1✔
801
            Token::Wire(String::from("x")),
1!
802
            "Unexpected Token"
803
        );
804
        assert_eq!(lexer.next_token(), Token::And, "Unexpected Token");
1!
805
        assert_eq!(
1✔
806
            lexer.next_token(),
1✔
807
            Token::Wire(String::from("y")),
1!
808
            "Unexpected Token"
809
        );
810
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
811
        assert_eq!(
1✔
812
            lexer.next_token(),
1✔
813
            Token::Wire(String::from("d")),
1!
814
            "Unexpected Token"
815
        );
816

817
        assert_eq!(
1✔
818
            lexer.next_token(),
1✔
819
            Token::Wire(String::from("x")),
1!
820
            "Unexpected Token"
821
        );
822
        assert_eq!(lexer.next_token(), Token::Or, "Unexpected Token");
1!
823
        assert_eq!(
1✔
824
            lexer.next_token(),
1✔
825
            Token::Wire(String::from("y")),
1!
826
            "Unexpected Token"
827
        );
828
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
829
        assert_eq!(
1✔
830
            lexer.next_token(),
1✔
831
            Token::Wire(String::from("e")),
1!
832
            "Unexpected Token"
833
        );
834
    }
2✔
835

836
    #[test]
837
    fn test_parser() {
2✔
838
        let mut parser = Parser::new(String::from(
1✔
839
            "123 -> x
840
                                           456 -> y
841
                                           x AND y -> d
842
                                           x OR y -> e
843
                                           x LSHIFT 2 -> f
844
                                           y RSHIFT 2 -> g
845
                                           NOT x -> h
846
                                           NOT y -> i",
847
        ));
848
        match parser.next_operation() {
1!
849
            Expression::Assign(c, v) => {
1✔
850
                if let Command::Result(RValue::Const(u)) = c {
1!
851
                    assert_eq!(u, 123, "A wrong signal was parsed");
1!
852
                } else {
853
                    panic!("It wasn't parsed correctly");
×
854
                }
855
                let LValue::Var(s) = v;
1✔
856
                assert_eq!(s, "x", "A wrong wire was parsed");
1!
857
            }
1✔
858
            _ => panic!("Shouldn't happen"),
×
859
        };
860

861
        match parser.next_operation() {
1!
862
            Expression::Assign(c, v) => {
1✔
863
                if let Command::Result(RValue::Const(u)) = c {
1!
864
                    assert_eq!(u, 456, "A wrong signal was parsed");
1!
865
                } else {
866
                    panic!("It wasn't parsed correctly");
×
867
                }
868
                let LValue::Var(s) = v;
1✔
869
                assert_eq!(s, "y", "A wrong wire was parsed");
1!
870
            }
1✔
871
            _ => panic!("Shouldn't happen"),
×
872
        };
873

874
        match parser.next_operation() {
1!
875
            Expression::Assign(c, v) => {
1✔
876
                if let Command::Binary(RValue::Var(x), Operation::And, RValue::Var(y)) = c {
1!
877
                    assert_eq!(x, "x", "A wrong wire was parsed");
1!
878
                    assert_eq!(y, "y", "A wrong wire was parsed");
1!
879
                } else {
1✔
880
                    panic!("It wasn't parsed correctly");
×
881
                }
882
                let LValue::Var(s) = v;
1✔
883
                assert_eq!(s, "d", "A wrong wire was parsed");
1!
884
            }
1!
885
            _ => panic!("Shouldn't happen"),
×
886
        };
887

888
        match parser.next_operation() {
1!
889
            Expression::Assign(c, v) => {
1✔
890
                if let Command::Binary(RValue::Var(x), Operation::Or, RValue::Var(y)) = c {
1!
891
                    assert_eq!(x, "x", "A wrong wire was parsed");
1!
892
                    assert_eq!(y, "y", "A wrong wire was parsed");
1!
893
                } else {
1✔
894
                    panic!("It wasn't parsed correctly");
×
895
                }
896
                let LValue::Var(s) = v;
1✔
897
                assert_eq!(s, "e", "A wrong wire was parsed");
1!
898
            }
1!
899
            _ => panic!("Shouldn't happen"),
×
900
        };
901
    }
2✔
902

903
    #[test]
904
    fn test_bobby_interpreter() {
2✔
905
        let input = String::from(
1✔
906
            "123 -> x
907
                                           456 -> y
908
                                           x AND y -> d
909
                                           x OR y -> e
910
                                           x LSHIFT 2 -> f
911
                                           y RSHIFT 2 -> g
912
                                           NOT x -> h
913
                                           NOT y -> i",
914
        );
915
        let mut bobby = BobbyInterpreter::new();
1✔
916
        bobby.interpret(input);
1✔
917
        bobby.print_ast();
1✔
918
        let def = 0xffffu16;
1✔
919

920
        assert_eq!(
1✔
921
            bobby.evaluate(&String::from("x")).unwrap_or(def.clone()),
1!
922
            123,
923
            "Unexpected value X"
924
        );
925
        assert_eq!(
1✔
926
            bobby.evaluate(&String::from("y")).unwrap_or(def.clone()),
1!
927
            456,
928
            "Unexpected value Y"
929
        );
930
        assert_eq!(
1✔
931
            bobby.evaluate(&String::from("h")).unwrap_or(def.clone()),
1!
932
            65412,
933
            "Unexpected value H"
934
        );
935
        assert_eq!(
1✔
936
            bobby.evaluate(&String::from("i")).unwrap_or(def.clone()),
1!
937
            65079,
938
            "Unexpected value I"
939
        );
940
        assert_eq!(
1✔
941
            bobby.evaluate(&String::from("d")).unwrap_or(def.clone()),
1!
942
            72,
943
            "Unexpected value D"
944
        );
945
        assert_eq!(
1✔
946
            bobby.evaluate(&String::from("e")).unwrap_or(def.clone()),
1!
947
            507,
948
            "Unexpected value E"
949
        );
950
        assert_eq!(
1✔
951
            bobby.evaluate(&String::from("f")).unwrap_or(def.clone()),
1!
952
            492,
953
            "Unexpected value F"
954
        );
955
        assert_eq!(
1✔
956
            bobby.evaluate(&String::from("g")).unwrap_or(def.clone()),
1!
957
            114,
958
            "Unexpected value G"
959
        );
960
    }
2✔
961

962
    #[test]
963
    fn test_lexer_eof() {
2✔
964
        let mut lexer = Lexer::new(String::from(
1✔
965
            "123 -> x
966
                                           456 -> y",
967
        ));
968
        assert_eq!(lexer.next_token(), Token::Signal(123), "Unexpected Token");
1!
969
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
970
        assert_eq!(
1✔
971
            lexer.next_token(),
1✔
972
            Token::Wire(String::from("x")),
1!
973
            "Unexpected Token"
974
        );
975

976
        assert_eq!(lexer.next_token(), Token::Signal(456), "Unexpected Token");
1!
977
        assert_eq!(lexer.next_token(), Token::Assign, "Unexpected Token");
1!
978
        assert_eq!(
1✔
979
            lexer.next_token(),
1✔
980
            Token::Wire(String::from("y")),
1!
981
            "Unexpected Token"
982
        );
983

984
        assert_eq!(lexer.next_token(), Token::EOF, "Unexpected Token");
1!
985
    }
2✔
986

987
    #[test]
988
    fn test_parser_with_const() {
2✔
989
        let mut parser = Parser::new(String::from(
1✔
990
            "jp RSHIFT 5 -> js
991
        1 AND io -> ip
992
        eo LSHIFT 15 -> es",
993
        ));
994

995
        match parser.next_operation() {
1!
996
            Expression::Assign(c, v) => {
1✔
997
                if let Command::Binary(RValue::Var(x), Operation::RShift, RValue::Const(y)) = c {
1!
998
                    assert_eq!(x, "jp", "A wrong wire was parsed");
1!
999
                    assert_eq!(y, 5, "A wrong wire was parsed");
1!
1000
                } else {
1✔
1001
                    panic!("It wasn't parsed correctly");
×
1002
                }
1003
                let LValue::Var(s) = v;
1✔
1004
                assert_eq!(s, "js", "A wrong wire was parsed");
1!
1005
            }
1!
1006
            _ => panic!("Shouldn't happen"),
×
1007
        };
1008

1009
        match parser.next_operation() {
1!
1010
            Expression::Assign(c, v) => {
1✔
1011
                if let Command::Binary(RValue::Const(x), Operation::And, RValue::Var(y)) = c {
1!
1012
                    assert_eq!(x, 1, "A wrong wire was parsed");
1!
1013
                    assert_eq!(y, "io", "A wrong wire was parsed");
1!
1014
                } else {
1✔
1015
                    panic!("It wasn't parsed correctly");
×
1016
                }
1017
                let LValue::Var(s) = v;
1✔
1018
                assert_eq!(s, "ip", "A wrong wire was parsed");
1!
1019
            }
1!
1020
            _ => panic!("Shouldn't happen"),
×
1021
        };
1022

1023
        match parser.next_operation() {
1!
1024
            Expression::Assign(c, v) => {
1✔
1025
                if let Command::Binary(RValue::Var(x), Operation::LShift, RValue::Const(y)) = c {
1!
1026
                    assert_eq!(x, "eo", "A wrong wire was parsed");
1!
1027
                    assert_eq!(y, 15, "A wrong wire was parsed");
1!
1028
                } else {
1✔
1029
                    panic!("It wasn't parsed correctly");
×
1030
                }
1031
                let LValue::Var(s) = v;
1✔
1032
                assert_eq!(s, "es", "A wrong wire was parsed");
1!
1033
            }
1!
1034
            _ => panic!("Shouldn't happen"),
×
1035
        };
1036
    }
2✔
1037

1038
    #[test]
1039
    fn test_bobby_interpreter_empty() {
2✔
1040
        let input = String::from(
1✔
1041
            "123 -> x
1042
                                           456 -> y",
1043
        );
1044
        let mut bobby = BobbyInterpreter::new();
1✔
1045
        bobby.interpret(input);
1✔
1046
        bobby.print_ast();
1✔
1047
        let def = 0xffffu16;
1✔
1048

1049
        assert_eq!(
1✔
1050
            bobby.evaluate(&String::from("vest")).unwrap_or(def.clone()),
1!
1051
            0xffffu16,
1052
            "We shouldn't find any value"
1053
        );
1054
    }
2✔
1055

1056
    #[test]
1057
    fn test_display() {
2✔
1058
        assert_eq!(Token::Signal(23).to_string(), "23");
1!
1059
        assert_eq!(Token::Wire(String::from("Vest")).to_string(), "Vest");
1!
1060
        assert_eq!(Token::And.to_string(), "and");
1!
1061
        assert_eq!(Token::Or.to_string(), "or");
1!
1062
        assert_eq!(Token::LeftShift.to_string(), "lshift");
1!
1063
        assert_eq!(Token::RightShift.to_string(), "rshift");
1!
1064
        assert_eq!(Token::Not.to_string(), "not");
1!
1065
        assert_eq!(Token::Assign.to_string(), "->");
1!
1066
        assert_eq!(Token::EOF.to_string(), "eof");
1!
1067

1068
        assert_eq!(
1✔
1069
            Expression::Assign(
1✔
1070
                Command::Result(RValue::Const(23)),
1✔
1071
                LValue::Var(String::from("abc"))
1!
1072
            )
1073
            .to_string(),
1074
            "Assign"
1075
        );
1076
        assert_eq!(Expression::NOP.to_string(), "NOP");
1!
1077
    }
2✔
1078

1079
    #[test]
1080
    fn test_debug() {
2✔
1081
        assert_eq!(
1✔
1082
            format!("{:?}", NextToken(Token::Signal(23), 12)),
1!
1083
            "NextToken(Signal(23), 12)"
1084
        );
1085

1086
        assert_eq!(format!("{:?}", RValue::Var(String::from("a"))), "a");
1!
1087
        assert_eq!(format!("{:?}", RValue::Const(23)), "23");
1!
1088

1089
        assert_eq!(
1✔
1090
            format!(
1✔
1091
                "{:?}",
1092
                Expression::Assign(
1✔
1093
                    Command::Result(RValue::Const(23)),
1✔
1094
                    LValue::Var(String::from("abc"))
1!
1095
                )
1096
            ),
1097
            "abc = 23"
1098
        );
1099
        assert_eq!(
1✔
1100
            format!(
1✔
1101
                "{:?}",
1102
                Expression::Assign(
1✔
1103
                    Command::Result(RValue::Var(String::from("a"))),
1✔
1104
                    LValue::Var(String::from("abc"))
1!
1105
                )
1106
            ),
1107
            "abc = a"
1108
        );
1109

1110
        assert_eq!(format!("{:?}", Expression::NOP), "NOP");
1!
1111
    }
2✔
1112

1113
    #[test]
1114
    fn test_parser_errors() {
2✔
1115
        let mut parser = Parser::new(String::from("2 -> x"));
1✔
1116
        let assign = parser.next_operation();
1✔
1117
        assert_eq!(
1✔
1118
            assign,
1119
            Expression::Assign(
1✔
1120
                Command::Result(RValue::Const(2)),
1✔
1121
                LValue::Var(String::from("x"))
1!
1122
            )
1123
        );
1124

1125
        let mut parser = Parser::new(String::from("x RSHIFT 2 -> y"));
1✔
1126
        let rshift_good = parser.next_operation();
1✔
1127
        assert_eq!(
1✔
1128
            rshift_good,
1129
            Expression::Assign(
1✔
1130
                Command::Binary(
1✔
1131
                    RValue::Var(String::from("x")),
1✔
1132
                    Operation::RShift,
1133
                    RValue::Const(2)
1✔
1134
                ),
1135
                LValue::Var(String::from("y"))
1!
1136
            )
1137
        );
1138

1139
        let mut parser = Parser::new(String::from("x LSHIFT 3 -> ly"));
1✔
1140
        let lshift_good = parser.next_operation();
1✔
1141
        assert_eq!(
1✔
1142
            lshift_good,
1143
            Expression::Assign(
1✔
1144
                Command::Binary(
1✔
1145
                    RValue::Var(String::from("x")),
1✔
1146
                    Operation::LShift,
1147
                    RValue::Const(3)
1✔
1148
                ),
1149
                LValue::Var(String::from("ly"))
1!
1150
            )
1151
        );
1152

1153
        let mut parser = Parser::new(String::from("x AND y -> ay"));
1✔
1154
        let and_good = parser.next_operation();
1✔
1155
        assert_eq!(
1✔
1156
            and_good,
1157
            Expression::Assign(
1✔
1158
                Command::Binary(
1✔
1159
                    RValue::Var(String::from("x")),
1✔
1160
                    Operation::And,
1✔
1161
                    RValue::Var(String::from("y"))
1✔
1162
                ),
1163
                LValue::Var(String::from("ay"))
1!
1164
            )
1165
        );
1166

1167
        let mut parser = Parser::new(String::from("y OR x -> oy"));
1✔
1168
        let or_good = parser.next_operation();
1✔
1169
        assert_eq!(
1✔
1170
            or_good,
1171
            Expression::Assign(
1✔
1172
                Command::Binary(
1✔
1173
                    RValue::Var(String::from("y")),
1✔
1174
                    Operation::Or,
1✔
1175
                    RValue::Var(String::from("x"))
1✔
1176
                ),
1177
                LValue::Var(String::from("oy"))
1!
1178
            )
1179
        );
1180

1181
        let mut parser = Parser::new(String::from("NOT y -> ny"));
1✔
1182
        let not_good = parser.next_operation();
1✔
1183
        assert_eq!(
1✔
1184
            not_good,
1185
            Expression::Assign(
1✔
1186
                Command::Unary(Operation::Not, RValue::Var(String::from("y"))),
1✔
1187
                LValue::Var(String::from("ny"))
1!
1188
            )
1189
        );
1190

1191
        let mut parser = Parser::new(String::from("2 LSHIFT 1 -> z"));
1✔
1192
        let lshift = parser.next_operation();
1✔
1193
        assert_eq!(lshift, Expression::NOP); // constants are not supported
1!
1194

1195
        let mut parser = Parser::new(String::from("3 AND 1 -> w"));
1✔
1196
        let and = parser.next_operation();
1✔
1197
        assert_eq!(and, Expression::NOP); // constants are not supported
1!
1198

1199
        let mut parser = Parser::new(String::from("3 OR 1 -> v"));
1✔
1200
        let or = parser.next_operation();
1✔
1201
        assert_eq!(or, Expression::NOP); // constants are not supported
1!
1202

1203
        let mut parser = Parser::new(String::from("4 RSHIFT 2 -> u"));
1✔
1204
        let rshift_bad = parser.next_operation();
1✔
1205
        assert_eq!(rshift_bad, Expression::NOP); // constants are not supported
1!
1206

1207
        let mut parser = Parser::new(String::from("x -> t"));
1✔
1208
        let assign_bad = parser.next_operation();
1✔
1209
        assert_eq!(
1✔
1210
            assign_bad,
1211
            Expression::Assign(
1✔
1212
                Command::Result(RValue::Var(String::from("x"))),
1✔
1213
                LValue::Var(String::from("t"))
1!
1214
            )
1215
        );
1216

1217
        let mut parser = Parser::new(String::from("8 RSHIFT x -> t"));
1✔
1218
        let rshift_x = parser.next_operation();
1✔
1219
        assert_eq!(rshift_x, Expression::NOP); // constants are not supported
1!
1220

1221
        let mut parser = Parser::new(String::from("2 RSHIFT -> s"));
1✔
1222
        let rshift_s = parser.next_operation();
1✔
1223
        assert_eq!(rshift_s, Expression::NOP);
1!
1224

1225
        let mut parser = Parser::new(String::from("RSHIFT -> r"));
1✔
1226
        let rshift_empty = parser.next_operation();
1✔
1227
        assert_eq!(rshift_empty, Expression::NOP);
1!
1228

1229
        let mut parser = Parser::new(String::from("RSHIFT AND OR LSHIFT -> q"));
1✔
1230
        let token_mess = parser.next_operation();
1✔
1231
        assert_eq!(token_mess, Expression::NOP);
1!
1232

1233
        let mut parser = Parser::new(String::from("2 NOT -> p"));
1✔
1234
        let not = parser.next_operation();
1✔
1235
        assert_eq!(not, Expression::NOP);
1!
1236

1237
        let mut parser = Parser::new(String::from("2 NOT NOT -> p"));
1✔
1238
        let double_not = parser.next_operation();
1✔
1239
        assert_eq!(double_not, Expression::NOP);
1!
1240

1241
        let mut parser = Parser::new(String::from("2 -> 2"));
1✔
1242
        let lvalue = parser.next_operation();
1✔
1243
        assert_eq!(lvalue, Expression::NOP);
1!
1244

1245
        let mut parser = Parser::new(String::from("-> x"));
1✔
1246
        let empty = parser.next_operation();
1✔
1247
        assert_eq!(empty, Expression::NOP);
1!
1248

1249
        let nop = parser.next_operation();
1✔
1250
        assert_eq!(nop, Expression::NOP);
1!
1251
        assert!(!parser.parsing, "Parsing is not stopped");
1!
1252
    }
2✔
1253

1254
    #[test]
1255
    fn test_interpreter() {
2✔
1256
        let mut bobby = BobbyInterpreter::new();
1✔
1257
        bobby.interpret(String::from(
1✔
1258
            r#"NOT a -> b
1259
        b AND d -> e
1260
        1 -> a
1261
        a -> d"#,
1262
        ));
1263
        let answer = bobby.evaluate(&String::from("e"));
1✔
1264
        assert_eq!(answer.unwrap(), 0);
1!
1265
    }
2✔
1266

1267
    #[test]
1268
    fn test_answers() {
2✔
1269
        const INPUT: &str = r#"1 -> b
1270
        b AND d -> e
1271
        NOT e -> a
1272
        3 -> d"#;
1273
        assert_eq!(count_input_a(INPUT), 65534);
1!
1274
        assert_eq!(count_input_a_override(INPUT), 65533);
1!
1275
    }
2✔
1276
}
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

© 2025 Coveralls, Inc