예제 #1
0
        public void TestCompression()
        {
            var tree     = new RadixTree <Service>();
            var service  = new Service(new string[0], "Service1Test", "Address1Test", 10000, "node1", new string[0]);
            var service2 = new Service(new string[0], "Service1Test", "Address2Test", 10000, "node1", new string[0]);

            tree.AddServiceToRoute("/test1/test2/test3/test4/test5", service);
            tree.AddServiceToRoute("/test1/test2/test3/test4/test5/test6", service2);

            Assert.Equal(1, tree.GetTopNode().ChildrenNodes.Count);

            tree.Compress();

            ////We should have 1 node in the tree
            Assert.Equal(1, tree.GetTopNode().ChildrenNodes.Count);

            ////The key length should be 5 long
            Assert.Equal(5, tree.GetTopNode().ChildrenNodes.KeyLength);

            string matchedpath;
            var    returnservice = tree.GetServiceFromRoute("/test1/test2/test3/test4/test5/test7", out matchedpath);

            Assert.Equal("/test1/test2/test3/test4/test5", matchedpath);
            Assert.Equal(returnservice.ServiceId, service.ServiceId);
        }
예제 #2
0
        public void TestSplitting()
        {
            var tree     = new RadixTree <Service>();
            var service  = new Service(new string[0], "Service1Test", "Address1Test", 10000, "node1", new string[0]);
            var service2 = new Service(new string[0], "Service1Test", "Address2Test", 10000, "node1", new string[0]);

            tree.AddServiceToRoute("/test1/test2/test3/test4/test5", service);
            tree.AddServiceToRoute("/test1/test2/test3/test4/test5/test6", service);

            tree.Compress();

            //Time to split the tree it should be 5 long at the moment but this should make it 2 long and then split
            tree.AddServiceToRoute("/test1/test2/test10/test6/test4/test6", service);

            var topNode = tree.GetTopNode();

            //Check the first node is two long
            Assert.Equal(2, topNode.ChildrenNodes.KeyLength);

            //find the root common node
            var commonNode = topNode.ChildrenNodes[new string[] { "test1", "test2" }];

            //check the keys are consistant
            foreach (var kv in commonNode.ChildrenNodes)
            {
                Assert.Equal(kv.Key.Length, commonNode.ChildrenNodes.KeyLength);
            }
        }
예제 #3
0
        //~ func TestDelete(t *testing.T) {
        public void TestDelete()
        {
            //~ r := New()
            var r = new RadixTree <int>();

            //~ s := []string{"", "A", "AB"}
            var s = new string[] { "", "A", "AB" };

            //~ for _, ss := range s {
            //~     r.Insert(ss, true)
            //~ }
            foreach (var ss in s)
            {
                r.GoInsert(ss, 1);
            }

            //~ for _, ss := range s {
            //~     _, ok := r.Delete(ss)
            //~     if !ok {
            //~         t.Fatalf("bad %q", ss)
            //~     }
            //~ }
            foreach (var ss in s)
            {
                var(_, ok) = r.GoDelete(ss);
                Assert.IsTrue(ok, "Removed key");
            }
        }
예제 #4
0
 public void TestFindLongestPrefix()
 {
     Assert.AreEqual(6, RadixTree <object> .FindLongestPrefix("abcdef", "abcdef"));
     Assert.AreEqual(3, RadixTree <object> .FindLongestPrefix("abcdef", "abcxyz"));
     Assert.AreEqual(3, RadixTree <object> .FindLongestPrefix("abc", "abcxyz"));
     Assert.AreEqual(3, RadixTree <object> .FindLongestPrefix("abcxyz", "abc"));
     Assert.AreEqual(0, RadixTree <object> .FindLongestPrefix("abc", "xyz"));
 }
예제 #5
0
        public void LongestPrefix_EmptyTree_NotFound(string input)
        {
            // Arrange
            var radixTree = new RadixTree <int>();

            // Act
            var(_, _, found) = radixTree.LongestPrefix(input);

            // Assert
            Assert.False(found, "should not find longest prefix match");
        }
