Добавил базовые методы и модели для тестирования нарезки дерева
continuous-integration/drone/push Build is passing Details

main
Андрей Иванов 2024-10-03 17:42:55 +03:00
parent c3d06df00a
commit 5693923d03
11 changed files with 281 additions and 69 deletions

View File

@ -12,7 +12,7 @@ race:
.PHONY: bench .PHONY: bench
bench: ## Бенчмарки bench: ## Бенчмарки
go test -benchtime=10x -benchmem -bench=Benchmark ./... | grep allocs go test -benchtime=3x -benchmem -bench=Benchmark ./... | grep allocs
help: ## Print this help and exit help: ## Print this help and exit
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

View File

@ -0,0 +1,5 @@
package main
func DecomposeTree(tree map[string]*WeightedNode, threshold int) ([]SubTree, error) {
return []SubTree{{path: "/", tree: tree["1.0.0.0"].node}}, nil
}

View File

@ -0,0 +1,32 @@
package main
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestDecomposeTree(t *testing.T){
for name, tt := range map[string]struct{
inputTree map[string]*WeightedNode
inputThreshold int
outputParts []SubTree
err string
}{
"Normal":{
inputTree: smallTree.Tree,
inputThreshold: smallTree.Threshold,
outputParts: smallTree.Parts,
},
}{
t.Run(name, func(t *testing.T) {
result, err := DecomposeTree(tt.inputTree, tt.inputThreshold)
if tt.err == "" {
require.NoError(t, err)
require.ElementsMatch(t, result, tt.outputParts)
} else {
require.EqualError(t, err, tt.err)
}
})
}
}

View File

