Skip to content

Commit

Permalink
test: adding basic unit testing for controllers helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
talasulin committed Oct 25, 2023
1 parent 6272196 commit 57adee2
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/zapr v1.2.3 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
Expand Down
199 changes: 199 additions & 0 deletions internal/controller/pvc_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package controller

import (
"fmt"
"github.com/AppsFlyer/local-pvc-releaser/internal/exporters"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2/klogr"
"os"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"testing"
)

func getReconciler() *PVCReconciler {
fakeClient, err := getFakeClient()
if err != nil {
fmt.Println("unable to create fake client. exiting..")
os.Exit(1)
}
logr := klogr.New()

collector := exporters.NewCollector()
reconciler := &PVCReconciler{
Client: fakeClient,
Scheme: fakeClient.Scheme(),
Logger: &logr,
DryRun: false,
Collector: collector,
PvcSelector: true,
PvcAnoCustomKey: "appsflyer.com/local-pvc-releaser",
PvcAnoCustomValue: "enabled",
}

return reconciler
}

func getFakeClient(initObjs ...client.Object) (client.WithWatch, error) {
scheme := runtime.NewScheme()
if err := corev1.AddToScheme(scheme); err != nil {
return nil, err
}
return fake.NewClientBuilder().WithScheme(scheme).WithObjects(initObjs...).Build(), nil
}

func TestFilterPVCListByPV(t *testing.T) {
reconciler := getReconciler()

// Create a sample PVC list
pvcList := &v1.PersistentVolumeClaimList{
Items: []v1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{Name: "pvc1"},
Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "pv1",
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "pvc2"},
Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "pv2",
},
},
},
}

// Create a sample PV
pvExist := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "pv1"},
}

pvNil := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "pv3"},
}

// Simulate successful filtering
result := reconciler.FilterPVCListByPV(pvcList, pvExist)

// Check if the result is as expected
if result == nil {

Check failure on line 82 in internal/controller/pvc_controller_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011(related information): this check suggests that the pointer can be nil (staticcheck)

Check failure on line 82 in internal/controller/pvc_controller_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011(related information): this check suggests that the pointer can be nil (staticcheck)
t.Error("Expected a non-nil result, got nil")
}

if result.Name != "pvc1" {

Check failure on line 86 in internal/controller/pvc_controller_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011: possible nil pointer dereference (staticcheck)

Check failure on line 86 in internal/controller/pvc_controller_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011: possible nil pointer dereference (staticcheck)
t.Errorf("Expected result to be pvc1, got %s", result.Name)
}

// Simulate non existed pv
result = reconciler.FilterPVCListByPV(pvcList, pvNil)

// Check if the result is as expected
if result != nil {
t.Error("Expected nil result, got non-nil object as the filter return matched value")
}
}

func TestFilterPVListByNodeName(t *testing.T) {
reconciler := getReconciler()

// Create a sample PV list
pvList := &v1.PersistentVolumeList{
Items: []v1.PersistentVolume{
{
ObjectMeta: metav1.ObjectMeta{Name: "pv1"},
Spec: v1.PersistentVolumeSpec{
NodeAffinity: &v1.VolumeNodeAffinity{
Required: &v1.NodeSelector{
NodeSelectorTerms: []v1.NodeSelectorTerm{
{
MatchExpressions: []v1.NodeSelectorRequirement{
{
Key: "kubernetes.io/hostname",
Operator: v1.NodeSelectorOpIn,
Values: []string{"node1"},
},
},
},
},
},
},
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "pv2"},
Spec: v1.PersistentVolumeSpec{
NodeAffinity: &v1.VolumeNodeAffinity{
Required: &v1.NodeSelector{
NodeSelectorTerms: []v1.NodeSelectorTerm{
{
MatchExpressions: []v1.NodeSelectorRequirement{
{
Key: "kubernetes.io/hostname",
Operator: v1.NodeSelectorOpIn,
Values: []string{"node2"},
},
},
},
},
},
},
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "pv3"},
Spec: v1.PersistentVolumeSpec{
NodeAffinity: &v1.VolumeNodeAffinity{
Required: &v1.NodeSelector{
NodeSelectorTerms: []v1.NodeSelectorTerm{
{
MatchExpressions: []v1.NodeSelectorRequirement{
{
Key: "kubernetes.io/hostname",
Operator: v1.NodeSelectorOpIn,
Values: []string{"node3"},
},
},
},
},
},
},
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
},
},
// Add more PVs as needed for additional test cases
},
}

// Call the function for matched results
nodeName := "node2"
result := reconciler.FilterPVListByNodeName(pvList, nodeName)

// Check if the result is as expected
if len(result) != 1 {
t.Errorf("Expected 1 related PV, got %d", len(result))
}

if result[0].Name != "pv2" {
t.Errorf("Expected result to be pv2, got %s", result[0].Name)
}

// Call the function with empty PV list
nodeNameNil := ""
result = reconciler.FilterPVListByNodeName(&v1.PersistentVolumeList{}, nodeNameNil)

// Check if the result is as expected
if len(result) != 0 {
t.Errorf("Expected 0 related PV, got %d", len(result))
}
}

0 comments on commit 57adee2

Please sign in to comment.