module linker_test_1 1.0;

require { 
	class file { read write };
	class lnk_file append;
	role g_b_role_2;
	attribute g_b_attr_3;
	attribute g_b_attr_5;
	attribute o4_b_attr_1;
	type g_b_type_3;
}

type tag_g_m1;

#test for type in module and attr in module, added to in module
attribute g_m1_attr_1;
type g_m1_type_1, g_m1_attr_1;
type g_m1_type_2;
typeattribute g_m1_type_2 g_m1_attr_1;

#add role in module test
role g_m1_role_1;
role g_m1_role_1 types g_m1_type_1;

# test for attr declared in base, added to in module
type g_m1_type_3;
typeattribute g_m1_type_3 g_b_attr_3;

# test for attr declared in base, added to in 2 modules
type g_m1_type_4;
typeattribute g_m1_type_4 g_b_attr_5;

# test for attr declared in base optional, added to in module
type g_m1_type_5;
typeattribute g_m1_type_5 o4_b_attr_1;

# test for attr declared in module, added to in base optional
attribute g_m1_attr_2;

#add type to base role test
role g_b_role_2 types g_m1_type_1;
role g_b_role_3;
role g_b_role_3 types g_m1_type_2;

#add type to base optional role test
role o1_b_role_2;
role o1_b_role_2 types g_m1_type_1;

#optional base role w/ adds in 2 modules
role o4_b_role_1;
role o4_b_role_1 types g_m1_type_2;

# attr a added to in base optional, declared/added to in module, added to in other module
attribute g_m1_attr_3;
type g_m1_type_6, g_m1_attr_3;

# attr a added to in base optional, declared/added in module , added to in other module optional
attribute g_m1_attr_4;
type g_m1_type_7, g_m1_attr_4;

# alias tests
typealias g_b_type_3 alias g_m_alias_1;

# single boolean in module
bool g_m1_bool_1 true;
if (g_m1_bool_1) {
	allow g_m1_type_1 g_m1_type_2 : lnk_file append;
}


optional {
	require {
		type optional_type;
		attribute g_b_attr_4;
		attribute o1_b_attr_2;
		class lnk_file { ioctl };
	}

	type tag_o1_m1;

	attribute o1_m1_attr_1;
	type o1_m1_type_2, o1_m1_attr_1;
	
	type o1_m1_type_1;
	role o1_m1_role_1;
	role o1_m1_role_1 types o1_m1_type_1;

	type o1_m1_type_3;
	typeattribute o1_m1_type_3 g_b_attr_4;

	type o1_m1_type_5;
	typeattribute o1_m1_type_5 o1_b_attr_2;	

	bool o1_m1_bool_1 false;
	if (o1_m1_bool_1) {
		allow o1_m1_type_2 o1_m1_type_1 : lnk_file ioctl;
	}
	
}

optional {
	require {
		type optional_type;
		#role g_b_role_4; // This causes a bug where the role scope doesn't get copied into base
	}
	
	type tag_o2_m1;

	role g_b_role_4;
	role g_b_role_4 types g_m1_type_2;
}

optional {
	require {
		attribute g_b_attr_6;
	}

	type tag_o3_m1;

	type o3_m1_type_1;	
	role o3_b_role_1;
        role o3_b_role_1 types o3_m1_type_1;

	type o3_m1_type_2, g_b_attr_6;

	attribute o3_m1_attr_1;	

	# attr a added to in base optional, declared/added in module optional, added to in other module
	attribute o3_m1_attr_2;
	type o3_m1_type_3, o3_m1_attr_2;

}

optional {
	require {
		type enable_optional;
	}
	type tag_o4_m1;

	attribute o4_m1_attr_1;
	type o4_m1_type_1;
	typeattribute o4_m1_type_1 o4_m1_attr_1;


}