예제 #6
0
        //~ func TestLongestPrefix(t *testing.T) {
        public void TestLongestPrefix()
        {
            //~ r := New()
            var r = new RadixTree <int>();

            //~ keys := []string{
            //~     "",
            //~     "foo",
            //~     "foobar",
            //~     "foobarbaz",
            //~     "foobarbazzip",
            //~     "foozip",
            //~ }
            var keys = new string[] {
                "",
                "foo",
                "foobar",
                "foobarbaz",
                "foobarbazzip",
                "foozip",
            };

            //~ for _, k := range keys {
            //~     r.Insert(k, nil)
            //~ }
            //~ if r.Len() != len(keys) {
            //~     t.Fatalf("bad len: %v %v", r.Len(), len(keys))
            //~ }
            foreach (var k in keys)
            {
                r.GoInsert(k, 1);
            }
            Assert.AreEqual(keys.Length, r.Count, "Tree count and key count match");

            //~ type exp struct {
            //~     inp string
            //~     out string
            //~ }
            //~ cases := []exp{
            //~     {"a", ""},
            //~     {"abc", ""},
            //~     {"fo", ""},
            //~     {"foo", "foo"},
            //~     {"foob", "foo"},
            //~     {"foobar", "foobar"},
            //~     {"foobarba", "foobar"},
            //~     {"foobarbaz", "foobarbaz"},
            //~     {"foobarbazzi", "foobarbaz"},
            //~     {"foobarbazzip", "foobarbazzip"},
            //~     {"foozi", "foo"},
            //~     {"foozip", "foozip"},
            //~     {"foozipzap", "foozip"},
            //~ }
            var cases = new (string inp, string @out)[]
예제 #7
0
        public void TryGetValue_EmptyTree_NotFound(string input)
        {
            // Arrange
            var radixTree = new RadixTree <int>();

            // Act
            var found = radixTree.TryGetValue(input, out int _);

            // Assert
            Assert.False(found, "should not find value");
        }
예제 #8
0
        public void Delete_EmptyTree_NoChange(string keyToDelete)
        {
            // Arrange
            var radixTree = new RadixTree <int>();

            // Act
            var(_, ok) = radixTree.Delete(keyToDelete);

            // Assert
            Assert.False(ok, "Key should not be removed");
            Assert.Equal(0, radixTree.Count);
        }
예제 #9
0
        public void TryGetValue_ExistingKey_ReturnsValue(string input)
        {
            // Arrange
            var rand = new Random();
            var keys = new[] {
                "",
                "foo",
            };
            var dictionary = keys.ToDictionary(x => x, _ => rand.Next());
            var radixTree  = new RadixTree <int>(dictionary);

            // Act
            var found = radixTree.TryGetValue(input, out int value);

            // Assert
            Assert.True(found, "should find value");
            Assert.Equal(dictionary[input], value);
        }
예제 #10
0
        public void Insert_NotExistingKey_Adds(int count)
        {
            //Arrange
            var expectedTree = Enumerable.Range(0, count).ToDictionary(_ => Guid.NewGuid().ToString(), x => x);
            var radixTree    = new RadixTree <int>();

            foreach (var item in expectedTree)
            {
                // Act
                var(_, updated) = radixTree.Insert(item.Key, item.Value);

                // Assert
                Assert.False(updated);
            }

            Assert.Equal(expectedTree.Count, radixTree.Count);
            Assert.Equal(expectedTree.Keys, radixTree.Keys);
            Assert.Equal(expectedTree, radixTree.ToDictionary());
        }
예제 #11
0
        public void TestRemovingAService()
        {
            var tree     = new RadixTree <Service>();
            var service  = new Service(new string[0], "Service1Test", "Address1Test", 10000, "node1", new string[0]);
            var service2 = new Service(new string[0], "Service1Test", "Address2Test", 10000, "node1", new string[0]);

            tree.AddServiceToRoute("/test1/test2/test3/test4/test5", service);
            tree.AddServiceToRoute("/test1/test2/test3/test4/test5/test6", service2);

            string matchedpath;
            var    returnservice = tree.GetServiceFromRoute("/test1/test2/test3/test4/test5/test7", out matchedpath);

            Assert.Equal("/test1/test2/test3/test4/test5", matchedpath);

            //now remove the service
            tree.RemoveService(service);

            //Now we should get no match
            returnservice = tree.GetServiceFromRoute("/test1/test2/test3/test4/test5/test7", out matchedpath);
            Assert.Null(returnservice);
        }
예제 #12
0
        public void LongestPrefix_ExistingPrefix_ReturnsValue(string input, string expected)
        {
            // Arrange
            var rand = new Random();
            var keys = new[] {
                "",
                "foo",
                "foobar",
                "foobarbaz",
                "foobarbazzip",
                "foozip",
            };
            var dictionary = keys.ToDictionary(x => x, _ => rand.Next());
            var radixTree  = new RadixTree <int>(dictionary);

            // Act
            var(key, value, found) = radixTree.LongestPrefix(input);

            // Assert
            Assert.True(found, "should find longest prefix match");
            Assert.Equal(expected, key);
            Assert.Equal(dictionary[expected], value);
        }
예제 #13
0
        //~ func TestRoot(t *testing.T) {
        public void TestRoot()
        {
            //~ r := New()
            var r = new RadixTree <int>();

            //~ _, ok := r.Delete("")
            //~ if ok {
            //~     t.Fatalf("bad")
            //~ }
            var(_, ok) = r.GoDelete("");
            Assert.IsFalse(ok, "Remove should fail");

            //~ _, ok = r.Insert("", true)
            //~ if ok {
            //~     t.Fatalf("bad")
            //~ }
            (_, ok) = r.GoInsert("", 0);
            Assert.IsFalse(ok, "Insert should not replace");

            //~ val, ok := r.Get("")
            //~ if !ok || val != true {
            //~     t.Fatalf("bad: %v", val)
            //~ }
            int val;

            (val, ok) = r.GoGet("");
            Assert.IsTrue(ok, "Get should not find key");
            Assert.AreEqual(default(int), val, "Get should return default int");

            //~ val, ok = r.Delete("")
            //~ if !ok || val != true {
            //~     t.Fatalf("bad: %v", val)
            //~ }
            (val, ok) = r.GoDelete("");
            Assert.IsTrue(ok, "Remove was successful");
            Assert.AreEqual(default(int), val, "Remove should return default int");
        }
예제 #14
0
        public static (GetRule, PathExpander) Parse(IDictionary <string, RuleDefinition> rules, GetRuleParser parserResolver)
        {
            var tree = new RadixTree <IRule>(rules.ToDictionary(x => x.Key.ToLower(), x => parserResolver(x.Value.Format).Parse(x.Value.Payload)));

            Option <IRule> RulesRepository(ConfigurationPath path) => tree.TryGetValue(path, out var rule) ? Option <IRule> .Some(rule) : Option <IRule> .None;

            IEnumerable <ConfigurationPath> PathExpander(ConfigurationPath path)
            {
                if (!path.IsScan)
                {
                    return new[] { path }
                }
                ;

                var keys = path == ConfigurationPath.FullScan
                    ? tree.Keys
                    : tree.ListPrefix($"{path.Folder}/").Select(c => c.key);

                return(keys.Select(ConfigurationPath.New).Where(x => !x.IsHidden(path.Folder)));
            }

            return(RulesRepository, PathExpander);
        }
    }
