public async Task GetObject_String_VerifyMatches(string content) { using (SharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) { // Put content into shared memory SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); // Get object from shared memory object readObject = await manager.GetObjectAsync(metadata.Name, 0, content.Length, typeof(string)); string readContent = readObject as string; // Verify read content matches the content that was written Assert.Equal(content, readContent); } }
public async Task PutObject_ByteArray_VerifySuccess(int contentSize) { using (SharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) { // Prepare content byte[] content = TestUtils.GetRandomBytesInArray(contentSize); // Put into shared memory SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); // Verify expected results Assert.NotNull(metadata); Assert.NotNull(metadata.MemoryMapName); Assert.True(Guid.TryParse(metadata.MemoryMapName, out _)); Assert.Equal(contentSize, metadata.Count); } }
public async Task FreeSharedMemoryMap_VerifySuccess() { // Prepare content string content = "foobar"; using (SharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) { // Put content into shared memory SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); string mapName = metadata.MemoryMapName; // Free the shared memory map and try top open it after freeing; should not open Assert.True(manager.TryFreeSharedMemoryMap(mapName)); Assert.False(_mapAccessor.TryOpen(mapName, out _)); } }
public async Task GetObject_ByteArray_VerifyMatches(int contentSize) { using (SharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) { // Prepare content and put into shared memory byte[] content = TestUtils.GetRandomBytesInArray(contentSize); SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); // Get object from shared memory object readObject = await manager.GetObjectAsync(metadata.MemoryMapName, 0, contentSize, typeof(byte[])); byte[] readContent = readObject as byte[]; // Verify read content matches the content that was written Assert.True(TestUtils.UnsafeCompare(content, readContent)); } }
public async Task PutObject_NoEvictions_VerifyGet(int contentSize) { using (ISharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) using (FunctionDataCache cache = new FunctionDataCache(manager, _loggerFactory, _testEnvironment)) { // Prepare content byte[] content = TestUtils.GetRandomBytesInArray(contentSize); // Put into shared memory SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); // Put into cache FunctionDataCacheKey key = new FunctionDataCacheKey("foo", "bar"); Assert.True(cache.TryPut(key, metadata, isIncrementActiveReference: false, isDeleteOnFailure: false)); // Get from cache Assert.True(cache.TryGet(key, isIncrementActiveReference: false, out SharedMemoryMetadata getMetadata)); // Compare if the obtained values are equal Assert.Equal(metadata, getMetadata); } }
public async Task PutObject_FailToPut_DoNotDeleteOnFailure() { int contentSize = 4 * 1024 * 1024; // 4MB int cacheSize = 3 * 1024 * 1024; // 3MB string cacheSizeVal = cacheSize.ToString(); IEnvironment environment = new TestEnvironment(); environment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheMaximumSizeBytesSettingName, cacheSizeVal); environment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheEnabledSettingName, "1"); using (SharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) using (FunctionDataCache cache = new FunctionDataCache(manager, _loggerFactory, environment)) { // Prepare content byte[] content = TestUtils.GetRandomBytesInArray(contentSize); // Put into shared memory SharedMemoryMetadata metadata = await manager.PutObjectAsync(content); // Try to put the object into the cache; this will fail because the cache is smaller than the object size. // Since isDeleteOnFailure is false, the object will not be deleted from shared memory. FunctionDataCacheKey key = new FunctionDataCacheKey("foo", "bar"); Assert.False(cache.TryPut(key, metadata, isIncrementActiveReference: true, isDeleteOnFailure: false)); // Ensure that nothing was cached and no references are held Assert.Empty(cache.LRUList); Assert.Empty(cache.ActiveReferences); Assert.Equal(cacheSize, cache.RemainingCapacityBytes); // Ensure that the SharedMemoryManager has the allocated memory map and it was not deleted Assert.Equal(1, manager.AllocatedSharedMemoryMaps.Count); // Try to open the shared memory map of the first object and ensure it exists and can be opened Assert.True(_mapAccessor.TryOpen(metadata.MemoryMapName, out var _)); } }
public async Task PutObject_ActiveReference_VerifyCorrectObjectEvicted() { int contentSize = 2 * 1024 * 1024; // 2MB int cacheSize = 6 * 1024 * 1024; // 6MB string cacheSizeVal = cacheSize.ToString(); IEnvironment environment = new TestEnvironment(); environment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheMaximumSizeBytesSettingName, cacheSizeVal); environment.SetEnvironmentVariable(FunctionDataCacheConstants.FunctionDataCacheEnabledSettingName, "1"); using (ISharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) using (FunctionDataCache cache = new FunctionDataCache(manager, _loggerFactory, environment)) { // Prepare content byte[] content = TestUtils.GetRandomBytesInArray(contentSize); // Put into shared memory as three distinct objects List <SharedMemoryMetadata> metadatas = new List <SharedMemoryMetadata>() { await manager.PutObjectAsync(content), await manager.PutObjectAsync(content), await manager.PutObjectAsync(content), }; // Put the three objects into the cache List <FunctionDataCacheKey> keys = new List <FunctionDataCacheKey>() { new FunctionDataCacheKey("foo_1", "bar_1"), new FunctionDataCacheKey("foo_2", "bar_2"), new FunctionDataCacheKey("foo_3", "bar_3"), }; // Put object (1) with an active reference Assert.True(cache.TryPut(keys[0], metadatas[0], isIncrementActiveReference: true, isDeleteOnFailure: false)); // Put objects (2) and (3) with NO active reference Assert.True(cache.TryPut(keys[1], metadatas[1], isIncrementActiveReference: false, isDeleteOnFailure: false)); Assert.True(cache.TryPut(keys[2], metadatas[2], isIncrementActiveReference: false, isDeleteOnFailure: false)); // Access the middle object so that now it is the most recently used Assert.True(cache.TryGet(keys[1], isIncrementActiveReference: false, out var _)); // The order of objects in LRU should be 1->3->2. // Since 2 is the most recently used, it is at the end of the list. // Evict an object and check that the right object was evicted (3) // Object (1) will not be evicted because it has an active reference even though it is before object (3) in the LRU list. Assert.True(cache.EvictOne()); Assert.False(cache.TryGet(keys[2], isIncrementActiveReference: false, out var _)); // Check if the other objects are still present; // We cannot check using TryGet as that will impact the LRU ordering Assert.Contains(keys[0], cache.LRUList); Assert.Contains(keys[1], cache.LRUList); // Evict an object and check that the right object was evicted (2) Assert.True(cache.EvictOne()); Assert.False(cache.TryGet(keys[1], isIncrementActiveReference: false, out var _)); // Check if the other object are still present; // We cannot check using TryGet as that will impact the LRU ordering Assert.Contains(keys[0], cache.LRUList); // The only object left is object (1) but it has an active reference so cannot be evicted Assert.False(cache.EvictOne()); Assert.Contains(keys[0], cache.LRUList); // Decrement the reference on object (1) cache.DecrementActiveReference(keys[0]); // Now object (1) should be evicted and the cache should be empty Assert.True(cache.EvictOne()); Assert.Empty(cache.LRUList); Assert.Empty(cache.ActiveReferences); Assert.Equal(cacheSize, cache.RemainingCapacityBytes); } }
public async Task PutThreeObjects_GetOne_VerifyLRUOrder() { int contentSize = 2 * 1024 * 1024; // 2MB using (ISharedMemoryManager manager = new SharedMemoryManager(_loggerFactory, _mapAccessor)) using (FunctionDataCache cache = new FunctionDataCache(manager, _loggerFactory, _testEnvironment)) { // Prepare content byte[] content = TestUtils.GetRandomBytesInArray(contentSize); // Put into shared memory as three distinct objects List <SharedMemoryMetadata> metadatas = new List <SharedMemoryMetadata>() { await manager.PutObjectAsync(content), await manager.PutObjectAsync(content), await manager.PutObjectAsync(content), }; // Put the three objects into the cache List <FunctionDataCacheKey> keys = new List <FunctionDataCacheKey>() { new FunctionDataCacheKey("foo_1", "bar_1"), new FunctionDataCacheKey("foo_2", "bar_2"), new FunctionDataCacheKey("foo_3", "bar_3"), }; for (int i = 0; i < 3; i++) { Assert.True(cache.TryPut(keys[i], metadatas[i], isIncrementActiveReference: false, isDeleteOnFailure: false)); } // Access the middle object so that now it is the most recently used Assert.True(cache.TryGet(keys[1], isIncrementActiveReference: false, out var _)); // The order of objects in LRU should be 1->3->2. // Since 2 is the most recently used, it is add the end of the list. int pos = 1; foreach (FunctionDataCacheKey key in cache.LRUList) { string keyId = key.Id; int num = int.Parse(keyId.Split("_")[1]); int expected; if (pos == 1) { expected = 1; } else if (pos == 2) { expected = 3; } else if (pos == 3) { expected = 2; } else { throw new Exception("Unexpected position"); } Assert.Equal(expected, num); pos++; } } }