Skip to content

Commit

Permalink
Add unit tests for testhelper package (#1835)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebrandon1 authored Jan 25, 2024
1 parent 2157f05 commit 0cf057b
Show file tree
Hide file tree
Showing 4 changed files with 1,213 additions and 0 deletions.
35 changes: 35 additions & 0 deletions pkg/provider/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (
"github.com/test-network-function/cnf-certification-test/internal/log"
)

// GetGuaranteedPodsWithExclusiveCPUs returns a slice of Pod objects that are guaranteed to have exclusive CPUs.
// It iterates over the Pods in the TestEnvironment and filters out the Pods that do not have exclusive CPUs.
// The filtered Pods are then returned as a slice.
func (env *TestEnvironment) GetGuaranteedPodsWithExclusiveCPUs() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -34,6 +37,8 @@ func (env *TestEnvironment) GetGuaranteedPodsWithExclusiveCPUs() []*Pod {
return filteredPods
}

// GetGuaranteedPodsWithIsolatedCPUs returns a list of pods from the TestEnvironment
// that are guaranteed to have isolated CPUs and are CPU isolation compliant.
func (env *TestEnvironment) GetGuaranteedPodsWithIsolatedCPUs() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -44,6 +49,10 @@ func (env *TestEnvironment) GetGuaranteedPodsWithIsolatedCPUs() []*Pod {
return filteredPods
}

// GetGuaranteedPods returns a slice of guaranteed pods in the test environment.
// A guaranteed pod is a pod that meets certain criteria specified by the IsPodGuaranteed method.
// The method iterates over all pods in the environment and filters out the guaranteed ones.
// It returns the filtered pods as a slice.
func (env *TestEnvironment) GetGuaranteedPods() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -54,6 +63,7 @@ func (env *TestEnvironment) GetGuaranteedPods() []*Pod {
return filteredPods
}

// GetNonGuaranteedPods returns a slice of non-guaranteed pods in the test environment.
func (env *TestEnvironment) GetNonGuaranteedPods() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -64,6 +74,9 @@ func (env *TestEnvironment) GetNonGuaranteedPods() []*Pod {
return filteredPods
}

// GetPodsWithoutAffinityRequiredLabel returns a slice of Pod objects that do not have the affinity required label.
// It iterates over the Pods in the TestEnvironment and filters out the ones that do not have the affinity required label.
// The filtered Pods are returned as a slice.
func (env *TestEnvironment) GetPodsWithoutAffinityRequiredLabel() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -74,6 +87,9 @@ func (env *TestEnvironment) GetPodsWithoutAffinityRequiredLabel() []*Pod {
return filteredPods
}

// GetAffinityRequiredPods returns a slice of Pod objects that have affinity required.
// It iterates over the Pods in the TestEnvironment and filters out the Pods that have affinity required.
// The filtered Pods are returned as a slice.
func (env *TestEnvironment) GetAffinityRequiredPods() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -84,6 +100,9 @@ func (env *TestEnvironment) GetAffinityRequiredPods() []*Pod {
return filteredPods
}

// GetHugepagesPods returns a slice of Pod objects that have hugepages enabled.
// It iterates over the Pods in the TestEnvironment and filters out the ones that do not have hugepages.
// The filtered Pods are returned as a []*Pod.
func (env *TestEnvironment) GetHugepagesPods() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -94,6 +113,7 @@ func (env *TestEnvironment) GetHugepagesPods() []*Pod {
return filteredPods
}

// GetCPUPinningPodsWithDpdk returns a slice of Pods that have CPU pinning enabled with DPDK.
func (env *TestEnvironment) GetCPUPinningPodsWithDpdk() []*Pod {
return filterDPDKRunningPods(env.GetGuaranteedPodsWithExclusiveCPUs())
}
Expand Down Expand Up @@ -135,6 +155,9 @@ func filterDPDKRunningPods(pods []*Pod) []*Pod {
return filteredPods
}

// GetShareProcessNamespacePods returns a slice of Pod objects that have the ShareProcessNamespace flag set to true.
// It iterates over the Pods in the TestEnvironment and filters out the ones that do not have the ShareProcessNamespace flag set.
// The filtered Pods are then returned as a slice.
func (env *TestEnvironment) GetShareProcessNamespacePods() []*Pod {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -145,6 +168,10 @@ func (env *TestEnvironment) GetShareProcessNamespacePods() []*Pod {
return filteredPods
}

// GetPodsUsingSRIOV returns a list of pods that are using SR-IOV.
// It iterates through the pods in the TestEnvironment and checks if each pod is using SR-IOV.
// If an error occurs while checking the SR-IOV usage for a pod, it returns an error.
// The filtered pods that are using SR-IOV are returned along with a nil error.
func (env *TestEnvironment) GetPodsUsingSRIOV() ([]*Pod, error) {
var filteredPods []*Pod
for _, p := range env.Pods {
Expand All @@ -169,18 +196,26 @@ func getContainers(pods []*Pod) []*Container {
return containers
}

// GetGuaranteedPodContainersWithExclusiveCPUs returns a slice of Container objects representing the containers
// that have exclusive CPUs in the TestEnvironment.
func (env *TestEnvironment) GetGuaranteedPodContainersWithExclusiveCPUs() []*Container {
return getContainers(env.GetGuaranteedPodsWithExclusiveCPUs())
}

// GetNonGuaranteedPodContainersWithoutHostPID returns a slice of containers from the test environment
// that belong to non-guaranteed pods without the HostPID setting enabled.
func (env *TestEnvironment) GetNonGuaranteedPodContainersWithoutHostPID() []*Container {
return getContainers(filterPodsWithoutHostPID(env.GetNonGuaranteedPods()))
}

// GetGuaranteedPodContainersWithExclusiveCPUsWithoutHostPID returns a slice of containers from the test environment
// that belong to pods with exclusive CPUs and do not have the host PID enabled.
func (env *TestEnvironment) GetGuaranteedPodContainersWithExclusiveCPUsWithoutHostPID() []*Container {
return getContainers(filterPodsWithoutHostPID(env.GetGuaranteedPodsWithExclusiveCPUs()))
}

// GetGuaranteedPodContainersWithIsolatedCPUsWithoutHostPID returns a slice of containers from the TestEnvironment
// that have guaranteed pods with isolated CPUs and without the HostPID flag set.
func (env *TestEnvironment) GetGuaranteedPodContainersWithIsolatedCPUsWithoutHostPID() []*Container {
return getContainers(filterPodsWithoutHostPID(env.GetGuaranteedPodsWithIsolatedCPUs()))
}
50 changes: 50 additions & 0 deletions pkg/provider/scale_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,53 @@ func TestCrScale_ToString(t *testing.T) {
})
}
}

func TestIsScaleObjectReady(t *testing.T) {
type fields struct {
Scale *scalingv1.Scale
}
tests := []struct {
name string
fields fields
want bool
}{
{
name: "test1",
fields: fields{
Scale: &scalingv1.Scale{
Spec: scalingv1.ScaleSpec{
Replicas: 2,
},
Status: scalingv1.ScaleStatus{
Replicas: 2,
},
},
},
want: true,
},
{
name: "test2",
fields: fields{
Scale: &scalingv1.Scale{
Spec: scalingv1.ScaleSpec{
Replicas: 2,
},
Status: scalingv1.ScaleStatus{
Replicas: 3,
},
},
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
crScale := CrScale{
Scale: tt.fields.Scale,
}
if got := crScale.IsScaleObjectReady(); got != tt.want {
t.Errorf("CrScale.IsScaleObjectReady() = %v, want %v", got, tt.want)
}
})
}
}
61 changes: 61 additions & 0 deletions pkg/testhelper/testhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func Equal(p, other []*ReportObject) bool {
return true
}

// FailureReasonOutTestString returns a string representation of the FailureReasonOut struct.
func FailureReasonOutTestString(p FailureReasonOut) (out string) {
out = "testhelper.FailureReasonOut{"
out += fmt.Sprintf("CompliantObjectsOut: %s,", ReportObjectTestStringPointer(p.CompliantObjectsOut))
Expand All @@ -67,6 +68,8 @@ func FailureReasonOutTestString(p FailureReasonOut) (out string) {
return out
}

// ReportObjectTestStringPointer takes a slice of pointers to ReportObject and returns a string representation of the objects.
// The returned string is in the format "[]*testhelper.ReportObject{&{...}, &{...}, ...}".
func ReportObjectTestStringPointer(p []*ReportObject) (out string) {
out = "[]*testhelper.ReportObject{"
for _, p := range p {
Expand All @@ -76,6 +79,9 @@ func ReportObjectTestStringPointer(p []*ReportObject) (out string) {
return out
}

// ReportObjectTestString returns a string representation of the given slice of ReportObject.
// Each ReportObject is formatted using the %#v format specifier and appended to the output string.
// The resulting string is enclosed in square brackets and prefixed with "[]testhelper.ReportObject{".
func ReportObjectTestString(p []*ReportObject) (out string) {
out = "[]testhelper.ReportObject{"
for _, p := range p {
Expand All @@ -85,6 +91,9 @@ func ReportObjectTestString(p []*ReportObject) (out string) {
return out
}

// Equal checks if the current FailureReasonOut is equal to the other FailureReasonOut.
// It compares the CompliantObjectsOut and NonCompliantObjectsOut fields of both structs.
// Returns true if they are equal, false otherwise.
func (p FailureReasonOut) Equal(other FailureReasonOut) bool {
return Equal(p.CompliantObjectsOut, other.CompliantObjectsOut) &&
Equal(p.NonCompliantObjectsOut, other.NonCompliantObjectsOut)
Expand Down Expand Up @@ -204,6 +213,10 @@ const (
PodRoleBinding = "Pods with RoleBindings details"
)

// SetContainerProcessValues sets the values for a container process in the report object.
// It takes the scheduling policy, scheduling priority, and command line as input parameters.
// It adds the process command line, scheduling policy, and scheduling priority fields to the report object.
// Finally, it sets the object type to ContainerProcessType.
func (obj *ReportObject) SetContainerProcessValues(aPolicy, aPriority, aCommandLine string) *ReportObject {
obj.AddField(ProcessCommandLine, aCommandLine)
obj.AddField(SchedulingPolicy, aPolicy)
Expand All @@ -212,6 +225,9 @@ func (obj *ReportObject) SetContainerProcessValues(aPolicy, aPriority, aCommandL
return obj
}

// NewContainerReportObject creates a new ReportObject for a container.
// It takes the namespace, pod name, container name, reason, and compliance status as parameters.
// It returns a pointer to the created ReportObject.
func NewContainerReportObject(aNamespace, aPodName, aContainerName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, ContainerType, isCompliant)
out.AddField(Namespace, aNamespace)
Expand All @@ -220,6 +236,9 @@ func NewContainerReportObject(aNamespace, aPodName, aContainerName, aReason stri
return out
}

// NewCertifiedContainerReportObject creates a new ReportObject for a certified container.
// It takes a ContainerImageIdentifier, aReason string, and a boolean indicating whether the container is compliant.
// It returns a pointer to the created ReportObject.
func NewCertifiedContainerReportObject(cii provider.ContainerImageIdentifier, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, ContainerImageType, isCompliant)
out.AddField(ImageDigest, cii.Digest)
Expand All @@ -229,67 +248,94 @@ func NewCertifiedContainerReportObject(cii provider.ContainerImageIdentifier, aR
return out
}

// NewNodeReportObject creates a new ReportObject for a node with the given name, reason, and compliance status.
// It returns the created ReportObject.
func NewNodeReportObject(aNodeName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, NodeType, isCompliant)
out.AddField(Name, aNodeName)
return out
}

// NewClusterVersionReportObject creates a new ReportObject for a cluster version.
// It takes the version, aReason, and isCompliant as input parameters and returns the created ReportObject.
func NewClusterVersionReportObject(version, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, OCPClusterType, isCompliant)
out.AddField(OCPClusterVersionType, version)
return out
}

// NewTaintReportObject creates a new ReportObject with taint-related information.
// It takes in the taintBit, nodeName, aReason, and isCompliant parameters and returns a pointer to the created ReportObject.
func NewTaintReportObject(taintBit, nodeName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, TaintType, isCompliant)
out.AddField(NodeType, nodeName)
out.AddField(TaintBit, taintBit)
return out
}

// NewPodReportObject creates a new ReportObject for a pod.
// It takes the namespace, pod name, reason, and compliance status as input parameters.
// It returns a pointer to the created ReportObject.
func NewPodReportObject(aNamespace, aPodName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, PodType, isCompliant)
out.AddField(Namespace, aNamespace)
out.AddField(PodName, aPodName)
return out
}

// NewHelmChartReportObject creates a new ReportObject for a Helm chart.
// It takes the namespace, Helm chart name, reason, and compliance status as input parameters.
// It returns the created ReportObject.
func NewHelmChartReportObject(aNamespace, aHelmChartName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, HelmType, isCompliant)
out.AddField(Namespace, aNamespace)
out.AddField(Name, aHelmChartName)
return out
}

// NewOperatorReportObject creates a new ReportObject for an operator.
// It takes the namespace, operator name, reason, and compliance status as input parameters.
// It returns the created ReportObject.
func NewOperatorReportObject(aNamespace, aOperatorName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, OperatorType, isCompliant)
out.AddField(Namespace, aNamespace)
out.AddField(Name, aOperatorName)
return out
}

// NewDeploymentReportObject creates a new ReportObject for a deployment.
// It takes the namespace, deployment name, reason, and compliance status as input parameters.
// It returns a pointer to the created ReportObject.
func NewDeploymentReportObject(aNamespace, aDeploymentName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, DeploymentType, isCompliant)
out.AddField(Namespace, aNamespace)
out.AddField(DeploymentName, aDeploymentName)
return out
}

// NewStatefulSetReportObject creates a new ReportObject for a StatefulSet.
// It takes the namespace, statefulSetName, reason, and compliance status as parameters.
// It returns the created ReportObject.
func NewStatefulSetReportObject(aNamespace, aStatefulSetName, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, StatefulSetType, isCompliant)
out.AddField(Namespace, aNamespace)
out.AddField(StatefulSetName, aStatefulSetName)
return out
}

