forked from knative/test-infra
-
Notifications
You must be signed in to change notification settings - Fork 1
/
resourcetree.go
96 lines (81 loc) · 3.08 KB
/
resourcetree.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resourcetree
import (
"container/list"
"reflect"
"knative.dev/test-infra/tools/webhook-apicoverage/coveragecalculator"
)
// ResourceTree encapsulates a tree corresponding to a resource type.
type ResourceTree struct {
ResourceName string
Root NodeInterface
Forest *ResourceForest
}
// coverageDataHelper is a encapsulator parameter type to the BuildCoverageData method
// so as to avoid long parameter list.
type coverageDataHelper struct {
typeCoverage *[]coveragecalculator.TypeCoverage
nodeRules NodeRules
fieldRules FieldRules
ignoredFields coveragecalculator.IgnoredFields
coveredTypes map[string]bool
}
func (r *ResourceTree) createNode(field string, parent NodeInterface, t reflect.Type) NodeInterface {
var n NodeInterface
switch t.Kind() {
case reflect.Struct:
n = new(StructKindNode)
case reflect.Array, reflect.Slice:
n = new(ArrayKindNode)
case reflect.Ptr, reflect.UnsafePointer, reflect.Uintptr:
n = new(PtrKindNode)
case reflect.Bool, reflect.String, reflect.Float32, reflect.Float64,
reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
n = new(BasicTypeKindNode)
default:
n = new(OtherKindNode) // Maps, interfaces, etc
}
n.initialize(field, parent, t, r)
if len(t.PkgPath()) != 0 {
typeName := t.PkgPath() + "." + t.Name()
if _, ok := r.Forest.ConnectedNodes[typeName]; !ok {
r.Forest.ConnectedNodes[typeName] = list.New()
}
r.Forest.ConnectedNodes[typeName].PushBack(n)
}
return n
}
// BuildResourceTree builds a resource tree by calling into analyzeType method starting from root.
func (r *ResourceTree) BuildResourceTree(t reflect.Type) {
r.Root = r.createNode(r.ResourceName, nil, t)
r.Root.buildChildNodes(t)
}
// UpdateCoverage updates coverage data in the resource tree based on the provided reflect.Value
func (r *ResourceTree) UpdateCoverage(v reflect.Value) {
r.Root.updateCoverage(v)
}
// BuildCoverageData calculates the coverage information for a resource tree by applying provided Node and Field rules.
func (r *ResourceTree) BuildCoverageData(nodeRules NodeRules, fieldRules FieldRules,
ignoredFields coveragecalculator.IgnoredFields) []coveragecalculator.TypeCoverage {
coverageHelper := coverageDataHelper{
nodeRules: nodeRules,
fieldRules: fieldRules,
typeCoverage: &[]coveragecalculator.TypeCoverage{},
ignoredFields: ignoredFields,
coveredTypes: make(map[string]bool),
}
r.Root.buildCoverageData(coverageHelper)
return *coverageHelper.typeCoverage
}