Skip to content

Commit e75a39d

Browse files
committed
Add unit tests for parser and lexer
Expand test coverage for the parser and lexer using existing patterns: test_parser! macro assertions for AST s-expressions and token-slice comparisons for the lexer. Closes: #43
1 parent 2fc4df7 commit e75a39d

2 files changed

Lines changed: 510 additions & 0 deletions

File tree

lexer/src/tests.rs

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,286 @@ fn lexer_test_unicode_escape_eight_digits() {
355355
&[Token::String(b"2".into())]
356356
);
357357
}
358+
359+
#[test]
360+
fn lexer_test_operators() {
361+
let arena = Bump::new();
362+
let str = b"~ !~ | |& >> ** **= ^= += -= *= %= == != <= >= < > && || !";
363+
assert_eq!(
364+
&lex(str, &arena, false, false),
365+
&[
366+
Token::Matching,
367+
Token::NotMatching,
368+
Token::Pipe,
369+
Token::DoublePipe,
370+
Token::AppendPipe,
371+
Token::Circumflex,
372+
Token::CaretAssign,
373+
Token::CaretAssign,
374+
Token::PlusAssign,
375+
Token::MinusAssign,
376+
Token::StarAssign,
377+
Token::PercentAssign,
378+
Token::EqualTo,
379+
Token::NotEqualTo,
380+
Token::LesserOrEqualThan,
381+
Token::GreaterOrEqualThan,
382+
Token::LesserThan,
383+
Token::GreaterThan,
384+
Token::BooleanAnd,
385+
Token::BooleanOr,
386+
Token::Negation,
387+
]
388+
);
389+
}
390+
391+
#[test]
392+
fn lexer_test_slash_assign() {
393+
let arena = Bump::new();
394+
assert_eq!(
395+
&lex(b"a/=1", &arena, false, false),
396+
&[
397+
Token::Identifier(Identifier { namespace: None, literal: "a" }),
398+
Token::SlashAssign,
399+
Token::SmallInt(1),
400+
]
401+
);
402+
}
403+
404+
#[test]
405+
fn lexer_test_control_flow_keywords() {
406+
let arena = Bump::new();
407+
let str = b"switch case default getline printf next nextfile exit return continue break";
408+
assert_eq!(
409+
&lex(str, &arena, false, false),
410+
&[
411+
Token::Switch,
412+
Token::Case,
413+
Token::Default,
414+
Token::Getline,
415+
Token::Printf,
416+
Token::Next,
417+
Token::NextFile,
418+
Token::Exit,
419+
Token::Return,
420+
Token::Continue,
421+
Token::Break,
422+
]
423+
);
424+
}
425+
426+
#[test]
427+
fn lexer_test_builtin_variables() {
428+
let arena = Bump::new();
429+
let str =
430+
b"NR NF FS RS OFS ORS FILENAME ARGC ARGV SUBSEP FNR ARGIND OFMT RSTART RLENGTH ENVIRON";
431+
assert_eq!(
432+
&lex(str, &arena, false, false),
433+
&[
434+
Token::NrVariable,
435+
Token::NfVariable,
436+
Token::FsVariable,
437+
Token::RsVariable,
438+
Token::OfsVariable,
439+
Token::OrsVariable,
440+
Token::FilenameVariable,
441+
Token::ArgcVariable,
442+
Token::ArgvVariable,
443+
Token::SubsepVariable,
444+
Token::FnrVariable,
445+
Token::ArgindVariable,
446+
Token::OfmtVariable,
447+
Token::RstartVariable,
448+
Token::RlengthVariable,
449+
Token::EnvironVariable,
450+
]
451+
);
452+
}
453+
454+
#[test]
455+
fn lexer_test_typed_regex() {
456+
let arena = Bump::new();
457+
assert_eq!(
458+
&lex(b"@/pat/", &arena, false, false),
459+
&[Token::TypedRegex(b"pat".into())]
460+
);
461+
}
462+
463+
#[test]
464+
fn lexer_test_comments() {
465+
let arena = Bump::new();
466+
let str = b"print 1 # comment\nprint 2";
467+
assert_eq!(
468+
&lex(str, &arena, false, false),
469+
&[
470+
Token::Print,
471+
Token::SmallInt(1),
472+
Token::Newline,
473+
Token::Print,
474+
Token::SmallInt(2),
475+
]
476+
);
477+
}
478+
479+
#[test]
480+
fn lexer_test_indirect_call() {
481+
let arena = Bump::new();
482+
assert_eq!(
483+
&lex(b"@foo @ns::bar", &arena, false, false),
484+
&[
485+
Token::IndirectCall(Identifier { namespace: None, literal: "foo" }),
486+
Token::IndirectCall(Identifier { namespace: Some("ns"), literal: "bar" }),
487+
]
488+
);
489+
}
490+
491+
#[test]
492+
#[should_panic]
493+
fn lexer_test_indirect_call_posix() {
494+
let arena = Bump::new();
495+
lex(b"@foo", &arena, true, false);
496+
}
497+
498+
#[test]
499+
fn lexer_test_concurrent_directive() {
500+
let arena = Bump::new();
501+
assert_eq!(
502+
&lex(b"@concurrent", &arena, false, false),
503+
&[Token::ConcurrentDirective]
504+
);
505+
}
506+
507+
#[test]
508+
fn lexer_test_load_and_namespace_directives() {
509+
let arena = Bump::new();
510+
assert_eq!(
511+
&lex(br#"@load "lib.so" @namespace "ns""#, &arena, false, false),
512+
&[
513+
Token::LoadDirective,
514+
Token::String(b"lib.so".into()),
515+
Token::NamespaceDirective,
516+
Token::String(b"ns".into()),
517+
]
518+
);
519+
}
520+
521+
#[test]
522+
fn lexer_test_regex_literals() {
523+
let arena = Bump::new();
524+
assert_eq!(
525+
&lex(b"/abc/", &arena, false, false),
526+
&[Token::Regex(b"abc".into())]
527+
);
528+
assert_eq!(
529+
&lex(b"/a\\/b/", &arena, false, false),
530+
&[Token::Regex(b"a/b".into())]
531+
);
532+
assert_eq!(
533+
&lex(b"x~/dot+/", &arena, false, false),
534+
&[
535+
Token::Identifier(Identifier { namespace: None, literal: "x" }),
536+
Token::Matching,
537+
Token::Regex(b"dot+".into()),
538+
]
539+
);
540+
}
541+
542+
#[test]
543+
fn lexer_test_switch_snippet() {
544+
let arena = Bump::new();
545+
let str = br#"switch (x) { case 1: print; default: break }"#;
546+
assert_eq!(
547+
&lex(str, &arena, false, false),
548+
&[
549+
Token::Switch,
550+
Token::OpenParent,
551+
Token::Identifier(Identifier { namespace: None, literal: "x" }),
552+
Token::ClosedParent,
553+
Token::OpenBrace,
554+
Token::Case,
555+
Token::SmallInt(1),
556+
Token::Colon,
557+
Token::Print,
558+
Token::Semicolon,
559+
Token::Default,
560+
Token::Colon,
561+
Token::Break,
562+
Token::ClosedBrace,
563+
]
564+
);
565+
}
566+
567+
#[test]
568+
fn lexer_test_getline_redirection() {
569+
let arena = Bump::new();
570+
let str = br#"getline getline x < "f" "cmd" | getline "cmd" |& getline"#;
571+
assert_eq!(
572+
&lex(str, &arena, false, false),
573+
&[
574+
Token::Getline,
575+
Token::Getline,
576+
Token::Identifier(Identifier { namespace: None, literal: "x" }),
577+
Token::LesserThan,
578+
Token::String(b"f".into()),
579+
Token::String(b"cmd".into()),
580+
Token::Pipe,
581+
Token::Getline,
582+
Token::String(b"cmd".into()),
583+
Token::DoublePipe,
584+
Token::Getline,
585+
]
586+
);
587+
}
588+
589+
#[test]
590+
fn lexer_test_print_redirection() {
591+
let arena = Bump::new();
592+
let str = br#"print > "out" print >> "out" print | "cmd" print |& "cmd""#;
593+
assert_eq!(
594+
&lex(str, &arena, false, false),
595+
&[
596+
Token::Print,
597+
Token::GreaterThan,
598+
Token::String(b"out".into()),
599+
Token::Print,
600+
Token::AppendPipe,
601+
Token::String(b"out".into()),
602+
Token::Print,
603+
Token::Pipe,
604+
Token::String(b"cmd".into()),
605+
Token::Print,
606+
Token::DoublePipe,
607+
Token::String(b"cmd".into()),
608+
]
609+
);
610+
}
611+
612+
#[test]
613+
fn lexer_test_func_keyword() {
614+
let arena = Bump::new();
615+
assert_eq!(
616+
&lex(b"func function", &arena, false, false),
617+
&[Token::Function, Token::Function]
618+
);
619+
}
620+
621+
#[test]
622+
fn lexer_test_func_keyword_posix() {
623+
let arena = Bump::new();
624+
assert_eq!(
625+
&lex(b"func", &arena, true, false),
626+
&[Token::Identifier(Identifier {
627+
namespace: None,
628+
literal: "func"
629+
})]
630+
);
631+
}
632+
633+
#[test]
634+
fn lexer_test_backslash_escape_in_string() {
635+
let arena = Bump::new();
636+
assert_eq!(
637+
&lex(b"\"\\n\\t\\\\\"", &arena, false, false),
638+
&[Token::String(b"\n\t\\".into())]
639+
);
640+
}

0 commit comments

Comments
 (0)