github.com/wangyougui/gf/v2@v2.6.5/util/gconv/gconv_z_unit_converter_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"encoding/json"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/wangyougui/gf/v2/os/gtime"
    15  	"github.com/wangyougui/gf/v2/test/gtest"
    16  	"github.com/wangyougui/gf/v2/util/gconv"
    17  )
    18  
    19  func TestConverter_ConvertWithRefer(t *testing.T) {
    20  	type tA struct {
    21  		Val int
    22  	}
    23  
    24  	type tB struct {
    25  		Val1 int32
    26  		Val2 string
    27  	}
    28  
    29  	gtest.C(t, func(t *gtest.T) {
    30  		err := gconv.RegisterConverter(func(a tA) (b *tB, err error) {
    31  			b = &tB{
    32  				Val1: int32(a.Val),
    33  				Val2: "abcd",
    34  			}
    35  			return
    36  		})
    37  		t.AssertNil(err)
    38  	})
    39  
    40  	gtest.C(t, func(t *gtest.T) {
    41  		a := &tA{
    42  			Val: 1,
    43  		}
    44  		var b tB
    45  		result := gconv.ConvertWithRefer(a, &b)
    46  		t.Assert(result.(*tB), &tB{
    47  			Val1: 1,
    48  			Val2: "abcd",
    49  		})
    50  	})
    51  
    52  	gtest.C(t, func(t *gtest.T) {
    53  		a := &tA{
    54  			Val: 1,
    55  		}
    56  		var b tB
    57  		result := gconv.ConvertWithRefer(a, b)
    58  		t.Assert(result.(tB), tB{
    59  			Val1: 1,
    60  			Val2: "abcd",
    61  		})
    62  	})
    63  }
    64  
    65  func TestConverter_Struct(t *testing.T) {
    66  	type tA struct {
    67  		Val int
    68  	}
    69  
    70  	type tB struct {
    71  		Val1 int32
    72  		Val2 string
    73  	}
    74  
    75  	type tAA struct {
    76  		ValTop int
    77  		ValTA  tA
    78  	}
    79  
    80  	type tBB struct {
    81  		ValTop int32
    82  		ValTB  tB
    83  	}
    84  
    85  	type tCC struct {
    86  		ValTop string
    87  		ValTa  *tB
    88  	}
    89  
    90  	type tDD struct {
    91  		ValTop string
    92  		ValTa  tB
    93  	}
    94  
    95  	type tEE struct {
    96  		Val1 time.Time  `json:"val1"`
    97  		Val2 *time.Time `json:"val2"`
    98  		Val3 *time.Time `json:"val3"`
    99  	}
   100  
   101  	type tFF struct {
   102  		Val1 json.RawMessage            `json:"val1"`
   103  		Val2 []json.RawMessage          `json:"val2"`
   104  		Val3 map[string]json.RawMessage `json:"val3"`
   105  	}
   106  
   107  	gtest.C(t, func(t *gtest.T) {
   108  		a := &tA{
   109  			Val: 1,
   110  		}
   111  		var b *tB
   112  		err := gconv.Scan(a, &b)
   113  		t.AssertNil(err)
   114  		t.AssertNE(b, nil)
   115  		t.Assert(b.Val1, 0)
   116  		t.Assert(b.Val2, "")
   117  	})
   118  
   119  	gtest.C(t, func(t *gtest.T) {
   120  		err := gconv.RegisterConverter(func(a tA) (b *tB, err error) {
   121  			b = &tB{
   122  				Val1: int32(a.Val),
   123  				Val2: "abc",
   124  			}
   125  			return
   126  		})
   127  		t.AssertNil(err)
   128  	})
   129  
   130  	gtest.C(t, func(t *gtest.T) {
   131  		a := &tA{
   132  			Val: 1,
   133  		}
   134  		var b *tB
   135  		err := gconv.Scan(a, &b)
   136  		t.AssertNil(err)
   137  		t.AssertNE(b, nil)
   138  		t.Assert(b.Val1, 1)
   139  		t.Assert(b.Val2, "abc")
   140  	})
   141  
   142  	gtest.C(t, func(t *gtest.T) {
   143  		a := &tA{
   144  			Val: 1,
   145  		}
   146  		var b *tB
   147  		err := gconv.Scan(a, &b)
   148  		t.AssertNil(err)
   149  		t.AssertNE(b, nil)
   150  		t.Assert(b.Val1, 1)
   151  		t.Assert(b.Val2, "abc")
   152  	})
   153  
   154  	gtest.C(t, func(t *gtest.T) {
   155  		a := &tA{
   156  			Val: 1,
   157  		}
   158  		var b *tB
   159  		err := gconv.Scan(a, &b)
   160  		t.AssertNil(err)
   161  		t.AssertNE(b, nil)
   162  		t.Assert(b.Val1, 1)
   163  		t.Assert(b.Val2, "abc")
   164  	})
   165  
   166  	gtest.C(t, func(t *gtest.T) {
   167  		a := &tA{
   168  			Val: 1,
   169  		}
   170  		var b *tB
   171  		err := gconv.Scan(a, &b)
   172  		t.AssertNil(err)
   173  		t.AssertNE(b, nil)
   174  		t.Assert(b.Val1, 1)
   175  		t.Assert(b.Val2, "abc")
   176  	})
   177  
   178  	gtest.C(t, func(t *gtest.T) {
   179  		aa := &tAA{
   180  			ValTop: 123,
   181  			ValTA:  tA{Val: 234},
   182  		}
   183  		var bb *tBB
   184  
   185  		err := gconv.Scan(aa, &bb)
   186  		t.AssertNil(err)
   187  		t.AssertNE(bb, nil)
   188  		t.Assert(bb.ValTop, 123)
   189  		t.AssertNE(bb.ValTB.Val1, 234)
   190  
   191  		err = gconv.RegisterConverter(func(a tAA) (b *tBB, err error) {
   192  			b = &tBB{
   193  				ValTop: int32(a.ValTop) + 2,
   194  			}
   195  			err = gconv.Scan(a.ValTA, &b.ValTB)
   196  			return
   197  		})
   198  		t.AssertNil(err)
   199  
   200  		err = gconv.Scan(aa, &bb)
   201  		t.AssertNil(err)
   202  		t.AssertNE(bb, nil)
   203  		t.Assert(bb.ValTop, 125)
   204  		t.Assert(bb.ValTB.Val1, 234)
   205  		t.Assert(bb.ValTB.Val2, "abc")
   206  
   207  	})
   208  
   209  	gtest.C(t, func(t *gtest.T) {
   210  		aa := &tAA{
   211  			ValTop: 123,
   212  			ValTA:  tA{Val: 234},
   213  		}
   214  		var cc *tCC
   215  		err := gconv.Scan(aa, &cc)
   216  		t.AssertNil(err)
   217  		t.AssertNE(cc, nil)
   218  		t.Assert(cc.ValTop, "123")
   219  		t.AssertNE(cc.ValTa, nil)
   220  		t.Assert(cc.ValTa.Val1, 234)
   221  		t.Assert(cc.ValTa.Val2, "abc")
   222  	})
   223  
   224  	gtest.C(t, func(t *gtest.T) {
   225  		aa := &tAA{
   226  			ValTop: 123,
   227  			ValTA:  tA{Val: 234},
   228  		}
   229  
   230  		var dd *tDD
   231  		err := gconv.Scan(aa, &dd)
   232  		t.AssertNil(err)
   233  		t.AssertNE(dd, nil)
   234  		t.Assert(dd.ValTop, "123")
   235  		t.Assert(dd.ValTa.Val1, 234)
   236  		t.Assert(dd.ValTa.Val2, "abc")
   237  	})
   238  
   239  	// fix: https://github.com/wangyougui/gf/issues/2665
   240  	gtest.C(t, func(t *gtest.T) {
   241  		aa := &tEE{}
   242  
   243  		var tmp = map[string]any{
   244  			"val1": "2023-04-15 19:10:00 +0800 CST",
   245  			"val2": "2023-04-15 19:10:00 +0800 CST",
   246  			"val3": "2006-01-02T15:04:05Z07:00",
   247  		}
   248  		err := gconv.Struct(tmp, aa)
   249  		t.AssertNil(err)
   250  		t.AssertNE(aa, nil)
   251  		t.Assert(aa.Val1.Local(), gtime.New("2023-04-15 19:10:00 +0800 CST").Local().Time)
   252  		t.Assert(aa.Val2.Local(), gtime.New("2023-04-15 19:10:00 +0800 CST").Local().Time)
   253  		t.Assert(aa.Val3.Local(), gtime.New("2006-01-02T15:04:05Z07:00").Local().Time)
   254  	})
   255  
   256  	// fix: https://github.com/wangyougui/gf/issues/3006
   257  	gtest.C(t, func(t *gtest.T) {
   258  		ff := &tFF{}
   259  		var tmp = map[string]any{
   260  			"val1": map[string]any{"hello": "world"},
   261  			"val2": []any{map[string]string{"hello": "world"}},
   262  			"val3": map[string]map[string]string{"val3": {"hello": "world"}},
   263  		}
   264  
   265  		err := gconv.Struct(tmp, ff)
   266  		t.AssertNil(err)
   267  		t.AssertNE(ff, nil)
   268  		t.Assert(ff.Val1, []byte(`{"hello":"world"}`))
   269  		t.AssertEQ(len(ff.Val2), 1)
   270  		t.Assert(ff.Val2[0], []byte(`{"hello":"world"}`))
   271  		t.AssertEQ(len(ff.Val3), 1)
   272  		t.Assert(ff.Val3["val3"], []byte(`{"hello":"world"}`))
   273  	})
   274  }
   275  
   276  func TestConverter_CustomBasicType_ToStruct(t *testing.T) {
   277  	type CustomString string
   278  	type CustomStruct struct {
   279  		S string
   280  	}
   281  	gtest.C(t, func(t *gtest.T) {
   282  		var (
   283  			a CustomString = "abc"
   284  			b *CustomStruct
   285  		)
   286  		err := gconv.Scan(a, &b)
   287  		t.AssertNE(err, nil)
   288  		t.Assert(b, nil)
   289  	})
   290  
   291  	gtest.C(t, func(t *gtest.T) {
   292  		err := gconv.RegisterConverter(func(a CustomString) (b *CustomStruct, err error) {
   293  			b = &CustomStruct{
   294  				S: string(a),
   295  			}
   296  			return
   297  		})
   298  		t.AssertNil(err)
   299  	})
   300  	gtest.C(t, func(t *gtest.T) {
   301  		var (
   302  			a CustomString = "abc"
   303  			b *CustomStruct
   304  		)
   305  		err := gconv.Scan(a, &b)
   306  		t.AssertNil(err)
   307  		t.AssertNE(b, nil)
   308  		t.Assert(b.S, a)
   309  	})
   310  	gtest.C(t, func(t *gtest.T) {
   311  		var (
   312  			a CustomString = "abc"
   313  			b *CustomStruct
   314  		)
   315  		err := gconv.Scan(&a, &b)
   316  		t.AssertNil(err)
   317  		t.AssertNE(b, nil)
   318  		t.Assert(b.S, a)
   319  	})
   320  }
   321  
   322  // fix: https://github.com/wangyougui/gf/issues/3099
   323  func TestConverter_CustomTimeType_ToStruct(t *testing.T) {
   324  	type timestamppb struct {
   325  		S string
   326  	}
   327  	type CustomGTime struct {
   328  		T *gtime.Time
   329  	}
   330  	type CustomPbTime struct {
   331  		T *timestamppb
   332  	}
   333  	gtest.C(t, func(t *gtest.T) {
   334  		var (
   335  			a = CustomGTime{
   336  				T: gtime.NewFromStrFormat("2023-10-26", "Y-m-d"),
   337  			}
   338  			b *CustomPbTime
   339  		)
   340  		err := gconv.Scan(a, &b)
   341  		t.AssertNil(err)
   342  		t.AssertNE(b, nil)
   343  		t.Assert(b.T.S, "")
   344  	})
   345  
   346  	gtest.C(t, func(t *gtest.T) {
   347  		err := gconv.RegisterConverter(func(in gtime.Time) (*timestamppb, error) {
   348  			return &timestamppb{
   349  				S: in.Local().Format("Y-m-d"),
   350  			}, nil
   351  		})
   352  		t.AssertNil(err)
   353  		err = gconv.RegisterConverter(func(in timestamppb) (*gtime.Time, error) {
   354  			return gtime.NewFromStr(in.S), nil
   355  		})
   356  		t.AssertNil(err)
   357  	})
   358  	gtest.C(t, func(t *gtest.T) {
   359  		var (
   360  			a = CustomGTime{
   361  				T: gtime.NewFromStrFormat("2023-10-26", "Y-m-d"),
   362  			}
   363  			b *CustomPbTime
   364  			c *CustomGTime
   365  		)
   366  		err := gconv.Scan(a, &b)
   367  		t.AssertNil(err)
   368  		t.AssertNE(b, nil)
   369  		t.AssertNE(b.T, nil)
   370  
   371  		err = gconv.Scan(b, &c)
   372  		t.AssertNil(err)
   373  		t.AssertNE(c, nil)
   374  		t.AssertNE(c.T, nil)
   375  		t.AssertEQ(a.T.Timestamp(), c.T.Timestamp())
   376  	})
   377  }