Ejemplo n.º 1
0
        public async Task TestReplaceAndRemove()
        {
            var key1      = "key1";
            var value1    = "value1";
            var fallback1 = "fallback1";

            var s1 = new InMemoryKeyValueStore();
            var s2 = NewFileBasedKeyValueStore("TestReplaceAndRemoveDir").WithFallbackStore(s1);
            var s3 = new InMemoryKeyValueStore().WithFallbackStore(s2);

            await s1.Set(key1, value1);

            // Test that replace with same value via s3 returns the old value (which is also value1):
            Assert.Equal(value1, await s3.Set(key1, value1));
            // s3 will ask s2 which will ask s1 so the value will be returned correctly:
            Assert.Equal(value1, await s3.Get(key1, fallback1));
            Assert.Single(await s3.GetAllKeys());

            Assert.True(await s3.Remove(key1));
            // Setting it again will return null since it was removed from all stores:
            Assert.Null(await s3.Set(key1, value1));
            Assert.True(await s1.Remove(key1));                  // Remove it only from s1
            Assert.Equal(value1, await s3.Get(key1, fallback1)); // Still cached in s3 and s2
            // s1 had the key already removed, so the combined remove result will be false:
            Assert.False(await s3.Remove(key1));
        }
Ejemplo n.º 2
0
        public async Task TestDualStore()
        {
            var firstStore = new InMemoryKeyValueStore();
            var secondStor = new InMemoryKeyValueStore();

            var dualStore = new DualStore(firstStore, secondStor);

            var key1   = "key1";
            var key2   = "key2";
            var value1 = "v1";
            var fallb1 = "f1";

            Assert.False(await dualStore.ContainsKey(key1));
            Assert.Null(await dualStore.Set(key1, value1));
            Assert.True(await dualStore.ContainsKey(key1));
            Assert.True(await firstStore.ContainsKey(key1));
            Assert.False(await secondStor.ContainsKey(key1));

            Assert.Single(await dualStore.GetAllKeys());
            Assert.Single(await firstStore.GetAllKeys());
            Assert.Empty(await secondStor.GetAllKeys());

            Assert.Equal(value1, await dualStore.Get(key1, fallb1));
            Assert.Equal(value1, await firstStore.Get(key1, fallb1));
            Assert.Equal(fallb1, await secondStor.Get(key1, fallb1));
            Assert.Equal(fallb1, await dualStore.Get(key2, fallb1));

            Assert.True(await dualStore.Remove(key1));
            Assert.Equal(fallb1, await dualStore.Get(key1, fallb1));
            Assert.Equal(fallb1, await firstStore.Get(key1, fallb1));
            Assert.False(await dualStore.Remove(key2));
        }
