Skip to content

Commit 0536868

Browse files
committed
Add unit tests for pkg/sharding/key
1 parent 9d26a97 commit 0536868

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed

pkg/sharding/key/key_suite_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2025 Tim Ebert.
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 key_test
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestKey(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Sharding Key Suite")
29+
}

pkg/sharding/key/key_test.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
Copyright 2025 Tim Ebert.
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 key_test
18+
19+
import (
20+
"reflect"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
"github.com/onsi/gomega/gcustom"
25+
gomegatypes "github.com/onsi/gomega/types"
26+
appsv1 "k8s.io/api/apps/v1"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/utils/ptr"
29+
30+
shardingv1alpha1 "github.com/timebertt/kubernetes-controller-sharding/pkg/apis/sharding/v1alpha1"
31+
. "github.com/timebertt/kubernetes-controller-sharding/pkg/sharding/key"
32+
)
33+
34+
var _ = Describe("#FuncForResource", func() {
35+
var controllerRing *shardingv1alpha1.ControllerRing
36+
37+
BeforeEach(func() {
38+
controllerRing = &shardingv1alpha1.ControllerRing{
39+
Spec: shardingv1alpha1.ControllerRingSpec{
40+
Resources: []shardingv1alpha1.RingResource{
41+
{
42+
GroupResource: metav1.GroupResource{
43+
Group: "operator",
44+
Resource: "foo",
45+
},
46+
ControlledResources: []metav1.GroupResource{
47+
{
48+
Group: "operator",
49+
Resource: "controlled",
50+
},
51+
{
52+
Resource: "foo",
53+
},
54+
},
55+
},
56+
{
57+
GroupResource: metav1.GroupResource{
58+
Resource: "foo",
59+
},
60+
},
61+
},
62+
},
63+
}
64+
})
65+
66+
It("should return an error if the resource is not part of the ring", func() {
67+
Expect(FuncForResource(metav1.GroupResource{
68+
Resource: "bar",
69+
}, controllerRing)).Error().To(
70+
MatchError(ContainSubstring("not found")),
71+
)
72+
})
73+
74+
It("should return ForObject if the resource is a main resource of the ring", func() {
75+
Expect(FuncForResource(metav1.GroupResource{
76+
Group: "operator",
77+
Resource: "foo",
78+
}, controllerRing)).To(
79+
beFunc(ForObject),
80+
)
81+
})
82+
83+
It("should return ForController if the resource is a controlled resource of the ring", func() {
84+
Expect(FuncForResource(metav1.GroupResource{
85+
Group: "operator",
86+
Resource: "controlled",
87+
}, controllerRing)).To(
88+
beFunc(ForController),
89+
)
90+
})
91+
92+
It("should return ForObject if the resource is a main and controlled resource of the ring", func() {
93+
Expect(FuncForResource(metav1.GroupResource{
94+
Resource: "foo",
95+
}, controllerRing)).To(
96+
beFunc(ForObject),
97+
)
98+
})
99+
})
100+
101+
var _ = Describe("#ForObject", func() {
102+
var obj *appsv1.Deployment
103+
104+
BeforeEach(func() {
105+
obj = &appsv1.Deployment{}
106+
obj.GetObjectKind().SetGroupVersionKind(appsv1.SchemeGroupVersion.WithKind("Deployment"))
107+
obj.Name = "foo"
108+
obj.Namespace = "bar"
109+
})
110+
111+
It("should return an error if the object has no TypeMeta", func() {
112+
Expect(ForObject(&appsv1.Deployment{})).Error().To(MatchError("apiVersion and kind must not be empty"))
113+
})
114+
115+
It("should return an error if the object has no name", func() {
116+
obj.Name = ""
117+
Expect(ForObject(obj)).Error().To(MatchError("name must not be empty"))
118+
119+
obj.GenerateName = "foo-"
120+
Expect(ForObject(obj)).Error().To(MatchError(ContainSubstring("generateName is not supported")))
121+
})
122+
123+
It("should return the object's hash key", func() {
124+
Expect(ForObject(obj)).To(Equal("apps/Deployment/bar/foo"))
125+
})
126+
})
127+
128+
var _ = Describe("#ForController", func() {
129+
var obj *appsv1.Deployment
130+
131+
BeforeEach(func() {
132+
obj = &appsv1.Deployment{}
133+
obj.SetOwnerReferences([]metav1.OwnerReference{
134+
{
135+
APIVersion: "other/v1",
136+
Kind: "Bar",
137+
Name: "owner-but-not-controller",
138+
},
139+
{
140+
APIVersion: "operator/v1",
141+
Kind: "Foo",
142+
Name: "foo",
143+
Controller: ptr.To(true),
144+
},
145+
})
146+
obj.Namespace = "bar"
147+
})
148+
149+
It("should return an empty key if the object has no controller ref", func() {
150+
Expect(ForController(&appsv1.Deployment{})).To(BeEmpty())
151+
152+
obj.OwnerReferences[1].Controller = nil
153+
Expect(ForController(obj)).To(BeEmpty())
154+
})
155+
156+
It("should return an error if the controller ref has no apiVersion", func() {
157+
obj.OwnerReferences[1].APIVersion = ""
158+
Expect(ForController(obj)).Error().To(MatchError("apiVersion of controller reference must not be empty"))
159+
})
160+
161+
It("should return an error if the controller ref has no kind", func() {
162+
obj.OwnerReferences[1].Kind = ""
163+
Expect(ForController(obj)).Error().To(MatchError("kind of controller reference must not be empty"))
164+
})
165+
166+
It("should return an error if the controller ref has no name", func() {
167+
obj.OwnerReferences[1].Name = ""
168+
Expect(ForController(obj)).Error().To(MatchError("name of controller reference must not be empty"))
169+
})
170+
171+
It("should return an error if the controller ref has an invalid apiVersion", func() {
172+
obj.OwnerReferences[1].APIVersion = "foo/bar/v1"
173+
Expect(ForController(obj)).Error().To(MatchError(ContainSubstring("invalid apiVersion of controller reference")))
174+
})
175+
176+
It("should return the controller's hash key", func() {
177+
Expect(ForController(obj)).To(Equal("operator/Foo/bar/foo"))
178+
})
179+
})
180+
181+
func beFunc(expected Func) gomegatypes.GomegaMatcher {
182+
return gcustom.MakeMatcher(func(actual Func) (bool, error) {
183+
return reflect.ValueOf(expected).Pointer() == reflect.ValueOf(actual).Pointer(), nil
184+
})
185+
}

0 commit comments

Comments
 (0)