github.com/vugu/vugu@v0.3.5/mod-check_test.go (about) 1 package vugu 2 3 import ( 4 "encoding/json" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 func TestModCheckerWidget(t *testing.T) { 11 12 // try a more complex but realistic example 13 14 assert := assert.New(t) 15 mt := NewModTracker() 16 17 type Tag struct { 18 Name string `vugu:"data" json:"name"` 19 Style int `vugu:"data" json:"style"` 20 } 21 22 type Widget struct { 23 ID int64 `vugu:"data" json:"id"` 24 Name string `vugu:"data" json:"name"` 25 Description *string `vugu:"data" json:"description"` 26 Active bool `vugu:"data" json:"active"` 27 StockCount *int32 `vugu:"data" json:"stock_count"` 28 Tags []Tag `vugu:"data" json:"tags"` 29 FeaturedTags []*Tag `vugu:"data" json:"-"` // calculated separately after loading 30 } 31 32 wjson := ` 33 [ 34 { 35 "id": 100, 36 "name": "Widgetron", 37 "description": "This one is electronical", 38 "active": true, 39 "stock_count": 42, 40 "tags": [{"name":"Electronical","style":314159},{"name":"Whatever","style":1}] 41 }, 42 { 43 "id": 101, 44 "name": "Widgetcron", 45 "description": "This one is chronical", 46 "active": true, 47 "stock_count": 2400, 48 "tags": [{"name":"Something","style":2400},{"name":"Whatever","style":1}] 49 }, 50 { 51 "id": 102, 52 "name": "Widgetevil", 53 "description": "This one is diabolical", 54 "active": false, 55 "stock_count": 13, 56 "tags": [{"name":"Something","style":666}] 57 } 58 ] 59 ` 60 61 var wlist []Widget 62 assert.NoError(json.Unmarshal([]byte(wjson), &wlist)) 63 64 // log.Printf("wlist: %#v", wlist) 65 66 mt.TrackNext() 67 assert.True(mt.ModCheckAll(&wlist)) 68 assert.True(mt.ModCheckAll(&wlist)) 69 70 mt.TrackNext() 71 assert.False(mt.ModCheckAll(&wlist)) 72 73 // change the sequence 74 mt.TrackNext() 75 wlist[0], wlist[1] = wlist[1], wlist[0] 76 assert.True(mt.ModCheckAll(&wlist)) 77 78 mt.TrackNext() 79 assert.False(mt.ModCheckAll(&wlist)) 80 81 // change a field value 82 mt.TrackNext() 83 wlist[0].Name = "Widgetcroninator" 84 assert.True(mt.ModCheckAll(&wlist)) 85 86 mt.TrackNext() 87 assert.False(mt.ModCheckAll(&wlist)) 88 89 // change a pointer field 90 mt.TrackNext() 91 newStockCount := int32(2401) 92 wlist[0].StockCount = &newStockCount 93 assert.True(mt.ModCheckAll(&wlist)) 94 95 mt.TrackNext() 96 assert.False(mt.ModCheckAll(&wlist)) 97 98 // log.Printf("dumpA: %s", mt.dump()) 99 100 // change the value pointed to by a field 101 mt.TrackNext() 102 *wlist[0].StockCount = 2402 103 assert.True(mt.ModCheckAll(&wlist)) 104 105 // log.Printf("dumpB: %s", mt.dump()) 106 107 mt.TrackNext() 108 assert.False(mt.ModCheckAll(&wlist)) 109 110 // set pointer field to nil 111 mt.TrackNext() 112 wlist[0].StockCount = nil 113 assert.True(mt.ModCheckAll(&wlist)) 114 115 mt.TrackNext() 116 assert.False(mt.ModCheckAll(&wlist)) 117 118 // log.Printf("dump: %s", mt.dump()) 119 120 // now try it with a slice of struct pointers 121 var wplist []*Widget 122 assert.NoError(json.Unmarshal([]byte(wjson), &wplist)) 123 124 mt.TrackNext() 125 assert.True(mt.ModCheckAll(&wplist)) 126 assert.True(mt.ModCheckAll(&wplist)) 127 128 mt.TrackNext() 129 assert.False(mt.ModCheckAll(&wplist)) 130 131 // change the sequence 132 mt.TrackNext() 133 wplist[0], wplist[1] = wplist[1], wplist[0] 134 assert.True(mt.ModCheckAll(&wplist)) 135 136 mt.TrackNext() 137 assert.False(mt.ModCheckAll(&wplist)) 138 139 // change a field value 140 mt.TrackNext() 141 wplist[0].Name = "Widgetcroninator" 142 assert.True(mt.ModCheckAll(&wplist)) 143 144 mt.TrackNext() 145 assert.False(mt.ModCheckAll(&wplist)) 146 147 // change a pointer field 148 mt.TrackNext() 149 newStockCount = int32(2401) 150 wplist[0].StockCount = &newStockCount 151 assert.True(mt.ModCheckAll(&wplist)) 152 153 mt.TrackNext() 154 assert.False(mt.ModCheckAll(&wplist)) 155 156 // log.Printf("dumpA: %s", mt.dump()) 157 158 // change the value pointed to by a field 159 mt.TrackNext() 160 *wplist[0].StockCount = 2402 161 assert.True(mt.ModCheckAll(&wplist)) 162 163 // log.Printf("dumpB: %s", mt.dump()) 164 165 mt.TrackNext() 166 assert.False(mt.ModCheckAll(&wplist)) 167 168 // set pointer field to nil 169 mt.TrackNext() 170 wplist[0].StockCount = nil 171 assert.True(mt.ModCheckAll(&wplist)) 172 173 mt.TrackNext() 174 assert.False(mt.ModCheckAll(&wplist)) 175 176 // set one of the struct elements to nil 177 mt.TrackNext() 178 wplist[0] = nil 179 assert.True(mt.ModCheckAll(&wplist)) 180 181 mt.TrackNext() 182 assert.False(mt.ModCheckAll(&wplist)) 183 184 } 185 186 func TestModCheckerStruct(t *testing.T) { 187 assert := assert.New(t) 188 mt := NewModTracker() 189 190 var s1 struct { 191 F1 string `vugu:"data"` 192 F2 int `vugu:"data"` 193 F3 float64 // not tagged 194 } 195 196 mt.TrackNext() 197 assert.True(mt.ModCheckAll(&s1)) 198 199 mt.TrackNext() 200 assert.False(mt.ModCheckAll(&s1)) 201 202 mt.TrackNext() 203 s1.F1 = "test1" 204 assert.True(mt.ModCheckAll(&s1)) 205 206 mt.TrackNext() 207 s1.F2 = 1 208 assert.True(mt.ModCheckAll(&s1)) 209 210 mt.TrackNext() 211 s1.F3 = 1.0 // field not tagged, should not cause modification 212 assert.False(mt.ModCheckAll(&s1)) 213 214 } 215 216 func TestModCheckerSliceArray(t *testing.T) { 217 218 assert := assert.New(t) 219 mt := NewModTracker() 220 221 var a1 [3]string 222 a1[0] = "s1" 223 a1[1] = "s2" 224 a1[2] = "s3" 225 226 assert.True(mt.ModCheckAll(&a1)) 227 228 // log.Printf("state1: \n%s", mt.dump()) 229 230 mt.TrackNext() 231 232 // log.Printf("state2: \n%s", mt.dump()) 233 234 assert.False(mt.ModCheckAll(&a1)) 235 236 // log.Printf("state3: \n%s", mt.dump()) 237 238 var s1 []string 239 s1 = a1[:] 240 241 mt.TrackNext() 242 assert.True(mt.ModCheckAll(&s1)) 243 244 mt.TrackNext() 245 assert.False(mt.ModCheckAll(&s1)) 246 247 mt.TrackNext() 248 s1 = a1[:2] 249 assert.True(mt.ModCheckAll(&s1)) 250 251 // swap two elements 252 mt.TrackNext() 253 s1[0], s1[1] = s1[1], s1[0] 254 assert.True(mt.ModCheckAll(&s1)) 255 256 mt.TrackNext() 257 assert.False(mt.ModCheckAll(&s1)) 258 259 } 260 261 func TestModCheckerStrings(t *testing.T) { 262 263 assert := assert.New(t) 264 265 var mt ModTracker 266 267 mt.TrackNext() 268 s := "testing" // initial value 269 assert.True(mt.ModCheckAll(&s)) 270 271 mt.TrackNext() 272 // no change 273 assert.False(mt.ModCheckAll(&s)) 274 275 mt.TrackNext() 276 s = "testing2" // different value 277 assert.True(mt.ModCheckAll(&s)) 278 279 mt.TrackNext() 280 s = "testing" // back to earlier value 281 assert.True(mt.ModCheckAll(&s)) 282 283 mt.TrackNext() 284 s = "testing" // same value 285 assert.False(mt.ModCheckAll(&s)) 286 287 // run through it again with a byte slice 288 289 mt.TrackNext() 290 b := []byte("testing") // initial value 291 assert.True(mt.ModCheckAll(&b)) 292 293 mt.TrackNext() 294 // no change 295 assert.False(mt.ModCheckAll(&b)) 296 297 mt.TrackNext() 298 b = []byte("testing2") // different value 299 assert.True(mt.ModCheckAll(&b)) 300 301 mt.TrackNext() 302 b = []byte("testing") // back to earlier value 303 assert.True(mt.ModCheckAll(&b)) 304 305 mt.TrackNext() 306 b = []byte("testing") // same value 307 assert.False(mt.ModCheckAll(&b)) 308 309 // check both 310 mt.TrackNext() 311 312 mt.TrackNext() 313 b = []byte("testing") 314 assert.True(mt.ModCheckAll(&b)) 315 s = "testing" 316 assert.True(mt.ModCheckAll(&s)) 317 318 mt.TrackNext() 319 b = []byte("testing") 320 assert.False(mt.ModCheckAll(&b)) 321 s = "testing" 322 assert.False(mt.ModCheckAll(&s)) 323 324 } 325 326 func TestModCheckerBool(t *testing.T) { 327 328 mt := NewModTracker() 329 330 var v1, v2 bool 331 check := func(vp *bool, newv bool, expectedMod bool) { 332 mt.TrackNext() 333 *vp = newv 334 mod := mt.ModCheckAll(vp) 335 if mod != expectedMod { 336 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 337 } 338 } 339 340 check(&v1, false, true) 341 check(&v1, false, false) 342 check(&v1, true, true) 343 check(&v1, true, false) 344 check(&v1, false, true) 345 check(&v1, false, false) 346 check(&v1, false, false) 347 check(&v2, false, true) 348 check(&v2, true, true) 349 check(&v2, false, true) 350 check(&v2, false, false) 351 352 } 353 354 func TestModCheckerInt(t *testing.T) { 355 356 mt := NewModTracker() 357 358 var v1, v2 int 359 check := func(vp *int, newv int, expectedMod bool) { 360 mt.TrackNext() 361 *vp = newv 362 mod := mt.ModCheckAll(vp) 363 if mod != expectedMod { 364 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 365 } 366 } 367 368 check(&v1, 1, true) 369 check(&v1, 1, false) 370 check(&v1, 2, true) 371 check(&v1, 2, false) 372 check(&v1, 1, true) 373 check(&v1, 1, false) 374 check(&v1, 1, false) 375 check(&v2, 1, true) 376 check(&v2, 2, true) 377 check(&v2, 1, true) 378 check(&v2, 1, false) 379 380 } 381 382 func TestModCheckerInt8(t *testing.T) { 383 384 mt := NewModTracker() 385 386 var v1, v2 int8 387 check := func(vp *int8, newv int8, expectedMod bool) { 388 mt.TrackNext() 389 *vp = newv 390 mod := mt.ModCheckAll(vp) 391 if mod != expectedMod { 392 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 393 } 394 } 395 396 check(&v1, 1, true) 397 check(&v1, 1, false) 398 check(&v1, 2, true) 399 check(&v1, 2, false) 400 check(&v1, 1, true) 401 check(&v1, 1, false) 402 check(&v1, 1, false) 403 check(&v2, 1, true) 404 check(&v2, 2, true) 405 check(&v2, 1, true) 406 check(&v2, 1, false) 407 408 } 409 410 func TestModCheckerInt16(t *testing.T) { 411 412 mt := NewModTracker() 413 414 var v1, v2 int16 415 check := func(vp *int16, newv int16, expectedMod bool) { 416 mt.TrackNext() 417 *vp = newv 418 mod := mt.ModCheckAll(vp) 419 if mod != expectedMod { 420 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 421 } 422 } 423 424 check(&v1, 1, true) 425 check(&v1, 1, false) 426 check(&v1, 2, true) 427 check(&v1, 2, false) 428 check(&v1, 1, true) 429 check(&v1, 1, false) 430 check(&v1, 1, false) 431 check(&v2, 1, true) 432 check(&v2, 2, true) 433 check(&v2, 1, true) 434 check(&v2, 1, false) 435 436 } 437 438 func TestModCheckerInt32(t *testing.T) { 439 440 mt := NewModTracker() 441 442 var v1, v2 int32 443 check := func(vp *int32, newv int32, expectedMod bool) { 444 mt.TrackNext() 445 *vp = newv 446 mod := mt.ModCheckAll(vp) 447 if mod != expectedMod { 448 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 449 } 450 } 451 452 check(&v1, 1, true) 453 check(&v1, 1, false) 454 check(&v1, 2, true) 455 check(&v1, 2, false) 456 check(&v1, 1, true) 457 check(&v1, 1, false) 458 check(&v1, 1, false) 459 check(&v2, 1, true) 460 check(&v2, 2, true) 461 check(&v2, 1, true) 462 check(&v2, 1, false) 463 464 } 465 466 func TestModCheckerInt64(t *testing.T) { 467 468 mt := NewModTracker() 469 470 var v1, v2 int64 471 check := func(vp *int64, newv int64, expectedMod bool) { 472 mt.TrackNext() 473 *vp = newv 474 mod := mt.ModCheckAll(vp) 475 if mod != expectedMod { 476 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 477 } 478 } 479 480 check(&v1, 1, true) 481 check(&v1, 1, false) 482 check(&v1, 2, true) 483 check(&v1, 2, false) 484 check(&v1, 1, true) 485 check(&v1, 1, false) 486 check(&v1, 1, false) 487 check(&v2, 1, true) 488 check(&v2, 2, true) 489 check(&v2, 1, true) 490 check(&v2, 1, false) 491 492 } 493 494 func TestModCheckerUint(t *testing.T) { 495 496 mt := NewModTracker() 497 498 var v1, v2 uint 499 check := func(vp *uint, newv uint, expectedMod bool) { 500 mt.TrackNext() 501 *vp = newv 502 mod := mt.ModCheckAll(vp) 503 if mod != expectedMod { 504 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 505 } 506 } 507 508 check(&v1, 1, true) 509 check(&v1, 1, false) 510 check(&v1, 2, true) 511 check(&v1, 2, false) 512 check(&v1, 1, true) 513 check(&v1, 1, false) 514 check(&v1, 1, false) 515 check(&v2, 1, true) 516 check(&v2, 2, true) 517 check(&v2, 1, true) 518 check(&v2, 1, false) 519 520 } 521 522 func TestModCheckerUint8(t *testing.T) { 523 524 mt := NewModTracker() 525 526 var v1, v2 uint8 527 check := func(vp *uint8, newv uint8, expectedMod bool) { 528 mt.TrackNext() 529 *vp = newv 530 mod := mt.ModCheckAll(vp) 531 if mod != expectedMod { 532 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 533 } 534 } 535 536 check(&v1, 1, true) 537 check(&v1, 1, false) 538 check(&v1, 2, true) 539 check(&v1, 2, false) 540 check(&v1, 1, true) 541 check(&v1, 1, false) 542 check(&v1, 1, false) 543 check(&v2, 1, true) 544 check(&v2, 2, true) 545 check(&v2, 1, true) 546 check(&v2, 1, false) 547 548 } 549 550 func TestModCheckerUint16(t *testing.T) { 551 552 mt := NewModTracker() 553 554 var v1, v2 uint16 555 check := func(vp *uint16, newv uint16, expectedMod bool) { 556 mt.TrackNext() 557 *vp = newv 558 mod := mt.ModCheckAll(vp) 559 if mod != expectedMod { 560 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 561 } 562 } 563 564 check(&v1, 1, true) 565 check(&v1, 1, false) 566 check(&v1, 2, true) 567 check(&v1, 2, false) 568 check(&v1, 1, true) 569 check(&v1, 1, false) 570 check(&v1, 1, false) 571 check(&v2, 1, true) 572 check(&v2, 2, true) 573 check(&v2, 1, true) 574 check(&v2, 1, false) 575 576 } 577 578 func TestModCheckerUint32(t *testing.T) { 579 580 mt := NewModTracker() 581 582 var v1, v2 uint32 583 check := func(vp *uint32, newv uint32, expectedMod bool) { 584 mt.TrackNext() 585 *vp = newv 586 mod := mt.ModCheckAll(vp) 587 if mod != expectedMod { 588 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 589 } 590 } 591 592 check(&v1, 1, true) 593 check(&v1, 1, false) 594 check(&v1, 2, true) 595 check(&v1, 2, false) 596 check(&v1, 1, true) 597 check(&v1, 1, false) 598 check(&v1, 1, false) 599 check(&v2, 1, true) 600 check(&v2, 2, true) 601 check(&v2, 1, true) 602 check(&v2, 1, false) 603 604 } 605 606 func TestModCheckerUint64(t *testing.T) { 607 608 mt := NewModTracker() 609 610 var v1, v2 uint64 611 check := func(vp *uint64, newv uint64, expectedMod bool) { 612 mt.TrackNext() 613 *vp = newv 614 mod := mt.ModCheckAll(vp) 615 if mod != expectedMod { 616 t.Errorf("check(%#v, %#v, %#v) wrong mod result: %v", vp, newv, expectedMod, mod) 617 } 618 } 619 620 check(&v1, 1, true) 621 check(&v1, 1, false) 622 check(&v1, 2, true) 623 check(&v1, 2, false) 624 check(&v1, 1, true) 625 check(&v1, 1, false) 626 check(&v1, 1, false) 627 check(&v2, 1, true) 628 check(&v2, 2, true) 629 check(&v2, 1, true) 630 check(&v2, 1, false) 631 632 }