@ -0,0 +1,232 @@
package main
type testDecomposingData struct {
Tree map[string]*WeightedNode
Threshold int
Parts []SubTree
}
var smallTree = testDecomposingData{
Tree: tree3by3.WeightingTreeWithStack(),
Threshold: 2,
Parts: []SubTree{
{
path: "/",
tree: tree3by3,
},
},
}
var tree3by3 = &Node{
ID: "1.0.0.0",
Name: "/",
Children: []*Node{
{
ID: "1.1.0.0",
Name: "folder1",
Children: []*Node{
{
ID: "1.1.1.0",
Name: "folder1",
Children: []*Node{
{
ID: "1.1.1.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.1.1.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.1.1.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.1.2.0",
Name: "folder2",
Children: []*Node{
{
ID: "1.1.2.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.1.2.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.1.2.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.1.3.0",
Name: "folder3",
Children: []*Node{
{
ID: "1.1.3.1",
Name: "folder3",
Children: []*Node{},
},
{
ID: "1.1.3.2",
Name: "folder3",
Children: []*Node{},
},
{
ID: "1.1.3.3",
Name: "folder3",
Children: []*Node{},
},
},
},
},
},
{
ID: "1.2.0.0",
Name: "folder2",
Children: []*Node{
{
ID: "1.2.1.0",
Name: "folder1",
Children: []*Node{
{
ID: "1.2.1.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.2.1.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.2.1.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.2.2.0",
Name: "folder2",
Children: []*Node{
{
ID: "1.2.2.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.2.2.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.2.2.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.2.3.0",
Name: "folder3",
Children: []*Node{
{
ID: "1.2.3.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.2.3.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.2.3.3",
Name: "folder3",
Children: []*Node{},
},
},
},
},
},
{
ID: "1.3.0.0",
Name: "folder3",
Children: []*Node{
{
ID: "1.3.1.0",
Name: "folder1",
Children: []*Node{
{
ID: "1.3.1.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.3.1.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.3.1.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.3.2.0",
Name: "folder2",
Children: []*Node{
{
ID: "1.3.2.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.3.2.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.3.2.3",
Name: "folder3",
Children: []*Node{},
},
},
},
{
ID: "1.3.3.0",
Name: "folder3",
Children: []*Node{
{
ID: "1.3.3.1",
Name: "folder1",
Children: []*Node{},
},
{
ID: "1.3.3.2",
Name: "folder2",
Children: []*Node{},
},
{
ID: "1.3.3.3",
Name: "folder3",
Children: []*Node{},
},
},
},
},
},
},
}

View File

@ -2,7 +2,7 @@ package main
import ( import (
"maps" "maps"
"tests/weghting_n_cutting_the_tree/dll" "tests/weighting_n_cutting_the_tree/dll"
) )
func (root *Node) WeightingTreeWithRecursion(parent *Node) map[string]*WeightedNode { func (root *Node) WeightingTreeWithRecursion(parent *Node) map[string]*WeightedNode {
@ -103,7 +103,3 @@ func (root *Node) WeightingTreeWithDLL() map[string]*WeightedNode {
return counter return counter
} }
func DecomposeTree(tree map[string]*WeightedNode, threshold int) ([]SubTree, error) {
return []SubTree{{path: "/", tree: tree["root"].node}}, nil
}

View File

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"github.com/stretchr/testify/require"
"sort" "sort"
"testing" "testing"
@ -10,9 +9,9 @@ import (
) )
func TestNode_WeighingTreeAllAlgo(t *testing.T) { func TestNode_WeighingTreeAllAlgo(t *testing.T) {
for name,tt := range map[string]TestTree{ for name,tt := range map[string]WeightedTree{
"Ordinary VFS tree": getTestTree(3, 3, nil), "Ordinary VFS tree": getWeightedTree(3, 3, nil),
"VFS in the form of a pathological tree":getTestTree(1, 7, nil), "VFS in the form of a pathological tree":getWeightedTree(1, 7, nil),
}{ }{
t.Run(name,func(t *testing.T) { t.Run(name,func(t *testing.T) {
t.Run("WeightingTreeWithRecursion", func(t *testing.T) { t.Run("WeightingTreeWithRecursion", func(t *testing.T) {
@ -34,31 +33,6 @@ func TestNode_WeighingTreeAllAlgo(t *testing.T) {
} }
} }
func TestDecomposeTree(t *testing.T){
for name, tt := range map[string]struct{
inputTree map[string]*WeightedNode
inputThreshold int
outputParts []SubTree
err string
}{
"Normal":{
inputTree: smallTree.Tree,
inputThreshold: smallTree.Threshold,
outputParts: smallTree.Parts,
},
}{
t.Run(name, func(t *testing.T) {
result, err := DecomposeTree(tt.inputTree, tt.inputThreshold)
if tt.err == "" {
require.NoError(t, err)
require.ElementsMatch(t, result, tt.outputParts)
} else {
require.EqualError(t, err, tt.err)
}
})
}
}
func Benchmark(b *testing.B) { func Benchmark(b *testing.B) {
b.StopTimer() b.StopTimer()
b.ResetTimer() b.ResetTimer()
@ -73,9 +47,9 @@ func Benchmark(b *testing.B) {
"Pathological tree (10K nodes)": {1, 10000}, // 10'000 nodes, "Pathological tree (10K nodes)": {1, 10000}, // 10'000 nodes,
}{ }{
b.Run(name, func(b *testing.B) { b.Run(name, func(b *testing.B) {
tree := getTestTree(tt.branches, tt.depth, nil) tree := getWeightedTree(tt.branches, tt.depth, nil)
b.Cleanup(func() { b.Cleanup(func() {
tree = TestTree{nil, nil} tree = WeightedTree{nil, nil}
}) })
b.Run("Weighing with recursion", func(b *testing.B) { b.Run("Weighing with recursion", func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {

View File

@ -5,14 +5,14 @@ import (
"maps" "maps"
) )
type TestTree struct { type WeightedTree struct {
Tree *Node Tree *Node
Weights map[string]*WeightedNode Weights map[string]*WeightedNode
} }
func getTestTree(branches, depth int, parent *Node) TestTree { func getWeightedTree(branches, depth int, parent *Node) WeightedTree {
if depth == 0 { if depth == 0 {
return TestTree{} return WeightedTree{}
} }
id := uuid.NewString() id := uuid.NewString()
node := &Node{ node := &Node{
@ -20,7 +20,7 @@ func getTestTree(branches, depth int, parent *Node) TestTree {
Name: id, Name: id,
Children: []*Node{}, Children: []*Node{},
} }
tree := TestTree{ tree := WeightedTree{
Tree: node, Tree: node,
Weights: map[string]*WeightedNode{id: &WeightedNode{ Weights: map[string]*WeightedNode{id: &WeightedNode{
node: node, node: node,
@ -30,7 +30,7 @@ func getTestTree(branches, depth int, parent *Node) TestTree {
}}, }},
} }
for i := 0; i < branches; i++ { for i := 0; i < branches; i++ {
childTree := getTestTree(branches, depth-1, node) childTree := getWeightedTree(branches, depth-1, node)
if childTree.Tree != nil { if childTree.Tree != nil {
tree.Tree.Children = append(tree.Tree.Children, childTree.Tree) tree.Tree.Children = append(tree.Tree.Children, childTree.Tree)
tree.Weights[id].children = append(tree.Weights[id].children, childTree.Tree) tree.Weights[id].children = append(tree.Weights[id].children, childTree.Tree)
@ -42,30 +42,3 @@ func getTestTree(branches, depth int, parent *Node) TestTree {
} }
return tree return tree
} }
type testDecomposingData struct {
Tree map[string]*WeightedNode
Threshold int
Parts []SubTree
}
var smallTree = testDecomposingData{
Tree: map[string]*WeightedNode{
"root": {
node: &Node{
ID: "root",
Name: "root",
},
},
},
Threshold: 2,
Parts: []SubTree{
{
path: "/",
tree: &Node{
ID: "root",
Name: "root",
},
},
},
}