Skip to content

Commit 57c50ae

Browse files
committed
add example testcases to verify that the generated code is actually working, include it in make test
On-behalf-of: @SAP [email protected]
1 parent f6db86a commit 57c50ae

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ lint: $(GOLANGCI_LINT)
9898
.PHONY: test
9999
test:
100100
go test ./...
101+
cd examples; go test ./...
101102

102103
# Note, running this locally if you have any modified files, even those that are not generated,
103104
# will result in an error. This target is mostly for CI jobs.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Copyright 2025 The KCP 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 kcp
18+
19+
import (
20+
"context"
21+
"testing"
22+
"time"
23+
24+
"github.com/kcp-dev/logicalcluster/v3"
25+
26+
clienttesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/util/wait"
29+
"k8s.io/apimachinery/pkg/watch"
30+
"k8s.io/client-go/tools/cache"
31+
32+
examplev1 "acme.corp/pkg/apis/example/v1"
33+
"acme.corp/pkg/kcp/clients/clientset/versioned/fake"
34+
informers "acme.corp/pkg/kcp/clients/informers/externalversions"
35+
)
36+
37+
// TestFakeClient demonstrates how to use a fake client with SharedInformerFactory in tests.
38+
func TestFakeClient(t *testing.T) {
39+
ctx, cancel := context.WithCancel(context.Background())
40+
defer cancel()
41+
42+
watcherStarted := make(chan struct{})
43+
// Create the fake client.
44+
client := fake.NewSimpleClientset()
45+
// A catch-all watch reactor that allows us to inject the watcherStarted channel.
46+
client.PrependWatchReactor("*", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
47+
gvr := action.GetResource()
48+
ns := action.GetNamespace()
49+
watch, err := client.Tracker().Watch(gvr, ns)
50+
if err != nil {
51+
return false, nil, err
52+
}
53+
close(watcherStarted)
54+
return true, watch, nil
55+
})
56+
57+
// We will create an informer that writes added testTypes to a channel.
58+
testTypes := make(chan *examplev1.TestType, 1)
59+
informerFactory := informers.NewSharedInformerFactory(client, 0)
60+
testTypeInformer := informerFactory.Example().V1().TestTypes().Informer()
61+
testTypeInformer.AddEventHandler(&cache.ResourceEventHandlerFuncs{
62+
AddFunc: func(obj interface{}) {
63+
testType := obj.(*examplev1.TestType)
64+
t.Logf("testType added: %s/%s", testType.Namespace, testType.Name)
65+
testTypes <- testType
66+
},
67+
})
68+
69+
// Make sure informers are running.
70+
informerFactory.Cluster(logicalcluster.Name("root")).Start(ctx.Done())
71+
72+
// This is not required in tests, but it serves as a proof-of-concept by
73+
// ensuring that the informer goroutine have warmed up and called List before
74+
// we send any events to it.
75+
cache.WaitForCacheSync(ctx.Done(), testTypeInformer.HasSynced)
76+
77+
// The fake client doesn't support resource version. Any writes to the client
78+
// after the informer's initial LIST and before the informer establishing the
79+
// watcher will be missed by the informer. Therefore we wait until the watcher
80+
// starts.
81+
// Note that the fake client isn't designed to work with informer. It
82+
// doesn't support resource version. It's encouraged to use a real client
83+
// in an integration/E2E test if you need to test complex behavior with
84+
// informer/controllers.
85+
<-watcherStarted
86+
// Inject an event into the fake client.
87+
p := &examplev1.TestType{ObjectMeta: metav1.ObjectMeta{Name: "my-testobj"}}
88+
_, err := client.ExampleV1().TestTypes().Cluster(logicalcluster.NewPath("root")).Namespace("test-ns").Create(ctx, p, metav1.CreateOptions{})
89+
if err != nil {
90+
t.Fatalf("error injecting testType add: %v", err)
91+
}
92+
93+
select {
94+
case testType := <-testTypes:
95+
t.Logf("Got testType from channel: %s/%s", testType.Namespace, testType.Name)
96+
case <-time.After(wait.ForeverTestTimeout):
97+
t.Error("Informer did not get the added testType")
98+
}
99+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
Copyright 2025 The KCP 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 kcpexisting
18+
19+
import (
20+
"context"
21+
"testing"
22+
"time"
23+
24+
"github.com/kcp-dev/logicalcluster/v3"
25+
26+
clienttesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/util/wait"
29+
"k8s.io/apimachinery/pkg/watch"
30+
"k8s.io/client-go/tools/cache"
31+
32+
examplev1 "acme.corp/pkg/apis/example/v1"
33+
"acme.corp/pkg/kcpexisting/clients/clientset/versioned/fake"
34+
informers "acme.corp/pkg/kcpexisting/clients/informers/externalversions"
35+
)
36+
37+
// TestFakeClient demonstrates how to use a fake client with SharedInformerFactory in tests.
38+
func TestFakeClient(t *testing.T) {
39+
ctx, cancel := context.WithCancel(context.Background())
40+
defer cancel()
41+
42+
watcherStarted := make(chan struct{})
43+
// Create the fake client.
44+
client := fake.NewSimpleClientset()
45+
// A catch-all watch reactor that allows us to inject the watcherStarted channel.
46+
client.PrependWatchReactor("*", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
47+
gvr := action.GetResource()
48+
ns := action.GetNamespace()
49+
watch, err := client.Tracker().Watch(gvr, ns)
50+
if err != nil {
51+
return false, nil, err
52+
}
53+
close(watcherStarted)
54+
return true, watch, nil
55+
})
56+
57+
// We will create an informer that writes added testTypes to a channel.
58+
testTypes := make(chan *examplev1.TestType, 1)
59+
informerFactory := informers.NewSharedInformerFactory(client, 0)
60+
testTypeInformer := informerFactory.Example().V1().TestTypes().Informer()
61+
testTypeInformer.AddEventHandler(&cache.ResourceEventHandlerFuncs{
62+
AddFunc: func(obj interface{}) {
63+
testType := obj.(*examplev1.TestType)
64+
t.Logf("testType added: %s/%s", testType.Namespace, testType.Name)
65+
testTypes <- testType
66+
},
67+
})
68+
69+
// Make sure informers are running.
70+
informerFactory.Cluster(logicalcluster.Name("root")).Start(ctx.Done())
71+
72+
// This is not required in tests, but it serves as a proof-of-concept by
73+
// ensuring that the informer goroutine have warmed up and called List before
74+
// we send any events to it.
75+
cache.WaitForCacheSync(ctx.Done(), testTypeInformer.HasSynced)
76+
77+
// The fake client doesn't support resource version. Any writes to the client
78+
// after the informer's initial LIST and before the informer establishing the
79+
// watcher will be missed by the informer. Therefore we wait until the watcher
80+
// starts.
81+
// Note that the fake client isn't designed to work with informer. It
82+
// doesn't support resource version. It's encouraged to use a real client
83+
// in an integration/E2E test if you need to test complex behavior with
84+
// informer/controllers.
85+
<-watcherStarted
86+
// Inject an event into the fake client.
87+
p := &examplev1.TestType{ObjectMeta: metav1.ObjectMeta{Name: "my-testobj"}}
88+
_, err := client.ExampleV1().TestTypes().Cluster(logicalcluster.NewPath("root")).Namespace("test-ns").Create(ctx, p, metav1.CreateOptions{})
89+
if err != nil {
90+
t.Fatalf("error injecting testType add: %v", err)
91+
}
92+
93+
select {
94+
case testType := <-testTypes:
95+
t.Logf("Got testType from channel: %s/%s", testType.Namespace, testType.Name)
96+
case <-time.After(wait.ForeverTestTimeout):
97+
t.Error("Informer did not get the added testType")
98+
}
99+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
Copyright 2025 The KCP 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 singlecluster
18+
19+
import (
20+
"context"
21+
"testing"
22+
"time"
23+
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/util/wait"
26+
"k8s.io/apimachinery/pkg/watch"
27+
clienttesting "k8s.io/client-go/testing"
28+
"k8s.io/client-go/tools/cache"
29+
30+
examplev1 "acme.corp/pkg/apis/example/v1"
31+
"acme.corp/pkg/generated/clientset/versioned/fake"
32+
informers "acme.corp/pkg/generated/informers/externalversions"
33+
)
34+
35+
// TestFakeClient demonstrates how to use a fake client with SharedInformerFactory in tests.
36+
func TestFakeClient(t *testing.T) {
37+
ctx, cancel := context.WithCancel(context.Background())
38+
defer cancel()
39+
40+
watcherStarted := make(chan struct{})
41+
// Create the fake client.
42+
client := fake.NewSimpleClientset()
43+
// A catch-all watch reactor that allows us to inject the watcherStarted channel.
44+
client.PrependWatchReactor("*", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
45+
gvr := action.GetResource()
46+
ns := action.GetNamespace()
47+
watch, err := client.Tracker().Watch(gvr, ns)
48+
if err != nil {
49+
return false, nil, err
50+
}
51+
close(watcherStarted)
52+
return true, watch, nil
53+
})
54+
55+
// We will create an informer that writes added testTypes to a channel.
56+
testTypes := make(chan *examplev1.TestType, 1)
57+
informerFactory := informers.NewSharedInformerFactory(client, 0)
58+
testTypeInformer := informerFactory.Example().V1().TestTypes().Informer()
59+
testTypeInformer.AddEventHandler(&cache.ResourceEventHandlerFuncs{
60+
AddFunc: func(obj interface{}) {
61+
testType := obj.(*examplev1.TestType)
62+
t.Logf("testType added: %s/%s", testType.Namespace, testType.Name)
63+
testTypes <- testType
64+
},
65+
})
66+
67+
// Make sure informers are running.
68+
informerFactory.Start(ctx.Done())
69+
70+
// This is not required in tests, but it serves as a proof-of-concept by
71+
// ensuring that the informer goroutine have warmed up and called List before
72+
// we send any events to it.
73+
cache.WaitForCacheSync(ctx.Done(), testTypeInformer.HasSynced)
74+
75+
// The fake client doesn't support resource version. Any writes to the client
76+
// after the informer's initial LIST and before the informer establishing the
77+
// watcher will be missed by the informer. Therefore we wait until the watcher
78+
// starts.
79+
// Note that the fake client isn't designed to work with informer. It
80+
// doesn't support resource version. It's encouraged to use a real client
81+
// in an integration/E2E test if you need to test complex behavior with
82+
// informer/controllers.
83+
<-watcherStarted
84+
// Inject an event into the fake client.
85+
p := &examplev1.TestType{ObjectMeta: metav1.ObjectMeta{Name: "my-testobj"}}
86+
_, err := client.ExampleV1().TestTypes("test-ns").Create(ctx, p, metav1.CreateOptions{})
87+
if err != nil {
88+
t.Fatalf("error injecting testType add: %v", err)
89+
}
90+
91+
select {
92+
case testType := <-testTypes:
93+
t.Logf("Got testType from channel: %s/%s", testType.Namespace, testType.Name)
94+
case <-time.After(wait.ForeverTestTimeout):
95+
t.Error("Informer did not get the added testType")
96+
}
97+
}

0 commit comments

Comments
 (0)