// NewCrdReportObject creates a new ReportObject for a custom resource definition (CRD).
// It takes the name, version, reason, and compliance status as parameters and returns the created ReportObject.
func NewCrdReportObject(aName, aVersion, aReason string, isCompliant bool) (out *ReportObject) {
out = NewReportObject(aReason, CustomResourceDefinitionType, isCompliant)
out.AddField(CustomResourceDefinitionName, aName)
out.AddField(CustomResourceDefinitionVersion, aVersion)
return out
}

// NewReportObject creates a new ReportObject with the specified reason, type, and compliance status.
// If isCompliant is true, the reason is added as a field with the key ReasonForCompliance.
// If isCompliant is false, the reason is added as a field with the key ReasonForNonCompliance.
// Returns a pointer to the created ReportObject.
func NewReportObject(aReason, aType string, isCompliant bool) (out *ReportObject) {
out = &ReportObject{}
out.ObjectType = aType
Expand All @@ -301,25 +347,40 @@ func NewReportObject(aReason, aType string, isCompliant bool) (out *ReportObject
return out
}

// AddField adds a key-value pair to the ReportObject.
// It appends the given key to the ObjectFieldsKeys slice and the given value to the ObjectFieldsValues slice.
// It returns the modified ReportObject.
func (obj *ReportObject) AddField(aKey, aValue string) (out *ReportObject) {
obj.ObjectFieldsKeys = append(obj.ObjectFieldsKeys, aKey)
obj.ObjectFieldsValues = append(obj.ObjectFieldsValues, aValue)
return obj
}

// NewNamespacedReportObject creates a new ReportObject with the specified reason, type, compliance status, and namespace.
// It adds the namespace field to the ReportObject.
func NewNamespacedReportObject(aReason, aType string, isCompliant bool, aNamespace string) (out *ReportObject) {
return NewReportObject(aReason, aType, isCompliant).AddField(Namespace, aNamespace)
}

// NewNamespacedNamedReportObject creates a new namespaced named report object with the given parameters.
// It returns a pointer to the created ReportObject.
// The report object contains the specified reason, type, compliance status, namespace, and name.
func NewNamespacedNamedReportObject(aReason, aType string, isCompliant bool, aNamespace, aName string) (out *ReportObject) {
return NewReportObject(aReason, aType, isCompliant).AddField(Namespace, aNamespace).AddField(Name, aName)
}

// SetType sets the type of the ReportObject.
// It takes aType as a parameter and updates the ObjectType field of the ReportObject.
// It returns a pointer to the updated ReportObject.
func (obj *ReportObject) SetType(aType string) (out *ReportObject) {
obj.ObjectType = aType
return obj
}

// ResultToString converts an integer result code into a corresponding string representation.
// It takes an integer result as input and returns the corresponding string representation.
// The possible result codes are SUCCESS, FAILURE, and ERROR.
// If the input result code is not recognized, an empty string is returned.
func ResultToString(result int) (str string) {
switch result {
case SUCCESS:
Expand Down
Loading

0 comments on commit 0cf057b

Please sign in to comment.