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 ×tamppb{ 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 }