Skip to content

Commit 3632987

Browse files
committed
tests
1 parent b3a7210 commit 3632987

File tree

1 file changed

+357
-3
lines changed

1 file changed

+357
-3
lines changed

listener/reconciler/kcp/reconciler_test.go

Lines changed: 357 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package kcp_test
22

33
import (
4+
"context"
5+
"os"
6+
"path/filepath"
47
"testing"
8+
"time"
59

610
kcpapis "github.com/kcp-dev/kcp/sdk/apis/apis/v1alpha1"
711
kcpcore "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1"
812
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
914
"k8s.io/apimachinery/pkg/runtime"
1015
"k8s.io/apimachinery/pkg/types"
1116
"k8s.io/client-go/rest"
1217
ctrl "sigs.k8s.io/controller-runtime"
1318
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
1419

20+
"github.com/platform-mesh/golang-commons/logger"
1521
"github.com/platform-mesh/golang-commons/logger/testlogger"
1622
"github.com/platform-mesh/kubernetes-graphql-gateway/common/config"
1723
"github.com/platform-mesh/kubernetes-graphql-gateway/listener/reconciler"
@@ -156,7 +162,7 @@ func TestKCPReconciler_SetupWithManager(t *testing.T) {
156162
return scheme
157163
}(),
158164
ManagerOpts: ctrl.Options{
159-
Metrics: server.Options{BindAddress: "0"}, // Disable metrics for tests
165+
Metrics: server.Options{BindAddress: "0"},
160166
Scheme: func() *runtime.Scheme {
161167
scheme := runtime.NewScheme()
162168
_ = kcpapis.AddToScheme(scheme)
@@ -171,7 +177,355 @@ func TestKCPReconciler_SetupWithManager(t *testing.T) {
171177
assert.NoError(t, err)
172178
assert.NotNil(t, reconciler)
173179

174-
// The SetupWithManager method should work without errors when properly initialized
180+
// Test SetupWithManager with nil manager (should work based on current implementation)
175181
err = reconciler.SetupWithManager(nil)
176-
assert.NoError(t, err)
182+
assert.NoError(t, err, "SetupWithManager should handle nil manager gracefully")
183+
184+
// Note: Cannot test calling SetupWithManager multiple times because it registers controllers
185+
// and duplicate controller names cause errors. This is expected behavior.
186+
}
187+
188+
func TestKCPReconciler_StartVirtualWorkspaceWatching(t *testing.T) {
189+
tempDir := t.TempDir()
190+
log := testlogger.New().HideLogOutput().Logger
191+
192+
reconciler, err := kcp.NewKCPReconciler(
193+
config.Config{
194+
OpenApiDefinitionsPath: tempDir,
195+
},
196+
reconciler.ReconcilerOpts{
197+
Config: &rest.Config{
198+
Host: "https://test.cluster",
199+
},
200+
Scheme: func() *runtime.Scheme {
201+
scheme := runtime.NewScheme()
202+
_ = kcpapis.AddToScheme(scheme)
203+
_ = kcpcore.AddToScheme(scheme)
204+
return scheme
205+
}(),
206+
ManagerOpts: ctrl.Options{
207+
Metrics: server.Options{BindAddress: "0"},
208+
Scheme: func() *runtime.Scheme {
209+
scheme := runtime.NewScheme()
210+
_ = kcpapis.AddToScheme(scheme)
211+
_ = kcpcore.AddToScheme(scheme)
212+
return scheme
213+
}(),
214+
},
215+
},
216+
log,
217+
)
218+
require.NoError(t, err)
219+
220+
tests := []struct {
221+
name string
222+
configPath string
223+
setupConfig func(string) error
224+
expectedError bool
225+
timeout time.Duration
226+
}{
227+
{
228+
name: "empty_config_path_should_return_immediately",
229+
configPath: "",
230+
setupConfig: func(string) error { return nil },
231+
expectedError: false,
232+
timeout: 100 * time.Millisecond,
233+
},
234+
{
235+
name: "valid_config_file_should_start_watching",
236+
configPath: filepath.Join(tempDir, "virtual-ws-config.yaml"),
237+
setupConfig: func(path string) error {
238+
content := `
239+
virtualWorkspaces:
240+
- name: "test-workspace"
241+
url: "https://test.cluster"
242+
`
243+
return os.WriteFile(path, []byte(content), 0644)
244+
},
245+
expectedError: false,
246+
timeout: 200 * time.Millisecond,
247+
},
248+
{
249+
name: "non_existent_config_file_should_handle_gracefully",
250+
configPath: filepath.Join(tempDir, "non-existent.yaml"),
251+
setupConfig: func(string) error {
252+
return nil // Don't create the file
253+
},
254+
expectedError: true, // May error when trying to watch non-existent directory
255+
timeout: 100 * time.Millisecond,
256+
},
257+
}
258+
259+
for _, tt := range tests {
260+
t.Run(tt.name, func(t *testing.T) {
261+
err := tt.setupConfig(tt.configPath)
262+
require.NoError(t, err)
263+
264+
ctx, cancel := context.WithTimeout(context.Background(), tt.timeout)
265+
defer cancel()
266+
267+
// Test the actual method
268+
err = reconciler.StartVirtualWorkspaceWatching(ctx, tt.configPath)
269+
270+
if tt.expectedError {
271+
assert.Error(t, err)
272+
} else {
273+
// Should either succeed or be cancelled by context timeout
274+
if err != nil {
275+
// Context cancellation or other expected errors are acceptable
276+
t.Logf("Got error (possibly expected): %v", err)
277+
}
278+
}
279+
})
280+
}
281+
}
282+
283+
func TestKCPReconciler_ManagerWrapper_Start(t *testing.T) {
284+
tempDir := t.TempDir()
285+
log := testlogger.New().HideLogOutput().Logger
286+
287+
reconciler, err := kcp.NewKCPReconciler(
288+
config.Config{
289+
OpenApiDefinitionsPath: tempDir,
290+
},
291+
reconciler.ReconcilerOpts{
292+
Config: &rest.Config{
293+
Host: "https://test.cluster",
294+
},
295+
Scheme: func() *runtime.Scheme {
296+
scheme := runtime.NewScheme()
297+
_ = kcpapis.AddToScheme(scheme)
298+
_ = kcpcore.AddToScheme(scheme)
299+
return scheme
300+
}(),
301+
ManagerOpts: ctrl.Options{
302+
Metrics: server.Options{BindAddress: "0"},
303+
Scheme: func() *runtime.Scheme {
304+
scheme := runtime.NewScheme()
305+
_ = kcpapis.AddToScheme(scheme)
306+
_ = kcpcore.AddToScheme(scheme)
307+
return scheme
308+
}(),
309+
},
310+
},
311+
log,
312+
)
313+
require.NoError(t, err)
314+
315+
// Test that GetManager returns a non-nil manager
316+
manager := reconciler.GetManager()
317+
assert.NotNil(t, manager)
318+
319+
// Test that the manager's Start method can be called
320+
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
321+
defer cancel()
322+
323+
// The Start method should be callable (it will likely fail due to no real cluster setup,
324+
// but it should not panic and should return an error or succeed)
325+
err = manager.Start(ctx)
326+
327+
// We expect either success or failure, but no panic
328+
// The exact behavior depends on the underlying multicluster manager implementation
329+
if err != nil {
330+
// This is expected since we don't have a real cluster setup
331+
t.Logf("Manager start failed as expected: %v", err)
332+
} else {
333+
t.Logf("Manager start succeeded unexpectedly")
334+
}
335+
336+
// The important thing is that we didn't panic and the method was callable
337+
assert.NotNil(t, manager, "Manager should not be nil")
338+
}
339+
340+
func TestKCPReconciler_Reconcile_NoOp_Behavior(t *testing.T) {
341+
tempDir := t.TempDir()
342+
log := testlogger.New().HideLogOutput().Logger
343+
344+
reconciler, err := kcp.NewKCPReconciler(
345+
config.Config{
346+
OpenApiDefinitionsPath: tempDir,
347+
},
348+
reconciler.ReconcilerOpts{
349+
Config: &rest.Config{
350+
Host: "https://test.cluster",
351+
},
352+
Scheme: func() *runtime.Scheme {
353+
scheme := runtime.NewScheme()
354+
_ = kcpapis.AddToScheme(scheme)
355+
_ = kcpcore.AddToScheme(scheme)
356+
return scheme
357+
}(),
358+
ManagerOpts: ctrl.Options{
359+
Metrics: server.Options{BindAddress: "0"},
360+
Scheme: func() *runtime.Scheme {
361+
scheme := runtime.NewScheme()
362+
_ = kcpapis.AddToScheme(scheme)
363+
_ = kcpcore.AddToScheme(scheme)
364+
return scheme
365+
}(),
366+
},
367+
},
368+
log,
369+
)
370+
require.NoError(t, err)
371+
372+
// Test multiple calls to Reconcile - should always return empty result and no error
373+
for i := 0; i < 5; i++ {
374+
req := ctrl.Request{
375+
NamespacedName: types.NamespacedName{
376+
Name: "test-resource",
377+
Namespace: "test-namespace",
378+
},
379+
}
380+
381+
result, err := reconciler.Reconcile(context.Background(), req)
382+
assert.NoError(t, err, "Reconcile should never return an error (iteration %d)", i)
383+
assert.Equal(t, ctrl.Result{}, result, "Reconcile should always return empty result (iteration %d)", i)
384+
}
385+
}
386+
387+
func TestKCPReconciler_NewKCPReconciler_Coverage_Improvements(t *testing.T) {
388+
log := testlogger.New().HideLogOutput().Logger
389+
390+
tests := []struct {
391+
name string
392+
appCfg config.Config
393+
opts reconciler.ReconcilerOpts
394+
expectedError bool
395+
errorContains string
396+
}{
397+
{
398+
name: "invalid_openapi_definitions_path",
399+
appCfg: config.Config{
400+
OpenApiDefinitionsPath: "/invalid/path/that/definitely/does/not/exist/anywhere",
401+
},
402+
opts: reconciler.ReconcilerOpts{
403+
Config: &rest.Config{Host: "https://kcp.example.com"},
404+
Scheme: func() *runtime.Scheme {
405+
scheme := runtime.NewScheme()
406+
_ = kcpapis.AddToScheme(scheme)
407+
_ = kcpcore.AddToScheme(scheme)
408+
return scheme
409+
}(),
410+
ManagerOpts: ctrl.Options{
411+
Metrics: server.Options{BindAddress: "0"},
412+
},
413+
},
414+
expectedError: true,
415+
errorContains: "failed to create or access schemas directory",
416+
},
417+
{
418+
name: "success_case_with_valid_temp_dir",
419+
appCfg: config.Config{
420+
OpenApiDefinitionsPath: t.TempDir(),
421+
},
422+
opts: reconciler.ReconcilerOpts{
423+
Config: &rest.Config{Host: "https://kcp.example.com"},
424+
Scheme: func() *runtime.Scheme {
425+
scheme := runtime.NewScheme()
426+
_ = kcpapis.AddToScheme(scheme)
427+
_ = kcpcore.AddToScheme(scheme)
428+
return scheme
429+
}(),
430+
ManagerOpts: ctrl.Options{
431+
Metrics: server.Options{BindAddress: "0"},
432+
Scheme: func() *runtime.Scheme {
433+
scheme := runtime.NewScheme()
434+
_ = kcpapis.AddToScheme(scheme)
435+
_ = kcpcore.AddToScheme(scheme)
436+
return scheme
437+
}(),
438+
},
439+
},
440+
expectedError: false,
441+
},
442+
}
443+
444+
for _, tt := range tests {
445+
t.Run(tt.name, func(t *testing.T) {
446+
reconciler, err := kcp.NewKCPReconciler(tt.appCfg, tt.opts, log)
447+
448+
if tt.expectedError {
449+
assert.Error(t, err)
450+
if tt.errorContains != "" {
451+
assert.Contains(t, err.Error(), tt.errorContains)
452+
}
453+
assert.Nil(t, reconciler)
454+
} else {
455+
assert.NoError(t, err)
456+
assert.NotNil(t, reconciler)
457+
assert.NotNil(t, reconciler.GetManager())
458+
}
459+
})
460+
}
461+
}
462+
463+
func TestKCPReconciler_NewKCPReconciler_ErrorCases(t *testing.T) {
464+
tests := []struct {
465+
name string
466+
setupTest func() (config.Config, reconciler.ReconcilerOpts, *testlogger.TestLogger)
467+
expectedError bool
468+
errorContains string
469+
}{
470+
{
471+
name: "nil_logger",
472+
setupTest: func() (config.Config, reconciler.ReconcilerOpts, *testlogger.TestLogger) {
473+
appCfg := config.Config{
474+
OpenApiDefinitionsPath: t.TempDir(),
475+
}
476+
opts := reconciler.ReconcilerOpts{
477+
Config: &rest.Config{Host: "https://kcp.example.com"},
478+
Scheme: runtime.NewScheme(),
479+
}
480+
return appCfg, opts, nil
481+
},
482+
expectedError: true,
483+
errorContains: "logger should not be nil",
484+
},
485+
{
486+
name: "invalid_config_for_provider",
487+
setupTest: func() (config.Config, reconciler.ReconcilerOpts, *testlogger.TestLogger) {
488+
log := testlogger.New().HideLogOutput()
489+
appCfg := config.Config{
490+
OpenApiDefinitionsPath: t.TempDir(),
491+
}
492+
opts := reconciler.ReconcilerOpts{
493+
Config: &rest.Config{}, // Empty config should cause provider creation to fail
494+
Scheme: func() *runtime.Scheme {
495+
scheme := runtime.NewScheme()
496+
_ = kcpapis.AddToScheme(scheme)
497+
_ = kcpcore.AddToScheme(scheme)
498+
return scheme
499+
}(),
500+
}
501+
return appCfg, opts, log
502+
},
503+
expectedError: true,
504+
errorContains: "failed to create",
505+
},
506+
}
507+
508+
for _, tt := range tests {
509+
t.Run(tt.name, func(t *testing.T) {
510+
appCfg, opts, log := tt.setupTest()
511+
512+
var actualLogger *logger.Logger
513+
if log != nil {
514+
actualLogger = log.Logger
515+
}
516+
517+
reconciler, err := kcp.NewKCPReconciler(appCfg, opts, actualLogger)
518+
519+
if tt.expectedError {
520+
assert.Error(t, err)
521+
if tt.errorContains != "" {
522+
assert.Contains(t, err.Error(), tt.errorContains)
523+
}
524+
assert.Nil(t, reconciler)
525+
} else {
526+
assert.NoError(t, err)
527+
assert.NotNil(t, reconciler)
528+
}
529+
})
530+
}
177531
}

0 commit comments

Comments
 (0)