Ejemplo n.º 3
0
        public async Task ExtendedTest1()
        {
            // Get your key from https://console.developers.google.com/apis/credentials
            var apiKey = "AIzaSyCtcFQMgRIUHhSuXggm4BtXT4eZvUrBWN0";
            // See https://docs.google.com/spreadsheets/d/1KBamVmgEUX-fyogMJ48TT6h2kAMKyWU1uBL5skCGRBM
            var sheetId           = "1KBamVmgEUX-fyogMJ48TT6h2kAMKyWU1uBL5skCGRBM";
            var sheetName         = "MySheet1"; // Has to match the sheet name
            var googleSheetsStore = new GoogleSheetsKeyValueStore(new InMemoryKeyValueStore(), apiKey, sheetId, sheetName);


            var localStore = new InMemoryKeyValueStore();
            var testStore  = new FeatureFlagStore(localStore, googleSheetsStore);

            IoC.inject.SetSingleton <FeatureFlagManager <FeatureFlag> >(new FeatureFlagManager <FeatureFlag>(testStore));

            var key1 = "MyFlag1";
            var key2 = "MyFlag2";
            var key3 = "MyFlag3";

            Assert.NotNull(await googleSheetsStore.Get <FeatureFlag>(key1, null));
            Assert.NotNull(await googleSheetsStore.Get <FeatureFlag>(key2, null));
            Assert.NotNull(await testStore.Get(key2, null));
            Assert.NotNull(await FeatureFlagManager <FeatureFlag> .instance.GetFeatureFlag(key2));

            Assert.False(await FeatureFlag.IsEnabled(key1));
            Assert.True(await FeatureFlag.IsEnabled(key2));

            var flag3_1 = await FeatureFlagManager <FeatureFlag> .instance.GetFeatureFlag(key3);

            Assert.Equal(40, flag3_1.rolloutPercentage);

            var localState3_1 = await localStore.Get <IFeatureFlagLocalState>(key3, null);

            var percent3_1 = localState3_1.randomPercentage;

            Assert.NotEqual(0, percent3_1);
            if (percent3_1 < flag3_1.rolloutPercentage)
            {
                Assert.True(await FeatureFlag.IsEnabled(key3));
            }
            else
            {
                Assert.False(await FeatureFlag.IsEnabled(key3));
            }
            localState3_1.randomPercentage = flag3_1.rolloutPercentage - 1;
            await localStore.Set(key3, localState3_1);

            var localState3_2 = await localStore.Get <IFeatureFlagLocalState>(key3, null);

            Assert.NotEqual(percent3_1, localState3_2.randomPercentage);

            var flag3_2 = await FeatureFlagManager <FeatureFlag> .instance.GetFeatureFlag(key3);

            Assert.Equal(localState3_2.randomPercentage, flag3_2.localState.randomPercentage);
            Assert.True(await flag3_2.IsEnabled());
            Assert.True(await FeatureFlag.IsEnabled(key3));
        }
Ejemplo n.º 4
0
        public async Task ExampleUsage2()
        {
            var storeDir = EnvironmentV2.instance.GetOrAddTempFolder("KeyValueStoreTests").GetChildDir("ExampleUsage2Dir");

            storeDir.DeleteV2(); // Cleanup before tests if the test file exists
            string   myKey1 = "test123";
            MyClass1 x1     = new MyClass1()
            {
                myString1 = "Abc", myString2 = "Abc2"
            };
            {   // Create a fast memory store and combine it with a LiteDB store that is persisted to disk:
                IKeyValueStore store = new InMemoryKeyValueStore().WithFallbackStore(new FileBasedKeyValueStore(storeDir));
                await store.Set(myKey1, x1);

                MyClass1 x2 = await store.Get <MyClass1>(myKey1, null);

                Assert.Equal(x1.myString1, x2.myString1);
                Assert.Equal(x1.myString2, x2.myString2);
            }
            { // Create a second store and check that the changes were persisted:
                IKeyValueStore store2 = new FileBasedKeyValueStore(storeDir);
                Assert.True(await store2.ContainsKey(myKey1));
                MyClass1 x2 = await store2.Get <MyClass1>(myKey1, null);

                Assert.Equal(x1.myString1, x2.myString1);
                Assert.Equal(x1.myString2, x2.myString2);
                Assert.True(await store2.Remove(myKey1));
                Assert.False(await store2.ContainsKey(myKey1));
            }
        }
