Добавил базовые методы и модели для тестирования нарезки дерева
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
c3d06df00a
commit
5693923d03
2
Makefile
2
Makefile
|
@ -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}'
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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++ {
|
|
@ -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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
Loading…
Reference in New Issue