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

GMESRC Repository Notifications gme-commit at list.isis.vanderbilt.edu
Wed Aug 21 14:40:13 CDT 2013


Author: ksmyth
Date: Wed Aug 21 14:40:13 2013
New Revision: 2299

Log:
Detect dup GUIDs in mga open, and reassign them

Added:
   trunk/Tests/GPyUnit/SFDemo_dup_guids.mga
   trunk/Tests/GPyUnit/test_mga_open.py
Modified:
   trunk/GME/Core/CoreBinFile.cpp
   trunk/GME/Core/CoreBinFile.h
   trunk/GME/Mga/MgaFCO.cpp
   trunk/GME/Mga/MgaLibOps.cpp
   trunk/GME/Mga/MgaLibRefr.h
   trunk/Tests/GPyUnit/__init__.py
   trunk/Tests/GPyUnit/test_copy.py
   trunk/Tests/GPyUnit/test_parser.py

Modified: trunk/GME/Core/CoreBinFile.cpp
==============================================================================
--- trunk/GME/Core/CoreBinFile.cpp	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/GME/Core/CoreBinFile.cpp	Wed Aug 21 14:40:13 2013	(r2299)
@@ -145,7 +145,7 @@
 	}
 }
 
-bool BinObject::HasGuidAndStatAttributes( bool* p_guidFound, bool* p_statusFound, bool* p_oldRegFound)
+void BinObject::HasGuidAndStatAttributes(GUID& t_guid, bool* p_statusFound, bool* p_oldRegFound)
 {
 	int a1( 0), a2( 0), a3( 0), a4( 0);
 
@@ -153,12 +153,30 @@
 	binattrs_iterator e = binattrs.end();
 	while( i != e)
 	{
-		switch( (i)->attrid)
+		switch ((i)->attrid)
 		{
-			case ATTRID_GUID1: ++a1;break;
-			case ATTRID_GUID2: ++a2;break;
-			case ATTRID_GUID3: ++a3;break;
-			case ATTRID_GUID4: ++a4;break;
+			case ATTRID_GUID1:
+				t_guid.Data1 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a;
+				break;
+			case ATTRID_GUID2:
+				t_guid.Data2 = (reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a) >> 16;
+				t_guid.Data3 = (reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a) & 0xFFFF;
+				break;
+
+			case ATTRID_GUID3: {
+				long v3 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a;
+				t_guid.Data4[0] = (v3 >> 24);
+				t_guid.Data4[1] = (v3 >> 16) & 0xFF;
+				t_guid.Data4[2] = (v3 >> 8) & 0xFF;
+				t_guid.Data4[3] = v3 & 0xFF;
+				} break;
+			case ATTRID_GUID4: {
+				long v4 = reinterpret_cast<BinAttr<VALTYPE_LONG>*>(&(*i))->a;
+				t_guid.Data4[4] = (v4 >> 24);
+				t_guid.Data4[5] = (v4 >> 16) & 0xFF;
+				t_guid.Data4[6] = (v4 >> 8) & 0xFF;
+				t_guid.Data4[7] = v4 & 0xFF;
+				} break;
 			case ATTRID_FILESTATUS: *p_statusFound = true; break;
 			case ATTRID_REGNOWNER + ATTRID_COLLECTION:
 				*p_oldRegFound = true; break;
@@ -166,12 +184,6 @@
 
 		++i;
 	}
-
-	// a1, a2, a3, a4 should be equal & have the 0 or 1 value
-	ASSERT( (a1 == 0 || a1 == 1) && a1 == a2 && a1 == a3 && a1 == a4);
-
-	*p_guidFound = a1 && a2 && a3 && a4;
-	return *p_guidFound;
 }
 
 // this method will create Guid attributes for mga objects
@@ -1059,6 +1071,46 @@
 	cifs_eof = file_buffer.getEnd();
 }
 
