mirror of
https://gitea.invidious.io/iv-org/shard-radix.git
synced 2024-08-15 00:43:21 +00:00
Makes node prioritization insertion-independent
The order in which nodes were inserted into a tree might produce failures in lookup mechanism. tree = Radix::Tree(Symbol).new tree.add "/one/:id", :one tree.add "/one-longer/:id", :two result = tree.find "/one-longer/10" # expected `true` result.found? # => false In above example, reversing the order of insertion solved the issue, but exposed the naive sorting/prioritization mechanism used. This change improves that by properly identifying the kind of node being evaluated and compared against others of the same kind. It is now possible to know in advance if a node contains an special condition (named parameter or globbing) or is a normal one: node = Radix::Node(Nil).new("a") node.normal? # => true node = Radix::Node(Nil).new(":query") node.named? # => true node = Radix::Node(Nil).new("*filepath") node.glob? # => true Which helps out with prioritization of nodes: - A normal node ranks higher than a named one - A named node ranks higher than a glob one - On two of same kind, ranks are based on priority With this change in place, above example works as expected: tree = Radix::Tree(Symbol).new tree.add "/one/:id", :one tree.add "/one-longer/:id", :two result = tree.find "/one-longer/10" result.found? # => true Fixes #18
This commit is contained in:
parent
0dc6e174d2
commit
1764332123
4 changed files with 187 additions and 68 deletions
|
@ -2,6 +2,16 @@ require "../spec_helper"
|
|||
|
||||
module Radix
|
||||
describe Node do
|
||||
describe "#glob?" do
|
||||
it "returns true when key contains a glob parameter (catch all)" do
|
||||
node = Node(Nil).new("a")
|
||||
node.glob?.should be_false
|
||||
|
||||
node = Node(Nil).new("*filepath")
|
||||
node.glob?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#key=" do
|
||||
it "accepts change of key after initialization" do
|
||||
node = Node(Nil).new("abc")
|
||||
|
@ -10,6 +20,38 @@ module Radix
|
|||
node.key = "xyz"
|
||||
node.key.should eq("xyz")
|
||||
end
|
||||
|
||||
it "also changes kind when modified" do
|
||||
node = Node(Nil).new("abc")
|
||||
node.normal?.should be_true
|
||||
|
||||
node.key = ":query"
|
||||
node.normal?.should be_false
|
||||
node.named?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#named?" do
|
||||
it "returns true when key contains a named parameter" do
|
||||
node = Node(Nil).new("a")
|
||||
node.named?.should be_false
|
||||
|
||||
node = Node(Nil).new(":query")
|
||||
node.named?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#normal?" do
|
||||
it "returns true when key does not contain named or glob parameters" do
|
||||
node = Node(Nil).new("a")
|
||||
node.normal?.should be_true
|
||||
|
||||
node = Node(Nil).new(":query")
|
||||
node.normal?.should be_false
|
||||
|
||||
node = Node(Nil).new("*filepath")
|
||||
node.normal?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe "#payload" do
|
||||
|
@ -36,7 +78,7 @@ module Radix
|
|||
end
|
||||
|
||||
describe "#priority" do
|
||||
it "calculates it based on key size" do
|
||||
it "calculates it based on key length" do
|
||||
node = Node(Nil).new("a")
|
||||
node.priority.should eq(1)
|
||||
|
||||
|
@ -44,20 +86,20 @@ module Radix
|
|||
node.priority.should eq(3)
|
||||
end
|
||||
|
||||
it "returns zero for catch all (globbed) key" do
|
||||
node = Node(Nil).new("*filepath")
|
||||
node.priority.should eq(-2)
|
||||
it "considers key length up until named parameter presence" do
|
||||
node = Node(Nil).new("/posts/:id")
|
||||
node.priority.should eq(7)
|
||||
|
||||
node = Node(Nil).new("/src/*filepath")
|
||||
node.priority.should eq(-2)
|
||||
node = Node(Nil).new("/u/:username")
|
||||
node.priority.should eq(3)
|
||||
end
|
||||
|
||||
it "returns one for keys with named parameters" do
|
||||
node = Node(Nil).new(":query")
|
||||
node.priority.should eq(-1)
|
||||
it "considers key length up until glob parameter presence" do
|
||||
node = Node(Nil).new("/search/*query")
|
||||
node.priority.should eq(8)
|
||||
|
||||
node = Node(Nil).new("/search/:query")
|
||||
node.priority.should eq(-1)
|
||||
node = Node(Nil).new("/*anything")
|
||||
node.priority.should eq(1)
|
||||
end
|
||||
|
||||
it "changes when key changes" do
|
||||
|
@ -67,16 +109,16 @@ module Radix
|
|||
node.key = "abc"
|
||||
node.priority.should eq(3)
|
||||
|
||||
node.key = "*filepath"
|
||||
node.priority.should eq(-2)
|
||||
node.key = "/src/*filepath"
|
||||
node.priority.should eq(5)
|
||||
|
||||
node.key = ":query"
|
||||
node.priority.should eq(-1)
|
||||
node.key = "/search/:query"
|
||||
node.priority.should eq(8)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#sort!" do
|
||||
it "orders children by priority" do
|
||||
it "orders children" do
|
||||
root = Node(Int32).new("/")
|
||||
node1 = Node(Int32).new("a", 1)
|
||||
node2 = Node(Int32).new("bc", 2)
|
||||
|
@ -90,7 +132,7 @@ module Radix
|
|||
root.children[2].should eq(node1)
|
||||
end
|
||||
|
||||
it "orders catch all and named parameters lower than others" do
|
||||
it "orders catch all and named parameters lower than normal nodes" do
|
||||
root = Node(Int32).new("/")
|
||||
node1 = Node(Int32).new("*filepath", 1)
|
||||
node2 = Node(Int32).new("abc", 2)
|
||||
|
|
|
@ -544,6 +544,19 @@ module Radix
|
|||
result.payload.should eq(:featured)
|
||||
end
|
||||
end
|
||||
|
||||
context "dealing with named parameters and shared key" do
|
||||
it "finds matching path" do
|
||||
tree = Tree(Symbol).new
|
||||
tree.add "/one/:id", :one
|
||||
tree.add "/one-longer/:id", :two
|
||||
|
||||
result = tree.find "/one-longer/10"
|
||||
result.found?.should be_true
|
||||
result.key.should eq("/one-longer/:id")
|
||||
result.params["id"].should eq("10")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue