Files
imgproxy/testutil/equal_but_not_same.go
Victor Sokolov f8133cd0b1 IMG-57: isSecurityOptionAllowed; shared parse fns (#1528)
* isSecurityOptionAllowed; shared parse fns

* We are not the same
2025-09-18 20:03:41 +06:00

168 lines
8.8 KiB
Go

package testutil
import (
"reflect"
"testing"
"github.com/stretchr/testify/require"
)
// EqualButNotSame asserts that expected and actual objects are not the same.
// It recursively checks all fields to ensure that no pointers are shared.
// If a pointer, slice or map are nil in either object, the test fails.
func EqualButNotSame(t *testing.T, expected, actual any) {
t.Helper()
expectedVal := reflect.ValueOf(expected)
actualVal := reflect.ValueOf(actual)
deepEqual(t, expectedVal, actualVal, "")
}
// deepEqual recursively verifies that all values are equal but pointers are different
// except for the Expires field which is explicitly allowed to be shared
func deepEqual(t *testing.T, left, right reflect.Value, fieldPath string) {
require.True(t, left.IsValid() && right.IsValid(), "invalid value at %s", fieldPath)
require.Equal(t, left.Type(), right.Type(), "types are not equal at %s", fieldPath)
switch left.Kind() {
case reflect.Ptr:
// Pointers should not be nil and must point to different objects
require.False(t, left.IsNil(), "nil pointer at %s (left)", fieldPath)
require.False(t, right.IsNil(), "nil pointer at %s (right)", fieldPath)
require.NotSame(t, left.Interface(), right.Interface(), "shared pointer at %s", fieldPath)
deepEqual(t, left.Elem(), right.Elem(), fieldPath)
case reflect.Slice:
// Slices should contain some elements and must not share the same underlying array
require.Equal(t, left.Len(), right.Len(), "slice length mismatch at %s", fieldPath)
require.NotEmpty(t, left.Len(), "slice must not be empty %s (left)", fieldPath)
require.NotEmpty(t, right.Len(), "slice must not be empty %s (right)", fieldPath)
require.NotEqual(t, left.Pointer(), right.Pointer(), "shared slices at %s", fieldPath)
// Recursively verify slice elements
for i := 0; i < left.Len(); i++ {
elemPath := buildPath(fieldPath, "[", anyToString(i), "]")
deepEqual(t, left.Index(i), right.Index(i), elemPath)
}
case reflect.Map:
// Maps should contain some elements and must not share the same underlying map
require.Equal(t, left.Len(), right.Len(), "map length mismatch at %s", fieldPath)
require.NotEmpty(t, left.Len(), "map must not be empty %s (left)", fieldPath)
require.NotEmpty(t, right.Len(), "map must not be empty %s (right)", fieldPath)
require.NotEqual(t, left.Pointer(), right.Pointer(), "shared maps at %s", fieldPath)
// Recursively verify map values
for _, key := range left.MapKeys() {
keyStr := anyToString(key.Interface())
keyPath := buildPath(fieldPath, "[", keyStr, "]")
originalMapVal := left.MapIndex(key)
clonedMapVal := right.MapIndex(key)
deepEqual(t, originalMapVal, clonedMapVal, keyPath)
}
case reflect.Struct:
require.Equal(t, left.Interface(), right.Interface(), "structs are not equal at %s", fieldPath)
// Fallback to recursive field-by-field comparison
for i := 0; i < left.NumField(); i++ {
field := left.Type().Field(i)
if !field.IsExported() {
continue // Skip unexported fields
}
nestedPath := buildPath(fieldPath, ".", field.Name, "")
originalFieldVal := left.Field(i)
clonedFieldVal := right.Field(i)
deepEqual(t, originalFieldVal, clonedFieldVal, nestedPath)
}
default:
// For primitive types, just verify equality
require.Equal(t, left.Interface(), right.Interface(), "values not equal at %s", fieldPath)
}
}
// buildPath builds a field path for error messages
func buildPath(basePath, separator, element, suffix string) string {
if basePath == "" {
return element + suffix
}
return basePath + separator + element + suffix
}
// anyToString converts an any to a string for path building
func anyToString(v any) string {
switch val := v.(type) {
case string:
return val
default:
return reflect.ValueOf(val).String()
}
}
// ........-------------------============++===============+=+==+++++++++++++++++++
// .........------------------==-=====#%%%%%%%%%#+============++==+==++++++++++++++
// .........--------------------===++#%##%%%##%#####===========+==+=++=++=+++++=+++
// ..........-----------------=-=+#%#####+++=-=-++#%#===========+==+==++=+==++++=+
// ..........-----------------==###+#####++=---.. .=++==============+===+=+=+=++=+
// .........-.---------------=--+=-=####++==---.. -=================++=+==++=++
// .. ........-.--------------==+. -#####+==---. ====================++==+++=
// .. ......---.-----------==-==- .+#++++=----. =====================++==++=
// ........--.-------------===-. -#%%%#+-=-=---. -=====================++==++
// ...........------------==++%= .+#+=+%#+#.=-.-- =====================+==++=+
// .........--------------===### ++=#%=%+#+ -+#+=. .--====================+==+==
// ........----------------===%# +.+###%+#- =+##.=. -===================++=++++
// ........---------------====## ++#%%##+#= -=- .==================++++++=++
// .......----------------===--+ .+#%#++++#= .. =========+=====+++=++=++++++
// .....----------------=-====-- -+==+%%#%#+- = ============+==++++=++==++=+
// ..----------------==========- -- #%%#%#+=. =- ========+===+=++=++++++++++++
// .----------------==-=========. ==-%#++#=-. =. ====+=====+==+==+++==++=++++++
// .--------------=--============.=-#%@%%%#+++--= ===+==++==++=+=+==+++++++++++++
// -------------=-================-=#####%#+- .- ==++++++=++=+++++++++++++++++++
// -------------=================- -.+%##+-.+-. . .+=++=++++++=+++++++++++++++++
// ---------==-================= = --.+%%#=. =+++++++++++++++++++++++++++
// -------=---===============. #= =+-==#++++. . -++++++++++++++++++++++++
// -----=-==============- .. +#= =%###++ .- .=+++++++++++++++++++
// --==-===========- .-==.. -### --++. +. . .=+++++++++++++++
// ============- .-=+##=++-. =#%# =+%##+ #=. =++++++++++
// ========== = =##+###=+===- +%%#..%+%+-+# #+- -++++++++
// ========= +==##%%##++-#++- ##=++=.+###%%% +++. .. . +++++++
// ========-.%++%%%%#+=+-## ++==++++=-..# -= =+#- -... . ++##+##
// ======++ -%+#%%%%#+=#=# =+++===+++. . +# -+%#- .---.......... ++##+#+
// ======+. -%=#%%%%#=+#+. =%%#+++##++=. .=#+=#%+. ..--..-........ - -++++##+
// +++++++-..%=#%%%%#=+#..###%%#+=+++=---+.=###%=. ..--.--...--... -. ++++#++
// ++=++++.%#+=#%%%#+++ =++%%@%%###%##++=.-###%+-..-------.------... .=. ++##+#
// +++++++.#%%=#%%%#+ .##%%%%%%%###%@@%##%=#%%#=-.--=-=---------... +=. =#####
// ++++++ .%%%#+#### ==##%%%@%%#=%@@@%%###+#%%+=--==-===--------....-#=. +####
// +++++= +%%%%-#- +#+#%%%@%%%#+%@@@@%%%%%%%%+==========--------..--#+--..... .####
// ++++= -.#%%%- #++##%%%%%%%#=%%@@@%#%%%%%%#+==+============------=#=--.. .... ###
// +++++ .#+%% .=%### +%%#%%@%=#%@@@%%%@@%%%+++++++================%+==--.. . . ##
// ++++ .==. =+##%%#%%%%%%%@%=#%@@@@%%%%@@%++++++++=++===========#%++=----. +#
// +++ .+#..=###%##%#@%#%#%%%%=##@@@%#=%%@%#######++++++++++=+++++%%#++=---..- =#
// +==--=.+##%%%%+=++++++#@%%%+#%@@@@%+=+#%###%#####++++++++=++++#%%%#++=---..--.-#
// +%%%-+=%#@@%%%+=#%+++#%@%%%##%%@@@@%%#=++#%%%%######+++++=++++%%%%##++===-. . +
// .- --%%@#@@@%%+++#%##@@@@%%%%%%%######%%##+#%######++#+++++++#%%%%##++++###+= -
// ..=++%@@%@@@%%%##%#%@@@@@%%%@@@@@%%%#++++++++%###+++###++++++@@%%%%##+==--==++#=
// -+#%%%@@%@@@@%%%%%@@@@@@@@%@@%%%%%%%###++++++++#####+++++++++%@%%%%######+=--..-
// +##%%%%@@@@@@@%%@@@@@@@@@@@@@@@@%%%##++#%#+++++++++++#####+++%@@@%%%#++=====++=-
// #%#@%@%@@@@@%%@@@@@@@@@@@@@%%%%%%%@%%#%%#####++++#+====++++++%@@@@@@@@@%#+==----
// ##%%@%%@@@@%@@@@@@@@@@@@@@@@@%%%%%%%%%%%#%%%%%###%+++======+++##+=+#+++##%%#%%%+
// +#%%@@@%@@@%@@%+#@@@@@@@@@@@@%%%%@@%%%%%@%%%%%%%%@#+++++===-===#++==+++=+++#%#%+
// #%%@@@%%@%%%%@#+#%@@@@%%%@@@@@@@%%%%@@%%%%@%%%%%%@#######+#+==+++=++=======+=++%
// ##@@@@@%%%%@#++++#%%%%%%%%@@@@@@@@@@@@@@@@@@@%%@@@##########+=++++++#++++++###+#
// ++#%@%%%%%#++++#+-###%%%%%%%@@%@@@@@@@@@@@@@@@@@@@##+##+####%#########+#########
// +++++++#++++##+#+ ++####%%%%%%@%@@@@@@@@@@@@@@@%%%####%%####%%#####%#%%#####%%##
// +#++#++++++++#+++ -+#+##%%%%@@%%@@@@@@@@@@@@@@@@@%####%%%%%%%%%%%%##%@@%%%%#%%%%
// +#+++#+#####++++= .=++##%#%%%%%%%@@@@@@@@@@@@@@@%####%%%%@%%@%%%%%%%%%@@%@%%%%%#
// ####+#+++++###+#-..=++##%%%%%%%#%@@@@@@@@@@@@@@@%####%%%%%%%%@%#################
// #++#++##+#++#++#..-=+###%%%%%%#+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%#################
// ++#+#++#+##++##=---=++####%%%###@@@%@@@@@@%%@@@@@@@@@@@@@@@@@%%+################
// +##+##++#++#++#--=+=++###%#%####@@@@@@@@@@@@@@@%@@@%%@%%%%%%###=+###############
// +++++##+#++#+++.-===+#####%%####@@@@@@@@%%@@%%@@%%%%%%########+==###############
// +++#++++++#+++..--==+##########%%%@@@@@%%%%%@@%%%%########%##+#=-###############
// +#++#++#+#++++..--===%#########%%%%%%%@%%%%%###%##############+==+##############
// ++++##+++++#++.==--=+@%##+###+#%%%%%%%%%%%####%##%%#%%%#######++==##############