private void WriteTest(string name, Instruction[] instructions, string input, CacheBuilder inputCache, string output, CacheBuilder outputCache, int?nopBreakpointId)
        {
            Trace.WriteLine(name);

            // generate sourcecode
            var cw = new CodeWriter(new StringWriter());

            cw.EmitDebugInfo       = DebugEnabled;
            cw.EmitDebugBreakpoint = DebugEnabled && nopBreakpointId == null;

            // cw.Begin(); // cache initialized by cache builder
            foreach (var insn in instructions)
            {
                if (insn.Prototype == InstructionPrototypes.Nop &&
                    insn.Get(0) == nopBreakpointId)
                {
                    cw.Write(new Instruction(InstructionPrototypes.Breakpoint));
                }

                cw.Write(insn);
            }

            cw.End();

            Trace.WriteLine(cw.Writer);
            this.DumpInfo("Input   ", input, inputCache.Build(), inputCache.CachePointer);
            this.DumpInfo("Expected", output, outputCache.Build(), outputCache.CachePointer);

            // run code
            var intptr = new BrainfuckInterpreter(cw.Writer.ToString(), inputCache.Build());

            intptr.Input        = new StringReader(input);
            intptr.Output       = new StringWriter();
            intptr.CachePointer = inputCache.CachePointer;

            if (nopBreakpointId != null)
            {
                intptr.NextBreakpoint();
                Assert.IsFalse(intptr.Terminated, "terminated");
            }
            else
            {
                intptr.Run();
            }

            this.DumpInfo("Actual  ", intptr.Output.ToString(), intptr.Cache, intptr.CachePointer);

            // asserts
            var prefix = $"\nTestcase: {name}\n";

            outputCache.CacheSize = inputCache.CacheSize;
            CollectionAssert.AreEqual(outputCache.Build(), intptr.Cache, prefix + "cache");
            Assert.AreEqual(outputCache.CachePointer, intptr.CachePointer, prefix + "cache pointer");
            Assert.AreEqual(output, intptr.Output.ToString(), prefix + "output");
        }
        public CachedFunctionWithSingleKey(
            Func <TParams, CancellationToken, ValueTask <TValue> > originalFunction,
            Func <TParams, TKey> keySelector,
            CachedFunctionWithSingleKeyConfiguration <TParams, TKey, TValue> config)
        {
            _originalFunction  = originalFunction;
            _keySelector       = keySelector;
            _onSuccessAction   = config.OnSuccessAction;
            _onExceptionAction = config.OnExceptionAction;

            if (config.DisableCaching)
            {
                _cache = NullCache <TKey, TValue> .Instance;
            }
            else
            {
                if (config.TimeToLive.HasValue)
                {
                    _timeToLive = config.TimeToLive.Value;
                }
                else
                {
                    _timeToLiveFactory = config.TimeToLiveFactory;
                }

                _cache = CacheBuilder.Build(config);
                _skipCacheGetPredicate = config.SkipCacheGetPredicate;
                _skipCacheSetPredicate = config.SkipCacheSetPredicate;
            }

            _cacheStatsIfSkipped = GetCacheStatsIfSkipped();
            _cacheEnabled        = _cache.LocalCacheEnabled || _cache.DistributedCacheEnabled;
            _measurementsEnabled = _onSuccessAction != null || _onExceptionAction != null;
        }
