[commit] r2002 - in trunk: GME/Mga Tests/GPyUnit

GMESRC Repository Notifications gme-commit at list.isis.vanderbilt.edu
Tue Aug 14 09:31:32 CDT 2012


Author: ksmyth
Date: Tue Aug 14 09:31:31 2012
New Revision: 2002

Log:
Fix bug where a derived reference with CompareToBase()==true (i.e. desynched) could become an invalid ref when setting the basetype reference. This operation now throws.

Modified:
   trunk/GME/Mga/MgaCheck.cpp
   trunk/GME/Mga/MgaReference.cpp
   trunk/Tests/GPyUnit/test_instances.py

Modified: trunk/GME/Mga/MgaCheck.cpp
==============================================================================
--- trunk/GME/Mga/MgaCheck.cpp	Mon Aug 13 15:07:51 2012	(r2001)
+++ trunk/GME/Mga/MgaCheck.cpp	Tue Aug 14 09:31:31 2012	(r2002)
@@ -297,6 +297,22 @@
 				if(!good)
 					COMTHROW(E_MGA_META_VIOLATION);
 			}
+			// inherited ref can only refer to a derived instance of the target
+			// of its base. (Derived null ref is also rejected, but null ref in archetype is accepted)
+			CoreObj basetype = self[ATTRID_DERIVED];
+			if (basetype && !(mgaproject->preferences & MGAPREF_FREEINSTANCEREFS))
+			{
+				CoreObj base_target = basetype[ATTRID_REFERENCE];
+				if (base_target)
+				{
+					for ( ; target; target = target[ATTRID_DERIVED]) {
+						if (COM_EQUAL(base_target, target))
+							break;
+					}
+					if (!target)
+						COMTHROW(E_MGA_INVALID_TARGET);
+				}
+			}
 		}
 		else if(typ == OBJTYPE_SET) {
 			CComQIPtr<IMgaMetaSet> setmeta = meta;

Modified: trunk/GME/Mga/MgaReference.cpp
==============================================================================
--- trunk/GME/Mga/MgaReference.cpp	Mon Aug 13 15:07:51 2012	(r2001)
+++ trunk/GME/Mga/MgaReference.cpp	Tue Aug 14 09:31:31 2012	(r2002)
@@ -52,32 +52,31 @@
 		if(t) ObjForCore(t)->SelfMark(OBJEVENT_REFERENCED);
 		ObjForCore(self)->SelfMark(OBJEVENT_RELATION);
 		COMTHROW(ObjForCore(self)->Check());
+
+		ITERATE_THROUGH(self[ATTRID_DERIVED + ATTRID_COLLECTION])
+		{
+			if (!ITER[ATTRID_MASTEROBJ])
+			{
+				COMTHROW(ObjForCore(ITER)->Check());
+			}
+		}
 	}
 	return true;
 }
 
 
 HRESULT FCO::put_Referred(IMgaFCO *newVal)	{
+		// Inherited ref can only refer to a derived instance of the target
+		// of its base. This is checked in FCO::CheckRCS
 		COMTRY_IN_TRANSACTION_MAYBE {
 			CheckWrite();
 			CHECK_MYINPTRPARVALIDNULL(newVal);
 			std::vector<CoreObj> peer(1);
 			peer[0] = CoreObj(newVal);
-			if(!(mgaproject->preferences & MGAPREF_FREEINSTANCEREFS)) {
-			  // inherited ref can only refer to a derived instance of the target
-			  // of its base. (Null ref is also rejected)
- 			  CoreObj d = self[ATTRID_DERIVED];
-			  if(d) {
-				CoreObj dt = d[ATTRID_REFERENCE];
-				if(dt) {
-					CoreObj t(peer[0]);
-					for( ; t; t = t[ATTRID_DERIVED]) {
-						if(COM_EQUAL(dt, t)) break;
-					}
-					if(!t) COMTHROW(E_MGA_INVALID_TARGET);
-				}
-              }
-			}
+			CoreObj t = self[ATTRID_REFERENCE];
+
+			// FIXME: this is suspect; it makes ref.Referred = ref.Referred a mutating operation (i.e. => CompareToBase() == true)
+			// fix: if(!COM_EQUAL(t, peer[0])) {
 			self[ATTRID_MASTEROBJ] = NULLCOREOBJ;
 			putreftask(false).DoWithDeriveds(self, &peer);
 		} COMCATCH_IN_TRANSACTION_MAYBE(;);

Modified: trunk/Tests/GPyUnit/test_instances.py
==============================================================================
--- trunk/Tests/GPyUnit/test_instances.py	Mon Aug 13 15:07:51 2012	(r2001)
+++ trunk/Tests/GPyUnit/test_instances.py	Tue Aug 14 09:31:31 2012	(r2002)
@@ -9,6 +9,7 @@
     return os.path.join(os.path.dirname(os.path.abspath(__file__)), file)
 
 class TestInstances(unittest.TestCase):
+    project = None
     def __init__(self, name, **kwds):
         super(TestInstances, self).__init__(name, **kwds)
 
@@ -29,4 +30,68 @@
                 self.project.RootFolder.DeriveRootObject(model, True)
         self.project.CommitTransaction()
 
-GPyUnit.util.MUGenerator(globals(), TestInstances)
+    @dec_disable_early_binding
+    def test_RedirectBaseReference(self):
+        self.project = GPyUnit.util.parse_xme(self.connstr)
+        self.project.BeginTransactionInNewTerr()
+        aspects = self.project.RootFolder.GetObjectByPathDisp("/@Aspects")
+        allproxy = self.project.RootFolder.GetObjectByPathDisp("/@Aspects/@AllRef")
+        aspects_instance = self.project.RootFolder.DeriveRootObject(aspects, True)
+        aspects_subtype = self.project.RootFolder.DeriveRootObject(aspects, False)
+        attributes = self.project.RootFolder.GetObjectByPathDisp("/@Stereotypes/@Attributes")
+        allproxy.Referred = attributes
+        for asp in (aspects_instance, aspects_subtype):
+            self.assertEqual(asp.GetObjectByPathDisp("/@AllRef").Referred.Name, attributes.Name)
+            self.assertEqual(asp.GetObjectByPathDisp("/@AllRef").Referred.ID, attributes.ID)
+        self.project.CommitTransaction()
+
+    @dec_disable_early_binding
+    def test_RedirectBaseReference2(self):
+        self.project = GPyUnit.util.parse_xme(self.connstr)
+        self.project.BeginTransactionInNewTerr()
+        aspects = self.project.RootFolder.GetObjectByPathDisp("/@Aspects")
+        allproxy = self.project.RootFolder.GetObjectByPathDisp("/@Aspects/@AllRef")
+        instances = []
+        for inst_flag in (True, False, True, False):
+            instances.append(aspects.DeriveChildObject(allproxy, allproxy.MetaRole, inst_flag))
+        attributes = self.project.RootFolder.GetObjectByPathDisp("/@Stereotypes/@Attributes")
+        allproxy.Referred = attributes
+        try:
+            instances[0].Referred = self.project.RootFolder.GetObjectByPathDisp("/@Constraints/@Constraints|kind=Aspect")
+        except Exception, e:
+            pass
+        else:
+            self.fail()
+        for asp in instances:
+            self.assertEqual(asp.Referred.Name, attributes.Name)
+            self.assertEqual(asp.Referred.ID, attributes.ID)
+        self.project.CommitTransaction()
+
+    @dec_disable_early_binding
+    def test_RedirectBaseReference3(self):
+        self.project = GPyUnit.util.parse_xme(self.connstr)
+        self.project.BeginTransactionInNewTerr()
+        aspects = self.project.RootFolder.GetObjectByPathDisp("/@Aspects")
+        allproxy = self.project.RootFolder.GetObjectByPathDisp("/@Aspects/@AllRef")
+        instances = []
+        for inst_flag in (True, False, True, False):
+            instances.append(aspects.DeriveChildObject(allproxy, allproxy.MetaRole, inst_flag))
+        self.assertFalse(instances[3].CompareToBase())
+        instances[3].Referred = instances[3].Referred
+        self.assertTrue(instances[3].CompareToBase())
+        attributes = self.project.RootFolder.GetObjectByPathDisp("/@Stereotypes/@Attributes")
+        try:
+            allproxy.Referred = attributes
+        except Exception, e:
+            pass
+        else:
+            self.fail()
+        instances[3].RevertToBase()
+        self.assertFalse(instances[3].CompareToBase())
+        allproxy.Referred = attributes
+        for asp in instances:
+            self.assertEqual(asp.Referred.Name, attributes.Name)
+            self.assertEqual(asp.Referred.ID, attributes.ID)
+        self.project.CommitTransaction()
+
+#GPyUnit.util.MUGenerator(globals(), TestInstances)


More information about the gme-commit mailing list