+// KMS: due to a bug in MgaFolder::CopyFCOs (ObjTreeCopyFoldersToo) fixed in r2297, some mga files may have duplicate GUIDs
+static void SetNewGuid(CCoreBinFile* p_bf, BinObject& o)
+{
+	CComVariant l1, l2, l3, l4;
+	l4.vt = l3.vt = l2.vt = l1.vt = VT_I4;
+	getMeAGuid( &l1.lVal, &l2.lVal, &l3.lVal, &l4.lVal);
+
+	binattrs_iterator i = o.binattrs.begin();
+	binattrs_iterator e = o.binattrs.end();
+	while( i != e)
+	{
+		switch (i->attrid)
+		{
+		case ATTRID_GUID1:
+			i->Set(p_bf, l1);
+			break;
+		case ATTRID_GUID2:
+			i->Set(p_bf, l2);
+			break;
+		case ATTRID_GUID3:
+			i->Set(p_bf, l3);
+			break;
+		case ATTRID_GUID4:
+			i->Set(p_bf, l4);
+			break;
+		default:
+			break;
+		}
+		i++;
+	}
+}
+
+struct GUID_hash {
+	size_t operator()(const GUID& guid) const
+	{
+		int* iGuid = (int*)(void*)&guid;
+		return iGuid[0] ^ iGuid[1] ^ iGuid[2] ^ iGuid[3];
+	}
+};
+
 void CCoreBinFile::LoadProject()
 {
 	InitMaxObjIDs();
@@ -1069,6 +1121,8 @@
 	cifs = file_buffer.getBegin();
 	cifs_eof = file_buffer.getEnd();
 
+	std::unordered_map<GUID, bool, GUID_hash> guids;
+
 	bindata guid;
 	read(guid);
 
@@ -1115,13 +1169,21 @@
 		// if the object read is folder or fco and it does NOT have guid attributes (old version mga file)
 		if( metaid >= DTID_MODEL && metaid <= DTID_FOLDER)	// 101 .. 106
 		{
-			bool stat_found( false), guid_found( false);
+			bool stat_found( false);
 
-			opened_object->second.HasGuidAndStatAttributes( &guid_found, &stat_found, &oldReg_found);
+			GUID zero_guid = {0};
+			GUID guid = {0};
+			opened_object->second.HasGuidAndStatAttributes(guid, &stat_found, &oldReg_found);
 
-			if( !guid_found) // we will create guid attributes for it
+			if(guid == zero_guid) // we will create guid attributes for it
 				opened_object->second.CreateGuidAttributes( this);
 
+			std::pair<std::hash_map<GUID, bool>::iterator, bool> guid_insert = guids.emplace(std::make_pair(guid, true));
+			if (guid_insert.second == true)
+			{
+				SetNewGuid(this, opened_object->second);
+			}
+
 			if( !stat_found && ( metaid == DTID_MODEL || metaid == DTID_FOLDER)) // we will create status attribute for M and F
 				opened_object->second.CreateStatusAttribute( this);
 		}

Modified: trunk/GME/Core/CoreBinFile.h
==============================================================================
--- trunk/GME/Core/CoreBinFile.h	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/GME/Core/CoreBinFile.h	Wed Aug 21 14:40:13 2013	(r2299)
@@ -146,7 +146,7 @@
 	binattrs_type binattrs;
 	bool deleted;
 
-	bool HasGuidAndStatAttributes( bool* p_guidFound, bool* p_statusFound, bool* p_oldRegFound);
+	void HasGuidAndStatAttributes(GUID& guid, bool* p_statusFound, bool* p_oldRegFound);
 	void CreateGuidAttributes( CCoreBinFile* p_bf);
 	void CreateStatusAttribute( CCoreBinFile* p_bf);
 	void UpgradeRegistryIfNecessary(CCoreBinFile* binFile);

Modified: trunk/GME/Mga/MgaFCO.cpp
==============================================================================
--- trunk/GME/Mga/MgaFCO.cpp	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/GME/Mga/MgaFCO.cpp	Wed Aug 21 14:40:13 2013	(r2299)
@@ -1234,16 +1234,16 @@
 		GUID t_guid;
 		t_guid.Data1 = v1;
 		t_guid.Data2 = (v2 >> 16);
-		t_guid.Data3 = (v2 << 16) >> 16;
+		t_guid.Data3 = v2 & 0xFFFF;
 		t_guid.Data4[0] = (v3 >> 24);
-		t_guid.Data4[1] = (v3 << 8) >> 24;
-		t_guid.Data4[2] = (v3 << 16) >> 24;
-		t_guid.Data4[3] = (v3 << 24) >> 24;
+		t_guid.Data4[1] = (v3 >> 16) & 0xFF;
+		t_guid.Data4[2] = (v3 >> 8) & 0xFF;
+		t_guid.Data4[3] = v3 & 0xFF;
 
 		t_guid.Data4[4] = (v4 >> 24);
-		t_guid.Data4[5] = (v4 << 8) >> 24;
-		t_guid.Data4[6] = (v4 << 16) >> 24;
-		t_guid.Data4[7] = (v4 << 24) >> 24;
+		t_guid.Data4[5] = (v4 >> 16) & 0xFF;
+		t_guid.Data4[6] = (v4 >> 8) & 0xFF;
+		t_guid.Data4[7] = v4 & 0xFF;
 
 		char buff[39];
 		sprintf( buff, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",

Modified: trunk/GME/Mga/MgaLibOps.cpp
==============================================================================
--- trunk/GME/Mga/MgaLibOps.cpp	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/GME/Mga/MgaLibOps.cpp	Wed Aug 21 14:40:13 2013	(r2299)
@@ -1377,17 +1377,17 @@
 	
 	GUID t_guid;
 	t_guid.Data1 = v1;
-	t_guid.Data2 = (v2 >> 16);
-	t_guid.Data3 = (v2 << 16) >> 16;
+	t_guid.Data2 = v2 >> 16;
+	t_guid.Data3 = v2 & 0xFFFF;
 	t_guid.Data4[0] = (v3 >> 24);
-	t_guid.Data4[1] = (v3 << 8) >> 24;
-	t_guid.Data4[2] = (v3 << 16) >> 24;
-	t_guid.Data4[3] = (v3 << 24) >> 24;
+	t_guid.Data4[1] = (v3 >> 16) & 0xFF;
+	t_guid.Data4[2] = (v3 >> 8) & 0xFF;
+	t_guid.Data4[3] = v3 & 0xFF;
 
 	t_guid.Data4[4] = (v4 >> 24);
-	t_guid.Data4[5] = (v4 << 8) >> 24;
-	t_guid.Data4[6] = (v4 << 16) >> 24;
-	t_guid.Data4[7] = (v4 << 24) >> 24;
+	t_guid.Data4[5] = (v4 >> 16) & 0xFF;
+	t_guid.Data4[6] = (v4 >> 8) & 0xFF;
+	t_guid.Data4[7] = v4 & 0xFF;
 
 	char buff[39];
 	sprintf( buff, "{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",

Modified: trunk/GME/Mga/MgaLibRefr.h
==============================================================================
--- trunk/GME/Mga/MgaLibRefr.h	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/GME/Mga/MgaLibRefr.h	Wed Aug 21 14:40:13 2013	(r2299)
@@ -85,17 +85,17 @@
 	{
 		const BinGuid &m_guid = *this;
 		p_guid.Data1 = m_guid.v1;
-		p_guid.Data2 = (m_guid.v2 >> 16);
-		p_guid.Data3 = (m_guid.v2 << 16) >> 16;
+		p_guid.Data2 = m_guid.v2 >> 16;
+		p_guid.Data3 = m_guid.v2 & 0xFFFF;
 		p_guid.Data4[0] = (m_guid.v3 >> 24);
-		p_guid.Data4[1] = (m_guid.v3 << 8) >> 24;
-		p_guid.Data4[2] = (m_guid.v3 << 16) >> 24;
-		p_guid.Data4[3] = (m_guid.v3 << 24) >> 24;
+		p_guid.Data4[1] = (m_guid.v3 >> 16) & 0xFF;
+		p_guid.Data4[2] = (m_guid.v3 >> 8) & 0xFF;
+		p_guid.Data4[3] = m_guid.v3 & 0xFF;
 
 		p_guid.Data4[4] = (m_guid.v4 >> 24);
-		p_guid.Data4[5] = (m_guid.v4 << 8) >> 24;
-		p_guid.Data4[6] = (m_guid.v4 << 16) >> 24;
-		p_guid.Data4[7] = (m_guid.v4 << 24) >> 24;
+		p_guid.Data4[5] = (m_guid.v4 >> 16) & 0xFF;
+		p_guid.Data4[6] = (m_guid.v4 >> 8) & 0xFF;
+		p_guid.Data4[7] = m_guid.v4 & 0xFF;
 	}
 };
 

Added: trunk/Tests/GPyUnit/SFDemo_dup_guids.mga
==============================================================================
Binary files /dev/null	00:00:00 1970	(empty, because file is newly added) and trunk/Tests/GPyUnit/SFDemo_dup_guids.mga	Wed Aug 21 14:40:13 2013	(r2299) differ

Modified: trunk/Tests/GPyUnit/__init__.py
==============================================================================
--- trunk/Tests/GPyUnit/__init__.py	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/Tests/GPyUnit/__init__.py	Wed Aug 21 14:40:13 2013	(r2299)
@@ -26,6 +26,7 @@
  'test_gmeoleapp',
  'test_parser',
  'test_copy',
+ 'test_mga_open',
  'test_registry',
  'test_instances',
  'GME_297.suite',

Modified: trunk/Tests/GPyUnit/test_copy.py
==============================================================================
--- trunk/Tests/GPyUnit/test_copy.py	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/Tests/GPyUnit/test_copy.py	Wed Aug 21 14:40:13 2013	(r2299)
@@ -7,7 +7,7 @@
     import os.path
     return os.path.join(os.path.dirname(os.path.abspath(__file__)), file)
 
-class TestParser(unittest.TestCase):
+class TestCopy(unittest.TestCase):
     def test_CopyFCODupGUID(self):
         mga = GPyUnit.util.parse_xme(self.connstr, _adjacent_file(r'..\..\Paradigms\SF\SFDemo.xme'))
         mga.Save()
@@ -29,7 +29,7 @@
     def connstr(self):
         return "MGA=" + _adjacent_file("copytest.mga")
 
-GPyUnit.util.MUGenerator(globals(), TestParser)
+GPyUnit.util.MUGenerator(globals(), TestCopy)
 
 if __name__ == "__main__":
         unittest.main()

Added: trunk/Tests/GPyUnit/test_mga_open.py
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/Tests/GPyUnit/test_mga_open.py	Wed Aug 21 14:40:13 2013	(r2299)
@@ -0,0 +1,45 @@
+from __future__ import with_statement
+
+import sys
+import os.path
+import unittest
+import GPyUnit.util
+import GPyUnit.util.gme
+from GPyUnit.util import DispatchEx
+
+def _adjacent_file(file):
+    import os.path
+    return os.path.join(os.path.dirname(os.path.abspath(__file__)), file)
+
+class TestMgaOpen(unittest.TestCase):
+    def __init__(self, name, **kwds):
+        super(TestMgaOpen, self).__init__(name, **kwds)
+        self.output_file = "test_mga_open-output.mga"
+        self.project = None
+        
+    def tearDown(self):
+        if not self.project is None:
+            self.project.Close(True)
+
+    def test(self):
+        from GPyUnit import util
+        util.register_xmp('SF')
+        with util.disable_early_binding():
+            self.project = DispatchEx("Mga.MgaProject")
+            self.project.Open("MGA=" + _adjacent_file('SFDemo_dup_guids.mga'))
+
+            self.project.BeginTransactionInNewTerr(0)
+            mga = self.project
+            self.assertEqual(mga.ObjectByPath('/@Folder1').GetGuidDisp(), '{8ce2ca06-2729-4e4c-955f-fc88194782cc}')
+            self.assertEqual(mga.ObjectByPath('/@Folder1/@System').GetGuidDisp(), '{a57ca6b2-d95e-485c-a768-98c16fd30588}')
+            self.assertEqual(mga.ObjectByPath('/@Folder1/@System/@DBSetup1').GetGuidDisp(), '{009ef956-cfe9-4b2a-9bed-3d486dfc71ce}')
+            self.assertNotEqual(mga.ObjectByPath('/@Folder1').GetGuidDisp(), mga.ObjectByPath('/@Folder2').GetGuidDisp())
+            self.assertNotEqual(mga.ObjectByPath('/@Folder1/@System').GetGuidDisp(), mga.ObjectByPath('/@Folder2/@System').GetGuidDisp())
+            self.assertNotEqual(mga.ObjectByPath('/@Folder1/@System/@DBSetup1').GetGuidDisp(), mga.ObjectByPath('/@Folder2/@System/@DBSetup1').GetGuidDisp())
+            self.project.AbortTransaction()
+            self.project.Save("MGA=" + _adjacent_file(self.output_file), False)
+            self.project.Close(True)
+
+
+if __name__ == "__main__":
+    unittest.main()

Modified: trunk/Tests/GPyUnit/test_parser.py
==============================================================================
--- trunk/Tests/GPyUnit/test_parser.py	Wed Aug 21 12:40:02 2013	(r2298)
+++ trunk/Tests/GPyUnit/test_parser.py	Wed Aug 21 14:40:13 2013	(r2299)
@@ -29,8 +29,10 @@
         try:
             mga.BeginTransactionInNewTerr()
             try:
+                self.assertEqual(mga.ObjectByPath('/@Folder1').GetGuidDisp(), '{8ce2ca06-2729-4e4c-955f-fc88194782cc}')
                 self.assertEqual(mga.ObjectByPath('/@Folder1/@System').GetGuidDisp(), '{a57ca6b2-d95e-485c-a768-98c16fd30588}')
                 self.assertEqual(mga.ObjectByPath('/@Folder1/@System/@DBSetup1').GetGuidDisp(), '{009ef956-cfe9-4b2a-9bed-3d486dfc71ce}')
+                self.assertNotEqual(mga.ObjectByPath('/@Folder1').GetGuidDisp(), mga.ObjectByPath('/@Folder2').GetGuidDisp())
                 self.assertNotEqual(mga.ObjectByPath('/@Folder1/@System').GetGuidDisp(), mga.ObjectByPath('/@Folder2/@System').GetGuidDisp())
                 self.assertNotEqual(mga.ObjectByPath('/@Folder1/@System/@DBSetup1').GetGuidDisp(), mga.ObjectByPath('/@Folder2/@System/@DBSetup1').GetGuidDisp())
             finally:


More information about the gme-commit mailing list