def test_duplicate_constants_raise_syntax_error(): with assert_raises(SymbolRedefinition): _build_node_tree("""namespace a{ const i8 foo = 17; const u16 foo = 0x42; } """)
def test_duplicate_structures_raise_syntax_error(): with assert_raises(SymbolRedefinition): _build_node_tree("""namespace a{ struct Foo { f : u8 : 2; } struct Foo { d : u32 : 32; } } """)
def test_signed_enum_value_in_unsigned_enum(): with assert_raises(InvalidSignError): _build_node_tree(""" namespace n { enum A : u16 { VALUE_1 = -1 } } """)
def test_not_enough_bits_for_enum_value(): with assert_raises(InvalidEnumValueError): _build_node_tree(""" namespace n { enum A : u8 { VALUE_1 = 256 } } """)
def test_exceeding_field_width_results_in_an_error(): with assert_raises(InvalidWidthError): _build_node_tree(""" namespace n { struct A { f : u8 : 9; } } """)
def test_duplicate_enum_value(): with assert_raises(DuplicateEnumValueError): _build_node_tree(""" namespace n { enum A : u16 { VALUE_1 = 1, VALUE_2 = 0, VALUE_3 } } """)
def test_multiple_archives_can_be_defined(): tree = _build_node_tree("""namespace foo { struct S { x : u64 : 64; } archive A { resource1 : vector< S >; } struct F { x : u64 : 64; } archive B { resource0 : vector< F >; resource1 : vector< S >; } } """) assert_equal( { ".foo", ".foo.S", ".foo.S.x", ".foo.A", ".foo.A.resource1", ".foo.A.resource1.@S", ".foo.F", ".foo.F.x", ".foo.B", ".foo.B.resource0", ".foo.B.resource0.@F", ".foo.B.resource1", ".foo.B.resource1.@S" }, tree.symbols())
def test_empty_schema_with_nested_namespace_parsed_correctly(): tree = _build_node_tree("namespace foo.bar.baz{}") for path, name in [(".foo", "foo"), (".foo.bar", "bar"), (".foo.bar.baz", "baz")]: node = tree.find(path) assert_is_instance(node, nodes.Namespace) assert_equal(name, node.name) assert_equal(path, node.path)
def test_archive_member_schemas_references_dependent_types(): root = _build_node_tree("""namespace n{ struct T { t : u8 : 7; } struct U { u : u8 : 7; } struct V { v : u8 : 7; } archive A { a : T; b : vector< V >; c : multivector< 17, U, V >; } } """) resolve_references(root) assert_equal( SyntaxTree.schema(root.find(".n.A.a")), "namespace n { struct T { t : u8 : 7; } }\n" "namespace n { a : T; }") assert_equal( SyntaxTree.schema(root.find(".n.A.b")), "namespace n { struct V { v : u8 : 7; } }\n" "namespace n { b : vector< V >; }") assert_equal( SyntaxTree.schema(root.find(".n.A.c")), "namespace n { struct U { u : u8 : 7; } }\n" "namespace n { struct V { v : u8 : 7; } }\n" "namespace n { c : multivector< 17, U, V >; }")
def test_archive_schema_preserves_references(): root = _build_node_tree("""namespace foo{ /// T Comment struct T { /* fieldA comment*/ fieldA : u8 : 7; } /** * Archive comment */ archive A { /// resource comment resourceA : T; } } """) resolve_references(root) expected = """namespace foo { struct T { fieldA : u8 : 7; } } namespace foo { archive A { resourceA : .foo.T; } } """ assert_equal(SyntaxTree.schema(root.find(".foo.A")), expected)
def test_schemas_are_not_duplicated_if_several_type_references_occur(): root = _build_node_tree("""namespace foo{ /// T Comment struct T { /* fieldA comment*/ fieldA : u8 : 7; } /** * Archive comment */ archive A { resourceA : T; resourceB : T; } } """) resolve_references(root) expected = """namespace foo { struct T { fieldA : u8 : 7; } } namespace foo { archive A { resourceA : .foo.T; resourceB : .foo.T; } } """ actual = SyntaxTree.schema(root.find(".foo.A")) assert_equal(actual, expected)
def __test(typename, width): tree = _build_node_tree("""namespace n{ struct s { f : %s; } } """ % typename) check_field(tree.find('.n.s.f'), typename, width, 0)
def test_constants_are_parsed(): tree = _build_node_tree("""namespace foo{ const i8 foo = 17; const u16 bar = 0x42; } """) assert_equal({".foo", ".foo.bar", ".foo.foo"}, tree.symbols()) check_constant(tree.find(".foo.foo"), "i8", "17") check_constant(tree.find(".foo.bar"), "u16", "0x42")
def test_archives_archive_resources_references_are_populated(): tree = _build_node_tree("""namespace foo{ archive A { resourceA : archive baz.B; } } """) assert_equal({".foo", ".foo.A", ".foo.A.resourceA", ".foo.A.resourceA.@baz@B"}, tree.symbols()) assert_is_instance(tree.find(".foo.A.resourceA.@baz@B"), refs.TypeReference)
def test_no_optional_decoration(): tree = _build_node_tree("""namespace foo{ archive A { resourceA : vector< S >; } } """) r = tree.find(".foo.A.resourceA") assert_equal(0, len(r.decorations)) assert_false(r.optional)
def __test(schema, references): tree = _build_node_tree("""namespace foo{ archive A { resourceA : %s; } } """ % schema) assert_equal({".foo", ".foo.A", ".foo.A.resourceA"}.union(references), tree.symbols()) for r in references: assert_is_instance(tree.find(r), refs.TypeReference)
def test_single_structure_is_parsed_correctly(): tree = _build_node_tree("""namespace foo{ struct Bar { fieldA : u8 : 2; fieldB : i64 : 33; } } """) assert_equal({".foo", ".foo.Bar", ".foo.Bar.fieldB", ".foo.Bar.fieldA"}, tree.symbols()) check_struct(tree.find(".foo.Bar"), 35, 5) check_field(tree.find(".foo.Bar.fieldA"), "u8", 2, 0) check_field(tree.find(".foo.Bar.fieldB"), "i64", 33, 2)
def test_optional_decoration(): tree = _build_node_tree("""namespace foo{ archive A { @optional resourceA : vector< S >; } } """) r = tree.find(".foo.A.resourceA") assert_equal(1, len(r.decorations)) assert_in("optional", r.decorations[0]) assert_true(r.optional)
def test_not_enough_bits_in_enum_field(): with assert_raises(InvalidEnumWidthError): tree = _build_node_tree(""" namespace n { enum A : i16 { VALUE_1 = 127 } struct B { f1 : A : 7; } } """) resolve_references(tree) _update_field_type_references(tree)
def test_constants_are_parsed(): tree = _build_node_tree("""namespace foo{ const i8 foo = -17; const u16 bar = 0x42; const i16 foo2 = -0x20; const u32 bar2 = 19; } """) assert_equal({".foo", ".foo.bar", ".foo.foo", ".foo.foo2", ".foo.bar2"}, tree.symbols()) check_constant(tree.find(".foo.foo"), "i8", -17) check_constant(tree.find(".foo.bar"), "u16", 0x42) check_constant(tree.find(".foo.foo2"), "i16", -0x20) check_constant(tree.find(".foo.bar2"), "u32", 19)
def test_two_structures_are_parsed_correctly(): tree = _build_node_tree("""namespace foo{ struct Bar { fieldA : u8 : 2; } struct Baz { fieldB : u32 : 17; } } """) assert_equal({".foo", ".foo.Baz", ".foo.Baz.fieldB", ".foo.Bar", ".foo.Bar.fieldA"}, tree.symbols()) check_struct(tree.find(".foo.Bar"), 2, 1) check_struct(tree.find(".foo.Baz"), 17, 3)
def test_multi_vector_builtin_types_are_correct(): tree = _build_node_tree("""namespace foo{ archive A { resourceA : multivector< 33, T >; } } """) res = tree.find(".foo.A.resourceA") assert_equal(33, res.width) assert_equal(1, len(res.builtins)) index_type = res.builtins[0] assert_equal({"IndexType33", "IndexType33.value"}, index_type.symbols()) check_struct(index_type, 33, 5) check_field(index_type.find("IndexType33.value"), "u64", 33, 0)
def test_implicit_references_are_represented_correctly(): tree = _build_node_tree("""namespace foo{ struct A { refB : u64 : 64; } struct B { x : u64 : 64; } @bound_implicitly( Bound: resourceA, resourceB ) archive X { resourceA : vector< A >; resourceB : vector< B >; } } """) b = tree.find(".foo.X.Bound") check_bound_resource(b, "Bound", ["resourceA", "resourceB"])
def test_namespace_merging_works_for_separate_namespaces(): tree = _build_node_tree(""" namespace n1 { struct A { refN1 : u64 : 64; } } namespace n2 { struct A { refN2 : u64 : 64; } } """) assert_equal( {'.n1', '.n1.A', '.n1.A.refN1', '.n2', '.n2.A', '.n2.A.refN2'}, tree.symbols())
def test_namespace_merging_works_for_same_namespaces_with_different_symbols(): tree = _build_node_tree(""" namespace n1.n2 { struct A { refN1 : u64 : 64; } } namespace n1.n2 { struct B { refN2 : u64 : 64; } } """) assert_equal({'.n1', '.n1.n2', '.n1.n2.A', '.n1.n2.A.refN1', '.n1.n2.B', '.n1.n2.B.refN2'}, tree.symbols())
def test_explicit_reference_decoration_spawns_all_the_right_references(): tree = _build_node_tree("""namespace foo{ archive X { @explicit_reference( A.refB, resourceB ) @explicit_reference( A.refC, resourceC ) resourceA : vector< A >; } } """) assert_equal( { ".foo", ".foo.X", ".foo.X.resourceA", ".foo.X.resourceA.@A", '.foo.X.resourceA.er_A_refC_resourceC', '.foo.X.resourceA.er_A_refC_resourceC.@A', '.foo.X.resourceA.er_A_refC_resourceC.@A@refC', '.foo.X.resourceA.er_A_refC_resourceC.@resourceC', '.foo.X.resourceA.er_A_refB_resourceB', '.foo.X.resourceA.er_A_refB_resourceB.@A', '.foo.X.resourceA.er_A_refB_resourceB.@A@refB', '.foo.X.resourceA.er_A_refB_resourceB.@resourceB' }, tree.symbols()) r = tree.find(".foo.X.resourceA") assert_equal(2, len(r.decorations)) check_explicit_reference(r.decorations[0], "A", "refB", "resourceB") check_explicit_reference(r.decorations[1], "A", "refC", "resourceC") assert_is_instance( tree.find(".foo.X.resourceA.er_A_refB_resourceB.@A@refB"), refs.FieldReference) assert_is_instance( tree.find(".foo.X.resourceA.er_A_refB_resourceB.@resourceB"), refs.ResourceReference) assert_is_instance( tree.find(".foo.X.resourceA.er_A_refC_resourceC.@A@refC"), refs.FieldReference) assert_is_instance( tree.find(".foo.X.resourceA.er_A_refC_resourceC.@resourceC"), refs.ResourceReference)
def test_enumeration(): tree = _build_node_tree(""" namespace n { enum A : u16 { VALUE_1, VALUE_2 = 4, VALUE_3, VALUE_4 = 0x10 } struct B { f1 : A; } } """) resolve_references(tree) _update_field_type_references(tree) _compute_structure_sizes(tree) assert_equal( { ".n", ".n.A", ".n.A.VALUE_1", ".n.A.VALUE_2", ".n.A.VALUE_3", ".n.A.VALUE_4", ".n.B", ".n.B.f1", ".n.B.f1.@@n@A" }, tree.symbols()) check_struct(tree.find(".n.B"), 16, 2)
def test_constants_are_placed_on_final_namespace(): tree = _build_node_tree("""namespace a.b{ const i8 foo = 17;}""") assert_equal({".a", ".a.b", ".a.b.foo"}, tree.symbols()) assert_is_instance(tree.find(".a.b.foo"), nodes.Constant)
def test_archive_without_namespace_raises(): with assert_raises(ParsingError): _build_node_tree("archive A { item : type; }")
def test_structure_without_namespace_trows(): with assert_raises(ParsingError): _build_node_tree("struct A { item : u32 : 16; }")