Exemplo n.º 3
0
        public async Task Sample2WithFluentApi()
        {
            // This func is to fetch the value from the data source. In this case it
            // is just a random generator, but this could be anything like a web service or database.
            // The parameter should be the same type as your cache key type, and the return value
            // should be the same type as your cache's value type.
            Func <int, Task <string> > loaderFunction = async(key) =>
            {
                int rnd = new Random().Next();
                return(await Task.FromResult(string.Format("value{0}", rnd)));
            };

            var cache = CacheBuilder.Build <int, string>()
                        .WithName(nameof(Sample2WithFluentApi))
                        .CacheItemExpiryFromSeconds(1)
                        .CacheItemExpiryPercentageRandomization(0)
                        .FlushIntervalFromSeconds(5)
                        .MaximumCacheSizeIndicator(100)
                        .CircuitBreakerTimeoutForAdditionalThreadsPerKeyFromSeconds(10)
                        .DisposeExpiredValuesIfDisposable()
                        .LoaderFunction(loaderFunction)
                        .Create();

            // Record the first hit values for 100 keys
            var firstHitValues = new List <string>();

            for (int key = 0; key < 100; key++)
            {
                var value = await cache.GetOrLoadAsync(key);

                firstHitValues.Add(value);
            }

            // Assert that 50 subsequent hits return the same values for all 100 keys.
            for (int i = 0; i < 50; i++)
            {
                for (int key = 0; key < 100; key++)
                {
                    var value = await cache.GetOrLoadAsync(key);

                    Assert.AreEqual(firstHitValues[key], value);
                }
            }

            // Wait a while so that all cache entries expire as per the configured options
            Thread.Sleep(1000);

            // Assert that the next hit returns fresh values. i.e. not equal to the first hit values.
            for (int key = 0; key < 100; key++)
            {
                var value = await cache.GetOrLoadAsync(key);

                Assert.AreNotEqual(firstHitValues[key], value);
            }
        }
        public CachedFunctionWithOuterKeyAndInnerEnumerableKeys(
            Func <TParams, ReadOnlyMemory <TInnerKey>, CancellationToken, ValueTask <IEnumerable <KeyValuePair <TInnerKey, TValue> > > > originalFunction,
            Func <TParams, TOuterKey> keySelector,
            CachedFunctionWithOuterKeyAndInnerEnumerableKeysConfiguration <TParams, TOuterKey, TInnerKey, TValue> config)
        {
            _originalFunction        = originalFunction;
            _keySelector             = keySelector;
            _maxBatchSize            = config.MaxBatchSize;
            _maxBatchSizeFactory     = config.MaxBatchSizeFactory;
            _batchBehaviour          = config.BatchBehaviour;
            _onSuccessAction         = config.OnSuccessAction;
            _onExceptionAction       = config.OnExceptionAction;
            _filterResponsePredicate = config.FilterResponsePredicate;

            if (config.DisableCaching)
            {
                _cache = NullCache <TOuterKey, TInnerKey, TValue> .Instance;
            }
            else
            {
                if (config.TimeToLive.HasValue)
                {
                    _timeToLive = config.TimeToLive.Value;
                }
                else
                {
                    _timeToLiveFactory = config.TimeToLiveFactory;
                }

                _cache       = CacheBuilder.Build(config);
                _keyComparer = config.KeyComparer ?? EqualityComparer <TInnerKey> .Default;
                _skipCacheGetOuterPredicate = config.SkipCacheGetOuterPredicate;
                _skipCacheGetInnerPredicate = config.SkipCacheGetInnerPredicate;
                _skipCacheSetOuterPredicate = config.SkipCacheSetOuterPredicate;
                _skipCacheSetInnerPredicate = config.SkipCacheSetInnerPredicate;
            }

            if (config.FillMissingKeysConstantValue.IsSet)
            {
                _shouldFillMissingKeys = true;
                _shouldFillMissingKeysWithConstantValue = true;
                _fillMissingKeysConstantValue           = config.FillMissingKeysConstantValue.Value;
            }
            else if (!(config.FillMissingKeysValueFactory is null))
            {
                _shouldFillMissingKeys       = true;
                _fillMissingKeysValueFactory = config.FillMissingKeysValueFactory;
            }

            _cacheEnabled        = _cache.LocalCacheEnabled || _cache.DistributedCacheEnabled;
            _measurementsEnabled = _onSuccessAction != null || _onExceptionAction != null;
        }
Exemplo n.º 5
0
        public void Build_HappyPath_ReturnsCacheObject()
        {
            var result = _sut.Build();

            result.Should().NotBeNull();
        }
Exemplo n.º 6
0
        public async Task Sample3WithFluentApiAndRandomItemExpiry()
        {
            // This func is to fetch the value from the data source. In this case it
            // is just a random generator, but this could be anything like a web service or database.
            // The parameter should be the same type as your cache key type, and the return value
            // should be the same type as your cache's value type.
            Func <int, Task <string> > loaderFunction = async(key) =>
            {
                int rnd = new Random().Next();
                return(await Task.FromResult(string.Format("value{0}", rnd)));
            };

            int expiryMs = 1000;
            var cache    = CacheBuilder.Build <int, string>()
                           .WithName(nameof(Sample3WithFluentApiAndRandomItemExpiry))
                           .CacheItemExpiryFromMilliseconds(expiryMs)
                           .CacheItemExpiryPercentageRandomization(100)
                           .FlushIntervalFromSeconds(5)
                           .MaximumCacheSizeIndicator(100)
                           .CircuitBreakerTimeoutForAdditionalThreadsPerKeyFromSeconds(10)
                           .DisposeExpiredValuesIfDisposable()
                           .LoaderFunction(loaderFunction)
                           .Create();

            // Record the first hit values for 100 keys
            var firstHitValues = new List <string>();

            for (int key = 0; key < 100; key++)
            {
                var value = await cache.GetOrLoadAsync(key);

                firstHitValues.Add(value);
            }

            // Assert that 10 subsequent hits return the same values for all 100 keys.
            for (int i = 0; i < 10; i++)
            {
                for (int key = 0; key < 100; key++)
                {
                    var value = await cache.GetOrLoadAsync(key);

                    value.Should().Be(firstHitValues[key]);
                }
            }

            // Wait the expiry time so that about half the cache entries randomly expire as per the configured options
            await Task.Delay(expiryMs);

            // Assert that the next hit returns fresh values. i.e. not equal to the first hit values.
            int oldValueCount = 0;
            int newValueCount = 0;

            for (int key = 0; key < 100; key++)
            {
                var value = await cache.GetOrLoadAsync(key);

                if (value == firstHitValues[key])
                {
                    oldValueCount++;
                }
                else
                {
                    newValueCount++;
                }
            }

            // Statistically, it should be about 50/50 split, but for this test to pass reliably, we considder 30% on either side success.
            oldValueCount.Should().BeGreaterOrEqualTo(30, "about half should have not yet expired");
            newValueCount.Should().BeGreaterOrEqualTo(30, "about half should have expired already");
        }