Changeset - 5051cf740055
[Not reviewed]
0 2 0
MH - 4 years ago 2021-04-07 13:17:40
henger@cwi.nl
Extended tests for union monomorphs
2 files changed with 112 insertions and 7 deletions:
0 comments (0 inline, 0 general)
src/protocol/tests/parser_monomorphs.rs
Show inline comments
 
@@ -71,3 +71,37 @@ fn test_enum_monomorphs() {
 
        .assert_has_monomorph("Answer<Answer<long>>");
 
    });
 
}
 

	
 
#[test]
 
fn test_union_monomorphs() {
 
    Tester::new_single_source_expect_ok(
 
        "no polymorph",
 
        "
 
        union Trinary { Undefined, Value(boolean) }
 
        int do_it() { auto a = Trinary::Value(true); return 0; }
 
        "
 
    ).for_union("Trinary", |e| { e
 
        .assert_num_monomorphs(0);
 
    });
 

	
 
    // TODO: Does this do what we want? Or do we expect the embedded monomorph
 
    //  Result<byte,int> to be instantiated as well? I don't think so.
 
    Tester::new_single_source_expect_ok(
 
        "polymorphs",
 
        "
 
        union Result<T, E>{ Ok(T), Err(E) }
 
        int instantiator() {
 
            auto a = Result<byte, boolean>::Ok(0);
 
            auto b = Result<boolean, byte>::Ok(true);
 
            auto c = Result<Result<byte, int>, Result<short, long>>::Err(Result::Ok(5));
 
            return 0;
 
        }
 
        "
 
    ).for_union("Result", |e| { e
 
        .assert_num_monomorphs(4)
 
        .assert_has_monomorph("byte;bool")
 
        .assert_has_monomorph("bool;byte")
 
        .assert_has_monomorph("Result<byte,int>;Result<short,long>")
 
        .assert_has_monomorph("short;long");
 
    });
 
}
 
\ No newline at end of file
src/protocol/tests/utils.rs
Show inline comments
 
@@ -152,13 +152,11 @@ impl AstOkTester {
 
            }
 
        }
 

	
 
        if found { return self }
 

	
 
        assert!(
 
            false, "[{}] Failed to find definition for struct '{}'",
 
            found, "[{}] Failed to find definition for struct '{}'",
 
            self.test_name, name
 
        );
 
        unreachable!()
 
        self
 
    }
 

	
 
    pub(crate) fn for_enum<F: Fn(EnumTester)>(self, name: &str, f: F) -> Self {
 
@@ -177,13 +175,34 @@ impl AstOkTester {
 
            }
 
        }
 

	
 
        if found { return self }
 
        assert!(
 
            found, "[{}] Failed to find definition for enum '{}'",
 
            self.test_name, name
 
        );
 
        self
 
    }
 

	
 
    pub(crate) fn for_union<F: Fn(UnionTester)>(self, name: &str, f: F) -> Self {
 
        let mut found = false;
 
        for definition in self.heap.definitions.iter() {
 
            if let Definition::Union(definition) = definition {
 
                if String::from_utf8_lossy(&definition.identifier.value) != name {
 
                    continue;
 
                }
 

	
 
                // Found union with the same name
 
                let tester = UnionTester::new(self.ctx(), definition);
 
                f(tester);
 
                found = true;
 
                break;
 
            }
 
        }
 

	
 
        assert!(
 
            false, "[{}] Failed to find definition for enum '{}'",
 
            found, "[{}] Failed to find definition for union '{}'",
 
            self.test_name, name
 
        );
 
        unreachable!()
 
        self
 
    }
 

	
 
    pub(crate) fn for_function<F: Fn(FunctionTester)>(self, name: &str, f: F) -> Self {
 
@@ -378,6 +397,57 @@ impl<'a> EnumTester<'a> {
 
    }
 
}
 

	
 
pub(crate) struct UnionTester<'a> {
 
    ctx: TestCtx<'a>,
 
    def: &'a UnionDefinition,
 
}
 

	
 
impl<'a> UnionTester<'a> {
 
    fn new(ctx: TestCtx<'a>, def: &'a UnionDefinition) -> Self {
 
        Self{ ctx, def }
 
    }
 

	
 
    pub(crate) fn assert_num_variants(self, num: usize) -> Self {
 
        assert_eq!(
 
            num, self.def.variants.len(),
 
            "[{}] Expected {} union variants, but found {} for {}",
 
            self.ctx.test_name, num, self.def.variants.len(), self.assert_postfix()
 
        );
 
        self
 
    }
 

	
 
    pub(crate) fn assert_num_monomorphs(self, num: usize) -> Self {
 
        let (is_equal, num_encountered) = has_equal_num_monomorphs(self.ctx, num, self.def.this.upcast());
 
        assert!(
 
            is_equal, "[{}] Expected {} monomorphs, but got {} for {}",
 
            self.ctx.test_name, num, num_encountered, self.assert_postfix()
 
        );
 
        self
 
    }
 

	
 
    pub(crate) fn assert_has_monomorph(self, serialized_monomorph: &str) -> Self {
 
        let (has_monomorph, serialized) = has_monomorph(self.ctx, self.def.this.upcast(), serialized_monomorph);
 
        assert!(
 
            has_monomorph, "[{}] Expected to find monomorph {}, but got {} for {}",
 
            self.ctx.test_name, serialized_monomorph, serialized, self.assert_postfix()
 
        );
 
        self
 
    }
 

	
 
    fn assert_postfix(&self) -> String {
 
        let mut v = String::new();
 
        v.push_str("Union{ name: ");
 
        v.push_str(&String::from_utf8_lossy(&self.def.identifier.value));
 
        v.push_str(", variants: [");
 
        for (variant_idx, variant) in self.def.variants.iter().enumerate() {
 
            if variant_idx != 0 { v.push_str(", "); }
 
            v.push_str(&String::from_utf8_lossy(&variant.identifier.value));
 
        }
 
        v.push_str("] }");
 
        v
 
    }
 
}
 

	
 
pub(crate) struct FunctionTester<'a> {
 
    ctx: TestCtx<'a>,
 
    def: &'a Function,
 
@@ -802,6 +872,7 @@ fn serialize_concrete_type(buffer: &mut String, heap: &Heap, def: DefinitionId,
 
        Definition::Component(definition) => &definition.poly_vars,
 
        Definition::Struct(definition) => &definition.poly_vars,
 
        Definition::Enum(definition) => &definition.poly_vars,
 
        Definition::Union(definition) => &definition.poly_vars,
 
        _ => unreachable!("Error in testing utility: unexpected type for concrete type serialization"),
 
    };
 

	
0 comments (0 inline, 0 general)