Ejemplo n.º 5
0
        public async Task ExampleUsage1()
        {
            // Get your key from https://console.developers.google.com/apis/credentials
            var apiKey = "AIzaSyCtcFQMgRIUHhSuXggm4BtXT4eZvUrBWN0";
            // See https://docs.google.com/spreadsheets/d/1Hwu4ZtRR0iXD65Wuj_XyJxLw4PN8SE0sRgnBKeVoq3A
            var            sheetId   = "1Hwu4ZtRR0iXD65Wuj_XyJxLw4PN8SE0sRgnBKeVoq3A";
            var            sheetName = "MySheet1"; // Has to match the sheet name
            IKeyValueStore newsStore = new GoogleSheetsKeyValueStore(new InMemoryKeyValueStore(), apiKey, sheetId, sheetName);

            var         newsLocalDataStore = new InMemoryKeyValueStore().GetTypeAdapter <News.LocalData>();
            NewsManager manager            = new NewsManager(newsLocalDataStore, newsStore.GetTypeAdapter <News>());

            IEnumerable <News> allNews = await manager.GetAllNews();

            var news1 = allNews.First();

            Assert.NotNull(news1);
            Assert.Equal("New", news1.type);
            Assert.Equal(News.NewsType.New, news1.GetNewsType());
            Assert.True(news1.GetDate(true).IsUtc());

            // Mark that the user has read the news:
            await manager.MarkNewsAsRead(news1);

            Assert.True(allNews.First().localData.isRead);
            Assert.True((await manager.GetAllNews()).First().localData.isRead);
            Assert.True((await newsLocalDataStore.Get(news1.key, null)).isRead);

            IEnumerable <News> unreadNews = await manager.GetAllUnreadNews();

            Assert.Contains(news1, allNews);
            Assert.DoesNotContain(news1, unreadNews);
        }
Ejemplo n.º 6
0
        public async Task TestDelayStoreWithExponentialBackoffRetry()
        {
            // Simulates the DB on the server:
            var innerStore = new InMemoryKeyValueStore();
            // Simulates the connection to the server:
            var simulatedRemoteConnection = new MockDekayKeyValueStore().WithFallbackStore(innerStore);
            var requestRetry = new RetryKeyValueStore(simulatedRemoteConnection, maxNrOfRetries: 5);
            var outerStore   = new InMemoryKeyValueStore().WithFallbackStore(requestRetry);

            var key1      = "key1";
            var value1    = "value1";
            var key2      = "key2";
            var value2    = "value2";
            var fallback2 = "fallback2";

            {
                var delayedSetTask = outerStore.Set(key1, value1);
                Assert.Equal(value1, await outerStore.Get(key1, ""));    // The outer store already has the update
                Assert.NotEqual(value1, await innerStore.Get(key1, "")); // The inner store did not get the update yet
                // After waiting for set to fully finish the inner store has the update too:
                await delayedSetTask;
                Assert.Equal(value1, await innerStore.Get(key1, ""));
            }

            // Now simulate that the remote DB/server never can be reached:
            simulatedRemoteConnection.throwTimeoutError = true;

            {
                var timeoutErrorCounter = 0;
                // In the retry listen to any error if the wrapped store:
                requestRetry.onError = (e) => {
                    Assert.IsType <TimeoutException>(e); // thrown by the simulatedRemoteConnection
                    timeoutErrorCounter++;
                };

                var delayedSetTask = outerStore.Set(key2, value2);
                Assert.Equal(value2, await outerStore.Get(key2, fallback2)); // In the outer store the value was set
                Assert.False(await innerStore.ContainsKey(key2));            // The inner store never got the update

                // The delayedSetTask was canceled after 5 retries:
                await Assert.ThrowsAsync <OperationCanceledException>(async() => await delayedSetTask);

                // There will be 5 TimeoutException in the simulatedRemoteConnection:
                Assert.Equal(requestRetry.maxNrOfRetries, timeoutErrorCounter);
            }
        }
