/// parser_validation.rs /// /// Simple tests for the validation phase use super::*; #[test] fn test_correct_struct_instance() { Tester::new_single_source_expect_ok( "single field", " struct Foo { s32 a } func bar(s32 arg) -> Foo { return Foo{ a: arg }; } " ); Tester::new_single_source_expect_ok( "multiple fields", " struct Foo { s32 a, s32 b } func bar(s32 arg) -> Foo { return Foo{ a: arg, b: arg }; } " ); Tester::new_single_source_expect_ok( "single field, explicit polymorph", " struct Foo{ T field } func bar(s32 arg) -> Foo { return Foo{ field: arg }; } " ); Tester::new_single_source_expect_ok( "single field, implicit polymorph", " struct Foo{ T field } func bar(s32 arg) -> s32 { auto thingo = Foo{ field: arg }; return arg; } " ); Tester::new_single_source_expect_ok( "multiple fields, same explicit polymorph", " struct Pair{ T1 first, T2 second } func bar(s32 arg) -> s32 { auto qux = Pair{ first: arg, second: arg }; return arg; } " ); Tester::new_single_source_expect_ok( "multiple fields, same implicit polymorph", " struct Pair{ T1 first, T2 second } func bar(s32 arg) -> s32 { auto wup = Pair{ first: arg, second: arg }; return arg; } " ); Tester::new_single_source_expect_ok( "multiple fields, different explicit polymorph", " struct Pair{ T1 first, T2 second } func bar(s32 arg1, s8 arg2) -> s32 { auto shoo = Pair{ first: arg1, second: arg2 }; return arg1; } " ); Tester::new_single_source_expect_ok( "multiple fields, different implicit polymorph", " struct Pair{ T1 first, T2 second } func bar(s32 arg1, s8 arg2) -> s32 { auto shrubbery = Pair{ first: arg1, second: arg2 }; return arg1; } " ); } #[test] fn test_incorrect_struct_instance() { Tester::new_single_source_expect_err( "reused field in definition", "struct Foo{ s32 a, s8 a }" ).error(|e| { e .assert_num(2) .assert_occurs_at(0, "a }") .assert_msg_has(0, "defined more than once") .assert_occurs_at(1, "a, ") .assert_msg_has(1, "other struct field"); }); Tester::new_single_source_expect_err( "reused field in instance", " struct Foo{ s32 a, s32 b } func bar() -> s32 { auto foo = Foo{ a: 5, a: 3 }; return 0; } " ).error(|e| { e .assert_occurs_at(0, "a: 3") .assert_msg_has(0, "field is specified more than once"); }); Tester::new_single_source_expect_err( "missing field", " struct Foo { s32 a, s32 b } func bar() -> s32 { auto foo = Foo{ a: 2 }; return 0; } " ).error(|e| { e .assert_occurs_at(0, "Foo{") .assert_msg_has(0, "'b' is missing"); }); Tester::new_single_source_expect_err( "missing fields", " struct Foo { s32 a, s32 b, s32 c } func bar() -> s32 { auto foo = Foo{ a: 2 }; return 0; } " ).error(|e| { e .assert_occurs_at(0, "Foo{") .assert_msg_has(0, "[b, c] are missing"); }); } #[test] fn test_correct_enum_instance() { Tester::new_single_source_expect_ok( "single variant", " enum Foo { A } func bar() -> Foo { return Foo::A; } " ); Tester::new_single_source_expect_ok( "multiple variants", " enum Foo { A=15, B = 0xF } func bar() -> Foo { auto a = Foo::A; return Foo::B; } " ); Tester::new_single_source_expect_ok( "explicit single polymorph", " enum Foo{ A } func bar() -> Foo { return Foo::A; } " ); Tester::new_single_source_expect_ok( "explicit multi-polymorph", " enum Foo{ A, B } func bar() -> Foo { return Foo::B; } " ); } #[test] fn test_incorrect_enum_instance() { Tester::new_single_source_expect_err( "variant name reuse", " enum Foo { A, A } func bar() -> Foo { return Foo::A; } " ).error(|e| { e .assert_num(2) .assert_occurs_at(0, "A }") .assert_msg_has(0, "defined more than once") .assert_occurs_at(1, "A, ") .assert_msg_has(1, "other enum variant is defined here"); }); Tester::new_single_source_expect_err( "undefined variant", " enum Foo { A } func bar() -> Foo { return Foo::B; } " ).error(|e| { e .assert_num(1) .assert_msg_has(0, "variant 'B' does not exist on the enum 'Foo'"); }); } #[test] fn test_correct_union_instance() { Tester::new_single_source_expect_ok( "single tag", " union Foo { A } func bar() -> Foo { return Foo::A; } " ); Tester::new_single_source_expect_ok( "multiple tags", " union Foo { A, B } func bar() -> Foo { return Foo::B; } " ); Tester::new_single_source_expect_ok( "single embedded", " union Foo { A(s32) } func bar() -> Foo { return Foo::A(5); } " ); Tester::new_single_source_expect_ok( "multiple embedded", " union Foo { A(s32), B(s8) } func bar() -> Foo { return Foo::B(2); } " ); Tester::new_single_source_expect_ok( "multiple values in embedded", " union Foo { A(s32, s8) } func bar() -> Foo { return Foo::A(0, 2); } " ); Tester::new_single_source_expect_ok( "mixed tag/embedded", " union OptionInt { None, Some(s32) } func bar() -> OptionInt { return OptionInt::Some(3); } " ); Tester::new_single_source_expect_ok( "single polymorphic var", " union Option { None, Some(T) } func bar() -> Option { return Option::Some(3); }" ); Tester::new_single_source_expect_ok( "multiple polymorphic vars", " union Result { Ok(T), Err(E), } func bar() -> Result { return Result::Ok(3); } " ); Tester::new_single_source_expect_ok( "multiple polymorphic in one variant", " union MaybePair{ None, Some(T1, T2) } func bar() -> MaybePair { return MaybePair::Some(1, 2); } " ); } #[test] fn test_incorrect_union_instance() { Tester::new_single_source_expect_err( "tag-variant name reuse", " union Foo{ A, A } " ).error(|e| { e .assert_num(2) .assert_occurs_at(0, "A }") .assert_msg_has(0, "union variant is defined more than once") .assert_occurs_at(1, "A, ") .assert_msg_has(1, "other union variant"); }); Tester::new_single_source_expect_err( "embedded-variant name reuse", " union Foo{ A(s32), A(s8) } " ).error(|e| { e .assert_num(2) .assert_occurs_at(0, "A(s8)") .assert_msg_has(0, "union variant is defined more than once") .assert_occurs_at(1, "A(s32)") .assert_msg_has(1, "other union variant"); }); Tester::new_single_source_expect_err( "undefined variant", " union Silly{ Thing(s8) } func bar() -> Silly { return Silly::Undefined(5); } " ).error(|e| { e .assert_msg_has(0, "variant 'Undefined' does not exist on the union 'Silly'"); }); Tester::new_single_source_expect_err( "using tag instead of embedded", " union Foo{ A(s32) } func bar() -> Foo { return Foo::A; } " ).error(|e| { e .assert_msg_has(0, "variant 'A' of union 'Foo' expects 1 embedded values, but 0 were"); }); Tester::new_single_source_expect_err( "using embedded instead of tag", " union Foo{ A } func bar() -> Foo { return Foo::A(3); } " ).error(|e| { e .assert_msg_has(0, "The variant 'A' of union 'Foo' expects 0"); }); Tester::new_single_source_expect_err( "wrong embedded value", " union Foo{ A(s32) } func bar() -> Foo { return Foo::A(false); } " ).error(|e| { e .assert_occurs_at(0, "Foo::A") .assert_msg_has(0, "failed to fully resolve") .assert_occurs_at(1, "false") .assert_msg_has(1, "has been resolved to 's32'") .assert_msg_has(1, "has been resolved to 'bool'"); }); } #[test] fn test_correct_tuple_members() { // Tuples with zero members Tester::new_single_source_expect_ok( "single zero-tuple", "struct Foo{ () bar }" ).for_struct("Foo", |s| { s .for_field("bar", |f| { f.assert_parser_type("()"); }) .assert_size_alignment("Foo", 0, 1); }); Tester::new_single_source_expect_ok( "triple zero-tuple", "struct Foo{ () bar, () baz, () qux }" ).for_struct("Foo", |s| { s .assert_size_alignment("Foo", 0, 1); }); // Tuples with one member (which are elided, because due to ambiguity // between a one-tuple literal and a parenthesized expression, we're not // going to be able to construct one-tuples). Tester::new_single_source_expect_ok( "single elided one-tuple", "struct Foo{ (u32) bar }" ).for_struct("Foo", |s| { s .for_field("bar", |f| { f.assert_parser_type("u32"); }) .assert_size_alignment("Foo", 4, 4); }); Tester::new_single_source_expect_ok( "triple elided one-tuple", "struct Foo{ (u8) bar, (u16) baz, (u32) qux }" ).for_struct("Foo", |s| { s .assert_size_alignment("Foo", 8, 4); }); // Tuples with three members Tester::new_single_source_expect_ok( "single three-tuple", "struct Foo{ (u8, u16, u32) bar }" ).for_struct("Foo", |s| { s .for_field("bar", |f| { f.assert_parser_type("(u8,u16,u32)"); }) .assert_size_alignment("Foo", 8, 4); }); Tester::new_single_source_expect_ok( "double three-tuple", "struct Foo{ (u8,u16,u32,) bar, (s8,s16,s32,) baz }" ).for_struct("Foo", |s| { s .for_field("bar", |f| { f.assert_parser_type("(u8,u16,u32)"); }) .for_field("baz", |f| { f.assert_parser_type("(s8,s16,s32)"); }) .assert_size_alignment("Foo", 16, 4); }); } #[test] fn test_correct_tuple_polymorph_args() { todo!("write"); } #[test] fn test_incorrect_tuple_polymorph_args() { todo!("write"); } #[test] fn test_polymorph_array_types() { Tester::new_single_source_expect_ok( "array of polymorph in struct", " struct Foo { T[] hello } struct Bar { Foo[] world } " ).for_struct("Bar", |s| { s .for_field("world", |f| { f.assert_parser_type("Foo[]"); }); }); Tester::new_single_source_expect_ok( "array of port in struct", " struct Bar { in[] inputs } " ).for_struct("Bar", |s| { s .for_field("inputs", |f| { f.assert_parser_type("in[]"); }); }); }