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

     1  package jzon
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"reflect"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestValEncoder_Iface_Error(t *testing.T) {
    14  	t.Run("chain error", func(t *testing.T) {
    15  		t.Run("", func(t *testing.T) {
    16  			testStreamerChainError(t, func(s *Streamer) {
    17  				(*ifaceValEncoder)(nil).Encode(nil, s, nil)
    18  			})
    19  		})
    20  	})
    21  }
    22  
    23  type testBarface interface {
    24  	Bar() (string, error)
    25  }
    26  
    27  type testBarfaceImpl struct {
    28  	s string
    29  	e error
    30  }
    31  
    32  func (i testBarfaceImpl) Bar() (string, error) {
    33  	return i.s, i.e
    34  }
    35  
    36  type testBarfaceImpl2 struct {
    37  	s string
    38  	e error
    39  }
    40  
    41  func (i *testBarfaceImpl2) Bar() (string, error) {
    42  	return i.s, i.e
    43  }
    44  
    45  type testBarfaceEncoder struct{}
    46  
    47  func (t testBarfaceEncoder) Encode(o interface{}, s *Streamer, opts *EncOpts) {
    48  	if s.Error != nil {
    49  		return
    50  	}
    51  	if o == nil {
    52  		s.Null()
    53  		return
    54  	}
    55  	bface, ok := o.(testBarface)
    56  	if !ok {
    57  		panic("should not reach")
    58  	} else {
    59  		b, err := bface.Bar()
    60  		if err != nil {
    61  			s.Error = err
    62  			return
    63  		}
    64  		s.String(b)
    65  	}
    66  }
    67  
    68  func TestValEncoder_Iface_NonPointerReceiver(t *testing.T) {
    69  	cfg := NewEncoderConfig(&EncoderOption{
    70  		IfaceEncoders: []IfaceValEncoderConfig{{
    71  			Type:    reflect.TypeOf((*testBarface)(nil)).Elem(),
    72  			Encoder: testBarfaceEncoder{},
    73  		}},
    74  	})
    75  	t.Run("non pointer", func(t *testing.T) {
    76  		t.Run("no error", func(t *testing.T) {
    77  			m := require.New(t)
    78  			s := strconv.Itoa(rand.Int())
    79  			b, err := cfg.Marshal(testBarfaceImpl{
    80  				s: s,
    81  			})
    82  			m.NoError(err)
    83  			m.Equal(strconv.Quote(s), string(b))
    84  		})
    85  	})
    86  	t.Run("pointer", func(t *testing.T) {
    87  		t.Run("nil", func(t *testing.T) {
    88  			m := require.New(t)
    89  			b, err := cfg.Marshal((*testBarfaceImpl)(nil))
    90  			m.NoError(err)
    91  			m.Equal("null", string(b))
    92  		})
    93  		t.Run("no error", func(t *testing.T) {
    94  			m := require.New(t)
    95  			s := strconv.Itoa(rand.Int())
    96  			b, err := cfg.Marshal(&testBarfaceImpl{
    97  				s: s,
    98  			})
    99  			m.NoError(err)
   100  			m.Equal(strconv.Quote(s), string(b))
   101  		})
   102  	})
   103  	t.Run("pointer of pointer", func(t *testing.T) {
   104  		t.Run("nil", func(t *testing.T) {
   105  			m := require.New(t)
   106  			b, err := cfg.Marshal((**testBarfaceImpl)(nil))
   107  			m.NoError(err)
   108  			m.Equal("null", string(b))
   109  		})
   110  		t.Run("pointer of nil", func(t *testing.T) {
   111  			m := require.New(t)
   112  			ptr := (*testBarfaceImpl)(nil)
   113  			b, err := cfg.Marshal(&ptr)
   114  			m.NoError(err)
   115  			m.Equal("null", string(b))
   116  		})
   117  		t.Run("no error", func(t *testing.T) {
   118  			m := require.New(t)
   119  			s := strconv.Itoa(rand.Int())
   120  			ptr := &testBarfaceImpl{
   121  				s: s,
   122  			}
   123  			b, err := cfg.Marshal(&ptr)
   124  			m.NoError(err)
   125  			m.Equal(strconv.Quote(s), string(b))
   126  		})
   127  		t.Run("error", func(t *testing.T) {
   128  			// TODO
   129  		})
   130  	})
   131  }
   132  
   133  func TestValEncoder_Iface_PointerReceiver(t *testing.T) {
   134  	cfg := NewEncoderConfig(&EncoderOption{
   135  		IfaceEncoders: []IfaceValEncoderConfig{{
   136  			Type:    reflect.TypeOf((*testBarface)(nil)).Elem(),
   137  			Encoder: testBarfaceEncoder{},
   138  		}},
   139  	})
   140  	t.Run("non pointer", func(t *testing.T) {
   141  		t.Run("no error", func(t *testing.T) {
   142  			m := require.New(t)
   143  			b, err := cfg.Marshal(testBarfaceImpl2{})
   144  			m.NoError(err)
   145  			m.Equal("{}", string(b))
   146  		})
   147  	})
   148  	t.Run("pointer", func(t *testing.T) {
   149  		t.Run("nil", func(t *testing.T) {
   150  			m := require.New(t)
   151  			b, err := cfg.Marshal((*testBarfaceImpl2)(nil))
   152  			m.NoError(err)
   153  			m.Equal("null", string(b))
   154  		})
   155  		t.Run("no error", func(t *testing.T) {
   156  			m := require.New(t)
   157  			s := strconv.Itoa(rand.Int())
   158  			b, err := cfg.Marshal(&testBarfaceImpl2{
   159  				s: s,
   160  			})
   161  			m.NoError(err)
   162  			m.Equal(strconv.Quote(s), string(b))
   163  		})
   164  	})
   165  	t.Run("pointer of pointer", func(t *testing.T) {
   166  		t.Run("nil", func(t *testing.T) {
   167  			m := require.New(t)
   168  			b, err := cfg.Marshal((**testBarfaceImpl2)(nil))
   169  			m.NoError(err)
   170  			m.Equal("null", string(b))
   171  		})
   172  		t.Run("pointer of nil", func(t *testing.T) {
   173  			m := require.New(t)
   174  			ptr := (*testBarfaceImpl2)(nil)
   175  			b, err := cfg.Marshal(&ptr)
   176  			m.NoError(err)
   177  			m.Equal("null", string(b))
   178  		})
   179  		t.Run("no error", func(t *testing.T) {
   180  			m := require.New(t)
   181  			s := strconv.Itoa(rand.Int())
   182  			ptr := &testBarfaceImpl2{
   183  				s: s,
   184  			}
   185  			b, err := cfg.Marshal(&ptr)
   186  			m.NoError(err)
   187  			m.Equal(strconv.Quote(s), string(b))
   188  		})
   189  		t.Run("error", func(t *testing.T) {
   190  			// TODO
   191  		})
   192  	})
   193  	t.Run("struct member", func(t *testing.T) {
   194  		t.Run("value", func(t *testing.T) {
   195  			type st struct {
   196  				A testBarfaceImpl2
   197  			}
   198  			t.Run("value", func(t *testing.T) {
   199  				m := require.New(t)
   200  				s := strconv.Itoa(rand.Int())
   201  				b, err := cfg.Marshal(st{
   202  					A: testBarfaceImpl2{
   203  						s: s,
   204  					},
   205  				})
   206  				m.NoError(err)
   207  				m.Equal(`{"A":"`+s+`"}`, string(b))
   208  			})
   209  			t.Run("ptr", func(t *testing.T) {
   210  				m := require.New(t)
   211  				s := strconv.Itoa(rand.Int())
   212  				b, err := cfg.Marshal(&st{
   213  					A: testBarfaceImpl2{
   214  						s: s,
   215  					},
   216  				})
   217  				m.NoError(err)
   218  				m.Equal(`{"A":"`+s+`"}`, string(b))
   219  			})
   220  		})
   221  		t.Run("pointer", func(t *testing.T) {
   222  			type st struct {
   223  				A *testBarfaceImpl2
   224  			}
   225  			t.Run("nil", func(t *testing.T) {
   226  				m := require.New(t)
   227  				b, err := cfg.Marshal(&st{})
   228  				m.NoError(err)
   229  				m.Equal(`{"A":null}`, string(b))
   230  			})
   231  		})
   232  	})
   233  }
   234  
   235  func TestValEncoder_Iface_Dynamic(t *testing.T) {
   236  	cfg := NewEncoderConfig(&EncoderOption{
   237  		IfaceEncoders: []IfaceValEncoderConfig{{
   238  			Type:    reflect.TypeOf((*testBarface)(nil)).Elem(),
   239  			Encoder: testBarfaceEncoder{},
   240  		}},
   241  	})
   242  	t.Run("iface nil", func(t *testing.T) {
   243  		m := require.New(t)
   244  		var i testBarface
   245  		b, err := cfg.Marshal(&i)
   246  		m.NoError(err)
   247  		m.Equal("null", string(b))
   248  	})
   249  	t.Run("iface", func(t *testing.T) {
   250  		m := require.New(t)
   251  		s := strconv.Itoa(rand.Int())
   252  		var i testBarface = testBarfaceImpl{
   253  			s: s,
   254  		}
   255  		b, err := cfg.Marshal(&i)
   256  		m.NoError(err)
   257  		m.Equal(strconv.Quote(s), string(b))
   258  	})
   259  	t.Run("iface 2", func(t *testing.T) {
   260  		m := require.New(t)
   261  		s := strconv.Itoa(rand.Int())
   262  		var i testBarface = &testBarfaceImpl2{
   263  			s: s,
   264  		}
   265  		b, err := cfg.Marshal(&i)
   266  		m.NoError(err)
   267  		m.Equal(strconv.Quote(s), string(b))
   268  	})
   269  }
   270  
   271  type testMapBarface map[int]int
   272  
   273  func (m testMapBarface) Bar() (string, error) {
   274  	s := fmt.Sprintf("%d", len(m))
   275  	return s, nil
   276  }
   277  
   278  func TestValEncoder_Iface_Direct(t *testing.T) {
   279  	cfg := NewEncoderConfig(&EncoderOption{
   280  		IfaceEncoders: []IfaceValEncoderConfig{{
   281  			Type:    reflect.TypeOf((*testBarface)(nil)).Elem(),
   282  			Encoder: testBarfaceEncoder{},
   283  		}},
   284  	})
   285  	t.Run("value", func(t *testing.T) {
   286  		t.Run("nil", func(t *testing.T) {
   287  			m := require.New(t)
   288  			b, err := cfg.Marshal(testMapBarface(nil))
   289  			m.NoError(err)
   290  			m.Equal(`"0"`, string(b))
   291  		})
   292  		t.Run("non nil", func(t *testing.T) {
   293  			m := require.New(t)
   294  			b, err := cfg.Marshal(testMapBarface{
   295  				1: 2,
   296  			})
   297  			m.NoError(err)
   298  			m.Equal(`"1"`, string(b))
   299  		})
   300  	})
   301  	t.Run("pointer", func(t *testing.T) {
   302  		t.Run("nil", func(t *testing.T) {
   303  			m := require.New(t)
   304  			b, err := cfg.Marshal((*testMapBarface)(nil))
   305  			m.NoError(err)
   306  			m.Equal(`null`, string(b))
   307  		})
   308  		t.Run("non nil", func(t *testing.T) {
   309  			m := require.New(t)
   310  			var i testMapBarface
   311  			b, err := cfg.Marshal(&i)
   312  			m.NoError(err)
   313  			m.Equal(`"0"`, string(b))
   314  		})
   315  		t.Run("non nil 2", func(t *testing.T) {
   316  			m := require.New(t)
   317  			b, err := cfg.Marshal(&testMapBarface{
   318  				1: 2,
   319  			})
   320  			m.NoError(err)
   321  			m.Equal(`"1"`, string(b))
   322  		})
   323  	})
   324  	t.Run("struct member", func(t *testing.T) {
   325  		type st struct {
   326  			A testMapBarface
   327  		}
   328  		m := require.New(t)
   329  		b, err := cfg.Marshal(&st{})
   330  		m.NoError(err)
   331  		m.Equal(`{"A":"0"}`, string(b))
   332  	})
   333  	t.Run("value of iface", func(t *testing.T) {
   334  		t.Run("value", func(t *testing.T) {
   335  			var bar testBarface = testMapBarface{
   336  				1: 2,
   337  			}
   338  			m := require.New(t)
   339  			b, err := cfg.Marshal(bar)
   340  			m.NoError(err)
   341  			m.Equal(`"1"`, string(b))
   342  		})
   343  		t.Run("pointer", func(t *testing.T) {
   344  			var bar testBarface = &testMapBarface{
   345  				1: 2,
   346  			}
   347  			m := require.New(t)
   348  			b, err := cfg.Marshal(bar)
   349  			m.NoError(err)
   350  			m.Equal(`"1"`, string(b))
   351  		})
   352  	})
   353  	t.Run("pointer of iface", func(t *testing.T) {
   354  		t.Run("nil", func(t *testing.T) {
   355  			var bar testBarface
   356  			m := require.New(t)
   357  			b, err := cfg.Marshal(&bar)
   358  			m.NoError(err)
   359  			m.Equal(`null`, string(b))
   360  		})
   361  		t.Run("value", func(t *testing.T) {
   362  			var bar testBarface = testMapBarface{
   363  				1: 2,
   364  			}
   365  			m := require.New(t)
   366  			b, err := cfg.Marshal(&bar)
   367  			m.NoError(err)
   368  			m.Equal(`"1"`, string(b))
   369  		})
   370  		t.Run("pointer", func(t *testing.T) {
   371  			var bar testBarface = &testMapBarface{
   372  				1: 2,
   373  			}
   374  			m := require.New(t)
   375  			b, err := cfg.Marshal(&bar)
   376  			m.NoError(err)
   377  			m.Equal(`"1"`, string(b))
   378  		})
   379  	})
   380  }
   381  
   382  func TestValEncoder_Iface_OmitEmpty(t *testing.T) {
   383  	cfg := NewEncoderConfig(&EncoderOption{
   384  		IfaceEncoders: []IfaceValEncoderConfig{{
   385  			Type:    reflect.TypeOf((*testBarface)(nil)).Elem(),
   386  			Encoder: testBarfaceEncoder{},
   387  		}},
   388  	})
   389  	t.Run("", func(t *testing.T) {
   390  		type st struct {
   391  			A testBarfaceImpl `json:",omitempty"`
   392  		}
   393  		m := require.New(t)
   394  		s := strconv.Itoa(rand.Int())
   395  		b, err := cfg.Marshal(st{
   396  			A: testBarfaceImpl{
   397  				s: s,
   398  			},
   399  		})
   400  		m.NoError(err)
   401  		m.Equal(`{"A":"`+s+`"}`, string(b))
   402  	})
   403  }