Ejemplo n.º 7
0
        private async Task TestPlayerPrefsFromBackgroundThreadTasks()
        {
            var myKey1      = "myKey1";
            var myVal1      = "myVal1";
            var myFallback1 = "myFallback1";

            var innerStore = new ExceptionWrapperKeyValueStore(new PlayerPrefsStore());
            await innerStore.Remove(myKey1); // Cleanup prefs from previous tests

            var outerStore = new InMemoryKeyValueStore().WithFallbackStore(innerStore);

            var task = TaskRunner.instance.RunInBackground(async(cancel) => {
                cancel.ThrowIfCancellationRequested();
                Assert.IsFalse(MainThread.isMainThread);

                var innerStoreThrewAnError = false;
                // Set and Get from a background thread will throw an exception in the innerStore
                innerStore.onError = (e) => { innerStoreThrewAnError = true; };
                // So only the outerStore will be updated when calling Set and Get from the background:
                await outerStore.Set(myKey1, myVal1);
                Assert.IsTrue(innerStoreThrewAnError);
                var x = await outerStore.Get(myKey1, myFallback1);
                // The value returned by Get was cached in the outer store so it will be correct:
                Assert.AreEqual(myVal1, x);
                // Check that the Set request never reached the real pref. store:
                Assert.AreEqual(myFallback1, await innerStore.Get(myKey1, myFallback1));
            }).task;
            await task;

            Assert.IsTrue(task.IsCompleted);
            Assert.IsNull(task.Exception);

            Assert.IsTrue(MainThread.isMainThread);
            // There should not be any errors when working on the main thread so
            // throw any errors that happen in the inner store:
            innerStore.onError = (e) => { throw e; };
            // In the main thread Set and Get will not throw errors:
            await outerStore.Set(myKey1, myVal1);

            Assert.AreEqual(myVal1, await outerStore.Get(myKey1, myFallback1));
            // Check that the Set request never reached the real pref. store:
            Assert.AreEqual(myVal1, await innerStore.Get(myKey1, myFallback1));
        }
Ejemplo n.º 8
0
        public async Task TestCachingValuesFromFallbackStores()
        {
            var key1      = "key1";
            var value1    = "value1";
            var fallback1 = "fallback1";

            var s1 = new InMemoryKeyValueStore();
            var s2 = NewFileBasedKeyValueStore("TestCachingValuesFromFallbackStoresDir").WithFallbackStore(s1);
            var s3 = new InMemoryKeyValueStore().WithFallbackStore(s2);

            await s1.Set(key1, value1);

            // s3 will ask s2 which will ask s1 so the value will be returned correctly:
            Assert.Equal(value1, await s3.Get(key1, fallback1));

            // Now the value should also be cached in the other stores, so s1 is not needed anymore:
            s2.fallbackStore = null;
            s3.fallbackStore = null;
            Assert.Equal(value1, await s2.Get(key1, fallback1));
            Assert.Equal(value1, await s3.Get(key1, fallback1));
        }
Ejemplo n.º 9
0
        public async Task TestStoreWithDelay()
        {
            // Simulates the DB on the server:
            var innerStore = new InMemoryKeyValueStore();
            // Simulates the connection to the server:
            var simulatedDelayStore = new MockDekayKeyValueStore().WithFallbackStore(innerStore);
            // Handles connection problems to the server:
            var exWrapperStore = new ExceptionWrapperKeyValueStore(simulatedDelayStore);
            // Represents the local cache in case the server cant be reached:
            var outerStore = new InMemoryKeyValueStore().WithFallbackStore(exWrapperStore);

            var key1   = "key1";
            var value1 = "value1";
            var key2   = "key2";
            var value2 = "value2";

            {
                var delayedSetTask = outerStore.Set(key1, value1);
                Assert.Equal(value1, await outerStore.Get(key1, ""));    // The outer store already has the update
                Assert.NotEqual(value1, await innerStore.Get(key1, "")); // The inner store did not get the update yet
                // After waiting for set to fully finish the inner store has the update too:
                await delayedSetTask;
                Assert.Equal(value1, await innerStore.Get(key1, ""));
            }

            simulatedDelayStore.throwTimeoutError = true;
            var simulatedErrorCatched = false;

            exWrapperStore.onError = (Exception e) => { simulatedErrorCatched = true; };

            {
                await outerStore.Set(key2, value2); // This will cause a timeout error in the "delayed" store

                Assert.True(simulatedErrorCatched);
                Assert.Contains(key2, await outerStore.GetAllKeys()); // In the outer store the value was set
                Assert.False(await innerStore.ContainsKey(key2));     // The inner store never got the update
                Assert.False(await exWrapperStore.ContainsKey(key2)); // The exc. wrapper returns false if an error is thrown
                Assert.Null(await exWrapperStore.GetAllKeys());       // Will throw another error and return null
            }
        }
