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);
            }
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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 _));
            }
        }
예제 #4
0
        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++;
                    }
                }
        }