use crate::{
metadata::{
tables::{CodedIndex, CodedIndexType, TableDataOwned, TableId, TypeAttributes, TypeDefRaw},
token::Token,
},
test::{create_test_assembly, get_testfile_mscorlib, TestAssembly},
Error, Result,
};
pub fn owned_circularity_validator_file_factory() -> Result<Vec<TestAssembly>> {
let mut assemblies = Vec::new();
let Some(clean_testfile) = get_testfile_mscorlib() else {
return Err(Error::Other(
"mscorlib.dll not available - test cannot run".to_string(),
));
};
assemblies.push(TestAssembly::new(&clean_testfile, true));
assemblies.push(create_assembly_with_circular_inheritance()?);
assemblies.push(create_assembly_with_self_referential_type()?);
assemblies.push(create_assembly_with_circular_interface_implementation()?);
Ok(assemblies)
}
pub fn create_assembly_with_circular_inheritance() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_a_name_index = assembly.string_add("TypeA")?;
let type_b_name_index = assembly.string_add("TypeB")?;
let type_a_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let type_b_rid = type_a_rid + 1;
let type_a = TypeDefRaw {
rid: type_a_rid,
token: Token::new(0x02000000 + type_a_rid),
offset: 0,
flags: TypeAttributes::PUBLIC,
type_name: type_a_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeDef, type_b_rid, CodedIndexType::TypeDefOrRef), field_list: 1,
method_list: 1,
};
let type_b = TypeDefRaw {
rid: type_b_rid,
token: Token::new(0x02000000 + type_b_rid),
offset: 0,
flags: TypeAttributes::PUBLIC,
type_name: type_b_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeDef, type_a_rid, CodedIndexType::TypeDefOrRef), field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_a))?;
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_b))?;
Ok(())
})
}
pub fn create_assembly_with_self_referential_type() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly.string_add("SelfReferentialType")?;
let type_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let self_ref_type = TypeDefRaw {
rid: type_rid,
token: Token::new(0x02000000 + type_rid),
offset: 0,
flags: TypeAttributes::PUBLIC,
type_name: type_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeDef, type_rid, CodedIndexType::TypeDefOrRef), field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(self_ref_type))?;
Ok(())
})
}
pub fn create_assembly_with_circular_interface_implementation() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let interface_i1_name_index = assembly.string_add("IInterface1")?;
let interface_i2_name_index = assembly.string_add("IInterface2")?;
let interface_i1_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let interface_i2_rid = interface_i1_rid + 1;
let interface_i1 = TypeDefRaw {
rid: interface_i1_rid,
token: Token::new(0x02000000 + interface_i1_rid),
offset: 0,
flags: TypeAttributes::INTERFACE | TypeAttributes::ABSTRACT | TypeAttributes::PUBLIC,
type_name: interface_i1_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(
TableId::TypeDef,
interface_i2_rid,
CodedIndexType::TypeDefOrRef,
), field_list: 1,
method_list: 1,
};
let interface_i2 = TypeDefRaw {
rid: interface_i2_rid,
token: Token::new(0x02000000 + interface_i2_rid),
offset: 0,
flags: TypeAttributes::INTERFACE | TypeAttributes::ABSTRACT | TypeAttributes::PUBLIC,
type_name: interface_i2_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(
TableId::TypeDef,
interface_i1_rid,
CodedIndexType::TypeDefOrRef,
), field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(interface_i1))?;
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(interface_i2))?;
Ok(())
})
}