def test_wrong_types_set_links(self): self.c1.association(self.c2, name="l", multiplicity="1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") try: set_links({o1: self.mcl}) exception_expected_() except CException as e: eq_(e.value, "link target 'MCL' is not an object, class, or link") try: set_links({o1: [o2, self.mcl]}) exception_expected_() except CException as e: eq_(e.value, "link target 'MCL' is not an object, class, or link") try: set_links({o1: [o2, None]}) exception_expected_() except CException as e: eq_(e.value, "link target 'None' is not an object, class, or link") try: set_links({self.mcl: o2}) exception_expected_() except CException as e: eq_(e.value, "link source 'MCL' is not an object, class, or link") try: set_links({None: o2}) exception_expected_() except CException as e: eq_(e.value, "link should not contain an empty source")
def test_link_association_ambiguous(self): self.c1.association(self.c2, name="a1", role_name="c2", multiplicity="*") self.c1.association(self.c2, name="a2", role_name="c2", multiplicity="*") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") try: set_links({o1: o2}) exception_expected_() except CException as e: eq_( e.value, "link specification ambiguous, multiple matching associations " + "found for source 'o1' and targets '['o2']'") try: set_links({o1: o2}, role_name="c2") exception_expected_() except CException as e: eq_( e.value, "link specification ambiguous, multiple matching associations " + "found for source 'o1' and targets '['o2']'")
def test_n_to_n_link(self): a = self.c1.association(self.c2, name="l", source_multiplicity="*") o1a = CObject(self.c1, "o1a") o1b = CObject(self.c1, "o1b") o1c = CObject(self.c1, "o1c") o2a = CObject(self.c2, "o2a") o2b = CObject(self.c2, "o2b") set_links({o1a: [o2a, o2b], o1b: [o2a], o1c: [o2b]}) eq_(o1a.linked, [o2a, o2b]) eq_(o1b.linked, [o2a]) eq_(o1c.linked, [o2b]) eq_(o2a.linked, [o1a, o1b]) eq_(o2b.linked, [o1a, o1c]) set_links({o2a: [o1a, o1b]}) try: set_links({o2b: []}) exception_expected_() except CException as e: eq_( e.value, "matching association not found for source 'o2b' and targets '[]'" ) set_links({o2b: []}, association=a) eq_(o1a.linked, [o2a]) eq_(o1b.linked, [o2a]) eq_(o1c.linked, []) eq_(o2a.linked, [o1a, o1b]) eq_(o2b.linked, [])
def test_link_delete_association(self): a = self.c1.association(self.c2, name="l", source_multiplicity="*", multiplicity="*") o1 = CObject(self.c1, "o2") o2 = CObject(self.c2, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c1, "o4") set_links({o1: [o2, o3]}) set_links({o4: [o2]}) set_links({o1: [o2]}) set_links({o4: [o3, o2]}) a.delete() eq_(o1.linked, []) eq_(o2.linked, []) eq_(o3.linked, []) eq_(o4.linked, []) try: set_links({o1: [o2, o3]}) exception_expected_() except CException as e: eq_( e.value, "matching association not found for source 'o2' and targets '['o2', 'o3']'" )
def test_delete_one_to_n_links(self): self.c1.association(self.c2, "l: 0..1 -> *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c2, "o4") o5 = CObject(self.c2, "o5") add_links({o1: [o3, o4], o2: [o5]}) o4.delete_links([o1]) eq_(o1.linked, [o3]) eq_(o2.linked, [o5]) eq_(o3.linked, [o1]) eq_(o4.linked, []) eq_(o5.linked, [o2]) o4.add_links([o2]) eq_(o2.linked, [o5, o4]) delete_links({o1: o3, o2: o2.linked}) eq_(o1.linked, []) eq_(o2.linked, []) eq_(o3.linked, []) eq_(o4.linked, []) eq_(o5.linked, [])
def test_creation_of_unnamed_object(self): o1 = CObject(self.cl) o2 = CObject(self.cl) o3 = CObject(self.cl, "x") eq_(set(self.cl.objects), {o1, o2, o3}) eq_(o1.name, None) eq_(o2.name, None) eq_(o3.name, "x")
def test_classifier_change_wrong_input_type(self): cl1 = CClass(self.mcl, "CL1") o1 = CObject(cl1, "O1") try: o1.classifier = self.mcl exception_expected_() except CException as e: ok_(e.value.endswith("' is not a class"))
def test_classifier_change_null_input(self): cl1 = CClass(self.mcl, "CL1") o1 = CObject(cl1, "O1") try: o1.classifier = None exception_expected_() except CException as e: eq_("'None' is not a class", e.value)
def test_classifier_change(self): cl1 = CClass(self.mcl, "CL1") cl2 = CClass(self.mcl, "CL2") o1 = CObject(cl1, "O1") o1.classifier = cl2 eq_(o1.classifier, cl2) eq_(cl1.objects, []) eq_(cl2.objects, [o1])
def test_attribute_value_type_check_list(self): self.cl.attributes = {"t": list} o = CObject(self.cl, "o") try: o.set_value("t", True) exception_expected_() except CException as e: eq_(f"value type for attribute 't' does not match attribute type", e.value)
def test_attribute_value_type_check_bool1(self): self.cl.attributes = {"t": bool} o = CObject(self.cl, "o") try: o.set_value("t", self.mcl) exception_expected_() except CException as e: eq_(f"value for attribute 't' is not a known attribute type", e.value)
def test_specific_n_to_n_link_multiplicity(self): a = self.c1.association(self.c2, name="l", source_multiplicity="1..2", multiplicity="2") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c1, "o4") o5 = CObject(self.c1, "o5") o6 = CObject(self.c2, "o6") try: set_links({o1: []}, association=a) exception_expected_() except CException as e: eq_( e.value, "links of object 'o1' have wrong multiplicity '0': should be '2'" ) try: set_links({o1: [o2]}, association=a) exception_expected_() except CException as e: eq_( e.value, "links of object 'o1' have wrong multiplicity '1': should be '2'" ) try: set_links({o1: [o2, o3, o6]}, association=a) exception_expected_() except CException as e: eq_( e.value, "links of object 'o1' have wrong multiplicity '3': should be '2'" ) set_links({o1: [o2, o3]}) eq_(o1.get_linked(association=a), [o2, o3]) set_links({o2: [o1, o4], o1: o3, o4: o3}) eq_(o2.get_linked(association=a), [o1, o4]) try: set_links({o2: []}, association=a) exception_expected_() except CException as e: eq_( e.value, "links of object 'o2' have wrong multiplicity '0': should be '1..2'" ) try: set_links({o2: [o1, o4, o5]}) exception_expected_() except CException as e: eq_( e.value, "links of object 'o2' have wrong multiplicity '3': should be '1..2'" )
def test_attribute_value_type_check_enum(self): enum_type = CEnum("EnumT", values=["A", "B", "C"]) self.cl.attributes = {"t": enum_type} o = CObject(self.cl, "o") try: o.set_value("t", True) exception_expected_() except CException as e: eq_(f"value type for attribute 't' does not match attribute type", e.value)
def test_attribute_value_type_check_object(self): attribute_type = CClass(self.mcl, "AttrType") self.cl.attributes = {"t": attribute_type} o = CObject(self.cl, "o") try: o.set_value("t", True) exception_expected_() except CException as e: eq_(f"value type for attribute 't' does not match attribute type", e.value)
def test_default_object_attribute_is_deleted_in_constructor(self): attribute_class = CClass(self.mcl, "AC") default_object = CObject(attribute_class) default_object.delete() try: CMetaclass("M", attributes={"ac": default_object}) exception_expected_() except CException as e: eq_(e.value, "cannot access named element that has been deleted")
def test_add_object_attribute_get_set_value(self): attribute_type = CClass(self.mcl, "AttrType") attribute_value = CObject(attribute_type, "attribute_value") o1 = CObject(self.cl, "o1") self.cl.attributes = { "attrTypeObj1": attribute_type, "attrTypeObj2": attribute_value } eq_(o1.get_value("attrTypeObj1"), None) eq_(o1.get_value("attrTypeObj2"), attribute_value)
def test_default_object_attribute_is_deleted_in_default_method(self): attr_cl = CClass(self.mcl, "AC") default_obj = CObject(attr_cl) default_obj.delete() try: a = CAttribute() a.default = default_obj exception_expected_() except CException as e: eq_(e.value, "cannot access named element that has been deleted")
def test_get_connected_elements_wrong_keyword_arg(self): o1 = CObject(self.cl, "o1") try: o1.get_connected_elements(a="o1") exception_expected_() except CException as e: eq_( e.value, "unknown keyword argument 'a', should be one of: " + "['add_links', 'add_bundles', 'process_bundles', " + "'stop_elements_inclusive', 'stop_elements_exclusive']")
def test_default_init_after_instance_creation(self): enum_type = CEnum("EnumT", values=["A", "B", "C"]) cl = CClass(self.mcl, "C", attributes={ "e1": enum_type, "e2": enum_type}) o = CObject(cl, "o") e2 = cl.get_attribute("e2") e2.default = "A" eq_(o.get_value("e1"), None) eq_(o.get_value("e2"), "A")
def test_values_setter_malformed_description(self): cl = CClass(self.mcl, "C", attributes={ "isBoolean": True, "intVal": 1}) o = CObject(cl, "o") try: o.values = [1, 2, 3] exception_expected_() except CException as e: eq_(e.value, "malformed attribute values description: '[1, 2, 3]'")
def test_add_links_one_to_n_link(self): self.c1.association(self.c2, name="l") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c2, "o4") o5 = CObject(self.c2, "o5") o6 = CObject(self.c2, "o6") add_links({o1: [o2, o3]}) eq_(o1.linked, [o2, o3]) eq_(o2.linked, [o1]) eq_(o3.linked, [o1]) add_links({o1: o4}) eq_(o1.linked, [o2, o3, o4]) eq_(o2.linked, [o1]) eq_(o3.linked, [o1]) eq_(o4.linked, [o1]) o1.add_links([o5, o6]) eq_(o1.linked, [o2, o3, o4, o5, o6]) eq_(o2.linked, [o1]) eq_(o3.linked, [o1]) eq_(o4.linked, [o1]) eq_(o5.linked, [o1]) eq_(o6.linked, [o1])
def test_delete_n_to_n_links(self): self.c1.association(self.c2, "l: * -> *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c2, "o4") o5 = CObject(self.c2, "o5") o6 = CObject(self.c2, "o6") add_links({o1: [o3, o4], o2: [o4, o5]}) o4.delete_links([o1, o2]) eq_(o1.linked, [o3]) eq_(o2.linked, [o5]) eq_(o3.linked, [o1]) eq_(o4.linked, []) eq_(o5.linked, [o2]) add_links({o4: [o1, o2], o6: [o2, o1]}) delete_links({o1: o6, o2: [o4, o5]}) eq_(o1.linked, [o3, o4]) eq_(o2.linked, [o6]) eq_(o3.linked, [o1]) eq_(o4.linked, [o1]) eq_(o5.linked, []) eq_(o6.linked, [o2])
def test_create_object_wrong_arg_types(self): try: CObject("CL", "o1") exception_expected_() except CException as e: eq_("'CL' is not a class", e.value) try: CObject(self.mcl, "o1") exception_expected_() except CException as e: eq_("'MCL' is not a class", e.value)
def test_get_objects_by_name(self): c1 = CClass(self.mcl) eq_(set(c1.get_objects("o1")), set()) o1 = CObject(c1, "o1") eq_(c1.objects, [o1]) eq_(set(c1.get_objects("o1")), {o1}) o2 = CObject(c1, "o1") eq_(set(c1.get_objects("o1")), {o1, o2}) ok_(o1 != o2) o3 = CObject(c1, "o1") eq_(set(c1.get_objects("o1")), {o1, o2, o3}) eq_(c1.get_object("o1"), o1)
def test_class_is_deleted_in_classifier_method(self): c1 = CClass(self.mcl, "CL1") c2 = CClass(self.mcl, "CL2") o1 = CObject(c2, "O1") c1.delete() try: o1.classifier = c1 exception_expected_() except CException as e: ok_( e.value.endswith( "cannot access named element that has been deleted"))
def test_class_instance_relation(self): cl1 = CClass(self.mcl, "CL1") cl2 = CClass(self.mcl, "CL2") eq_(set(cl1.objects), set()) o1 = CObject(cl1, "O1") o2 = CObject(cl1, "O2") o3 = CObject(cl2, "O3") eq_(set(cl1.objects), {o1, o2}) eq_(set(cl2.objects), {o3}) eq_(o1.classifier, cl1) eq_(o2.classifier, cl1) eq_(o3.classifier, cl2)
def test_delete_class_that_is_an_attribute_type(self): b1 = CBundle("B1") mcl = CMetaclass("MCL") cl1 = CClass(mcl, "CL1", bundles=b1) cl2 = CClass(mcl, "CL2", bundles=b1) cl3 = CClass(mcl, "CL3", bundles=b1) o3 = CObject(cl3, "O3") ea1 = CAttribute(type=cl3, default=o3) m = CMetaclass("M", bundles=b1, attributes={"o": ea1}) c = CClass(m) cl1.delete() cl3.delete() try: # we just use list here, in order to not get a warning that ea1.default has no effect list([ea1.default]) exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value) try: # we just use list here, in order to not get a warning that ea1.type has no effect list([ea1.type]) exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value) try: ea1.default = "3" exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value) try: ea1.type = cl1 exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value) try: ea1.type = cl2 exception_expected_() except CException as e: eq_("default value '' incompatible with attribute's type 'CL2'", e.value) try: c.set_value("o", CObject(cl2)) exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value) try: c.get_value("o") exception_expected_() except CException as e: eq_("cannot access named element that has been deleted", e.value)
def test_wrong_format_set_links(self): self.c1.association(self.c2, name="l", multiplicity="1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") try: # noinspection PyTypeChecker set_links([o1, o2]) exception_expected_() except CException as e: eq_( e.value, "link definitions should be of the form {<link source 1>: " + "<link target(s) 1>, ..., <link source n>: <link target(s) n>}" )
def test_link_label_none_default(self): a1 = self.c1.association(self.c2, name="a1", multiplicity="*") a2 = self.c1.association(self.c2, multiplicity="*") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o3 = CObject(self.c2, "o3") l1 = set_links({o1: o2}, association=a1) l2 = set_links({o1: [o2, o3]}, association=a2) eq_(l1[0].label, None) eq_(l2[0].label, None) eq_(l2[1].label, None)
def test_delete_link_no_matching_link(self): a = self.c1.association(self.c2, "l: 0..1 -> *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c2, "o4") o5 = CObject(self.c2, "o5") add_links({o1: [o3, o4], o2: [o5]}, association=a) try: delete_links({o1: o5}) exception_expected_() except CException as e: eq_(e.value, "no link found for 'o1 -> o5' in delete links") b = self.c1.association(self.c2, "l: 0..1 -> *") try: delete_links({o1: o5}) exception_expected_() except CException as e: eq_(e.value, "no link found for 'o1 -> o5' in delete links") try: o4.delete_links([o1], association=b) exception_expected_() except CException as e: eq_( e.value, "no link found for 'o4 -> o1' in delete links for given association" )