mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-04 02:56:18 +00:00
factory: use customised deep compare
reflect.DeepEqual would return false when comparing nil map/slice with empty map/slice. We would want to return success in such case, since it is possible for upper layers to send these kind of configs. Fixes: #844 Signed-off-by: Peng Tao <bergwolf@gmail.com>
This commit is contained in:
parent
4c82d526ee
commit
32ef29bd18
@ -100,6 +100,71 @@ func resetHypervisorConfig(config *vc.VMConfig) {
|
|||||||
config.ProxyConfig = vc.ProxyConfig{}
|
config.ProxyConfig = vc.ProxyConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func compareStruct(foo, bar reflect.Value) bool {
|
||||||
|
for i := 0; i < foo.NumField(); i++ {
|
||||||
|
if !deepCompareValue(foo.Field(i), bar.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareMap(foo, bar reflect.Value) bool {
|
||||||
|
if foo.Len() != bar.Len() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range foo.MapKeys() {
|
||||||
|
if !deepCompareValue(foo.MapIndex(k), bar.MapIndex(k)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareSlice(foo, bar reflect.Value) bool {
|
||||||
|
if foo.Len() != bar.Len() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for j := 0; j < foo.Len(); j++ {
|
||||||
|
if !deepCompareValue(foo.Index(j), bar.Index(j)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func deepCompareValue(foo, bar reflect.Value) bool {
|
||||||
|
if !foo.IsValid() || !bar.IsValid() {
|
||||||
|
return foo.IsValid() == bar.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
if foo.Type() != bar.Type() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch foo.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
return compareMap(foo, bar)
|
||||||
|
case reflect.Array:
|
||||||
|
fallthrough
|
||||||
|
case reflect.Slice:
|
||||||
|
return compareSlice(foo, bar)
|
||||||
|
case reflect.Struct:
|
||||||
|
return compareStruct(foo, bar)
|
||||||
|
default:
|
||||||
|
return foo.Interface() == bar.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deepCompare(foo, bar interface{}) bool {
|
||||||
|
v1 := reflect.ValueOf(foo)
|
||||||
|
v2 := reflect.ValueOf(bar)
|
||||||
|
|
||||||
|
return deepCompareValue(v1, v2)
|
||||||
|
}
|
||||||
|
|
||||||
// It's important that baseConfig and newConfig are passed by value!
|
// It's important that baseConfig and newConfig are passed by value!
|
||||||
func checkVMConfig(config1, config2 vc.VMConfig) error {
|
func checkVMConfig(config1, config2 vc.VMConfig) error {
|
||||||
if config1.HypervisorType != config2.HypervisorType {
|
if config1.HypervisorType != config2.HypervisorType {
|
||||||
@ -114,7 +179,7 @@ func checkVMConfig(config1, config2 vc.VMConfig) error {
|
|||||||
resetHypervisorConfig(&config1)
|
resetHypervisorConfig(&config1)
|
||||||
resetHypervisorConfig(&config2)
|
resetHypervisorConfig(&config2)
|
||||||
|
|
||||||
if !reflect.DeepEqual(config1, config2) {
|
if !deepCompare(config1, config2) {
|
||||||
return fmt.Errorf("hypervisor config does not match, base: %+v. new: %+v", config1, config2)
|
return fmt.Errorf("hypervisor config does not match, base: %+v. new: %+v", config1, config2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/factory/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewFactory(t *testing.T) {
|
func TestNewFactory(t *testing.T) {
|
||||||
@ -248,3 +249,66 @@ func TestFactoryGetVM(t *testing.T) {
|
|||||||
|
|
||||||
f.CloseFactory(ctx)
|
f.CloseFactory(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeepCompare(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
foo := vc.VMConfig{}
|
||||||
|
bar := vc.VMConfig{}
|
||||||
|
assert.True(deepCompare(foo, bar))
|
||||||
|
|
||||||
|
foo.HypervisorConfig.NumVCPUs = 1
|
||||||
|
assert.False(deepCompare(foo, bar))
|
||||||
|
bar.HypervisorConfig.NumVCPUs = 1
|
||||||
|
assert.True(deepCompare(foo, bar))
|
||||||
|
|
||||||
|
// slice
|
||||||
|
foo.HypervisorConfig.KernelParams = []vc.Param{}
|
||||||
|
assert.True(deepCompare(foo, bar))
|
||||||
|
foo.HypervisorConfig.KernelParams = append(foo.HypervisorConfig.KernelParams, vc.Param{Key: "key", Value: "value"})
|
||||||
|
assert.False(deepCompare(foo, bar))
|
||||||
|
bar.HypervisorConfig.KernelParams = append(bar.HypervisorConfig.KernelParams, vc.Param{Key: "key", Value: "value"})
|
||||||
|
assert.True(deepCompare(foo, bar))
|
||||||
|
|
||||||
|
// map
|
||||||
|
var fooMap map[string]vc.VMConfig
|
||||||
|
var barMap map[string]vc.VMConfig
|
||||||
|
assert.False(deepCompare(foo, fooMap))
|
||||||
|
assert.True(deepCompare(fooMap, barMap))
|
||||||
|
fooMap = make(map[string]vc.VMConfig)
|
||||||
|
assert.True(deepCompare(fooMap, barMap))
|
||||||
|
fooMap["foo"] = foo
|
||||||
|
assert.False(deepCompare(fooMap, barMap))
|
||||||
|
barMap = make(map[string]vc.VMConfig)
|
||||||
|
assert.False(deepCompare(fooMap, barMap))
|
||||||
|
barMap["foo"] = bar
|
||||||
|
assert.True(deepCompare(fooMap, barMap))
|
||||||
|
|
||||||
|
// invalid interface
|
||||||
|
var f1 vc.Factory
|
||||||
|
var f2 vc.Factory
|
||||||
|
var f3 base.FactoryBase
|
||||||
|
assert.True(deepCompare(f1, f2))
|
||||||
|
assert.True(deepCompare(f1, f3))
|
||||||
|
|
||||||
|
// valid interface
|
||||||
|
var config Config
|
||||||
|
var err error
|
||||||
|
ctx := context.Background()
|
||||||
|
config.VMConfig = vc.VMConfig{
|
||||||
|
HypervisorType: vc.MockHypervisor,
|
||||||
|
AgentType: vc.NoopAgentType,
|
||||||
|
ProxyType: vc.NoopProxyType,
|
||||||
|
}
|
||||||
|
testDir, _ := ioutil.TempDir("", "vmfactory-tmp-")
|
||||||
|
config.VMConfig.HypervisorConfig = vc.HypervisorConfig{
|
||||||
|
KernelPath: testDir,
|
||||||
|
ImagePath: testDir,
|
||||||
|
}
|
||||||
|
f1, err = NewFactory(ctx, config, false)
|
||||||
|
assert.Nil(err)
|
||||||
|
assert.True(deepCompare(f1, f1))
|
||||||
|
f2, err = NewFactory(ctx, config, false)
|
||||||
|
assert.Nil(err)
|
||||||
|
assert.False(deepCompare(f1, f2))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user