mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-04 09:48:17 +08:00
153 lines
3.7 KiB
Go
153 lines
3.7 KiB
Go
//go:build gin_bind_encoding
|
|
|
|
package bindingcodec
|
|
|
|
import (
|
|
"encoding"
|
|
"errors"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// mockBindUnmarshaler implements the bindUnmarshaler interface for testing
|
|
type mockBindUnmarshaler struct {
|
|
receivedParam string
|
|
returnError error
|
|
}
|
|
|
|
func (m *mockBindUnmarshaler) UnmarshalParam(param string) error {
|
|
m.receivedParam = param
|
|
return m.returnError
|
|
}
|
|
|
|
// mockTextUnmarshaler implements encoding.TextUnmarshaler for testing
|
|
type mockTextUnmarshaler struct {
|
|
receivedText []byte
|
|
returnError error
|
|
}
|
|
|
|
func (m *mockTextUnmarshaler) UnmarshalText(text []byte) error {
|
|
m.receivedText = text
|
|
return m.returnError
|
|
}
|
|
|
|
func TestTrySetByInterface_WithBindUnmarshaler(t *testing.T) {
|
|
api := bindingApi{}
|
|
mock := &mockBindUnmarshaler{}
|
|
value := reflect.ValueOf(mock).Elem()
|
|
|
|
inputVal := "test-value"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.True(t, isSet)
|
|
require.NoError(t, err)
|
|
require.Equal(t, inputVal, mock.receivedParam)
|
|
}
|
|
|
|
func TestTrySetByInterface_WithBindUnmarshalerError(t *testing.T) {
|
|
api := bindingApi{}
|
|
expectedErr := errors.New("unmarshal error")
|
|
mock := &mockBindUnmarshaler{returnError: expectedErr}
|
|
value := reflect.ValueOf(mock).Elem()
|
|
|
|
inputVal := "test-value"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.True(t, isSet)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestTrySetByInterface_WithTextUnmarshaler(t *testing.T) {
|
|
api := bindingApi{}
|
|
mock := &mockTextUnmarshaler{}
|
|
value := reflect.ValueOf(mock).Elem()
|
|
|
|
inputVal := "text-value"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.True(t, isSet)
|
|
require.NoError(t, err)
|
|
require.Equal(t, []byte(inputVal), mock.receivedText)
|
|
}
|
|
|
|
func TestTrySetByInterface_WithTextUnmarshalerError(t *testing.T) {
|
|
api := bindingApi{}
|
|
expectedErr := errors.New("text unmarshal error")
|
|
mock := &mockTextUnmarshaler{returnError: expectedErr}
|
|
value := reflect.ValueOf(mock).Elem()
|
|
|
|
inputVal := "text-value"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.True(t, isSet)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestTrySetByInterface_WithTimeTime(t *testing.T) {
|
|
api := bindingApi{}
|
|
now := time.Now()
|
|
value := reflect.ValueOf(&now).Elem()
|
|
|
|
inputVal := "2023-01-01T00:00:00Z"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.False(t, isSet)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// TestTrySetByInterface_WithoutInterface tests behavior with regular types
|
|
func TestTrySetByInterface_WithoutInterface(t *testing.T) {
|
|
api := bindingApi{}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
value any
|
|
}{
|
|
{"string", "test"},
|
|
{"int", 42},
|
|
{"bool", true},
|
|
{"struct", struct{ Field string }{"value"}},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ptr := reflect.New(reflect.TypeOf(tc.value))
|
|
ptr.Elem().Set(reflect.ValueOf(tc.value))
|
|
value := ptr.Elem()
|
|
|
|
isSet, err := api.TrySetByInterface("input", value)
|
|
require.False(t, isSet)
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// mockBothInterfaces implements both bindUnmarshaler and encoding.TextUnmarshaler
|
|
type mockBothInterfaces struct {
|
|
bindCalled bool
|
|
textCalled bool
|
|
}
|
|
|
|
func (m *mockBothInterfaces) UnmarshalParam(param string) error {
|
|
m.bindCalled = true
|
|
return nil
|
|
}
|
|
|
|
func (m *mockBothInterfaces) UnmarshalText(text []byte) error {
|
|
m.textCalled = true
|
|
return nil
|
|
}
|
|
|
|
var _ encoding.TextUnmarshaler = (*mockBothInterfaces)(nil)
|
|
|
|
func TestTrySetByInterface_PriorityBindUnmarshaler(t *testing.T) {
|
|
api := bindingApi{}
|
|
mock := &mockBothInterfaces{}
|
|
value := reflect.ValueOf(mock).Elem()
|
|
|
|
inputVal := "test"
|
|
isSet, err := api.TrySetByInterface(inputVal, value)
|
|
require.True(t, isSet)
|
|
require.NoError(t, err)
|
|
require.True(t, mock.bindCalled)
|
|
require.False(t, mock.textCalled)
|
|
}
|