예제 #15
0
        public void Test()
        {
            var values = new[]
            {
                "Id",
                "Name",
                "DecimalProp1",
                "DecimalProp2",
                "DecimalProp3",
                "DecimalProp4",
                "DecimalProp5",
                "DecimalProp6",
                "DecimalProp7",
                "DecimalProp8",
                "DecimalProp9",
                "StringProp1",
                "StringProp2",
                "StringProp3",
                "StringProp4",
                "StringProp5",
                "StringProp6",
                "StringProp7",
                "StringProp8",
                "StringProp9",
                "Realllll",
                "ReallllllyLongggggggPropertyyyyyyyyy1",
                "ReallllllyLonggggggg1Propertyyyyyyyyy1",
                "ReallllllyLongggggggPropertyyyyyyyyy2",
                "ReallllllyLonggggggg2Propertyyyyyyyyy1",
                "Parent",
                "Children",
            };

            var tree = new RadixTree();

            for (var index = 0; index < values.Length; index++)
            {
                tree.Add(values[index], index);
            }

            var assemblyName    = new AssemblyName($"DynamicTyping{Guid.NewGuid():N}");
            var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName.Name);

            var typeBuilder   = moduleBuilder.DefineType("Person", TypeAttributes.Public | TypeAttributes.Class);
            var methodBuilder = typeBuilder.DefineMethod("Resolve", MethodAttributes.Public | MethodAttributes.Static, typeof(string), new[] { typeof(string) });

            RadixTreeCompiler.Build(tree, methodBuilder, (il, isRef) =>
            {
                if (isRef)
                {
                    il.Emit(OpCodes.Ldarga, 0);
                }
                else
                {
                    il.Emit(OpCodes.Ldarg_0);
                }
            }, (il, node) =>
            {
                il.Emit(OpCodes.Ldstr, node.Key);
                il.Emit(OpCodes.Ret);
            }, il =>
            {
                il.Emit(OpCodes.Ldstr, "None");
                il.Emit(OpCodes.Ret);
            });
            var type   = typeBuilder.CreateType();
            var method = type.GetMethod(methodBuilder.Name);

            var path = @"C:\Projects\PactTest\DynamicTyping\DynamicTyping.Tests\bin\Debug\output.dll";

            File.Delete(path);
            new AssemblyGenerator().GenerateAssembly(type.Assembly, path);

            foreach (var item in values)
            {
                _testOutputHelper.WriteLine(item + " = " + (string)method.Invoke(null, new object[] { item }));
            }

            _testOutputHelper.WriteLine("Invalid = " + (string)method.Invoke(null, new object[] { "Invalid" }));
        }
