// Test that buffer of array does not move during compaction if fixed keyword applied. static bool TestCompactionForNotFixedArray() { bool retVal = true; // First we create objects and holes that keeps some space that could be used by compaction. // Small count so compaction does not happen. object[] arrayOfArrays = new object[10]; RunAllocations(arrayOfArrays); // This is the array that we expect to move in during compaction. int[] testNativeBuffer = new int[100]; // Fill it, so it is not optimized out for (int i = 0; i < testNativeBuffer.Length; i++) { testNativeBuffer[i] = i; } // Address before compaction uint addrBeforeCompaction = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); // Causes compaction. InitiateCompactoin(); // Address after compaction. uint addrAfterCompaction = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); // Should be different addresses. retVal = addrBeforeCompaction != addrAfterCompaction; if (retVal) { Debug.Print("Testing of buffer move during compaction succeeded"); } else { Debug.Print("Testing of fixed keyword failed"); } return(retVal); }
// Test that buffer of array actually moves during compaction. unsafe static bool TestCompactionForFixedArray() { bool retVal = true; // First we create objects and holes that keeps some space that could be used by compaction. // Small count so compaction does not happen. object[] arrayOfArrays = new object[10]; RunAllocations(arrayOfArrays); // This is the array that we expect to move in during compaction. int[] testNativeBuffer = new int[100]; // Fill it, so it is not optimized out for (int i = 0; i < testNativeBuffer.Length; i++) { testNativeBuffer[i] = i; } fixed(int *pFixedArray = testNativeBuffer) { // Address before compaction uint addrBeforeCompaction = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); // Causes compaction. InitiateCompactoin(); // Address after compaction. uint addrAfterCompaction = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); // Should be equal addresses, becuase array was pinned. retVal = addrBeforeCompaction == addrAfterCompaction; // Check that access to the buffer through the reference is the same as through array for (int i = 0; i < testNativeBuffer.Length; i++) { retVal = retVal && (pFixedArray[i] == testNativeBuffer[i]); } // Update the data of array through reference, then check that it was updated properly Random random = new Random(); for (int i = 0; i < testNativeBuffer.Length; i++) { int value = 2 * random.Next(); pFixedArray[i] = value; // Check that value is set properly and can be accessed through reference and array if (pFixedArray[i] != value || testNativeBuffer[i] != value) { retVal = false; } } // Test that access through *pFixedArray is the same as pFixedArray[0]; *pFixedArray = 2 * random.Next(); if (pFixedArray[0] != *pFixedArray || testNativeBuffer[0] != *pFixedArray) { retVal = false; } } // Since we exited "fixed" block, the testNativeBuffer is now movable. // It is very important to see that now buffer moves, this is the prove that it was unpinned. . uint addrBeforeCompaction1 = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); InitiateCompactoin(); uint addrAfterCompaction1 = TestBasicTypes.Get_Buffer_Address_Array(testNativeBuffer); // Verifies that now buffer moved. retVal = retVal && (addrBeforeCompaction1 != addrAfterCompaction1); if (retVal) { Debug.Print("Testing of fixed keyword succeded"); } else { Debug.Print("Testing of fixed keyword failed"); } return(retVal); }