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); }
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); } }
//~ 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"); } }
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")); }
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"); }
//~ 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)[]
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"); }
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); }
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); }
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()); }
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); }
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); }
//~ 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"); }
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); } }
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" })); }
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" }, }; }
public RadixTreeWithOneWord() { this.tree = new RadixTree(); this.tree.AddWord(this.wordToAdd); }
/// <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; } }
public RadixTreeWithManyWords() { this.tree = new RadixTree(this.words); }
public RoutingData(RadixTree <IService> tree) { Tree = tree; }
public EmptyRadixTree() { this.tree = new RadixTree(); }