github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_encoder_native_map_test.go (about)

     1  package jzon
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"math"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestValEncoder_Map_Error(t *testing.T) {
    14  	t.Run("chain error", func(t *testing.T) {
    15  		testStreamerChainError(t, func(s *Streamer) {
    16  			(*directMapEncoder)(nil).Encode(nil, s, nil)
    17  		})
    18  	})
    19  	t.Run("element error", func(t *testing.T) {
    20  		e := errors.New("test")
    21  		checkEncodeValueWithStandard(t, map[string]json.Marshaler{
    22  			"key": testJSONMarshaler{
    23  				err: e,
    24  			},
    25  		}, e)
    26  	})
    27  }
    28  
    29  func TestValEncoder_Map(t *testing.T) {
    30  	t.Run("nil", func(t *testing.T) {
    31  		var m map[string]int
    32  		checkEncodeValueWithStandard(t, m, nil)
    33  	})
    34  	t.Run("nil pointer", func(t *testing.T) {
    35  		var m map[string]int
    36  		checkEncodeValueWithStandard(t, &m, nil)
    37  	})
    38  	t.Run("simple", func(t *testing.T) {
    39  		m := map[string]int{"1": 2}
    40  		checkEncodeValueWithStandard(t, m, nil)
    41  	})
    42  	t.Run("pointer elem", func(t *testing.T) {
    43  		i := 3
    44  		m := map[string]*int{
    45  			"1": (*int)(nil),
    46  			"2": &i,
    47  		}
    48  		checkEncodeValueWithStandard(t, m, nil)
    49  	})
    50  }
    51  
    52  type testMapIntKey2 int
    53  
    54  func (i testMapIntKey2) MarshalText() ([]byte, error) {
    55  	return []byte(strconv.Itoa(int(i * 2))), nil
    56  }
    57  
    58  type testMapIntKey2Ptr int
    59  
    60  func (i *testMapIntKey2Ptr) MarshalText() ([]byte, error) {
    61  	return []byte(strconv.Itoa(int(*i * 2))), nil
    62  }
    63  
    64  type testMapStringKey2 string
    65  
    66  func (s testMapStringKey2) MarshalText() ([]byte, error) {
    67  	return []byte(strconv.Itoa(len(s))), nil
    68  }
    69  
    70  type testMapStringKey2Ptr string
    71  
    72  func (s *testMapStringKey2Ptr) MarshalText() ([]byte, error) {
    73  	return []byte(strconv.Itoa(len(*s))), nil
    74  }
    75  
    76  func TestValEncoder_Native_Map_KeyEncoder_TextMarshaler(t *testing.T) {
    77  	t.Run("not supported", func(t *testing.T) {
    78  		type key testTextMarshaler
    79  		m := map[key]int{{
    80  			data: "a",
    81  		}: 1}
    82  		checkEncodeValueWithStandard(t, m, TypeNotSupportedError(""))
    83  	})
    84  	t.Run("marshaler 1-non pointer", func(t *testing.T) {
    85  		t.Run("no error", func(t *testing.T) {
    86  			type key = testTextMarshaler
    87  			m := map[key]int{{
    88  				data: "a",
    89  			}: 1}
    90  			checkEncodeValueWithStandard(t, m, nil)
    91  		})
    92  		t.Run("no error 2", func(t *testing.T) {
    93  			type key = testTextMarshaler
    94  			m := map[key]int{{
    95  				data: "a",
    96  			}: 1}
    97  			checkEncodeValueWithStandard(t, &m, nil)
    98  		})
    99  		t.Run("error", func(t *testing.T) {
   100  			type key = testTextMarshaler
   101  			e := errors.New("test")
   102  			m := map[key]int{{
   103  				data: "a",
   104  				err:  e,
   105  			}: 1}
   106  			checkEncodeValueWithStandard(t, m, e)
   107  		})
   108  	})
   109  	t.Run("marshaler 1-pointer", func(t *testing.T) {
   110  		t.Run("no error", func(t *testing.T) {
   111  			type key = *testTextMarshaler
   112  			m := map[key]int{{
   113  				data: "a",
   114  			}: 1}
   115  			checkEncodeValueWithStandard(t, m, nil)
   116  		})
   117  		t.Run("no error 2", func(t *testing.T) {
   118  			type key = *testTextMarshaler
   119  			m := map[key]int{{
   120  				data: "a",
   121  			}: 1}
   122  			checkEncodeValueWithStandard(t, &m, nil)
   123  		})
   124  		t.Run("error", func(t *testing.T) {
   125  			e := errors.New("test")
   126  			type key = *testTextMarshaler
   127  			m := map[key]int{{
   128  				data: "a",
   129  				err:  e,
   130  			}: 1}
   131  			checkEncodeValueWithStandard(t, m, e)
   132  		})
   133  		t.Run("nil", func(t *testing.T) {
   134  			type key = *testTextMarshaler
   135  			m := map[key]int{nil: 1}
   136  			v := "go1.13.15"
   137  			if goVersion.LessEqual(v) {
   138  				b, err := Marshal(m)
   139  				require.NoError(t, err)
   140  				require.Equal(t, `{"":1}`, string(b))
   141  			} else {
   142  				checkEncodeValueWithStandard(t, m, nil)
   143  			}
   144  		})
   145  	})
   146  	t.Run("marshaler 2-non pointer", func(t *testing.T) {
   147  		type key = testTextMarshaler2
   148  		m := map[key]int{{
   149  			data: "a",
   150  		}: 1}
   151  		checkEncodeValueWithStandard(t, m, TypeNotSupportedError(""))
   152  	})
   153  	t.Run("marshaler 2-pointer", func(t *testing.T) {
   154  		t.Run("no error", func(t *testing.T) {
   155  			type key = *testTextMarshaler2
   156  			m := map[key]int{{
   157  				data: "a",
   158  			}: 1}
   159  			checkEncodeValueWithStandard(t, m, nil)
   160  		})
   161  		t.Run("error", func(t *testing.T) {
   162  			e := errors.New("test")
   163  			type key = *testTextMarshaler2
   164  			m := map[key]int{{
   165  				data: "a",
   166  				err:  e,
   167  			}: 1}
   168  			checkEncodeValueWithStandard(t, m, e)
   169  		})
   170  		t.Run("nil", func(t *testing.T) {
   171  			type key = *testTextMarshaler2
   172  			m := map[key]int{nil: 1}
   173  			v := "go1.13.15"
   174  			if goVersion.LessEqual(v) {
   175  				b, err := Marshal(m)
   176  				require.NoError(t, err)
   177  				require.Equal(t, `{"":1}`, string(b))
   178  			} else {
   179  				checkEncodeValueWithStandard(t, m, nil)
   180  			}
   181  		})
   182  	})
   183  	t.Run("int key", func(t *testing.T) {
   184  		t.Run("value", func(t *testing.T) {
   185  			m := map[testMapIntKey2]testMapIntKey2{
   186  				1: 2,
   187  			}
   188  			checkEncodeValueWithStandard(t, m, nil)
   189  		})
   190  		t.Run("ptr", func(t *testing.T) {
   191  			m := map[testMapIntKey2Ptr]testMapIntKey2Ptr{
   192  				1: 2,
   193  			}
   194  			checkEncodeValueWithStandard(t, m, nil)
   195  		})
   196  	})
   197  	t.Run("string key", func(t *testing.T) {
   198  		t.Run("value", func(t *testing.T) {
   199  			// the MarshalText of the key is ignored
   200  			m := map[testMapStringKey2]testMapStringKey2{
   201  				"key": "value",
   202  			}
   203  			checkEncodeValueWithStandard(t, m, nil)
   204  		})
   205  		t.Run("ptr", func(t *testing.T) {
   206  			// the MarshalText of the key is ignored
   207  			m := map[testMapStringKey2Ptr]testMapStringKey2Ptr{
   208  				"key": "value",
   209  			}
   210  			checkEncodeValueWithStandard(t, m, nil)
   211  		})
   212  	})
   213  }
   214  
   215  func TestValEncoder_Native_Map_KeyEncoder_String(t *testing.T) {
   216  	t.Run("string", func(t *testing.T) {
   217  		type key string
   218  		m := map[key]int{"a": 1}
   219  		checkEncodeValueWithStandard(t, m, nil)
   220  	})
   221  }
   222  
   223  func TestValEncoder_Native_Map_KeyEncoder_Int(t *testing.T) {
   224  	t.Run("int8", func(t *testing.T) {
   225  		type key int8
   226  		m := map[key]key{
   227  			math.MaxInt8: math.MaxInt8,
   228  			math.MinInt8: math.MinInt8,
   229  		}
   230  		checkEncodeValueWithStandard(t, m, nil)
   231  	})
   232  	t.Run("int16", func(t *testing.T) {
   233  		type key int16
   234  		m := map[key]key{
   235  			math.MaxInt16: math.MaxInt16,
   236  			math.MinInt16: math.MinInt16,
   237  		}
   238  		checkEncodeValueWithStandard(t, m, nil)
   239  	})
   240  	t.Run("int32", func(t *testing.T) {
   241  		type key int32
   242  		m := map[key]key{
   243  			math.MaxInt32: math.MaxInt32,
   244  			math.MinInt32: math.MinInt32,
   245  		}
   246  		checkEncodeValueWithStandard(t, m, nil)
   247  	})
   248  	t.Run("int64", func(t *testing.T) {
   249  		type key int64
   250  		m := map[key]key{
   251  			math.MaxInt64: math.MaxInt64,
   252  			math.MinInt64: math.MinInt64,
   253  		}
   254  		checkEncodeValueWithStandard(t, m, nil)
   255  	})
   256  }
   257  
   258  func TestValEncoder_Native_Map_KeyEncoder_Uint(t *testing.T) {
   259  	t.Run("uint8", func(t *testing.T) {
   260  		type key uint8
   261  		m := map[key]key{
   262  			math.MaxUint8: math.MaxUint8,
   263  		}
   264  		checkEncodeValueWithStandard(t, m, nil)
   265  	})
   266  	t.Run("uint16", func(t *testing.T) {
   267  		type key uint16
   268  		m := map[key]key{
   269  			math.MaxUint16: math.MaxUint16,
   270  		}
   271  		checkEncodeValueWithStandard(t, m, nil)
   272  	})
   273  	t.Run("uint32", func(t *testing.T) {
   274  		type key uint32
   275  		m := map[key]key{
   276  			math.MaxUint32: math.MaxUint32,
   277  		}
   278  		checkEncodeValueWithStandard(t, m, nil)
   279  	})
   280  	t.Run("uint64", func(t *testing.T) {
   281  		type key uint64
   282  		m := map[key]key{
   283  			math.MaxUint64: math.MaxUint64,
   284  		}
   285  		checkEncodeValueWithStandard(t, m, nil)
   286  	})
   287  }
   288  
   289  func TestValEncoder_Map_OmitEmpty(t *testing.T) {
   290  	t.Run("normal", func(t *testing.T) {
   291  		type M map[int]int
   292  		type st struct {
   293  			M M `json:",omitempty"`
   294  		}
   295  		t.Run("nil", func(t *testing.T) {
   296  			checkEncodeValueWithStandard(t, st{}, nil)
   297  		})
   298  		t.Run("empty", func(t *testing.T) {
   299  			checkEncodeValueWithStandard(t, st{
   300  				M: M{},
   301  			}, nil)
   302  		})
   303  		t.Run("non empty", func(t *testing.T) {
   304  			checkEncodeValueWithStandard(t, st{
   305  				M: M{1: 2},
   306  			}, nil)
   307  		})
   308  	})
   309  }