mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-23 22:16:45 +00:00
feat: Improve test coverage of important packages
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/config"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
)
|
||||
|
||||
func TestCreateEventPredicate_CreateEvent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
reloadOnCreate bool
|
||||
syncAfterRestart bool
|
||||
initialized bool
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "reload on create enabled, initialized",
|
||||
reloadOnCreate: true,
|
||||
syncAfterRestart: false,
|
||||
initialized: true,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "reload on create disabled, initialized",
|
||||
reloadOnCreate: false,
|
||||
syncAfterRestart: false,
|
||||
initialized: true,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "not initialized, sync after restart enabled",
|
||||
reloadOnCreate: true,
|
||||
syncAfterRestart: true,
|
||||
initialized: false,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "not initialized, sync after restart disabled",
|
||||
reloadOnCreate: true,
|
||||
syncAfterRestart: false,
|
||||
initialized: false,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "not initialized, sync after restart disabled, reload on create disabled",
|
||||
reloadOnCreate: false,
|
||||
syncAfterRestart: false,
|
||||
initialized: false,
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
ReloadOnCreate: tt.reloadOnCreate,
|
||||
SyncAfterRestart: tt.syncAfterRestart,
|
||||
}
|
||||
initialized := tt.initialized
|
||||
|
||||
pred := createEventPredicate(cfg, &initialized)
|
||||
|
||||
cm := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}
|
||||
|
||||
e := event.CreateEvent{Object: cm}
|
||||
result := pred.Create(e)
|
||||
|
||||
if result != tt.expectedResult {
|
||||
t.Errorf("CreateFunc() = %v, want %v", result, tt.expectedResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateEventPredicate_UpdateEvent(t *testing.T) {
|
||||
cfg := &config.Config{}
|
||||
initialized := true
|
||||
|
||||
pred := createEventPredicate(cfg, &initialized)
|
||||
|
||||
cm := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}
|
||||
|
||||
e := event.UpdateEvent{ObjectOld: cm, ObjectNew: cm}
|
||||
result := pred.Update(e)
|
||||
|
||||
// Update events should always return true
|
||||
if !result {
|
||||
t.Error("UpdateFunc() should always return true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateEventPredicate_DeleteEvent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
reloadOnDelete bool
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "reload on delete enabled",
|
||||
reloadOnDelete: true,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "reload on delete disabled",
|
||||
reloadOnDelete: false,
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
ReloadOnDelete: tt.reloadOnDelete,
|
||||
}
|
||||
initialized := true
|
||||
|
||||
pred := createEventPredicate(cfg, &initialized)
|
||||
|
||||
cm := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}
|
||||
|
||||
e := event.DeleteEvent{Object: cm}
|
||||
result := pred.Delete(e)
|
||||
|
||||
if result != tt.expectedResult {
|
||||
t.Errorf("DeleteFunc() = %v, want %v", result, tt.expectedResult)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateEventPredicate_GenericEvent(t *testing.T) {
|
||||
cfg := &config.Config{}
|
||||
initialized := true
|
||||
|
||||
pred := createEventPredicate(cfg, &initialized)
|
||||
|
||||
cm := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}
|
||||
|
||||
e := event.GenericEvent{Object: cm}
|
||||
result := pred.Generic(e)
|
||||
|
||||
// Generic events should always return false
|
||||
if result {
|
||||
t.Error("GenericFunc() should always return false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildEventFilter(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
ReloadOnCreate: true,
|
||||
ReloadOnDelete: true,
|
||||
}
|
||||
initialized := true
|
||||
|
||||
// Create a simple always-true predicate as the resource predicate
|
||||
resourcePred := &alwaysTruePredicate{}
|
||||
|
||||
filter := BuildEventFilter(resourcePred, cfg, &initialized)
|
||||
|
||||
// The filter should be created without error
|
||||
if filter == nil {
|
||||
t.Fatal("BuildEventFilter() should return a non-nil predicate")
|
||||
}
|
||||
|
||||
// Test update event passes (since resourcePred returns true and update always returns true)
|
||||
cm := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}
|
||||
|
||||
e := event.UpdateEvent{ObjectOld: cm, ObjectNew: cm}
|
||||
result := filter.Update(e)
|
||||
|
||||
// Since namespace filter is empty (all namespaces allowed), this should pass
|
||||
if !result {
|
||||
t.Error("UpdateFunc() should return true when all predicates pass")
|
||||
}
|
||||
}
|
||||
|
||||
// alwaysTruePredicate is a helper predicate for testing
|
||||
type alwaysTruePredicate struct{}
|
||||
|
||||
func (p *alwaysTruePredicate) Create(_ event.CreateEvent) bool { return true }
|
||||
func (p *alwaysTruePredicate) Delete(_ event.DeleteEvent) bool { return true }
|
||||
func (p *alwaysTruePredicate) Update(_ event.UpdateEvent) bool { return true }
|
||||
func (p *alwaysTruePredicate) Generic(_ event.GenericEvent) bool { return true }
|
||||
@@ -0,0 +1,131 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stakater/Reloader/internal/pkg/reload"
|
||||
"github.com/stakater/Reloader/internal/pkg/workload"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestUpdateWorkloadWithRetry_SwitchCases(t *testing.T) {
|
||||
// Test that the switch statement correctly identifies workload types
|
||||
// Note: Full integration tests require a fake k8s client, so we just test type detection
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
workload workload.WorkloadAccessor
|
||||
expectedKind workload.Kind
|
||||
}{
|
||||
{
|
||||
name: "deployment workload",
|
||||
workload: workload.NewDeploymentWorkload(&appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}),
|
||||
expectedKind: workload.KindDeployment,
|
||||
},
|
||||
{
|
||||
name: "daemonset workload",
|
||||
workload: workload.NewDaemonSetWorkload(&appsv1.DaemonSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}),
|
||||
expectedKind: workload.KindDaemonSet,
|
||||
},
|
||||
{
|
||||
name: "statefulset workload",
|
||||
workload: workload.NewStatefulSetWorkload(&appsv1.StatefulSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}),
|
||||
expectedKind: workload.KindStatefulSet,
|
||||
},
|
||||
{
|
||||
name: "job workload",
|
||||
workload: workload.NewJobWorkload(&batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}),
|
||||
expectedKind: workload.KindJob,
|
||||
},
|
||||
{
|
||||
name: "cronjob workload",
|
||||
workload: workload.NewCronJobWorkload(&batchv1.CronJob{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
|
||||
}),
|
||||
expectedKind: workload.KindCronJob,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Verify the workload kind is correctly identified
|
||||
if tt.workload.Kind() != tt.expectedKind {
|
||||
t.Errorf("workload.Kind() = %v, want %v", tt.workload.Kind(), tt.expectedKind)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJobWorkloadTypeCast(t *testing.T) {
|
||||
// Test that JobWorkload type cast works correctly
|
||||
job := &batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-job", Namespace: "default"},
|
||||
}
|
||||
jobWl := workload.NewJobWorkload(job)
|
||||
|
||||
if jobWl.GetName() != "test-job" {
|
||||
t.Errorf("JobWorkload.GetName() = %v, want test-job", jobWl.GetName())
|
||||
}
|
||||
|
||||
// Test GetJob method
|
||||
gotJob := jobWl.GetJob()
|
||||
if gotJob.Name != "test-job" {
|
||||
t.Errorf("JobWorkload.GetJob().Name = %v, want test-job", gotJob.Name)
|
||||
}
|
||||
|
||||
// Verify it satisfies WorkloadAccessor interface
|
||||
var _ workload.WorkloadAccessor = jobWl
|
||||
}
|
||||
|
||||
func TestCronJobWorkloadTypeCast(t *testing.T) {
|
||||
// Test that CronJobWorkload type cast works correctly
|
||||
cronJob := &batchv1.CronJob{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-cronjob", Namespace: "default"},
|
||||
Spec: batchv1.CronJobSpec{
|
||||
Schedule: "*/5 * * * *",
|
||||
},
|
||||
}
|
||||
cronJobWl := workload.NewCronJobWorkload(cronJob)
|
||||
|
||||
if cronJobWl.GetName() != "test-cronjob" {
|
||||
t.Errorf("CronJobWorkload.GetName() = %v, want test-cronjob", cronJobWl.GetName())
|
||||
}
|
||||
|
||||
// Test GetCronJob method
|
||||
gotCronJob := cronJobWl.GetCronJob()
|
||||
if gotCronJob.Name != "test-cronjob" {
|
||||
t.Errorf("CronJobWorkload.GetCronJob().Name = %v, want test-cronjob", gotCronJob.Name)
|
||||
}
|
||||
|
||||
// Verify it satisfies WorkloadAccessor interface
|
||||
var _ workload.WorkloadAccessor = cronJobWl
|
||||
}
|
||||
|
||||
func TestResourceTypeKind(t *testing.T) {
|
||||
// Test that ResourceType.Kind() returns correct values
|
||||
tests := []struct {
|
||||
resourceType reload.ResourceType
|
||||
expectedKind string
|
||||
}{
|
||||
{reload.ResourceTypeConfigMap, "ConfigMap"},
|
||||
{reload.ResourceTypeSecret, "Secret"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(string(tt.resourceType), func(t *testing.T) {
|
||||
if got := tt.resourceType.Kind(); got != tt.expectedKind {
|
||||
t.Errorf("ResourceType.Kind() = %v, want %v", got, tt.expectedKind)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user