public void TestAddOrUpdate()
        {
            var comPlusCache = new ComPlusCache("TestCache");

            comPlusCache.Clear();
            Assert.AreEqual("World", comPlusCache.AddOrUpdate("Entry 1", () => "World", () => "Hello"));
            Assert.AreEqual("World", comPlusCache["Entry 1"]);
            Assert.AreEqual("Brave New World",
                            comPlusCache.AddOrUpdate("Entry 1", () => "Hello World", () => "Brave New World"));
            Assert.AreEqual("Brave New World 2",
                            comPlusCache.AddOrUpdate("Entry 1", () => "Hello World", () => "Brave New World 2"));
            Assert.AreEqual("Brave New World 3",
                            comPlusCache.AddOrUpdate("Entry 1", () => "Hello World", () => "Brave New World 3"));
            comPlusCache.AddOrUpdate("Entry 2", () => new Dynamo(), () => null);
            Assert.IsNotNull(comPlusCache["Entry 2"]);
            Assert.IsTrue(comPlusCache["Entry 2"] is DynamicObject);
        }
        public void TestStressConcurrent()
        {
            const int threadCount = 4;
            const int loops       = 1000;
            var       totalLoops  = 0;
            var       threads     = new Thread[threadCount];

            for (var i = 0; i < threadCount; i++)
            {
                (threads[i] = new Thread(context =>
                {
                    var externalCache = new ComPlusCache();
                    for (var j = 0; j < loops; j++)
                    {
                        var item = new Dynamo();
                        var item2 = new Dynamo();
                        item["P1"] = "Property " + j;
                        externalCache.AddOrUpdate($"Item {(int) context}-{j}", () => item, () => item2);
                        Assert.IsTrue(externalCache.Contains($"Item {(int) context}-{j}"));
                        var returnedItem = (Dynamo)externalCache.Get($"Item {(int) context}-{j}");
                        Assert.AreEqual("Property " + j, returnedItem["P1"]);
                        externalCache.Remove($"Item {(int) context}-{j}");
                        Assert.IsFalse(externalCache.Contains($"Item {(int) context}-{j}"));
                        externalCache.AddOrUpdate($"Item {j}", () => item, () => item2);
                        Assert.IsTrue(externalCache.Contains($"Item {j}"));
                        var item3 = externalCache.GetOrAdd($"Item {j}", () => item2);
                        Assert.IsNotNull(item3);
                        Interlocked.Increment(ref totalLoops);
                    }
                })).Start(i);
            }
            foreach (var thread in threads)
            {
                thread.Join();
            }
            Assert.AreEqual(threadCount * loops, totalLoops);
        }
        public void TestAddOrUpdateParallelWithSameComPlusReference()
        {
            var cd = new ComPlusCache("Concurrent");

            //var dict = new ConcurrentDictionary<string, int>();
            cd.Clear();
            var addCnt   = 0;
            var updCnt   = 0;
            var totalCnt = 0;

            Parallel.For(0, 10000, i =>
            {
                Interlocked.Increment(ref totalCnt);
                cd.AddOrUpdate("1", () =>
                {
                    Interlocked.Increment(ref addCnt);
                    return(1);
                }, () =>
                {
                    Interlocked.Increment(ref updCnt);
                    return(new Random().Next(10000));
                });
            });
            var cnt = 0;

            // ReSharper disable once UnusedVariable
            foreach (var item in cd)
            {
                cnt++;
            }
            Assert.AreEqual(1, cnt);
            Assert.AreEqual(10000, totalCnt);
            Assert.AreEqual(1, addCnt);
            Assert.AreEqual(9999, updCnt);
            Assert.AreNotEqual(-1, (int)cd["1"]);

            int value = (int)cd.GetOrAdd("2", () => 100);

            Assert.AreEqual(100, value);

            // Should return 100, as key 2 is already set to that value
            value = (int)cd.GetOrAdd("2", () => 10000);
            Assert.AreEqual(100, value);
        }