예제 #16
0
        public void Setup()
        {
            var items = new List <string>
            {
                "Id",
                "Name",
                "DecimalProp1",
                "DecimalProp2",
                "DecimalProp3",
                "DecimalProp4",
                "DecimalProp5",
                "DecimalProp6",
                "DecimalProp7",
                "DecimalProp8",
                "DecimalProp9",
                "StringProp1",
                "StringProp2",
                "StringProp3",
                "StringProp4",
                "StringProp5",
                "StringProp6",
                "StringProp7",
                "StringProp8",
                "StringProp9",
                "Parent",
                "Children",
            };

            var tree = new RadixTree();

            for (var index = 0; index < items.Count; index++)
            {
                tree.Add(items[index], index);
            }

            var assemblyName    = new AssemblyName($"DynamicTyping{Guid.NewGuid():N}");
            var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName.Name);

            var typeBuilder   = moduleBuilder.DefineType("Person", TypeAttributes.Public | TypeAttributes.Class);
            var methodBuilder = typeBuilder.DefineMethod("Resolve", MethodAttributes.Public | MethodAttributes.Static, typeof(string), new[] { typeof(string) });

            RadixTreeCompiler.Build(tree, methodBuilder, (il, isRef) =>
            {
                if (isRef)
                {
                    il.Emit(OpCodes.Ldarga, 0);
                }
                else
                {
                    il.Emit(OpCodes.Ldarg_0);
                }
            }, (il, node) =>
            {
                il.Emit(OpCodes.Ldstr, node.Key);
                il.Emit(OpCodes.Ret);
            }, il =>
            {
                il.Emit(OpCodes.Ldstr, "None");
                il.Emit(OpCodes.Ret);
            });

            var type   = typeBuilder.CreateType();
            var method = type.GetMethod(methodBuilder.Name);

            _dynamic = (Func <string, string>)Delegate.CreateDelegate(typeof(Func <string, string>), method);

            _dict = new Dictionary <string, string>
            {
                { "Id", "Id" },
                { "Name", "Name" },
                { "DecimalProp1", "DecimalProp1" },
                { "DecimalProp2", "DecimalProp2" },
                { "DecimalProp3", "DecimalProp3" },
                { "DecimalProp4", "DecimalProp4" },
                { "DecimalProp5", "DecimalProp5" },
                { "DecimalProp6", "DecimalProp6" },
                { "DecimalProp7", "DecimalProp7" },
                { "DecimalProp8", "DecimalProp8" },
                { "DecimalProp9", "DecimalProp9" },
                { "StringProp1", "StringProp1" },
                { "StringProp2", "StringProp2" },
                { "StringProp3", "StringProp3" },
                { "StringProp4", "StringProp4" },
                { "StringProp5", "StringProp5" },
                { "StringProp6", "StringProp6" },
                { "StringProp7", "StringProp7" },
                { "StringProp8", "StringProp8" },
                { "StringProp9", "StringProp9" },
                { "Parent", "Parent" },
                { "Children", "Children" },
            };
        }
