aboutsummaryrefslogtreecommitdiffstats
path: root/utils/merkletrie/noder
diff options
context:
space:
mode:
authorAlberto Cortés <alcortesm@gmail.com>2017-02-22 16:45:46 +0100
committerGitHub <noreply@github.com>2017-02-22 16:45:46 +0100
commitb5da4e98571b02dc106de4f9b2cb2a298489f1b1 (patch)
tree26f44140f9bf4dc5291e0b88c9f4f91354afffad /utils/merkletrie/noder
parenta79bc09bdc6517e0dc9cc5f7936cf6312c3c1db3 (diff)
downloadgo-git-b5da4e98571b02dc106de4f9b2cb2a298489f1b1.tar.gz
Fix issue 275 (edited) (#276)
Fix #275 . It was not possible to write a test for this issue as the original fsnoder didn't support filenames with length > 1. Therefore this patch has 3 commits: add support for long filenames in fsnoder. add a test case for the issue using the new long filenames from step 1. fix the issue by comparing paths level by level instead of lexigographically over the whole path.
Diffstat (limited to 'utils/merkletrie/noder')
-rw-r--r--utils/merkletrie/noder/noder_test.go8
-rw-r--r--utils/merkletrie/noder/path.go31
-rw-r--r--utils/merkletrie/noder/path_test.go151
3 files changed, 188 insertions, 2 deletions
diff --git a/utils/merkletrie/noder/noder_test.go b/utils/merkletrie/noder/noder_test.go
index 14bef4a..5e014fe 100644
--- a/utils/merkletrie/noder/noder_test.go
+++ b/utils/merkletrie/noder/noder_test.go
@@ -1,6 +1,12 @@
package noder
-import . "gopkg.in/check.v1"
+import (
+ "testing"
+
+ . "gopkg.in/check.v1"
+)
+
+func Test(t *testing.T) { TestingT(t) }
type NoderSuite struct{}
diff --git a/utils/merkletrie/noder/path.go b/utils/merkletrie/noder/path.go
index c992f7e..85742db 100644
--- a/utils/merkletrie/noder/path.go
+++ b/utils/merkletrie/noder/path.go
@@ -1,6 +1,9 @@
package noder
-import "bytes"
+import (
+ "bytes"
+ "strings"
+)
// Path values represent a noder and its ancestors. The root goes first
// and the actual final noder the path is refering to will be the last.
@@ -57,3 +60,29 @@ func (p Path) Children() ([]Noder, error) {
func (p Path) NumChildren() (int, error) {
return p.Last().NumChildren()
}
+
+// Compare returns -1, 0 or 1 if the path p is smaller, equal or bigger
+// than other, in "directory order"; for example:
+//
+// "a" < "b"
+// "a/b/c/d/z" < "b"
+// "a/b/a" > "a/b"
+func (p Path) Compare(other Path) int {
+ i := 0
+ for {
+ switch {
+ case len(other) == len(p) && i == len(p):
+ return 0
+ case i == len(other):
+ return 1
+ case i == len(p):
+ return -1
+ default:
+ cmp := strings.Compare(p[i].Name(), other[i].Name())
+ if cmp != 0 {
+ return cmp
+ }
+ }
+ i++
+ }
+}
diff --git a/utils/merkletrie/noder/path_test.go b/utils/merkletrie/noder/path_test.go
new file mode 100644
index 0000000..44e3c3c
--- /dev/null
+++ b/utils/merkletrie/noder/path_test.go
@@ -0,0 +1,151 @@
+package noder
+
+import . "gopkg.in/check.v1"
+
+type PathSuite struct{}
+
+var _ = Suite(&PathSuite{})
+
+func (s *PathSuite) TestShortFile(c *C) {
+ f := &noderMock{
+ name: "1",
+ isDir: false,
+ }
+ p := Path([]Noder{f})
+ c.Assert(p.String(), Equals, "1")
+}
+
+func (s *PathSuite) TestShortDir(c *C) {
+ d := &noderMock{
+ name: "1",
+ isDir: true,
+ children: NoChildren,
+ }
+ p := Path([]Noder{d})
+ c.Assert(p.String(), Equals, "1")
+}
+
+func (s *PathSuite) TestLongFile(c *C) {
+ n3 := &noderMock{
+ name: "3",
+ isDir: false,
+ }
+ n2 := &noderMock{
+ name: "2",
+ isDir: true,
+ children: []Noder{n3},
+ }
+ n1 := &noderMock{
+ name: "1",
+ isDir: true,
+ children: []Noder{n2},
+ }
+ p := Path([]Noder{n1, n2, n3})
+ c.Assert(p.String(), Equals, "1/2/3")
+}
+
+func (s *PathSuite) TestLongDir(c *C) {
+ n3 := &noderMock{
+ name: "3",
+ isDir: true,
+ children: NoChildren,
+ }
+ n2 := &noderMock{
+ name: "2",
+ isDir: true,
+ children: []Noder{n3},
+ }
+ n1 := &noderMock{
+ name: "1",
+ isDir: true,
+ children: []Noder{n2},
+ }
+ p := Path([]Noder{n1, n2, n3})
+ c.Assert(p.String(), Equals, "1/2/3")
+}
+
+func (s *PathSuite) TestCompareDepth1(c *C) {
+ p1 := Path([]Noder{&noderMock{name: "a"}})
+ p2 := Path([]Noder{&noderMock{name: "b"}})
+ c.Assert(p1.Compare(p2), Equals, -1)
+ c.Assert(p2.Compare(p1), Equals, 1)
+
+ p1 = Path([]Noder{&noderMock{name: "a"}})
+ p2 = Path([]Noder{&noderMock{name: "a"}})
+ c.Assert(p1.Compare(p2), Equals, 0)
+ c.Assert(p2.Compare(p1), Equals, 0)
+
+ p1 = Path([]Noder{&noderMock{name: "a.go"}})
+ p2 = Path([]Noder{&noderMock{name: "a"}})
+ c.Assert(p1.Compare(p2), Equals, 1)
+ c.Assert(p2.Compare(p1), Equals, -1)
+}
+
+func (s *PathSuite) TestCompareDepth2(c *C) {
+ p1 := Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "b"},
+ })
+ p2 := Path([]Noder{
+ &noderMock{name: "b"},
+ &noderMock{name: "a"},
+ })
+ c.Assert(p1.Compare(p2), Equals, -1)
+ c.Assert(p2.Compare(p1), Equals, 1)
+
+ p1 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "b"},
+ })
+ p2 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "b"},
+ })
+ c.Assert(p1.Compare(p2), Equals, 0)
+ c.Assert(p2.Compare(p1), Equals, 0)
+
+ p1 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "b"},
+ })
+ p2 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "a"},
+ })
+ c.Assert(p1.Compare(p2), Equals, 1)
+ c.Assert(p2.Compare(p1), Equals, -1)
+}
+
+func (s *PathSuite) TestCompareMixedDepths(c *C) {
+ p1 := Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "b"},
+ })
+ p2 := Path([]Noder{&noderMock{name: "b"}})
+ c.Assert(p1.Compare(p2), Equals, -1)
+ c.Assert(p2.Compare(p1), Equals, 1)
+
+ p1 = Path([]Noder{
+ &noderMock{name: "b"},
+ &noderMock{name: "b"},
+ })
+ p2 = Path([]Noder{&noderMock{name: "b"}})
+ c.Assert(p1.Compare(p2), Equals, 1)
+ c.Assert(p2.Compare(p1), Equals, -1)
+
+ p1 = Path([]Noder{&noderMock{name: "a.go"}})
+ p2 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "a.go"},
+ })
+ c.Assert(p1.Compare(p2), Equals, 1)
+ c.Assert(p2.Compare(p1), Equals, -1)
+
+ p1 = Path([]Noder{&noderMock{name: "b.go"}})
+ p2 = Path([]Noder{
+ &noderMock{name: "a"},
+ &noderMock{name: "a.go"},
+ })
+ c.Assert(p1.Compare(p2), Equals, 1)
+ c.Assert(p2.Compare(p1), Equals, -1)
+}