diff --git a/pkg/apis/nfd/v1alpha1/feature.go b/pkg/apis/nfd/v1alpha1/feature.go index 6f112d83e..b3a9b1d5d 100644 --- a/pkg/apis/nfd/v1alpha1/feature.go +++ b/pkg/apis/nfd/v1alpha1/feature.go @@ -65,7 +65,6 @@ func NewInstanceFeature(attrs map[string]string) *InstanceFeature { } // InsertAttributeFeatures inserts new values into a specific feature. -// TODO: add unit tests func (f *Features) InsertAttributeFeatures(domain, feature string, values map[string]string) { if f.Attributes == nil { f.Attributes = make(map[string]AttributeFeatureSet) @@ -83,7 +82,6 @@ func (f *Features) InsertAttributeFeatures(domain, feature string, values map[st // Exists returns a non-empty string if a feature exists. The return value is // the type of the feautre, i.e. "flag", "attribute" or "instance". -// TODO: add unit tests func (f *Features) Exists(name string) string { if _, ok := f.Flags[name]; ok { return "flag" @@ -99,7 +97,6 @@ func (f *Features) Exists(name string) string { // MergeInto merges two FeatureSpecs into one. Data in the input object takes // precedence (overwrite) over data of the existing object we're merging into. -// TODO: add unit tests func (in *NodeFeatureSpec) MergeInto(out *NodeFeatureSpec) { in.Features.MergeInto(&out.Features) if in.Labels != nil { @@ -115,7 +112,6 @@ func (in *NodeFeatureSpec) MergeInto(out *NodeFeatureSpec) { // MergeInto merges two sets of features into one. Features from the input set // take precedence (overwrite) features from the existing features of the set // we're merging into. -// TODO: add unit tests func (in *Features) MergeInto(out *Features) { if in.Flags != nil { if out.Flags == nil { @@ -150,7 +146,6 @@ func (in *Features) MergeInto(out *Features) { } // MergeInto merges two sets of flag featues. -// TODO: add unit tests func (in *FlagFeatureSet) MergeInto(out *FlagFeatureSet) { if in.Elements != nil { if out.Elements == nil { @@ -163,7 +158,6 @@ func (in *FlagFeatureSet) MergeInto(out *FlagFeatureSet) { } // MergeInto merges two sets of attribute featues. -// TODO: add unit tests func (in *AttributeFeatureSet) MergeInto(out *AttributeFeatureSet) { if in.Elements != nil { if out.Elements == nil { @@ -176,7 +170,6 @@ func (in *AttributeFeatureSet) MergeInto(out *AttributeFeatureSet) { } // MergeInto merges two sets of instance featues. -// TODO: add unit tests func (in *InstanceFeatureSet) MergeInto(out *InstanceFeatureSet) { if in.Elements != nil { if out.Elements == nil { diff --git a/pkg/apis/nfd/v1alpha1/feature_test.go b/pkg/apis/nfd/v1alpha1/feature_test.go new file mode 100644 index 000000000..fe8d23009 --- /dev/null +++ b/pkg/apis/nfd/v1alpha1/feature_test.go @@ -0,0 +1,198 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFlagFeatureSet(t *testing.T) { + f1 := FlagFeatureSet{} + f2 := FlagFeatureSet{} + var expectedElems map[string]Nil = nil + + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewFlagFeatures() + expectedElems = make(map[string]Nil) + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewFlagFeatures("k1") + expectedElems["k1"] = Nil{} + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewFlagFeatures("k2") + expectedElems["k2"] = Nil{} + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) +} + +func TestAttributeFeatureSet(t *testing.T) { + f1 := AttributeFeatureSet{} + f2 := AttributeFeatureSet{} + var expectedElems map[string]string = nil + + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewAttributeFeatures(map[string]string{}) + expectedElems = make(map[string]string) + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewAttributeFeatures(map[string]string{"k1": "v1"}) + expectedElems["k1"] = "v1" + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewAttributeFeatures(map[string]string{"k2": "v2"}) + expectedElems["k2"] = "v2" + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewAttributeFeatures(map[string]string{"k1": "v1.overridden", "k3": "v3"}) + expectedElems["k1"] = "v1.overridden" + expectedElems["k3"] = "v3" + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) +} + +func TestInstanceFeatureSet(t *testing.T) { + f1 := InstanceFeatureSet{} + f2 := InstanceFeatureSet{} + var expectedElems []InstanceFeature = nil + + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewInstanceFeatures([]InstanceFeature{}) + expectedElems = []InstanceFeature{} + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewInstanceFeatures([]InstanceFeature{InstanceFeature{}}) + expectedElems = append(expectedElems, InstanceFeature{}) + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2 = NewInstanceFeatures([]InstanceFeature{ + InstanceFeature{ + Attributes: map[string]string{ + "a1": "v1", + "a2": "v2", + }, + }, + }) + expectedElems = append(expectedElems, *NewInstanceFeature(map[string]string{"a1": "v1", "a2": "v2"})) + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) + + f2.Elements[0].Attributes["a2"] = "v2.2" + expectedElems = append(expectedElems, *NewInstanceFeature(map[string]string{"a1": "v1", "a2": "v2.2"})) + f2.MergeInto(&f1) + assert.Equal(t, expectedElems, f1.Elements) +} + +func TestFeature(t *testing.T) { + f := Features{} + + // Test Exists() and InsertAttributeFeatures() + assert.Empty(t, f.Exists("dom.attr"), "empty features shouldn't contain anything") + + f.InsertAttributeFeatures("dom", "attr", map[string]string{"k1": "v1", "k2": "v2"}) + expectedAttributes := map[string]string{"k1": "v1", "k2": "v2"} + assert.Equal(t, "attribute", f.Exists("dom.attr"), "attribute feature should exist") + assert.Equal(t, expectedAttributes, f.Attributes["dom.attr"].Elements) + + f.InsertAttributeFeatures("dom", "attr", map[string]string{"k2": "v2.override", "k3": "v3"}) + expectedAttributes["k2"] = "v2.override" + expectedAttributes["k3"] = "v3" + assert.Equal(t, expectedAttributes, f.Attributes["dom.attr"].Elements) + + // Test merging + f = Features{} + f2 := Features{} + expectedFeatures := Features{} + + f2.MergeInto(&f) + assert.Equal(t, expectedFeatures, f) + + f2 = *NewFeatures() + f2.Flags["dom.flag"] = NewFlagFeatures("k1", "k2") + f2.Attributes["dom.attr"] = NewAttributeFeatures(map[string]string{"k1": "v1", "k2": "v2"}) + f2.Instances["dom.inst"] = NewInstanceFeatures([]InstanceFeature{ + *NewInstanceFeature(map[string]string{"a1": "v1.1", "a2": "v1.2"}), + *NewInstanceFeature(map[string]string{"a1": "v2.1", "a2": "v2.2"}), + }) + f2.MergeInto(&f) + assert.Equal(t, f2, f) + + f2.Flags["dom.flag"] = NewFlagFeatures("k3") + f2.Attributes["dom.attr"] = NewAttributeFeatures(map[string]string{"k1": "v1.override"}) + f2.Instances["dom.inst"] = NewInstanceFeatures([]InstanceFeature{ + *NewInstanceFeature(map[string]string{"a1": "v3.1", "a3": "v3.3"}), + }) + f2.MergeInto(&f) + expectedFeatures = *NewFeatures() + expectedFeatures.Flags["dom.flag"] = FlagFeatureSet{Elements: map[string]Nil{"k1": Nil{}, "k2": Nil{}, "k3": Nil{}}} + expectedFeatures.Attributes["dom.attr"] = AttributeFeatureSet{Elements: map[string]string{"k1": "v1.override", "k2": "v2"}} + expectedFeatures.Instances["dom.inst"] = InstanceFeatureSet{ + Elements: []InstanceFeature{ + InstanceFeature{Attributes: map[string]string{"a1": "v1.1", "a2": "v1.2"}}, + InstanceFeature{Attributes: map[string]string{"a1": "v2.1", "a2": "v2.2"}}, + InstanceFeature{Attributes: map[string]string{"a1": "v3.1", "a3": "v3.3"}}, + }, + } + assert.Equal(t, expectedFeatures, f) +} + +func TestFeatureSoec(t *testing.T) { + // Test merging + f := NodeFeatureSpec{} + f2 := NodeFeatureSpec{} + expectedFeatures := NodeFeatureSpec{} + + f2.MergeInto(&f) + assert.Equal(t, expectedFeatures, f) + + f2 = *NewNodeFeatureSpec() + f2.Labels = map[string]string{"l1": "v1", "l2": "v2"} + f2.Features = *NewFeatures() + f2.Features.Flags["dom.flag"] = NewFlagFeatures("k1", "k2") + + expectedFeatures = *f2.DeepCopy() + f2.MergeInto(&f) + assert.Equal(t, expectedFeatures, f) + + // Check that second merge updates the object correctly + f2 = *NewNodeFeatureSpec() + f2.Labels = map[string]string{"l1": "v1.override", "l3": "v3"} + f2.Features = *NewFeatures() + f2.Features.Flags["dom.flag2"] = NewFlagFeatures("k3") + + expectedFeatures.Labels["l1"] = "v1.override" + expectedFeatures.Labels["l3"] = "v3" + expectedFeatures.Features.Flags["dom.flag2"] = FlagFeatureSet{Elements: map[string]Nil{"k3": Nil{}}} + + f2.MergeInto(&f) + assert.Equal(t, expectedFeatures, f) +}