예제 #17
0
 public RadixTreeWithOneWord()
 {
     this.tree = new RadixTree();
     this.tree.AddWord(this.wordToAdd);
 }
예제 #18
0
        /// <summary>
        /// Creates a new storage instance with specified types of keys and values.
        /// </summary>
        /// <typeparam name="TKey">The type of key</typeparam>
        /// <typeparam name="TValue">The type of value</typeparam>
        /// <param name="keySerializer">Object implementing ISerializer interface for key serialization</param>
        /// <param name="valueSerializer">Object implementing ISerializer interface for value serialization</param>
        /// <param name="settings">Setiings of creating storage</param>
        /// <returns>New storage instance</returns>
        public IKeyValueStorage <KeyOf <TKey>, ValueOf <TValue> > CreateRadixTreeStorage <TKey, TValue>(ISerializer <TKey> keySerializer,
                                                                                                        ISerializer <TValue> valueSerializer,
                                                                                                        RadixTreeStorageSettings settings)
        {
            bool usePageCache = settings.CacheSettings != null;

            if (settings.MaxEmptyPages < 0)
            {
                throw new ArgumentException("MaxEmptyPages shouldn't be negative", nameof(settings));
            }

            if (usePageCache)
            {
                if (settings.CacheSettings.MaxCachedPages < 0)
                {
                    throw new ArgumentException("MaxCachedPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages < 0)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages > settings.CacheSettings.MaxCachedPages)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn be equal to or less than MaxCachedPages", nameof(settings));
                }
            }

            IPageManager pageManager   = null;
            IPageManager fsPageManager = null;

            try
            {
                fsPageManager = new FileSystemPageManager((int)settings.PageSize, settings.ForcedWrites, 1, true)
                {
                    MaxEmptyPages = settings.MaxEmptyPages
                };

                pageManager = usePageCache ?
                              new CachingPageManager(fsPageManager, settings.CacheSettings.MaxCachedPages, settings.CacheSettings.MaxDirtyPages)
                                : fsPageManager;

                var ks = new Serializer <KeyOf <TKey> >(obj => keySerializer.Serialize(obj), bytes => keySerializer.Deserialize(bytes));
                var vs = new Serializer <ValueOf <TValue> >(obj => valueSerializer.Serialize(obj), bytes => valueSerializer.Deserialize(bytes));

                var radixTree = new RadixTree <KeyOf <TKey>, ValueOf <TValue> >(
                    new RadixTreeNodeStorage(pageManager),
                    new ValueStorage <ValueOf <TValue> >(new MemoryManager(new FreeSpaceMap(pageManager), pageManager), vs), ks);

                return(new RadixTreeKeyValueStorage <KeyOf <TKey>, ValueOf <TValue> >(pageManager, radixTree, settings.AutoFlushInterval, settings.AutoFlushTimeout));
            }
            catch (Exception)
            {
                if (pageManager != null)
                {
                    pageManager.Close();
                }
                else
                {
                    fsPageManager?.Close();
                }

                throw;
            }
        }
예제 #19
0
 public RadixTreeWithManyWords()
 {
     this.tree = new RadixTree(this.words);
 }
예제 #20
0
 public RoutingData(RadixTree <IService> tree)
 {
     Tree = tree;
 }
예제 #21
0
 public EmptyRadixTree()
 {
     this.tree = new RadixTree();
 }