Skip to content

Commit da4b0b0

Browse files
committed
Validation for behaviors
1 parent 4b29407 commit da4b0b0

File tree

6 files changed

+134
-27
lines changed

6 files changed

+134
-27
lines changed

test/conformance/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ filegroup(
2424
name = "all-srcs",
2525
srcs = [
2626
":package-srcs",
27+
"//test/conformance/behaviors:all-srcs",
2728
"//test/conformance/kubetestgen:all-srcs",
2829
],
2930
tags = ["automanaged"],

test/conformance/behaviors/BUILD

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
2+
3+
go_library(
4+
name = "go_default_library",
5+
srcs = ["types.go"],
6+
importpath = "k8s.io/kubernetes/test/conformance/behaviors",
7+
visibility = ["//visibility:public"],
8+
)
9+
10+
go_test(
11+
name = "go_default_test",
12+
srcs = ["behaviors_test.go"],
13+
data = glob(["*/*.yaml"]),
14+
embed = [":go_default_library"],
15+
deps = [
16+
"//vendor/gopkg.in/yaml.v2:go_default_library",
17+
],
18+
)
19+
20+
filegroup(
21+
name = "package-srcs",
22+
srcs = glob(["**"]),
23+
tags = ["automanaged"],
24+
visibility = ["//visibility:private"],
25+
)
26+
27+
filegroup(
28+
name = "all-srcs",
29+
srcs = [":package-srcs"],
30+
tags = ["automanaged"],
31+
visibility = ["//visibility:public"],
32+
)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package behaviors
18+
19+
import (
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
23+
"regexp"
24+
"testing"
25+
26+
"gopkg.in/yaml.v2"
27+
)
28+
29+
func TestValidate(t *testing.T) {
30+
var behaviorFiles []string
31+
32+
err := filepath.Walk(".",
33+
func(path string, info os.FileInfo, err error) error {
34+
if err != nil {
35+
t.Errorf("%q", err.Error())
36+
}
37+
38+
r, _ := regexp.Compile(".+.yaml$")
39+
if r.MatchString(path) {
40+
behaviorFiles = append(behaviorFiles, path)
41+
}
42+
return nil
43+
})
44+
if err != nil {
45+
t.Errorf("%q", err.Error())
46+
}
47+
48+
for _, file := range behaviorFiles {
49+
validateSuite(file, t)
50+
}
51+
}
52+
53+
func validateSuite(path string, t *testing.T) {
54+
var suite Suite
55+
yamlFile, err := ioutil.ReadFile(path)
56+
if err != nil {
57+
t.Errorf("%q", err.Error())
58+
}
59+
err = yaml.UnmarshalStrict(yamlFile, &suite)
60+
61+
if err != nil {
62+
t.Errorf("%q", err.Error())
63+
}
64+
65+
behaviorIDList := make(map[string]bool)
66+
67+
for _, behavior := range suite.Behaviors {
68+
69+
// Ensure no behavior IDs are duplicated
70+
if _, ok := behaviorIDList[behavior.ID]; ok {
71+
t.Errorf("Duplicate behavior ID: %s", behavior.ID)
72+
}
73+
behaviorIDList[behavior.ID] = true
74+
}
75+
}

test/conformance/kubetestgen/types.go renamed to test/conformance/behaviors/types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2019 The Kubernetes Authors.
2+
Copyright 2020 The Kubernetes Authors.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package main
17+
package behaviors
1818

1919
// Area is a conformance area composed of a list of test suites
2020
type Area struct {

test/conformance/kubetestgen/BUILD

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
22

33
go_library(
44
name = "go_default_library",
5-
srcs = [
6-
"kubetestgen.go",
7-
"types.go",
8-
],
5+
srcs = ["kubetestgen.go"],
96
importpath = "k8s.io/kubernetes/test/conformance/kubetestgen",
107
visibility = ["//visibility:private"],
118
deps = [
9+
"//test/conformance/behaviors:go_default_library",
1210
"//vendor/github.com/go-openapi/analysis:go_default_library",
1311
"//vendor/github.com/go-openapi/loads:go_default_library",
1412
"//vendor/github.com/go-openapi/spec:go_default_library",

test/conformance/kubetestgen/kubetestgen.go

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/go-openapi/loads"
2828
"github.com/go-openapi/spec"
2929
"gopkg.in/yaml.v2"
30+
"k8s.io/kubernetes/test/conformance/behaviors"
3031
)
3132

3233
type options struct {
@@ -67,19 +68,19 @@ func main() {
6768
defMap[d.Ref.String()] = d
6869
}
6970

70-
var suites []Suite
71-
var suiteMapping = make(map[string]*Suite)
71+
var suites []behaviors.Suite
72+
var suiteMapping = make(map[string]*behaviors.Suite)
7273

7374
for _, v := range defs {
7475
if !v.TopLevel || o.resource != v.Name {
7576
continue
7677
}
7778
name := trimObjectName(v.Name)
7879

79-
defaultsuite := Suite{
80+
defaultsuite := behaviors.Suite{
8081
Suite: o.area + "/spec",
8182
Description: "Base suite for " + o.area,
82-
Behaviors: []Behavior{},
83+
Behaviors: []behaviors.Behavior{},
8384
}
8485

8586
_ = defaultsuite
@@ -89,10 +90,10 @@ func main() {
8990

9091
if propSchema.Ref.String() != "" || propSchema.Type[0] == "array" {
9192
if _, ok := suiteMapping[id]; !ok {
92-
newsuite := Suite{
93+
newsuite := behaviors.Suite{
9394
Suite: o.area + "/" + p,
9495
Description: "Suite for " + o.area + "/" + p,
95-
Behaviors: []Behavior{},
96+
Behaviors: []behaviors.Behavior{},
9697
}
9798
suiteMapping[id] = &newsuite
9899
}
@@ -101,10 +102,10 @@ func main() {
101102
suiteMapping[id].Behaviors = behaviors
102103
} else {
103104
if _, ok := suiteMapping["default"]; !ok {
104-
newsuite := Suite{
105+
newsuite := behaviors.Suite{
105106
Suite: o.area + "/spec",
106107
Description: "Base suite for " + o.area,
107-
Behaviors: []Behavior{},
108+
Behaviors: []behaviors.Behavior{},
108109
}
109110
suiteMapping["default"] = &newsuite
110111
}
@@ -122,12 +123,12 @@ func main() {
122123
break
123124
}
124125

125-
var area Area = Area{o.area, suites}
126+
var area behaviors.Area = behaviors.Area{Area: o.area, Suites: suites}
126127
countFields(suites)
127128
printYAML(o.behaviorsDir+o.area, area)
128129
}
129130

130-
func printYAML(fileName string, areaO Area) {
131+
func printYAML(fileName string, areaO behaviors.Area) {
131132
f, err := os.Create(fileName + ".yaml")
132133
if err != nil {
133134
fmt.Printf("ERROR: %s\n", err.Error())
@@ -147,7 +148,7 @@ func printYAML(fileName string, areaO Area) {
147148
}
148149
}
149150

150-
func countFields(suites []Suite) {
151+
func countFields(suites []behaviors.Suite) {
151152
var fieldsMapping map[string]int
152153
fieldsMapping = make(map[string]int)
153154
for _, suite := range suites {
@@ -174,43 +175,43 @@ func trimObjectName(name string) string {
174175
return name
175176
}
176177

177-
func objectBehaviors(id string, s *spec.Schema) []Behavior {
178+
func objectBehaviors(id string, s *spec.Schema) []behaviors.Behavior {
178179
if strings.Contains(id, "openAPIV3Schema") || strings.Contains(id, "JSONSchema") || strings.Contains(s.Ref.String(), "JSONSchema") {
179-
return []Behavior{}
180+
return []behaviors.Behavior{}
180181
}
181182

182183
ref, ok := defMap[s.Ref.String()]
183184
if !ok {
184-
return []Behavior{}
185+
return []behaviors.Behavior{}
185186
}
186187

187188
return schemaBehaviors(id, trimObjectName(ref.Name), ref.Schema)
188189
}
189190

190-
func schemaBehaviors(base, apiObject string, s *spec.Schema) []Behavior {
191-
var behaviors []Behavior
191+
func schemaBehaviors(base, apiObject string, s *spec.Schema) []behaviors.Behavior {
192+
var behaviors []behaviors.Behavior
192193
for p, propSchema := range s.Properties {
193194
b := schemaBehavior(base, apiObject, p, propSchema)
194195
behaviors = append(behaviors, b...)
195196
}
196197
return behaviors
197198
}
198199

199-
func schemaBehavior(base, apiObject, p string, propSchema spec.Schema) []Behavior {
200+
func schemaBehavior(base, apiObject, p string, propSchema spec.Schema) []behaviors.Behavior {
200201

201202
id := strings.Join([]string{base, p}, "/")
202203
if propSchema.Ref.String() != "" {
203204
if apiObject == trimObjectName(propSchema.Ref.String()) {
204-
return []Behavior{}
205+
return []behaviors.Behavior{}
205206
}
206207
return objectBehaviors(id, &propSchema)
207208
}
208-
var b []Behavior
209+
var b []behaviors.Behavior
209210
switch propSchema.Type[0] {
210211
case "array":
211212
b = objectBehaviors(id, propSchema.Items.Schema)
212213
case "boolean":
213-
b = []Behavior{
214+
b = []behaviors.Behavior{
214215
{
215216
ID: id,
216217
APIObject: apiObject,
@@ -227,7 +228,7 @@ func schemaBehavior(base, apiObject, p string, propSchema spec.Schema) []Behavio
227228
},
228229
}
229230
default:
230-
b = []Behavior{{
231+
b = []behaviors.Behavior{{
231232
ID: id,
232233
APIObject: apiObject,
233234
APIField: p,

0 commit comments

Comments
 (0)