Ejemplo n.º 10
0
        public async Task ExampleUsage3()
        {
            // Simulate the DB on the server
            var simulatedDb = new InMemoryKeyValueStore();
            // Simulate the connection (with a delay) to the server:
            var simulatedRemoteConnection = new MockDelayKeyValueStore(simulatedDb);

            // The connection to the server is wrapped by a automatic retry for failing requests:
            var requestRetry = new RetryKeyValueStore(simulatedRemoteConnection, maxNrOfRetries: 5);
            // Any errors in the inner layers like connection errors, DB errors are catched by default:
            var errorHandler = new ExceptionWrapperKeyValueStore(requestRetry);
            // The outer store is a local in memory cache and the main point of contact:
            var outerStore = new InMemoryKeyValueStore().WithFallbackStore(errorHandler);

            var key1      = "key1";
            var value1    = "value1";
            var fallback1 = "fallback1";
            await outerStore.Set(key1, value1);

            Assert.Equal(value1, await outerStore.Get(key1, fallback1));
            Assert.Equal(value1, await simulatedDb.Get(key1, fallback1));

            // Simmulate connection problems to the remote DB:
            simulatedRemoteConnection.throwTimeoutError = true;

            var key2      = "key2";
            var value2    = "value2";
            var fallback2 = "fallback2";
            // Awaiting a set will take some time since there will be 5 retries:
            await outerStore.Set(key2, value2);

            // The outer store has the set value cached:
            Assert.Equal(value2, await outerStore.Get(key2, fallback2));
            // But the request never reached the simulated DB:
            Assert.False(await simulatedDb.ContainsKey(key2));
        }
Ejemplo n.º 11
0
        public void ExampleUsage1()
        {
            IKeyValueStore store  = new InMemoryKeyValueStore();
            string         myKey1 = "myKey1";
            MyClass1       x1     = new MyClass1()
            {
                myString1 = "Abc", myString2 = "Abc2"
            };

            store.Set(myKey1, x1);
            MyClass1 x2 = store.Get <MyClass1>(myKey1, defaultValue: null).Result;

            Assert.Equal(x1.myString1, x2.myString1);
            Assert.Equal(x1.myString2, x2.myString2);
        }
        public void PutKeyExist()
        {
            var serdes = new StringSerDes();

            byte[] key = serdes.Serialize("key", new SerializationContext()),
            value  = serdes.Serialize("value", new SerializationContext()),
            value2 = serdes.Serialize("value2", new SerializationContext());

            var store = new InMemoryKeyValueStore("store");

            store.Put(new Bytes(key), value);
            store.Put(new Bytes(key), value2);
            Assert.AreEqual(1, store.ApproximateNumEntries());
            var v = store.Get(new Bytes(key));

            Assert.AreEqual("value2", serdes.Deserialize(v, new SerializationContext()));
        }
Ejemplo n.º 13
0
        public async Task TestExceptionCatching()
        {
            var    myKey1          = "key1";
            int    myValue1        = 1;
            string myDefaultString = "myDefaultValue";

            var innerStore     = new InMemoryKeyValueStore();
            var exHandlerStore = new ExceptionWrapperKeyValueStore(innerStore, new HashSet <Type>());

            await innerStore.Set(myKey1, myValue1);

            // Cause an InvalidCastException:
            await Assert.ThrowsAsync <InvalidCastException>(() => innerStore.Get <string>(myKey1, myDefaultString));

            // Cause an InvalidCastException which is then catched and instead the default is returned:
            string x = await exHandlerStore.Get <string>(myKey1, myDefaultString);

            Assert.Equal(myDefaultString, x);

            // Add the InvalidCastException to the list of errors that should not be ignored:
            exHandlerStore.errorTypeBlackList.Add(typeof(InvalidCastException));
            // Now the same Get request passes the InvalidCastException on:
            await Assert.ThrowsAsync <InvalidCastException>(() => exHandlerStore.Get <string>(myKey1, myDefaultString));
        }