def test_link_delete_object(self): 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") add_links({o1: [o2, o3]}) add_links({o4: [o3, o2]}) o2.delete() eq_(o1.linked, [o3]) eq_(o3.linked, [o1, o4]) eq_(o4.linked, [o3]) try: add_links({o1: [o2]}) exception_expected_() except CException as e: eq_(e.value, "cannot link to deleted target") try: add_links({o2: [o1]}) exception_expected_() except CException as e: eq_(e.value, "cannot link to deleted 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_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_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_get_links_self_link(self): a1 = self.c1.association(self.c1, role_name="to", source_role_name="from", source_multiplicity="*", multiplicity="*") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c1, "o3") o4 = CObject(self.c1, "o4") set_links({o1: [o2, o3, o1]}) o4.add_links([o1, o3]) link1 = o1.links[0] link2 = [o for o in o1.links if o.association == a1][0] link3 = [o for o in o1.links if o.role_name == "to"][0] link4 = [o for o in o1.links if o.source_role_name == "from"][0] eq_(link1, link2) eq_(link1, link3) eq_(link1, link4) eq_(link1.association, a1) eq_(link1.source, o1) eq_(link1.target, o2) eq_(len(o1.links), 4) eq_(len(o2.links), 1) eq_(len(o3.links), 2) eq_(len(o4.links), 2)
def test_delete_links_wrong_association(self): self.c1.association(self.c2, "a: [sourceA] * -> [targetA] *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o1.add_links(o2) try: o1.delete_links(o2, association=o1) exception_expected_() except CException as e: eq_(e.value, "'o1' is not a association") b = self.c1.association(self.c2, "b: [sourceB] * -> [targetB] *") try: o1.delete_links(o2, association=b) exception_expected_() except CException as e: eq_( e.value, "no link found for 'o1 -> o2' in delete links for given association" ) try: o1.delete_links(o2, association=b, role_name="x") exception_expected_() except CException as e: eq_( e.value, "no link found for 'o1 -> o2' in delete links for given role name 'x' and for given association" )
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_add_one_to_one_link(self): self.c1.association(self.c2, "l: 1 -> [target] 0..1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o3 = CObject(self.c2, "o3") eq_(o1.linked, []) add_links({o1: o3}) eq_(o1.linked, [o3]) eq_(o3.linked, [o1]) set_links({o1: []}, role_name="target") eq_(o1.linked, []) o1.add_links(o2) eq_(o1.linked, [o2]) eq_(o2.linked, [o1]) try: add_links({o1: o3}) exception_expected_() except CException as e: eq_( e.value, "links of object 'o1' have wrong multiplicity '2': should be '0..1'" ) eq_(o1.linked, [o2]) eq_(o2.linked, [o1]) eq_(o3.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_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" )
def test_delete_one_to_one_link(self): self.c1.association(self.c2, "l: 1 -> [c2] 0..1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o3 = CObject(self.c1, "o3") o4 = CObject(self.c2, "o4") links = add_links({o1: o2, o3: o4}) o1.delete_links(o2) eq_(o1.linked, []) eq_(o2.linked, []) eq_(o3.linked, [o4]) eq_(o4.linked, [o3]) eq_(o1.links, []) eq_(o2.links, []) eq_(o3.links, [links[1]]) eq_(o4.links, [links[1]]) delete_links({o3: o4}) eq_(o1.linked, []) eq_(o2.linked, []) eq_(o3.linked, []) eq_(o4.linked, []) eq_(o1.links, []) eq_(o2.links, []) eq_(o3.links, []) eq_(o4.links, [])
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_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_attribute_values_same_name_inheritance(self): t1 = CClass(self.mcl, "T1") t2 = CClass(self.mcl, "T2") c = CClass(self.mcl, "C", superclasses=[t1, t2]) sc = CClass(self.mcl, "C", superclasses=c) t1.attributes = {"i": 0} t2.attributes = {"i": 1} c.attributes = {"i": 2} sc.attributes = {"i": 3} o1 = CObject(sc) o2 = CObject(c) o3 = CObject(t1) eq_(o1.get_value("i"), 3) eq_(o2.get_value("i"), 2) eq_(o3.get_value("i"), 0) eq_(o1.get_value("i", sc), 3) eq_(o1.get_value("i", c), 2) eq_(o1.get_value("i", t2), 1) eq_(o1.get_value("i", t1), 0) eq_(o2.get_value("i", c), 2) eq_(o2.get_value("i", t2), 1) eq_(o2.get_value("i", t1), 0) eq_(o3.get_value("i", t1), 0) o1.set_value("i", 10) o2.set_value("i", 11) o3.set_value("i", 12) eq_(o1.get_value("i"), 10) eq_(o2.get_value("i"), 11) eq_(o3.get_value("i"), 12) eq_(o1.get_value("i", sc), 10) eq_(o1.get_value("i", c), 2) eq_(o1.get_value("i", t2), 1) eq_(o1.get_value("i", t1), 0) eq_(o2.get_value("i", c), 11) eq_(o2.get_value("i", t2), 1) eq_(o2.get_value("i", t1), 0) eq_(o3.get_value("i", t1), 12) o1.set_value("i", 130, sc) o1.set_value("i", 100, t1) o1.set_value("i", 110, t2) o1.set_value("i", 120, c) eq_(o1.get_value("i"), 130) eq_(o1.get_value("i", sc), 130) eq_(o1.get_value("i", c), 120) eq_(o1.get_value("i", t2), 110) eq_(o1.get_value("i", t1), 100)
def test_delete_link_select_by_association(self): a = self.c1.association(self.c2, "a: * -> *") b = self.c1.association(self.c2, "b: * -> *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c2, "o3") o4 = CObject(self.c2, "o4") add_links({o1: [o3], o2: [o3, o4]}, association=b) delete_links({o2: o3}) eq_(o1.linked, [o3]) eq_(o2.linked, [o4]) eq_(o3.linked, [o1]) eq_(o4.linked, [o2]) add_links({o1: [o3], o2: [o3, o4]}, association=a) try: delete_links({o1: o3}) exception_expected_() except CException as e: eq_( e.value, "link definition in delete links ambiguous for link 'o1->o3': found multiple matches" ) delete_links({o1: o3, o2: o4}, association=b) eq_(o1.linked, [o3]) eq_(o2.linked, [o3, o4]) eq_(o3.linked, [o1, o2]) eq_(o4.linked, [o2]) for o in [o1, o2, o3, o4]: for lo in o.links: eq_(lo.association, a) o1.add_links(o3, association=b) try: o1.delete_links(o3) exception_expected_() except CException as e: eq_( e.value, "link definition in delete links ambiguous for link 'o1->o3': found multiple matches" ) eq_(o1.linked, [o3, o3]) eq_(o2.linked, [o3, o4]) eq_(o3.linked, [o1, o2, o1]) eq_(o4.linked, [o2]) o1.delete_links(o3, association=a) eq_(o1.linked, [o3]) eq_(o2.linked, [o3, o4]) eq_(o3.linked, [o2, o1]) eq_(o4.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_object_attribute_of_superclass_type(self): attribute_super_type = CClass(self.mcl, "AttrSuperType") attribute_type = CClass(self.mcl, "AttrType", superclasses=attribute_super_type) attribute_value = CObject(attribute_type, "attribute_value") o = CObject(self.cl, "o1") self.cl.attributes = { "attrTypeObj1": attribute_super_type, "attrTypeObj2": attribute_value } o.set_value("attrTypeObj1", attribute_value) o.set_value("attrTypeObj2", attribute_value) eq_(o.get_value("attrTypeObj1"), attribute_value) eq_(o.get_value("attrTypeObj2"), attribute_value)
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_links_wrong_role_name(self): self.c1.association(self.c2, "a: [sourceA] * -> [targetA] *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") o1.add_links(o2) try: o1.delete_links(o2, role_name="target") exception_expected_() except CException as e: eq_( e.value, "no link found for 'o1 -> o2' in delete links for given role name 'target'" )
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_delete_class_instance_relation(self): cl1 = CClass(self.mcl, "CL1") cl2 = CClass(self.mcl, "CL2") obj1 = CObject(cl1, "O1") obj2 = CObject(cl1, "O2") obj3 = CObject(cl2, "O3") cl1.delete() eq_(obj1.classifier, None) eq_(obj2.classifier, None) eq_(obj3.classifier, cl2) eq_(set(cl2.objects), {obj3}) eq_(cl1.objects, [])
def test_link_source_multiplicity(self): self.c1.association(self.c2, "[sourceRole1] 1 -> [role1] *") self.c1.association(self.c2, "[sourceRole2] 1 -> [role2] 1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c2, "o3") CObject(self.c2, "o4") CObject(self.c2, "o5") set_links({o1: o3}, role_name="role1") set_links({o2: o3}, role_name="role1") eq_(o3.get_linked(role_name="sourceRole1"), [o2])
def test_wrong_types_add_links(self): self.c1.association(self.c2, name="l", multiplicity="1") o1 = CObject(self.c1, "o1") o2 = CObject(self.c2, "o2") try: add_links({o1: self.mcl}) exception_expected_() except CException as e: eq_(e.value, "link target 'MCL' is not an object, class, or link") try: o1.add_links([o2, self.mcl]) exception_expected_() except CException as e: eq_(e.value, "link target 'MCL' is not an object, class, or link")
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_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_set_links_multiple_links_in_definition(self): self.c1.association(self.c2, "[sourceRole1] * -> [role1] *") o1 = CObject(self.c1, "o1") o2 = CObject(self.c1, "o2") o3 = CObject(self.c1, "o3") o4 = CObject(self.c2, "o4") o5 = CObject(self.c2, "o5") set_links({o1: o4, o2: [o4], o5: [o1, o2, o3]}) eq_(o1.get_linked(), [o4, o5]) eq_(o2.get_linked(), [o4, o5]) eq_(o3.get_linked(), [o5]) eq_(o4.get_linked(), [o1, o2]) eq_(o5.get_linked(), [o1, o2, o3])
def test_object_type_attribute_values(self): attribute_type = CClass(self.mcl, "AttrType") attribute_value = CObject(attribute_type, "attribute_value") self.cl.attributes = {"attrTypeObj": attribute_value} object_attribute = self.cl.get_attribute("attrTypeObj") eq_(object_attribute.type, attribute_type) o = CObject(self.cl, "o") eq_(o.get_value("attrTypeObj"), attribute_value) non_attribute_value = CObject(self.cl, "non_attribute_value") try: o.set_value("attrTypeObj", non_attribute_value) exception_expected_() except CException as e: eq_(e.value, "type of 'non_attribute_value' is not matching type of attribute 'attrTypeObj'")
def test_remove_n_to_n_link(self): 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], o4: o2}) set_links({o1: o2, o4: [o3, o2]}) eq_(o1.linked, [o2]) eq_(o2.linked, [o1, o4]) eq_(o3.linked, [o4]) eq_(o4.linked, [o3, o2])
def test_delete_class_from_bundle(self): b1 = CBundle("B1") cl1 = CClass(self.mcl, "CL1", bundles=b1) cl1.delete() eq_(set(b1.get_elements(type=CClass)), set()) cl1 = CClass(self.mcl, "CL1", bundles=b1) cl2 = CClass(self.mcl, "CL2", bundles=b1) cl3 = CClass(self.mcl, "CL3", superclasses=cl2, attributes={"i": 1}, bundles=b1) cl3.set_value("i", 7) CObject(cl3, bundles=b1) cl1.delete() eq_(set(b1.get_elements(type=CClass)), {cl2, cl3}) cl3.delete() eq_(set(b1.get_elements(type=CClass)), {cl2}) eq_(cl3.superclasses, []) eq_(cl2.subclasses, []) eq_(cl3.attributes, []) eq_(cl3.attribute_names, []) eq_(cl3.metaclass, None) eq_(cl3.objects, []) eq_(cl3.name, None) eq_(cl3.bundles, []) eq_(b1.get_elements(type=CObject), []) try: cl3.get_value("i") exception_expected_() except CException as e: eq_("can't get value 'i' on deleted class", e.value)