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

     1  package jzon
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestValEncoder_JsonMarshaler_Error(t *testing.T) {
    13  	t.Run("chain error", func(t *testing.T) {
    14  		t.Run("", func(t *testing.T) {
    15  			testStreamerChainError(t, func(s *Streamer) {
    16  				(*jsonMarshalerEncoder)(nil).Encode(nil, s, nil)
    17  			})
    18  		})
    19  		t.Run("dynamic", func(t *testing.T) {
    20  			testStreamerChainError(t, func(s *Streamer) {
    21  				(*dynamicJSONMarshalerEncoder)(nil).Encode(nil, s, nil)
    22  			})
    23  		})
    24  	})
    25  }
    26  
    27  func TestValEncoder_JsonMarshaler_NonPointerReceiver(t *testing.T) {
    28  	f := checkEncodeValueWithStandard
    29  	t.Run("non pointer", func(t *testing.T) {
    30  		t.Run("no error", func(t *testing.T) {
    31  			f(t, testJSONMarshaler{
    32  				data: `{"a":1}`,
    33  			}, nil)
    34  		})
    35  		t.Run("error", func(t *testing.T) {
    36  			e := errors.New("test")
    37  			f(t, testJSONMarshaler{
    38  				data: `{"a":1}`,
    39  				err:  e,
    40  			}, e)
    41  		})
    42  	})
    43  	t.Run("pointer", func(t *testing.T) {
    44  		t.Run("nil", func(t *testing.T) {
    45  			f(t, (*testJSONMarshaler)(nil), nil)
    46  		})
    47  		t.Run("no error", func(t *testing.T) {
    48  			f(t, &testJSONMarshaler{
    49  				data: `{"a":2}`,
    50  			}, nil)
    51  		})
    52  		t.Run("error", func(t *testing.T) {
    53  			e := errors.New("test")
    54  			f(t, &testJSONMarshaler{
    55  				data: `{"a":2}`,
    56  				err:  e,
    57  			}, e)
    58  		})
    59  	})
    60  	t.Run("pointer of pointer", func(t *testing.T) {
    61  		t.Run("nil", func(t *testing.T) {
    62  			f(t, (**testJSONMarshaler)(nil), nil)
    63  		})
    64  		t.Run("pointer of nil", func(t *testing.T) {
    65  			ptr := (*testJSONMarshaler)(nil)
    66  			f(t, &ptr, nil)
    67  		})
    68  		t.Run("no error", func(t *testing.T) {
    69  			ptr := &testJSONMarshaler{
    70  				data: `{"a":2}`,
    71  			}
    72  			f(t, &ptr, nil)
    73  		})
    74  		t.Run("error", func(t *testing.T) {
    75  			e := errors.New("test")
    76  			ptr := &testJSONMarshaler{
    77  				data: `{"a":2}`,
    78  				err:  e,
    79  			}
    80  			f(t, &ptr, e)
    81  		})
    82  	})
    83  }
    84  
    85  func TestValEncoder_JsonMarshaler_PointerReceiver(t *testing.T) {
    86  	f := checkEncodeValueWithStandard
    87  	t.Run("non pointer", func(t *testing.T) {
    88  		t.Run("no error", func(t *testing.T) {
    89  			f(t, testJSONMarshaler2{
    90  				data: `{"b":1}`,
    91  			}, nil)
    92  		})
    93  		t.Run("error", func(t *testing.T) {
    94  			e := errors.New("test")
    95  			f(t, testJSONMarshaler2{
    96  				data: `{"b":1}`,
    97  				err:  e,
    98  			}, nil)
    99  		})
   100  	})
   101  	t.Run("pointer", func(t *testing.T) {
   102  		t.Run("nil", func(t *testing.T) {
   103  			f(t, (*testJSONMarshaler2)(nil), nil)
   104  		})
   105  		t.Run("no error", func(t *testing.T) {
   106  			f(t, &testJSONMarshaler2{
   107  				data: `{"b":1}`,
   108  			}, nil)
   109  		})
   110  		t.Run("error", func(t *testing.T) {
   111  			e := errors.New("test")
   112  			f(t, &testJSONMarshaler2{
   113  				data: `{"b":1}`,
   114  				err:  e,
   115  			}, e)
   116  		})
   117  	})
   118  	t.Run("pointer of pointer", func(t *testing.T) {
   119  		t.Run("nil", func(t *testing.T) {
   120  			f(t, (**testJSONMarshaler2)(nil), nil)
   121  		})
   122  		t.Run("pointer of nil", func(t *testing.T) {
   123  			ptr := (*testJSONMarshaler2)(nil)
   124  			f(t, &ptr, nil)
   125  		})
   126  		t.Run("no error", func(t *testing.T) {
   127  			ptr := &testJSONMarshaler2{
   128  				data: `{"a":2}`,
   129  			}
   130  			f(t, &ptr, nil)
   131  		})
   132  		t.Run("error", func(t *testing.T) {
   133  			e := errors.New("test")
   134  			ptr := &testJSONMarshaler2{
   135  				data: `{"a":2}`,
   136  				err:  e,
   137  			}
   138  			f(t, &ptr, e)
   139  		})
   140  	})
   141  	t.Run("struct member", func(t *testing.T) {
   142  		t.Run("value", func(t *testing.T) {
   143  			type st struct {
   144  				A testJSONMarshaler2
   145  			}
   146  			/*
   147  			 * with the current implementation,
   148  			 * only one of the following two test can succeed
   149  			 */
   150  			t.Run("value", func(t *testing.T) {
   151  				skipTest(t, "pointer encoder on value")
   152  				checkEncodeValueWithStandard(t, st{
   153  					A: testJSONMarshaler2{
   154  						data: `{"a":2}`,
   155  					},
   156  				}, nil)
   157  			})
   158  			t.Run("ptr", func(t *testing.T) {
   159  				checkEncodeValueWithStandard(t, &st{
   160  					A: testJSONMarshaler2{
   161  						data: `{"a":2}`,
   162  					},
   163  				}, nil)
   164  			})
   165  		})
   166  		t.Run("pointer", func(t *testing.T) {
   167  			type st struct {
   168  				A *testJSONMarshaler2
   169  			}
   170  			t.Run("nil", func(t *testing.T) {
   171  				checkEncodeValueWithStandard(t, &st{}, nil)
   172  			})
   173  		})
   174  	})
   175  }
   176  
   177  func TestValEncoder_DynamicJsonMarshaler(t *testing.T) {
   178  	t.Run("marshaler nil", func(t *testing.T) {
   179  		var i json.Marshaler
   180  		checkEncodeValueWithStandard(t, &i, nil)
   181  	})
   182  	t.Run("marshaler error", func(t *testing.T) {
   183  		e := errors.New("test")
   184  		var i json.Marshaler = testJSONMarshaler{
   185  			data: `"test"`,
   186  			err:  e,
   187  		}
   188  		checkEncodeValueWithStandard(t, &i, e)
   189  	})
   190  	t.Run("marshaler", func(t *testing.T) {
   191  		var i json.Marshaler = testJSONMarshaler{
   192  			data: `"test"`,
   193  		}
   194  		checkEncodeValueWithStandard(t, &i, nil)
   195  	})
   196  	t.Run("marshaler 2", func(t *testing.T) {
   197  		var i json.Marshaler = &testJSONMarshaler{
   198  			data: `"test 2"`,
   199  		}
   200  		checkEncodeValueWithStandard(t, &i, nil)
   201  	})
   202  }
   203  
   204  func TestValEncoder_JsonMarshaler_Direct(t *testing.T) {
   205  	t.Run("value", func(t *testing.T) {
   206  		t.Run("nil", func(t *testing.T) {
   207  			checkEncodeValueWithStandard(t, testMapJSONMarshaler(nil), nil)
   208  		})
   209  		t.Run("non nil", func(t *testing.T) {
   210  			checkEncodeValueWithStandard(t, testMapJSONMarshaler{
   211  				1: 2,
   212  			}, nil)
   213  		})
   214  	})
   215  	t.Run("pointer", func(t *testing.T) {
   216  		t.Run("nil", func(t *testing.T) {
   217  			checkEncodeValueWithStandard(t, (*testMapJSONMarshaler)(nil), nil)
   218  		})
   219  		t.Run("non nil", func(t *testing.T) {
   220  			var m testMapJSONMarshaler
   221  			checkEncodeValueWithStandard(t, &m, nil)
   222  		})
   223  		t.Run("non nil 2", func(t *testing.T) {
   224  			checkEncodeValueWithStandard(t, &testMapJSONMarshaler{
   225  				1: 2,
   226  			}, nil)
   227  		})
   228  	})
   229  	t.Run("struct member", func(t *testing.T) {
   230  		type st struct {
   231  			A testMapJSONMarshaler
   232  		}
   233  		checkEncodeValueWithStandard(t, &st{}, nil)
   234  	})
   235  	t.Run("value of marshaler", func(t *testing.T) {
   236  		t.Run("nil", func(t *testing.T) {
   237  			var m json.Marshaler
   238  			checkEncodeValueWithStandard(t, m, nil)
   239  		})
   240  		t.Run("value", func(t *testing.T) {
   241  			var m json.Marshaler = testMapJSONMarshaler{
   242  				1: 2,
   243  			}
   244  			checkEncodeValueWithStandard(t, m, nil)
   245  		})
   246  		t.Run("pointer", func(t *testing.T) {
   247  			var m json.Marshaler = &testMapJSONMarshaler{
   248  				1: 2,
   249  			}
   250  			checkEncodeValueWithStandard(t, m, nil)
   251  		})
   252  	})
   253  	t.Run("pointer of marshaler", func(t *testing.T) {
   254  		t.Run("nil", func(t *testing.T) {
   255  			var m json.Marshaler
   256  			checkEncodeValueWithStandard(t, &m, nil)
   257  		})
   258  		t.Run("value", func(t *testing.T) {
   259  			var m json.Marshaler = testMapJSONMarshaler{
   260  				1: 2,
   261  			}
   262  			checkEncodeValueWithStandard(t, &m, nil)
   263  		})
   264  		t.Run("pointer", func(t *testing.T) {
   265  			var m json.Marshaler = &testMapJSONMarshaler{
   266  				1: 2,
   267  			}
   268  			checkEncodeValueWithStandard(t, &m, nil)
   269  		})
   270  	})
   271  }
   272  
   273  func TestValEncoder_JsonMarshaler_OmitEmpty(t *testing.T) {
   274  	t.Run("json marshaler", func(t *testing.T) {
   275  		type st struct {
   276  			A testJSONMarshaler `json:",omitempty"`
   277  		}
   278  		checkEncodeValueWithStandard(t, st{
   279  			A: testJSONMarshaler{
   280  				data: "true",
   281  			},
   282  		}, nil)
   283  	})
   284  	t.Run("indirect json marshaler", func(t *testing.T) {
   285  		t.Run("bool", func(t *testing.T) {
   286  			type st struct {
   287  				A testBoolJSONMarshaler `json:",omitempty"`
   288  			}
   289  			require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   290  			checkEncodeValueWithStandard(t, st{
   291  				A: true,
   292  			}, nil)
   293  			checkEncodeValueWithStandard(t, st{
   294  				A: false,
   295  			}, nil)
   296  		})
   297  		t.Run("array", func(t *testing.T) {
   298  			type st struct {
   299  				A testIndirectArrayMarshaler `json:",omitempty"`
   300  			}
   301  			require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   302  			checkEncodeValueWithStandard(t, st{}, nil)
   303  			checkEncodeValueWithStandard(t, st{
   304  				A: testIndirectArrayMarshaler{2},
   305  			}, nil)
   306  		})
   307  		t.Run("slice", func(t *testing.T) {
   308  			type st struct {
   309  				A testSliceMarshaler `json:",omitempty"`
   310  			}
   311  			require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   312  			t.Run("nil", func(t *testing.T) {
   313  				checkEncodeValueWithStandard(t, st{}, nil)
   314  			})
   315  			t.Run("empty", func(t *testing.T) {
   316  				checkEncodeValueWithStandard(t, st{
   317  					A: testSliceMarshaler{},
   318  				}, nil)
   319  			})
   320  			t.Run("non empty", func(t *testing.T) {
   321  				checkEncodeValueWithStandard(t, st{
   322  					A: testSliceMarshaler{4, 5, 6},
   323  				}, nil)
   324  			})
   325  		})
   326  		t.Run("struct", func(t *testing.T) {
   327  			type st struct {
   328  				A testIndirectStructMarshaler `json:",omitempty"`
   329  			}
   330  			require.True(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   331  			checkEncodeValueWithStandard(t, st{}, nil)
   332  			checkEncodeValueWithStandard(t, st{
   333  				A: testIndirectStructMarshaler{1},
   334  			}, nil)
   335  		})
   336  	})
   337  	t.Run("direct json marshaler", func(t *testing.T) {
   338  		t.Run("array", func(t *testing.T) {
   339  			type st struct {
   340  				A testDirectArrayMarshaler `json:",omitempty"`
   341  			}
   342  			require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   343  			checkEncodeValueWithStandard(t, st{}, nil)
   344  			i := 123
   345  			checkEncodeValueWithStandard(t, st{
   346  				A: testDirectArrayMarshaler{&i},
   347  			}, nil)
   348  		})
   349  		t.Run("map", func(t *testing.T) {
   350  			type st struct {
   351  				A testMapJSONMarshaler `json:",omitempty"`
   352  			}
   353  			require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   354  			t.Run("nil", func(t *testing.T) {
   355  				checkEncodeValueWithStandard(t, st{}, nil)
   356  			})
   357  			t.Run("zero", func(t *testing.T) {
   358  				checkEncodeValueWithStandard(t, st{
   359  					A: testMapJSONMarshaler{},
   360  				}, nil)
   361  			})
   362  			t.Run("non zero", func(t *testing.T) {
   363  				checkEncodeValueWithStandard(t, st{
   364  					A: testMapJSONMarshaler{1: 2},
   365  				}, nil)
   366  			})
   367  		})
   368  		t.Run("struct", func(t *testing.T) {
   369  			type st struct {
   370  				A testDirectStructMarshaler `json:",omitempty"`
   371  			}
   372  			require.False(t, ifaceIndir(rtypeOfType(reflect.TypeOf(st{}).Field(0).Type)))
   373  			checkEncodeValueWithStandard(t, st{}, nil)
   374  			i := 2
   375  			checkEncodeValueWithStandard(t, st{
   376  				A: testDirectStructMarshaler{&i},
   377  			}, nil)
   378  		})
   379  	})
   380  	t.Run("pointer json marshaler", func(t *testing.T) {
   381  		t.Run("value field", func(t *testing.T) {
   382  			type st struct {
   383  				A testJSONMarshaler2 `json:",omitempty"`
   384  			}
   385  			t.Run("no data", func(t *testing.T) {
   386  				skipTest(t, "incompatible with std")
   387  				checkEncodeValueWithStandard(t, &st{
   388  					A: testJSONMarshaler2{},
   389  				}, nil)
   390  			})
   391  			t.Run("with data", func(t *testing.T) {
   392  				checkEncodeValueWithStandard(t, &st{
   393  					A: testJSONMarshaler2{
   394  						data: "true",
   395  					},
   396  				}, nil)
   397  			})
   398  		})
   399  		t.Run("pointer field", func(t *testing.T) {
   400  			type st struct {
   401  				A *testJSONMarshaler2 `json:",omitempty"`
   402  			}
   403  			t.Run("nil", func(t *testing.T) {
   404  				skipTest(t, "incompatible with std")
   405  				checkEncodeValueWithStandard(t, &st{}, nil)
   406  			})
   407  			t.Run("no data", func(t *testing.T) {
   408  				skipTest(t, "incompatible with std")
   409  				checkEncodeValueWithStandard(t, &st{
   410  					A: &testJSONMarshaler2{},
   411  				}, nil)
   412  			})
   413  			t.Run("with data", func(t *testing.T) {
   414  				checkEncodeValueWithStandard(t, &st{
   415  					A: &testJSONMarshaler2{
   416  						data: "true",
   417  					},
   418  				}, nil)
   419  			})
   420  		})
   421  
   422  	})
   423  	t.Run("dynamic json marshaler", func(t *testing.T) {
   424  		type st struct {
   425  			A json.Marshaler `json:",omitempty"`
   426  		}
   427  		t.Run("nil", func(t *testing.T) {
   428  			checkEncodeValueWithStandard(t, st{}, nil)
   429  		})
   430  		t.Run("nil pointer", func(t *testing.T) {
   431  			checkEncodeValueWithStandard(t, st{
   432  				A: (*testJSONMarshaler2)(nil),
   433  			}, nil)
   434  		})
   435  	})
   436  }