Skip to content

Commit b8b0ceb

Browse files
committed
feat: unit tests for listener/apischema/builder
1 parent 77aa21a commit b8b0ceb

File tree

1 file changed

+271
-0
lines changed

1 file changed

+271
-0
lines changed

listener/apischema/builder_test.go

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
package apischema
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"testing"
7+
8+
"github.com/openmfp/kubernetes-graphql-gateway/common"
9+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/client-go/openapi"
12+
"k8s.io/kube-openapi/pkg/validation/spec"
13+
)
14+
15+
// TestGetOpenAPISchemaKey tests the getOpenAPISchemaKey function. It checks if the
16+
// function correctly formats the GroupVersionKind into the expected schema key format.
17+
func TestGetOpenAPISchemaKey(t *testing.T) {
18+
tests := []struct {
19+
gvk metav1.GroupVersionKind
20+
want string
21+
}{
22+
{
23+
gvk: metav1.GroupVersionKind{Group: "example.group", Version: "v1", Kind: "KindA"},
24+
want: "group.example.v1.KindA",
25+
},
26+
{
27+
gvk: metav1.GroupVersionKind{Group: "io.openmfp.core", Version: "v2beta", Kind: "MyCRD"},
28+
want: "core.openmfp.io.v2beta.MyCRD",
29+
},
30+
}
31+
32+
for _, tc := range tests {
33+
got := getOpenAPISchemaKey(tc.gvk)
34+
if got != tc.want {
35+
t.Errorf("getOpenAPISchemaKey(%+v) = %q; want %q", tc.gvk, got, tc.want)
36+
}
37+
}
38+
}
39+
40+
// TestGetCRDGroupVersionKind tests the getCRDGroupVersionKind function. It checks if the
41+
// function correctly extracts the GroupVersionKind from the CRD spec and handles errors.
42+
func TestGetCRDGroupVersionKind(t *testing.T) {
43+
tests := []struct {
44+
name string
45+
spec apiextensionsv1.CustomResourceDefinitionSpec
46+
want *metav1.GroupVersionKind
47+
wantErr error
48+
}{
49+
{
50+
name: "has versions",
51+
spec: apiextensionsv1.CustomResourceDefinitionSpec{
52+
Group: "test.group",
53+
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
54+
{Name: "v1beta1"},
55+
{Name: "v1"},
56+
},
57+
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Foo"},
58+
},
59+
want: &metav1.GroupVersionKind{Group: "test.group", Version: "v1beta1", Kind: "Foo"},
60+
wantErr: nil,
61+
},
62+
{
63+
name: "no versions",
64+
spec: apiextensionsv1.CustomResourceDefinitionSpec{
65+
Group: "empty.group",
66+
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{},
67+
Names: apiextensionsv1.CustomResourceDefinitionNames{Kind: "Bar"},
68+
},
69+
want: nil,
70+
wantErr: ErrCRDNoVersions,
71+
},
72+
}
73+
74+
for _, tc := range tests {
75+
t.Run(tc.name, func(t *testing.T) {
76+
got, err := getCRDGroupVersionKind(tc.spec)
77+
if tc.wantErr != nil {
78+
if err != tc.wantErr {
79+
t.Fatalf("expected error %v, got %v", tc.wantErr, err)
80+
}
81+
return
82+
}
83+
if err != nil {
84+
t.Fatalf("unexpected error: %v", err)
85+
}
86+
if got == nil || *got != *tc.want {
87+
t.Errorf("got %+v; want %+v", got, tc.want)
88+
}
89+
})
90+
}
91+
}
92+
93+
type fakeClient struct {
94+
paths map[string]openapi.GroupVersion
95+
}
96+
97+
func (f *fakeClient) Paths() (map[string]openapi.GroupVersion, error) {
98+
return f.paths, nil
99+
}
100+
101+
type fakeErrClient struct{}
102+
103+
func (f *fakeErrClient) Paths() (map[string]openapi.GroupVersion, error) {
104+
return nil, errors.New("fail Paths")
105+
}
106+
107+
// TestNewSchemaBuilder tests the NewSchemaBuilder function. It checks if the
108+
// SchemaBuilder is correctly initialized with the expected number of schemas
109+
// and the expected schema key.
110+
func TestNewSchemaBuilder(t *testing.T) {
111+
tests := []struct {
112+
name string
113+
client openapi.Client
114+
wantLen int
115+
wantKey string
116+
wantError bool
117+
}{
118+
{
119+
name: "populates schemas",
120+
client: &fakeClient{paths: map[string]openapi.GroupVersion{"/X/v1": fakeGV{data: func() []byte {
121+
d, _ := json.Marshal(&schemaResponse{Components: schemasComponentsWrapper{Schemas: map[string]*spec.Schema{"X.v1.K": {}}}})
122+
return d
123+
}(), err: nil}}},
124+
wantLen: 1,
125+
wantKey: "X.v1.K",
126+
},
127+
{
128+
name: "error on Paths",
129+
client: &fakeErrClient{},
130+
wantLen: 0,
131+
wantError: true,
132+
},
133+
}
134+
for _, tc := range tests {
135+
t.Run(tc.name, func(t *testing.T) {
136+
b := NewSchemaBuilder(tc.client, []string{"X/v1"})
137+
if tc.wantError {
138+
if b.err == nil {
139+
t.Error("expected error, got nil")
140+
}
141+
if len(b.schemas) != 0 {
142+
t.Errorf("expected 0 schemas on error, got %d", len(b.schemas))
143+
}
144+
return
145+
}
146+
if len(b.schemas) != tc.wantLen {
147+
t.Fatalf("expected %d schema entry, got %d", tc.wantLen, len(b.schemas))
148+
}
149+
if tc.wantKey != "" {
150+
if _, ok := b.schemas[tc.wantKey]; !ok {
151+
t.Errorf("schema key %s not found in builder.schemas", tc.wantKey)
152+
}
153+
}
154+
})
155+
}
156+
}
157+
158+
// TestWithCRDCategories_AddsExtension tests the WithCRDCategories method
159+
// for the SchemaBuilder struct. It checks if the categories are correctly added to the schema's extensions.
160+
func TestWithCRDCategories_AddsExtension(t *testing.T) {
161+
tests := []struct {
162+
name string
163+
key string
164+
crd *apiextensionsv1.CustomResourceDefinition
165+
wantCats []string
166+
}{
167+
{
168+
name: "adds categories",
169+
key: "g.v1.K",
170+
crd: &apiextensionsv1.CustomResourceDefinition{
171+
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
172+
Group: "g",
173+
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{Name: "v1"}},
174+
Names: apiextensionsv1.CustomResourceDefinitionNames{
175+
Kind: "K",
176+
Categories: []string{"cat1", "cat2"},
177+
},
178+
},
179+
},
180+
wantCats: []string{"cat1", "cat2"},
181+
},
182+
{
183+
name: "no categories",
184+
key: "g.v1.K",
185+
crd: &apiextensionsv1.CustomResourceDefinition{
186+
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
187+
Group: "g",
188+
Versions: []apiextensionsv1.CustomResourceDefinitionVersion{{Name: "v1"}},
189+
Names: apiextensionsv1.CustomResourceDefinitionNames{
190+
Kind: "K",
191+
},
192+
},
193+
},
194+
wantCats: nil,
195+
},
196+
}
197+
for _, tc := range tests {
198+
t.Run(tc.name, func(t *testing.T) {
199+
b := &SchemaBuilder{schemas: map[string]*spec.Schema{
200+
tc.key: {VendorExtensible: spec.VendorExtensible{Extensions: map[string]interface{}{}}},
201+
}}
202+
b.WithCRDCategories(tc.crd)
203+
ext, found := b.schemas[tc.key].VendorExtensible.Extensions[common.CategoriesExtensionKey]
204+
if tc.wantCats == nil {
205+
if found {
206+
t.Errorf("expected no categories, but found: %#v", ext)
207+
}
208+
return
209+
}
210+
if !found {
211+
t.Fatal("expected CategoriesExtensionKey to be set")
212+
}
213+
cats, ok := ext.([]string)
214+
if !ok || len(cats) != len(tc.wantCats) || cats[0] != tc.wantCats[0] {
215+
t.Errorf("unexpected categories: %#v", ext)
216+
}
217+
})
218+
}
219+
}
220+
221+
// TestWithApiResourceCategories_AddsExtension tests the WithApiResourceCategories method
222+
// for the SchemaBuilder struct. It checks if the categories are correctly added to the schema's extensions.
223+
func TestWithApiResourceCategories_AddsExtension(t *testing.T) {
224+
tests := []struct {
225+
name string
226+
key string
227+
list []*metav1.APIResourceList
228+
wantCats []string
229+
}{
230+
{
231+
name: "adds categories",
232+
key: "h.v1.P",
233+
list: []*metav1.APIResourceList{{
234+
GroupVersion: "h/v1",
235+
APIResources: []metav1.APIResource{{Kind: "P", Categories: []string{"A", "B"}}},
236+
}},
237+
wantCats: []string{"A", "B"},
238+
},
239+
{
240+
name: "no categories",
241+
key: "h.v1.P",
242+
list: []*metav1.APIResourceList{{
243+
GroupVersion: "h/v1",
244+
APIResources: []metav1.APIResource{{Kind: "P"}},
245+
}},
246+
wantCats: nil,
247+
},
248+
}
249+
for _, tc := range tests {
250+
t.Run(tc.name, func(t *testing.T) {
251+
b := &SchemaBuilder{schemas: map[string]*spec.Schema{
252+
tc.key: {VendorExtensible: spec.VendorExtensible{Extensions: map[string]interface{}{}}},
253+
}}
254+
b.WithApiResourceCategories(tc.list)
255+
ext, found := b.schemas[tc.key].VendorExtensible.Extensions[common.CategoriesExtensionKey]
256+
if tc.wantCats == nil {
257+
if found {
258+
t.Errorf("expected no categories, but found: %#v", ext)
259+
}
260+
return
261+
}
262+
if !found {
263+
t.Fatal("expected CategoriesExtensionKey to be set by WithApiResourceCategories")
264+
}
265+
cats, ok := ext.([]string)
266+
if !ok || len(cats) != len(tc.wantCats) || cats[len(tc.wantCats)-1] != tc.wantCats[len(tc.wantCats)-1] {
267+
t.Errorf("unexpected categories: %#v", ext)
268+
}
269+
})
270+
}
271+
}

0 commit comments

Comments
 (0)