Skip to content

Commit 07ae744

Browse files
authored
api: add tests that ensure types and reasons are registered correctly (#122)
Signed-off-by: Joe Lanford <[email protected]>
1 parent c96fef5 commit 07ae744

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

api/v1alpha1/operator_types_test.go

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package v1alpha1_test
2+
3+
import (
4+
"fmt"
5+
"go/ast"
6+
"go/parser"
7+
"go/token"
8+
"io/fs"
9+
"strconv"
10+
"strings"
11+
12+
. "github.com/onsi/ginkgo/v2"
13+
. "github.com/onsi/gomega"
14+
15+
operatorutil "github.com/operator-framework/operator-controller/internal/util"
16+
)
17+
18+
var _ = Describe("OperatorTypes", func() {
19+
Describe("Condition Type and Reason constants", func() {
20+
It("should register types in operatorutil.ConditionTypes", func() {
21+
types, err := parseConstants("Type")
22+
Expect(err).NotTo(HaveOccurred())
23+
24+
for _, t := range types {
25+
Expect(t).To(BeElementOf(operatorutil.ConditionTypes), "Append Type%s to operatorutil.ConditionTypes in this package's init function.", t)
26+
}
27+
for _, t := range operatorutil.ConditionTypes {
28+
Expect(t).To(BeElementOf(types), "There must be a Type%[1]s string literal constant for type %[1]q (i.e. 'const Type%[1]s = %[1]q')", t)
29+
}
30+
})
31+
It("should register reasons in operatorutil.ConditionReasons", func() {
32+
reasons, err := parseConstants("Reason")
33+
Expect(err).NotTo(HaveOccurred())
34+
35+
for _, r := range reasons {
36+
Expect(r).To(BeElementOf(operatorutil.ConditionReasons), "Append Reason%s to operatorutil.ConditionReasons in this package's init function.", r)
37+
}
38+
for _, r := range operatorutil.ConditionReasons {
39+
Expect(r).To(BeElementOf(reasons), "There must be a Reason%[1]s string literal constant for reason %[1]q (i.e. 'const Reason%[1]s = %[1]q')", r)
40+
}
41+
})
42+
})
43+
})
44+
45+
// parseConstants parses the values of the top-level constants in the current
46+
// directory whose names start with the given prefix. When running as part of a
47+
// test, the current directory is the directory of the file that contains the
48+
// test in which this function is called.
49+
func parseConstants(prefix string) ([]string, error) {
50+
fset := token.NewFileSet()
51+
// ParseDir returns a map of package name to package ASTs. An AST is a representation of the source code
52+
// that can be traversed to extract information. The map is keyed by the package name.
53+
pkgs, err := parser.ParseDir(fset, ".", func(info fs.FileInfo) bool {
54+
return !strings.HasSuffix(info.Name(), "_test.go")
55+
}, 0)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
var constValues []string
61+
62+
// Iterate all of the top-level declarations in each package's files,
63+
// looking for constants that start with the prefix. When we find one,
64+
// add its value to the constValues list.
65+
for _, pkg := range pkgs {
66+
for _, f := range pkg.Files {
67+
for _, d := range f.Decls {
68+
genDecl, ok := d.(*ast.GenDecl)
69+
if !ok {
70+
continue
71+
}
72+
for _, s := range genDecl.Specs {
73+
valueSpec, ok := s.(*ast.ValueSpec)
74+
if !ok || len(valueSpec.Names) != 1 || valueSpec.Names[0].Obj.Kind != ast.Con || !strings.HasPrefix(valueSpec.Names[0].String(), prefix) {
75+
continue
76+
}
77+
for _, val := range valueSpec.Values {
78+
lit, ok := val.(*ast.BasicLit)
79+
if !ok || lit.Kind != token.STRING {
80+
continue
81+
}
82+
v, err := strconv.Unquote(lit.Value)
83+
if err != nil {
84+
return nil, fmt.Errorf("unquote literal string %s: %v", lit.Value, err)
85+
}
86+
constValues = append(constValues, v)
87+
}
88+
}
89+
}
90+
}
91+
}
92+
return constValues, nil
93+
}

api/v1alpha1/v1alpha1_suite_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package v1alpha1_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestV1alpha1(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "V1alpha1 Suite")
13+
}

0 commit comments

Comments
 (0)