diff --git a/README.md b/README.md index de458b6..63fe1bf 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ package main import ( "fmt" - "github.com/johnfercher/tree/pkg/node" "github.com/johnfercher/tree/pkg/tree" ) @@ -23,31 +22,34 @@ import ( func main() { tr := tree.New[string]() - tr.AddRoot(node.New(0, "0.0")) + tr.AddRoot(tree.NewNode(0, "0.0")) - tr.Add(0, node.New(1, "0.1")) - tr.Add(0, node.New(2, "0.2")) + tr.Add(0, tree.NewNode(1, "0.1")) + tr.Add(0, tree.NewNode(2, "0.2")) - tr.Add(1, node.New(3, "1.3")) - tr.Add(1, node.New(4, "1.4")) + tr.Add(1, tree.NewNode(3, "1.3")) + tr.Add(1, tree.NewNode(4, "1.4")) - tr.Add(2, node.New(5, "2.5")) - tr.Add(2, node.New(6, "2.6")) + tr.Add(2, tree.NewNode(5, "2.5")) + tr.Add(2, tree.NewNode(6, "2.6")) root, ok := tr.GetRoot() - fmt.Println(ok) - fmt.Println(root) + fmt.Println(ok) // true + fmt.Println(root.Get()) // 0.0 node, ok := tr.Get(3) - fmt.Println(ok) - fmt.Println(node) + fmt.Println(ok) // true + fmt.Println(node.Get()) // 1.3 structure, ok := tr.GetStructure() - fmt.Println(ok) - fmt.Println(structure) + fmt.Println(ok) // true + fmt.Println(structure) // (NULL) -> (0), (0) -> (1), (1) -> (3), (1) -> (4), (0) -> (2), (2) -> (5), (2) -> (6) nodes, ok := tr.Backtrack(6) - fmt.Println(ok) - fmt.Println(nodes) + fmt.Println(ok) // true + for _, node := range nodes { + fmt.Println(node.Get()) // 2.6, 0.2, 0.0 + } } + ``` diff --git a/cmd/main.go b/cmd/main.go index 8ef1d3c..6f3df32 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" - "github.com/johnfercher/tree/pkg/node" "github.com/johnfercher/tree/pkg/tree" ) @@ -11,30 +10,32 @@ import ( func main() { tr := tree.New[string]() - tr.AddRoot(node.New(0, "0.0")) + tr.AddRoot(tree.NewNode(0, "0.0")) - tr.Add(0, node.New(1, "0.1")) - tr.Add(0, node.New(2, "0.2")) + tr.Add(0, tree.NewNode(1, "0.1")) + tr.Add(0, tree.NewNode(2, "0.2")) - tr.Add(1, node.New(3, "1.3")) - tr.Add(1, node.New(4, "1.4")) + tr.Add(1, tree.NewNode(3, "1.3")) + tr.Add(1, tree.NewNode(4, "1.4")) - tr.Add(2, node.New(5, "2.5")) - tr.Add(2, node.New(6, "2.6")) + tr.Add(2, tree.NewNode(5, "2.5")) + tr.Add(2, tree.NewNode(6, "2.6")) root, ok := tr.GetRoot() - fmt.Println(ok) - fmt.Println(root) + fmt.Println(ok) // true + fmt.Println(root.Get()) // 0.0 node, ok := tr.Get(3) - fmt.Println(ok) - fmt.Println(node) + fmt.Println(ok) // true + fmt.Println(node.Get()) // 1.3 structure, ok := tr.GetStructure() - fmt.Println(ok) - fmt.Println(structure) + fmt.Println(ok) // true + fmt.Println(structure) // (NULL) -> (0), (0) -> (1), (1) -> (3), (1) -> (4), (0) -> (2), (2) -> (5), (2) -> (6) nodes, ok := tr.Backtrack(6) - fmt.Println(ok) - fmt.Println(nodes) + fmt.Println(ok) // true + for _, node := range nodes { + fmt.Println(node.Get()) // 2.6, 0.2, 0.0 + } } diff --git a/pkg/node/node_test.go b/pkg/node/node_test.go deleted file mode 100644 index b1a07d9..0000000 --- a/pkg/node/node_test.go +++ /dev/null @@ -1,262 +0,0 @@ -package node_test - -import ( - "fmt" - "testing" - - "github.com/johnfercher/tree/pkg/node" - "github.com/johnfercher/tree/pkg/tree" - "github.com/stretchr/testify/assert" -) - -type anyType struct { - Value string -} - -func TestNewNode(t *testing.T) { - // Arrange - elements := []interface{}{ - true, - 42, - 3.14, - "string1", - &anyType{Value: "string2"}, - } - - types := []interface{}{ - "bool", - "int", - "float64", - "string", - "*node_test.anyType", - } - - for i, element := range elements { - // Act - sut := node.New(0, element) - data := sut.GetData() - - // Assert - assert.NotNil(t, sut) - assert.Equal(t, "*node.Node[interface {}]", fmt.Sprintf("%T", sut)) - assert.Equal(t, element, data) - assert.Equal(t, types[i], fmt.Sprintf("%T", data)) - } -} - -func TestNode_GetData(t *testing.T) { - // Arrange - sut := node.New(0, 42) - - // Act - n := sut.GetData() - - // Assert - assert.Equal(t, 42, n) -} - -func TestNode_IsRoot(t *testing.T) { - // Arrange - root := node.New(0, 42) - anyNode := node.New(1, 43) - leaf := node.New(2, 44) - - root.AddNext(anyNode) - anyNode.AddNext(leaf) - - // Act - rootTrue := root.IsRoot() - rootFalse1 := anyNode.IsRoot() - rootFalse2 := leaf.IsRoot() - - // Assert - assert.True(t, rootTrue) - assert.False(t, rootFalse1) - assert.False(t, rootFalse2) -} - -func TestNode_IsLeaf(t *testing.T) { - // Arrange - root := node.New(0, 42) - anyNode := node.New(1, 43) - leaf := node.New(2, 44) - - root.AddNext(anyNode) - anyNode.AddNext(leaf) - - // Act - leafFalse1 := root.IsLeaf() - leafFalse2 := anyNode.IsLeaf() - leafTrue := leaf.IsLeaf() - - // Assert - assert.False(t, leafFalse1) - assert.False(t, leafFalse2) - assert.True(t, leafTrue) -} - -func TestNode_Backtrack_WhenBuildManually_ShouldReturnCorrectly(t *testing.T) { - // Arrange - root := node.New(0, 42) - anyNode := node.New(1, 43) - leaf := node.New(2, 44) - - root.AddNext(anyNode) - anyNode.AddNext(leaf) - - // Act - arr1 := root.Backtrack() - arr2 := anyNode.Backtrack() - arr3 := leaf.Backtrack() - - // Assert - assert.Equal(t, 1, len(arr1)) - assert.Equal(t, 2, len(arr2)) - assert.Equal(t, 3, len(arr3)) -} - -func TestNode_Backtrack_WhenBuildByTree_ShouldReturnCorrectly(t *testing.T) { - // Arrange - tr := tree.New[string]() - - tr.AddRoot(node.New(0, "0.0")) - tr.Add(0, node.New(1, "1.0")) - tr.Add(0, node.New(2, "1.1")) - tr.Add(0, node.New(3, "1.2")) - tr.Add(1, node.New(4, "2.0")) - tr.Add(1, node.New(5, "2.1")) - tr.Add(1, node.New(6, "2.2")) - tr.Add(2, node.New(7, "2.0")) - tr.Add(2, node.New(8, "2.1")) - tr.Add(2, node.New(9, "2.2")) - tr.Add(3, node.New(10, "3.0")) - tr.Add(3, node.New(11, "3.1")) - tr.Add(3, node.New(12, "3.2")) - tr.Add(4, node.New(13, "4.0")) - - // Act & Assert - anyNode, _ := tr.Get(0) - backtracked := anyNode.Backtrack() - assert.Equal(t, 1, len(backtracked)) - assert.Equal(t, "0.0", backtracked[0].GetData()) - - anyNode, _ = tr.Get(1) - backtracked = anyNode.Backtrack() - assert.Equal(t, 2, len(backtracked)) - assert.Equal(t, "1.0", backtracked[0].GetData()) - assert.Equal(t, "0.0", backtracked[1].GetData()) - - anyNode, _ = tr.Get(2) - backtracked = anyNode.Backtrack() - assert.Equal(t, 2, len(backtracked)) - assert.Equal(t, "1.1", backtracked[0].GetData()) - assert.Equal(t, "0.0", backtracked[1].GetData()) - - anyNode, _ = tr.Get(3) - backtracked = anyNode.Backtrack() - assert.Equal(t, 2, len(backtracked)) - assert.Equal(t, "1.2", backtracked[0].GetData()) - assert.Equal(t, "0.0", backtracked[1].GetData()) - - anyNode, _ = tr.Get(4) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.0", backtracked[0].GetData()) - assert.Equal(t, "1.0", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(5) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.1", backtracked[0].GetData()) - assert.Equal(t, "1.0", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(6) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.2", backtracked[0].GetData()) - assert.Equal(t, "1.0", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(7) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.0", backtracked[0].GetData()) - assert.Equal(t, "1.1", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(8) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.1", backtracked[0].GetData()) - assert.Equal(t, "1.1", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(9) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "2.2", backtracked[0].GetData()) - assert.Equal(t, "1.1", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(10) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "3.0", backtracked[0].GetData()) - assert.Equal(t, "1.2", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(11) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "3.1", backtracked[0].GetData()) - assert.Equal(t, "1.2", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(12) - backtracked = anyNode.Backtrack() - assert.Equal(t, 3, len(backtracked)) - assert.Equal(t, "3.2", backtracked[0].GetData()) - assert.Equal(t, "1.2", backtracked[1].GetData()) - assert.Equal(t, "0.0", backtracked[2].GetData()) - - anyNode, _ = tr.Get(13) - backtracked = anyNode.Backtrack() - assert.Equal(t, 4, len(backtracked)) - assert.Equal(t, "4.0", backtracked[0].GetData()) - assert.Equal(t, "2.0", backtracked[1].GetData()) - assert.Equal(t, "1.0", backtracked[2].GetData()) - assert.Equal(t, "0.0", backtracked[3].GetData()) -} - -func TestNode_GetStructure(t *testing.T) { - // Arrange - tr := tree.New[string]() - - tr.AddRoot(node.New(0, "0.0")) - tr.Add(0, node.New(1, "1.0")) - tr.Add(0, node.New(2, "1.1")) - tr.Add(0, node.New(3, "1.2")) - tr.Add(1, node.New(4, "2.0")) - tr.Add(1, node.New(5, "2.1")) - tr.Add(1, node.New(6, "2.2")) - tr.Add(2, node.New(7, "2.0")) - tr.Add(2, node.New(8, "2.1")) - tr.Add(2, node.New(9, "2.2")) - tr.Add(3, node.New(10, "3.0")) - tr.Add(3, node.New(11, "3.1")) - tr.Add(3, node.New(12, "3.2")) - tr.Add(4, node.New(13, "4.0")) - - node, _ := tr.Get(0) - - // Act - structure := node.GetStructure() - - // Assert - assert.Equal(t, 14, len(structure)) - for _, str := range structure { - assert.NotEmpty(t, str) - } -} diff --git a/pkg/node/node.go b/pkg/tree/node.go similarity index 79% rename from pkg/node/node.go rename to pkg/tree/node.go index 5439eb6..3fb4c2c 100644 --- a/pkg/node/node.go +++ b/pkg/tree/node.go @@ -1,4 +1,4 @@ -package node +package tree import ( "fmt" @@ -6,25 +6,21 @@ import ( // nolint:structcheck,gocritic type Node[T any] struct { - ID int - Data T + id int + data T previous *Node[T] nexts []*Node[T] } -func New[T any](id int, data T) *Node[T] { +func NewNode[T any](id int, data T) *Node[T] { return &Node[T]{ - ID: id, - Data: data, + id: id, + data: data, } } -func (n *Node[T]) GetData() T { - return n.Data -} - -func (n *Node[T]) GetNexts() []*Node[T] { - return n.nexts +func (n *Node[T]) Get() (int, T) { + return n.id, n.data } func (n *Node[T]) IsRoot() bool { @@ -50,9 +46,9 @@ func (n *Node[T]) Backtrack() []*Node[T] { func (n *Node[T]) GetStructure() []string { var structure []string if n.previous == nil { - structure = append(structure, fmt.Sprintf("(NULL) -> (%d)", n.ID)) + structure = append(structure, fmt.Sprintf("(NULL) -> (%d)", n.id)) } else { - structure = append(structure, fmt.Sprintf("(%d) -> (%d)", n.previous.ID, n.ID)) + structure = append(structure, fmt.Sprintf("(%d) -> (%d)", n.previous.id, n.id)) } for _, next := range n.nexts { diff --git a/pkg/tree/node_test.go b/pkg/tree/node_test.go new file mode 100644 index 0000000..3d35cf3 --- /dev/null +++ b/pkg/tree/node_test.go @@ -0,0 +1,354 @@ +package tree_test + +import ( + "fmt" + "testing" + + "github.com/johnfercher/tree/pkg/tree" + + "github.com/stretchr/testify/assert" +) + +type anyType struct { + Value string +} + +func TestNewNode(t *testing.T) { + // Arrange + elements := []interface{}{ + true, + 42, + 3.14, + "string1", + &anyType{Value: "string2"}, + } + + types := []interface{}{ + "bool", + "int", + "float64", + "string", + "*tree_test.anyType", + } + + for i, element := range elements { + // Act + sut := tree.NewNode(0, element) + id, data := sut.Get() + + // Assert + assert.NotNil(t, sut) + assert.Equal(t, "*tree.Node[interface {}]", fmt.Sprintf("%T", sut)) + assert.Equal(t, 0, id) + assert.Equal(t, element, data) + assert.Equal(t, types[i], fmt.Sprintf("%T", data)) + } +} + +func TestNode_GetData(t *testing.T) { + // Arrange + sut := tree.NewNode(0, 42) + + // Act + id, n := sut.Get() + + // Assert + assert.Equal(t, 0, id) + assert.Equal(t, 42, n) +} + +func TestNode_IsRoot(t *testing.T) { + // Arrange + root := tree.NewNode(0, 42) + anyNode := tree.NewNode(1, 43) + leaf := tree.NewNode(2, 44) + + root.AddNext(anyNode) + anyNode.AddNext(leaf) + + // Act + rootTrue := root.IsRoot() + rootFalse1 := anyNode.IsRoot() + rootFalse2 := leaf.IsRoot() + + // Assert + assert.True(t, rootTrue) + assert.False(t, rootFalse1) + assert.False(t, rootFalse2) +} + +func TestNode_IsLeaf(t *testing.T) { + // Arrange + root := tree.NewNode(0, 42) + anyNode := tree.NewNode(1, 43) + leaf := tree.NewNode(2, 44) + + root.AddNext(anyNode) + anyNode.AddNext(leaf) + + // Act + leafFalse1 := root.IsLeaf() + leafFalse2 := anyNode.IsLeaf() + leafTrue := leaf.IsLeaf() + + // Assert + assert.False(t, leafFalse1) + assert.False(t, leafFalse2) + assert.True(t, leafTrue) +} + +func TestNode_Backtrack_WhenBuildManually_ShouldReturnCorrectly(t *testing.T) { + // Arrange + root := tree.NewNode(0, 42) + anyNode := tree.NewNode(1, 43) + leaf := tree.NewNode(2, 44) + + root.AddNext(anyNode) + anyNode.AddNext(leaf) + + // Act + arr1 := root.Backtrack() + arr2 := anyNode.Backtrack() + arr3 := leaf.Backtrack() + + // Assert + assert.Equal(t, 1, len(arr1)) + assert.Equal(t, 2, len(arr2)) + assert.Equal(t, 3, len(arr3)) +} + +func TestNode_Backtrack_WhenBuildByTree_ShouldReturnCorrectly(t *testing.T) { + // Arrange + tr := tree.New[string]() + + tr.AddRoot(tree.NewNode(0, "0.0")) + tr.Add(0, tree.NewNode(1, "1.0")) + tr.Add(0, tree.NewNode(2, "1.1")) + tr.Add(0, tree.NewNode(3, "1.2")) + tr.Add(1, tree.NewNode(4, "2.0")) + tr.Add(1, tree.NewNode(5, "2.1")) + tr.Add(1, tree.NewNode(6, "2.2")) + tr.Add(2, tree.NewNode(7, "2.0")) + tr.Add(2, tree.NewNode(8, "2.1")) + tr.Add(2, tree.NewNode(9, "2.2")) + tr.Add(3, tree.NewNode(10, "3.0")) + tr.Add(3, tree.NewNode(11, "3.1")) + tr.Add(3, tree.NewNode(12, "3.2")) + tr.Add(4, tree.NewNode(13, "4.0")) + + // Act & Assert + // Case 0 + anyNode, _ := tr.Get(0) + backtracked := anyNode.Backtrack() + assert.Equal(t, 1, len(backtracked)) + id, data := backtracked[0].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 1 + anyNode, _ = tr.Get(1) + backtracked = anyNode.Backtrack() + assert.Equal(t, 2, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 1, id) + assert.Equal(t, "1.0", data) + id, data = backtracked[1].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 2 + anyNode, _ = tr.Get(2) + backtracked = anyNode.Backtrack() + assert.Equal(t, 2, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 2, id) + assert.Equal(t, "1.1", data) + id, data = backtracked[1].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 3 + anyNode, _ = tr.Get(3) + backtracked = anyNode.Backtrack() + assert.Equal(t, 2, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 3, id) + assert.Equal(t, "1.2", data) + id, data = backtracked[1].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 4 + anyNode, _ = tr.Get(4) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 4, id) + assert.Equal(t, "2.0", data) + id, data = backtracked[1].Get() + assert.Equal(t, 1, id) + assert.Equal(t, "1.0", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 5 + anyNode, _ = tr.Get(5) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 5, id) + assert.Equal(t, "2.1", data) + id, data = backtracked[1].Get() + assert.Equal(t, 1, id) + assert.Equal(t, "1.0", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 6 + anyNode, _ = tr.Get(6) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 6, id) + assert.Equal(t, "2.2", data) + id, data = backtracked[1].Get() + assert.Equal(t, 1, id) + assert.Equal(t, "1.0", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 7 + anyNode, _ = tr.Get(7) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 7, id) + assert.Equal(t, "2.0", data) + id, data = backtracked[1].Get() + assert.Equal(t, 2, id) + assert.Equal(t, "1.1", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 8 + anyNode, _ = tr.Get(8) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 8, id) + assert.Equal(t, "2.1", data) + id, data = backtracked[1].Get() + assert.Equal(t, 2, id) + assert.Equal(t, "1.1", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 9 + anyNode, _ = tr.Get(9) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 9, id) + assert.Equal(t, "2.2", data) + id, data = backtracked[1].Get() + assert.Equal(t, 2, id) + assert.Equal(t, "1.1", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 10 + anyNode, _ = tr.Get(10) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 10, id) + assert.Equal(t, "3.0", data) + id, data = backtracked[1].Get() + assert.Equal(t, 3, id) + assert.Equal(t, "1.2", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 11 + anyNode, _ = tr.Get(11) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 11, id) + assert.Equal(t, "3.1", data) + id, data = backtracked[1].Get() + assert.Equal(t, 3, id) + assert.Equal(t, "1.2", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 12 + anyNode, _ = tr.Get(12) + backtracked = anyNode.Backtrack() + assert.Equal(t, 3, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 12, id) + assert.Equal(t, "3.2", data) + id, data = backtracked[1].Get() + assert.Equal(t, 3, id) + assert.Equal(t, "1.2", data) + id, data = backtracked[2].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) + + // Case 13 + anyNode, _ = tr.Get(13) + backtracked = anyNode.Backtrack() + assert.Equal(t, 4, len(backtracked)) + id, data = backtracked[0].Get() + assert.Equal(t, 13, id) + assert.Equal(t, "4.0", data) + id, data = backtracked[1].Get() + assert.Equal(t, 4, id) + assert.Equal(t, "2.0", data) + id, data = backtracked[2].Get() + assert.Equal(t, 1, id) + assert.Equal(t, "1.0", data) + id, data = backtracked[3].Get() + assert.Equal(t, 0, id) + assert.Equal(t, "0.0", data) +} + +func TestNode_GetStructure(t *testing.T) { + // Arrange + tr := tree.New[string]() + + tr.AddRoot(tree.NewNode(0, "0.0")) + tr.Add(0, tree.NewNode(1, "1.0")) + tr.Add(0, tree.NewNode(2, "1.1")) + tr.Add(0, tree.NewNode(3, "1.2")) + tr.Add(1, tree.NewNode(4, "2.0")) + tr.Add(1, tree.NewNode(5, "2.1")) + tr.Add(1, tree.NewNode(6, "2.2")) + tr.Add(2, tree.NewNode(7, "2.0")) + tr.Add(2, tree.NewNode(8, "2.1")) + tr.Add(2, tree.NewNode(9, "2.2")) + tr.Add(3, tree.NewNode(10, "3.0")) + tr.Add(3, tree.NewNode(11, "3.1")) + tr.Add(3, tree.NewNode(12, "3.2")) + tr.Add(4, tree.NewNode(13, "4.0")) + + node, _ := tr.Get(0) + + // Act + structure := node.GetStructure() + + // Assert + assert.Equal(t, 14, len(structure)) + for _, str := range structure { + assert.NotEmpty(t, str) + } +} diff --git a/pkg/tree/tree.go b/pkg/tree/tree.go index 65d2c63..72801db 100644 --- a/pkg/tree/tree.go +++ b/pkg/tree/tree.go @@ -1,19 +1,15 @@ package tree -import ( - "github.com/johnfercher/tree/pkg/node" -) - // nolint:structcheck,gocritic type Tree[T any] struct { - root *node.Node[T] + root *Node[T] } func New[T any]() *Tree[T] { return &Tree[T]{} } -func (t *Tree[T]) AddRoot(node *node.Node[T]) (addedRoot bool) { +func (t *Tree[T]) AddRoot(node *Node[T]) (addedRoot bool) { if t.root == nil { t.root = node return true @@ -22,7 +18,7 @@ func (t *Tree[T]) AddRoot(node *node.Node[T]) (addedRoot bool) { return false } -func (t *Tree[T]) GetRoot() (root *node.Node[T], hasRoot bool) { +func (t *Tree[T]) GetRoot() (root *Node[T], hasRoot bool) { if t.root == nil { return nil, false } @@ -30,7 +26,7 @@ func (t *Tree[T]) GetRoot() (root *node.Node[T], hasRoot bool) { return t.root, true } -func (t *Tree[T]) Add(parentID int, node *node.Node[T]) (addedNode bool) { +func (t *Tree[T]) Add(parentID int, node *Node[T]) (addedNode bool) { if t.root == nil { return false } @@ -38,19 +34,19 @@ func (t *Tree[T]) Add(parentID int, node *node.Node[T]) (addedNode bool) { return t.add(parentID, t.root, node) } -func (t *Tree[T]) Get(id int) (node *node.Node[T], found bool) { +func (t *Tree[T]) Get(id int) (node *Node[T], found bool) { if t.root == nil { return nil, false } - if t.root.ID == id { + if t.root.id == id { return t.root, true } return t.get(id, t.root) } -func (t *Tree[T]) Backtrack(id int) ([]*node.Node[T], bool) { +func (t *Tree[T]) Backtrack(id int) ([]*Node[T], bool) { n, found := t.Get(id) if !found { return nil, found @@ -67,14 +63,13 @@ func (t *Tree[T]) GetStructure() ([]string, bool) { return t.root.GetStructure(), true } -func (t *Tree[T]) add(parentID int, parentNode *node.Node[T], newNode *node.Node[T]) bool { - if parentID == parentNode.ID { +func (t *Tree[T]) add(parentID int, parentNode *Node[T], newNode *Node[T]) bool { + if parentID == parentNode.id { parentNode.AddNext(newNode) return true } - nexts := parentNode.GetNexts() - for _, next := range nexts { + for _, next := range parentNode.nexts { added := t.add(parentID, next, newNode) if added { return true @@ -84,10 +79,9 @@ func (t *Tree[T]) add(parentID int, parentNode *node.Node[T], newNode *node.Node return false } -func (t *Tree[T]) get(id int, parent *node.Node[T]) (*node.Node[T], bool) { - nexts := parent.GetNexts() - for _, next := range nexts { - if next.ID == id { +func (t *Tree[T]) get(id int, parent *Node[T]) (*Node[T], bool) { + for _, next := range parent.nexts { + if next.id == id { return next, true } diff --git a/pkg/tree/tree_test.go b/pkg/tree/tree_test.go index 2cbe388..b086fe7 100644 --- a/pkg/tree/tree_test.go +++ b/pkg/tree/tree_test.go @@ -4,7 +4,6 @@ import ( "fmt" "testing" - "github.com/johnfercher/tree/pkg/node" "github.com/johnfercher/tree/pkg/tree" "github.com/stretchr/testify/assert" ) @@ -23,7 +22,7 @@ func TestTree_AddRoot_WhenTreeIsEmpty_ShouldReturnTrue(t *testing.T) { sut := tree.New[int]() // Act - added := sut.AddRoot(node.New(0, 42)) + added := sut.AddRoot(tree.NewNode(0, 42)) // Assert assert.True(t, added) @@ -34,8 +33,8 @@ func TestTree_AddRoot_WhenTreeIsNotEmpty_ShouldReturnFalse(t *testing.T) { sut := tree.New[int]() // Act - _ = sut.AddRoot(node.New(0, 42)) - added := sut.AddRoot(node.New(0, 43)) + _ = sut.AddRoot(tree.NewNode(0, 42)) + added := sut.AddRoot(tree.NewNode(0, 43)) // Assert assert.False(t, added) @@ -56,7 +55,7 @@ func TestTree_GetRoot_WhenThereIsNotRoot_ShouldReturnFalse(t *testing.T) { func TestTree_GetRoot_WhenThereIsRoot_ShouldReturnTrue(t *testing.T) { // Arrange sut := tree.New[int]() - sut.AddRoot(node.New(0, 42)) + sut.AddRoot(tree.NewNode(0, 42)) // Act root, hasRoot := sut.GetRoot() @@ -71,7 +70,7 @@ func TestTree_Add_WhenThereIsNoRoot_ShouldReturnFalse(t *testing.T) { tr := tree.New[int]() // Act - added := tr.Add(0, node.New(0, 42)) + added := tr.Add(0, tree.NewNode(0, 42)) // Assert assert.False(t, added) @@ -82,8 +81,8 @@ func TestTree_Add_WhenRootIsNotRight_ShouldReturnTrue(t *testing.T) { tr := tree.New[int]() // Act - _ = tr.AddRoot(node.New(0, 42)) - added := tr.Add(3, node.New(1, 42)) + _ = tr.AddRoot(tree.NewNode(0, 42)) + added := tr.Add(3, tree.NewNode(1, 42)) // Assert assert.False(t, added) @@ -94,8 +93,8 @@ func TestTree_Add_WhenThereIsRootAndRootIsRight_ShouldReturnTrue(t *testing.T) { tr := tree.New[int]() // Act - _ = tr.AddRoot(node.New(0, 42)) - added := tr.Add(0, node.New(1, 42)) + _ = tr.AddRoot(tree.NewNode(0, 42)) + added := tr.Add(0, tree.NewNode(1, 42)) // Assert assert.True(t, added) @@ -117,8 +116,8 @@ func TestTree_Get_WhenThereIsNoId_ShouldReturnFalse(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0")) - tr.Add(0, node.New(1, "1.0")) + tr.AddRoot(tree.NewNode(0, "0")) + tr.Add(0, tree.NewNode(1, "1.0")) // Act node, found := tr.Get(8) @@ -132,7 +131,7 @@ func TestTree_Get_WhenThereIsIdOnRoot_ShouldReturnTrue(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0")) + tr.AddRoot(tree.NewNode(0, "0")) // Act node, found := tr.Get(0) @@ -146,8 +145,8 @@ func TestTree_Get_WhenThereIsId_ShouldReturnTrue(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0")) - tr.Add(0, node.New(1, "1.0")) + tr.AddRoot(tree.NewNode(0, "0")) + tr.Add(0, tree.NewNode(1, "1.0")) // Act node, found := tr.Get(1) @@ -161,7 +160,7 @@ func TestTree_Backtrack_WhenIdNotFound_ShouldReturnFalse(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0.0")) + tr.AddRoot(tree.NewNode(0, "0.0")) // Act n, found := tr.Backtrack(1) @@ -175,10 +174,10 @@ func TestTree_Backtrack_WhenIdFound_ShouldReturnTrue(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0.0")) - tr.Add(0, node.New(1, "1.0")) - tr.Add(1, node.New(2, "2.0")) - tr.Add(2, node.New(3, "3.0")) + tr.AddRoot(tree.NewNode(0, "0.0")) + tr.Add(0, tree.NewNode(1, "1.0")) + tr.Add(1, tree.NewNode(2, "2.0")) + tr.Add(2, tree.NewNode(3, "3.0")) // Act n, found := tr.Backtrack(3) @@ -204,20 +203,20 @@ func TestTree_GetStructure_WhenThereIsRoot_ShouldReturnTrue(t *testing.T) { // Arrange tr := tree.New[string]() - tr.AddRoot(node.New(0, "0.0")) - tr.Add(0, node.New(1, "1.0")) - tr.Add(0, node.New(2, "1.1")) - tr.Add(0, node.New(3, "1.2")) - tr.Add(1, node.New(4, "2.0")) - tr.Add(1, node.New(5, "2.1")) - tr.Add(1, node.New(6, "2.2")) - tr.Add(2, node.New(7, "2.0")) - tr.Add(2, node.New(8, "2.1")) - tr.Add(2, node.New(9, "2.2")) - tr.Add(3, node.New(10, "3.0")) - tr.Add(3, node.New(11, "3.1")) - tr.Add(3, node.New(12, "3.2")) - tr.Add(4, node.New(13, "4.0")) + tr.AddRoot(tree.NewNode(0, "0.0")) + tr.Add(0, tree.NewNode(1, "1.0")) + tr.Add(0, tree.NewNode(2, "1.1")) + tr.Add(0, tree.NewNode(3, "1.2")) + tr.Add(1, tree.NewNode(4, "2.0")) + tr.Add(1, tree.NewNode(5, "2.1")) + tr.Add(1, tree.NewNode(6, "2.2")) + tr.Add(2, tree.NewNode(7, "2.0")) + tr.Add(2, tree.NewNode(8, "2.1")) + tr.Add(2, tree.NewNode(9, "2.2")) + tr.Add(3, tree.NewNode(10, "3.0")) + tr.Add(3, tree.NewNode(11, "3.1")) + tr.Add(3, tree.NewNode(12, "3.2")) + tr.Add(4, tree.NewNode(13, "4.0")) // Act structure, found := tr.GetStructure()