Provisioning: Remove again dependency cycle between provisioning app and grafana (#110863)
* Remove dependency cycle between provisioning app and grafana * Format code * Fix linting
This commit is contained in:
committed by
GitHub
parent
5520a38726
commit
09ef9c8176
@@ -0,0 +1,172 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsInterfaceNil(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
expected bool
|
||||
}{
|
||||
// True nil cases
|
||||
{"true nil interface", nil, true},
|
||||
{"nil pointer", (*int)(nil), true},
|
||||
{"nil slice", ([]int)(nil), true},
|
||||
{"nil map", (map[string]int)(nil), true},
|
||||
{"nil function", (func())(nil), true},
|
||||
{"nil interface wrapped in interface", (interface{})(nil), true},
|
||||
|
||||
// Channels are not handled by IsInterfaceNil (not in switch statement)
|
||||
{"nil channel - not handled", (chan int)(nil), false},
|
||||
|
||||
// Non-nil cases
|
||||
{"non-nil pointer", func() interface{} { val := 42; return &val }(), false},
|
||||
{"non-nil slice", []int{1, 2, 3}, false},
|
||||
{"empty slice", []int{}, false},
|
||||
{"non-nil map", map[string]int{"key": 1}, false},
|
||||
{"empty map", make(map[string]int), false},
|
||||
{"non-nil function", func() {}, false},
|
||||
{"non-nil channel", make(chan int), false},
|
||||
|
||||
// Basic value types
|
||||
{"string value", "hello", false},
|
||||
{"empty string", "", false},
|
||||
{"int value", 42, false},
|
||||
{"zero int", 0, false},
|
||||
{"bool true", true, false},
|
||||
{"bool false", false, false},
|
||||
{"float64", 3.14, false},
|
||||
{"complex128", complex(1, 2), false},
|
||||
|
||||
// Composite value types
|
||||
{"struct value", struct{ x int }{x: 1}, false},
|
||||
{"array value", [3]int{1, 2, 3}, false},
|
||||
{"zero array", [3]int{}, false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := IsInterfaceNil(tc.value)
|
||||
assert.Equal(t, tc.expected, result, "IsInterfaceNil(%v) should return %t", tc.value, tc.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInterfaceNil_NestedInterfaces(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "nested interface with nil",
|
||||
value: func() interface{} {
|
||||
var inner *int = nil
|
||||
var middle interface{} = inner
|
||||
return middle
|
||||
}(),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "nested interface with value",
|
||||
value: func() interface{} {
|
||||
val := 42
|
||||
inner := &val
|
||||
var middle interface{} = inner
|
||||
return middle
|
||||
}(),
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "interface containing interface with value",
|
||||
value: func() interface{} {
|
||||
var inner interface{} = 42
|
||||
outer := inner
|
||||
return outer
|
||||
}(),
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "interface containing nil interface",
|
||||
value: func() interface{} {
|
||||
var inner interface{} = nil
|
||||
outer := inner
|
||||
return outer
|
||||
}(),
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := IsInterfaceNil(tc.value)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInterfaceNil_ReflectKinds(t *testing.T) {
|
||||
t.Run("handles specific nilable reflect kinds", func(t *testing.T) {
|
||||
// Test the specific nilable kinds that the function handles
|
||||
// according to its switch statement: Ptr, Slice, Map, Func, Interface
|
||||
nilableTestCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
}{
|
||||
{"nil pointer", (*int)(nil)},
|
||||
{"nil slice", ([]int)(nil)},
|
||||
{"nil map", (map[string]int)(nil)},
|
||||
{"nil function", (func())(nil)},
|
||||
{"nil interface", (interface{})(nil)},
|
||||
}
|
||||
|
||||
for _, tc := range nilableTestCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.True(t, IsInterfaceNil(tc.value), "%s should be detected as nil", tc.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("does not handle channels and other nilable types", func(t *testing.T) {
|
||||
// Test that nilable kinds NOT in the switch statement return false
|
||||
unhandledTestCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
}{
|
||||
{"nil channel", (chan int)(nil)},
|
||||
// UnsafePointer would be another example, but harder to test
|
||||
}
|
||||
|
||||
for _, tc := range unhandledTestCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.False(t, IsInterfaceNil(tc.value), "%s should not be detected as nil (unhandled type)", tc.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("handles non-nilable kinds", func(t *testing.T) {
|
||||
// Test kinds that cannot be nil
|
||||
nonNilableTestCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
}{
|
||||
{"int", 42},
|
||||
{"string", "test"},
|
||||
{"bool", true},
|
||||
{"struct", struct{ x int }{x: 1}},
|
||||
{"array", [3]int{1, 2, 3}},
|
||||
{"float64", 3.14},
|
||||
{"complex128", complex(1, 2)},
|
||||
}
|
||||
|
||||
for _, tc := range nonNilableTestCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.False(t, IsInterfaceNil(tc.value), "%s should not be detected as nil (non-nilable)", tc.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user