mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-09-26 19:46:43 +02:00
168 lines
8.8 KiB
Go
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()
|
|
}
|
|
}
|
|
|
|
// ........-------------------============++===============+=+==+++++++++++++++++++
|
|
// .........------------------==-=====#%%%%%%%%%#+============++==+==++++++++++++++
|
|
// .........--------------------===++#%##%%%##%#####===========+==+=++=++=+++++=+++
|
|
// ..........-----------------=-=+#%#####+++=-=-++#%#===========+==+==++=+==++++=+
|
|
// ..........-----------------==###+#####++=---.. .=++==============+===+=+=+=++=+
|
|
// .........-.---------------=--+=-=####++==---.. -=================++=+==++=++
|
|
// .. ........-.--------------==+. -#####+==---. ====================++==+++=
|
|
// .. ......---.-----------==-==- .+#++++=----. =====================++==++=
|
|
// ........--.-------------===-. -#%%%#+-=-=---. -=====================++==++
|
|
// ...........------------==++%= .+#+=+%#+#.=-.-- =====================+==++=+
|
|
// .........--------------===### ++=#%=%+#+ -+#+=. .--====================+==+==
|
|
// ........----------------===%# +.+###%+#- =+##.=. -===================++=++++
|
|
// ........---------------====## ++#%%##+#= -=- .==================++++++=++
|
|
// .......----------------===--+ .+#%#++++#= .. =========+=====+++=++=++++++
|
|
// .....----------------=-====-- -+==+%%#%#+- = ============+==++++=++==++=+
|
|
// ..----------------==========- -- #%%#%#+=. =- ========+===+=++=++++++++++++
|
|
// .----------------==-=========. ==-%#++#=-. =. ====+=====+==+==+++==++=++++++
|
|
// .--------------=--============.=-#%@%%%#+++--= ===+==++==++=+=+==+++++++++++++
|
|
// -------------=-================-=#####%#+- .- ==++++++=++=+++++++++++++++++++
|
|
// -------------=================- -.+%##+-.+-. . .+=++=++++++=+++++++++++++++++
|
|
// ---------==-================= = --.+%%#=. =+++++++++++++++++++++++++++
|
|
// -------=---===============. #= =+-==#++++. . -++++++++++++++++++++++++
|
|
// -----=-==============- .. +#= =%###++ .- .=+++++++++++++++++++
|
|
// --==-===========- .-==.. -### --++. +. . .=+++++++++++++++
|
|
// ============- .-=+##=++-. =#%# =+%##+ #=. =++++++++++
|
|
// ========== = =##+###=+===- +%%#..%+%+-+# #+- -++++++++
|
|
// ========= +==##%%##++-#++- ##=++=.+###%%% +++. .. . +++++++
|
|
// ========-.%++%%%%#+=+-## ++==++++=-..# -= =+#- -... . ++##+##
|
|
// ======++ -%+#%%%%#+=#=# =+++===+++. . +# -+%#- .---.......... ++##+#+
|
|
// ======+. -%=#%%%%#=+#+. =%%#+++##++=. .=#+=#%+. ..--..-........ - -++++##+
|
|
// +++++++-..%=#%%%%#=+#..###%%#+=+++=---+.=###%=. ..--.--...--... -. ++++#++
|
|
// ++=++++.%#+=#%%%#+++ =++%%@%%###%##++=.-###%+-..-------.------... .=. ++##+#
|
|
// +++++++.#%%=#%%%#+ .##%%%%%%%###%@@%##%=#%%#=-.--=-=---------... +=. =#####
|
|
// ++++++ .%%%#+#### ==##%%%@%%#=%@@@%%###+#%%+=--==-===--------....-#=. +####
|
|
// +++++= +%%%%-#- +#+#%%%@%%%#+%@@@@%%%%%%%%+==========--------..--#+--..... .####
|
|
// ++++= -.#%%%- #++##%%%%%%%#=%%@@@%#%%%%%%#+==+============------=#=--.. .... ###
|
|
// +++++ .#+%% .=%### +%%#%%@%=#%@@@%%%@@%%%+++++++================%+==--.. . . ##
|
|
// ++++ .==. =+##%%#%%%%%%%@%=#%@@@@%%%%@@%++++++++=++===========#%++=----. +#
|
|
// +++ .+#..=###%##%#@%#%#%%%%=##@@@%#=%%@%#######++++++++++=+++++%%#++=---..- =#
|
|
// +==--=.+##%%%%+=++++++#@%%%+#%@@@@%+=+#%###%#####++++++++=++++#%%%#++=---..--.-#
|
|
// +%%%-+=%#@@%%%+=#%+++#%@%%%##%%@@@@%%#=++#%%%%######+++++=++++%%%%##++===-. . +
|
|
// .- --%%@#@@@%%+++#%##@@@@%%%%%%%######%%##+#%######++#+++++++#%%%%##++++###+= -
|
|
// ..=++%@@%@@@%%%##%#%@@@@@%%%@@@@@%%%#++++++++%###+++###++++++@@%%%%##+==--==++#=
|
|
// -+#%%%@@%@@@@%%%%%@@@@@@@@%@@%%%%%%%###++++++++#####+++++++++%@%%%%######+=--..-
|
|
// +##%%%%@@@@@@@%%@@@@@@@@@@@@@@@@%%%##++#%#+++++++++++#####+++%@@@%%%#++=====++=-
|
|
// #%#@%@%@@@@@%%@@@@@@@@@@@@@%%%%%%%@%%#%%#####++++#+====++++++%@@@@@@@@@%#+==----
|
|
// ##%%@%%@@@@%@@@@@@@@@@@@@@@@@%%%%%%%%%%%#%%%%%###%+++======+++##+=+#+++##%%#%%%+
|
|
// +#%%@@@%@@@%@@%+#@@@@@@@@@@@@%%%%@@%%%%%@%%%%%%%%@#+++++===-===#++==+++=+++#%#%+
|
|
// #%%@@@%%@%%%%@#+#%@@@@%%%@@@@@@@%%%%@@%%%%@%%%%%%@#######+#+==+++=++=======+=++%
|
|
// ##@@@@@%%%%@#++++#%%%%%%%%@@@@@@@@@@@@@@@@@@@%%@@@##########+=++++++#++++++###+#
|
|
// ++#%@%%%%%#++++#+-###%%%%%%%@@%@@@@@@@@@@@@@@@@@@@##+##+####%#########+#########
|
|
// +++++++#++++##+#+ ++####%%%%%%@%@@@@@@@@@@@@@@@%%%####%%####%%#####%#%%#####%%##
|
|
// +#++#++++++++#+++ -+#+##%%%%@@%%@@@@@@@@@@@@@@@@@%####%%%%%%%%%%%%##%@@%%%%#%%%%
|
|
// +#+++#+#####++++= .=++##%#%%%%%%%@@@@@@@@@@@@@@@%####%%%%@%%@%%%%%%%%%@@%@%%%%%#
|
|
// ####+#+++++###+#-..=++##%%%%%%%#%@@@@@@@@@@@@@@@%####%%%%%%%%@%#################
|
|
// #++#++##+#++#++#..-=+###%%%%%%#+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%#################
|
|
// ++#+#++#+##++##=---=++####%%%###@@@%@@@@@@%%@@@@@@@@@@@@@@@@@%%+################
|
|
// +##+##++#++#++#--=+=++###%#%####@@@@@@@@@@@@@@@%@@@%%@%%%%%%###=+###############
|
|
// +++++##+#++#+++.-===+#####%%####@@@@@@@@%%@@%%@@%%%%%%########+==###############
|
|
// +++#++++++#+++..--==+##########%%%@@@@@%%%%%@@%%%%########%##+#=-###############
|
|
// +#++#++#+#++++..--===%#########%%%%%%%@%%%%%###%##############+==+##############
|
|
// ++++##+++++#++.==--=+@%##+###+#%%%%%%%%%%%####%##%%#%%%#######++==##############
|