github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/swarm/storage/feed/lookup/lookup_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package lookup_test 18 19 import ( 20 "context" 21 "fmt" 22 "math/rand" 23 "testing" 24 25 "github.com/ethereum/go-ethereum/swarm/log" 26 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 27 ) 28 29 type Data struct { 30 Payload uint64 31 Time uint64 32 } 33 34 type Store map[lookup.EpochID]*Data 35 36 func write(store Store, epoch lookup.Epoch, value *Data) { 37 log.Debug("Write: %d-%d, value='%d'\n", epoch.Base(), epoch.Level, value.Payload) 38 store[epoch.ID()] = value 39 } 40 41 func update(store Store, last lookup.Epoch, now uint64, value *Data) lookup.Epoch { 42 epoch := lookup.GetNextEpoch(last, now) 43 44 write(store, epoch, value) 45 46 return epoch 47 } 48 49 const Day = 60 * 60 * 24 50 const Year = Day * 365 51 const Month = Day * 30 52 53 func makeReadFunc(store Store, counter *int) lookup.ReadFunc { 54 return func(ctx context.Context, epoch lookup.Epoch, now uint64) (interface{}, error) { 55 *counter++ 56 data := store[epoch.ID()] 57 var valueStr string 58 if data != nil { 59 valueStr = fmt.Sprintf("%d", data.Payload) 60 } 61 log.Debug("Read: %d-%d, value='%s'\n", epoch.Base(), epoch.Level, valueStr) 62 if data != nil && data.Time <= now { 63 return data, nil 64 } 65 return nil, nil 66 } 67 } 68 69 func TestLookup(t *testing.T) { 70 71 store := make(Store) 72 readCount := 0 73 readFunc := makeReadFunc(store, &readCount) 74 75 // write an update every month for 12 months 3 years ago and then silence for two years 76 now := uint64(1533799046) 77 var epoch lookup.Epoch 78 79 var lastData *Data 80 for i := uint64(0); i < 12; i++ { 81 t := uint64(now - Year*3 + i*Month) 82 data := Data{ 83 Payload: t, //our "payload" will be the timestamp itself. 84 Time: t, 85 } 86 epoch = update(store, epoch, t, &data) 87 lastData = &data 88 } 89 90 // try to get the last value 91 92 value, err := lookup.Lookup(context.Background(), now, lookup.NoClue, readFunc) 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 readCountWithoutHint := readCount 98 99 if value != lastData { 100 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 101 } 102 103 // reset the read count for the next test 104 readCount = 0 105 // Provide a hint to get a faster lookup. In particular, we give the exact location of the last update 106 value, err = lookup.Lookup(context.Background(), now, epoch, readFunc) 107 if err != nil { 108 t.Fatal(err) 109 } 110 111 if value != lastData { 112 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 113 } 114 115 if readCount > readCountWithoutHint { 116 t.Fatalf("Expected lookup to complete with fewer or same reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 117 } 118 119 // try to get an intermediate value 120 // if we look for a value in now - Year*3 + 6*Month, we should get that value 121 // Since the "payload" is the timestamp itself, we can check this. 122 123 expectedTime := now - Year*3 + 6*Month 124 125 value, err = lookup.Lookup(context.Background(), expectedTime, lookup.NoClue, readFunc) 126 if err != nil { 127 t.Fatal(err) 128 } 129 130 data, ok := value.(*Data) 131 132 if !ok { 133 t.Fatal("Expected value to contain data") 134 } 135 136 if data.Time != expectedTime { 137 t.Fatalf("Expected value timestamp to be %d, got %d", data.Time, expectedTime) 138 } 139 140 } 141 142 func TestOneUpdateAt0(t *testing.T) { 143 144 store := make(Store) 145 readCount := 0 146 147 readFunc := makeReadFunc(store, &readCount) 148 now := uint64(1533903729) 149 150 var epoch lookup.Epoch 151 data := Data{ 152 Payload: 79, 153 Time: 0, 154 } 155 update(store, epoch, 0, &data) 156 157 value, err := lookup.Lookup(context.Background(), now, lookup.NoClue, readFunc) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if value != &data { 162 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", data, value) 163 } 164 } 165 166 // Tests the update is found even when a bad hint is given 167 func TestBadHint(t *testing.T) { 168 169 store := make(Store) 170 readCount := 0 171 172 readFunc := makeReadFunc(store, &readCount) 173 now := uint64(1533903729) 174 175 var epoch lookup.Epoch 176 data := Data{ 177 Payload: 79, 178 Time: 0, 179 } 180 181 // place an update for t=1200 182 update(store, epoch, 1200, &data) 183 184 // come up with some evil hint 185 badHint := lookup.Epoch{ 186 Level: 18, 187 Time: 1200000000, 188 } 189 190 value, err := lookup.Lookup(context.Background(), now, badHint, readFunc) 191 if err != nil { 192 t.Fatal(err) 193 } 194 if value != &data { 195 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", data, value) 196 } 197 } 198 199 // Tests whether the update is found when the bad hint is exactly below the last update 200 func TestBadHintNextToUpdate(t *testing.T) { 201 store := make(Store) 202 readCount := 0 203 204 readFunc := makeReadFunc(store, &readCount) 205 now := uint64(1533903729) 206 var last *Data 207 208 /* the following loop places updates in the following epochs: 209 Update# Time Base Level 210 0 1200000000 1174405120 25 211 1 1200000001 1191182336 24 212 2 1200000002 1199570944 23 213 3 1200000003 1199570944 22 214 4 1200000004 1199570944 21 215 216 The situation we want to trigger is to give a bad hint exactly 217 in T=1200000005, B=1199570944 and L=20, which is where the next 218 update would have logically been. 219 This affects only when the bad hint's base == previous update's base, 220 in this case 1199570944 221 222 */ 223 var epoch lookup.Epoch 224 for i := uint64(0); i < 5; i++ { 225 data := Data{ 226 Payload: i, 227 Time: 0, 228 } 229 last = &data 230 epoch = update(store, epoch, 1200000000+i, &data) 231 } 232 233 // come up with some evil hint: 234 // put it where the next update would have been 235 badHint := lookup.Epoch{ 236 Level: 20, 237 Time: 1200000005, 238 } 239 240 value, err := lookup.Lookup(context.Background(), now, badHint, readFunc) 241 if err != nil { 242 t.Fatal(err) 243 } 244 if value != last { 245 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", last, value) 246 } 247 } 248 249 func TestContextCancellation(t *testing.T) { 250 251 readFunc := func(ctx context.Context, epoch lookup.Epoch, now uint64) (interface{}, error) { 252 <-ctx.Done() 253 return nil, ctx.Err() 254 } 255 256 ctx, cancel := context.WithCancel(context.Background()) 257 258 errc := make(chan error) 259 260 go func() { 261 _, err := lookup.Lookup(ctx, 1200000000, lookup.NoClue, readFunc) 262 errc <- err 263 }() 264 265 cancel() 266 267 if err := <-errc; err != context.Canceled { 268 t.Fatalf("Expected lookup to return a context Cancelled error, got %v", err) 269 } 270 271 // text context cancellation during hint lookup: 272 ctx, cancel = context.WithCancel(context.Background()) 273 errc = make(chan error) 274 someHint := lookup.Epoch{ 275 Level: 25, 276 Time: 300, 277 } 278 279 readFunc = func(ctx context.Context, epoch lookup.Epoch, now uint64) (interface{}, error) { 280 if epoch == someHint { 281 go cancel() 282 <-ctx.Done() 283 return nil, ctx.Err() 284 } 285 return nil, nil 286 } 287 288 go func() { 289 _, err := lookup.Lookup(ctx, 301, someHint, readFunc) 290 errc <- err 291 }() 292 293 if err := <-errc; err != context.Canceled { 294 t.Fatalf("Expected lookup to return a context Cancelled error, got %v", err) 295 } 296 297 } 298 299 func TestLookupFail(t *testing.T) { 300 301 store := make(Store) 302 readCount := 0 303 304 readFunc := makeReadFunc(store, &readCount) 305 now := uint64(1533903729) 306 307 // don't write anything and try to look up. 308 // we're testing we don't get stuck in a loop 309 310 value, err := lookup.Lookup(context.Background(), now, lookup.NoClue, readFunc) 311 if err != nil { 312 t.Fatal(err) 313 } 314 if value != nil { 315 t.Fatal("Expected value to be nil, since the update should've failed") 316 } 317 318 expectedReads := now/(1<<lookup.HighestLevel) + 1 319 if uint64(readCount) != expectedReads { 320 t.Fatalf("Expected lookup to fail after %d reads. Did %d reads.", expectedReads, readCount) 321 } 322 } 323 324 func TestHighFreqUpdates(t *testing.T) { 325 326 store := make(Store) 327 readCount := 0 328 329 readFunc := makeReadFunc(store, &readCount) 330 now := uint64(1533903729) 331 332 // write an update every second for the last 1000 seconds 333 var epoch lookup.Epoch 334 335 var lastData *Data 336 for i := uint64(0); i <= 994; i++ { 337 T := uint64(now - 1000 + i) 338 data := Data{ 339 Payload: T, //our "payload" will be the timestamp itself. 340 Time: T, 341 } 342 epoch = update(store, epoch, T, &data) 343 lastData = &data 344 } 345 346 value, err := lookup.Lookup(context.Background(), lastData.Time, lookup.NoClue, readFunc) 347 if err != nil { 348 t.Fatal(err) 349 } 350 351 if value != lastData { 352 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 353 } 354 355 readCountWithoutHint := readCount 356 // reset the read count for the next test 357 readCount = 0 358 // Provide a hint to get a faster lookup. In particular, we give the exact location of the last update 359 value, err = lookup.Lookup(context.Background(), now, epoch, readFunc) 360 if err != nil { 361 t.Fatal(err) 362 } 363 364 if value != lastData { 365 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 366 } 367 368 if readCount > readCountWithoutHint { 369 t.Fatalf("Expected lookup to complete with fewer or equal reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 370 } 371 372 for i := uint64(0); i <= 994; i++ { 373 T := uint64(now - 1000 + i) // update every second for the last 1000 seconds 374 value, err := lookup.Lookup(context.Background(), T, lookup.NoClue, readFunc) 375 if err != nil { 376 t.Fatal(err) 377 } 378 data, _ := value.(*Data) 379 if data == nil { 380 t.Fatalf("Expected lookup to return %d, got nil", T) 381 } 382 if data.Payload != T { 383 t.Fatalf("Expected lookup to return %d, got %d", T, data.Time) 384 } 385 } 386 } 387 388 func TestSparseUpdates(t *testing.T) { 389 390 store := make(Store) 391 readCount := 0 392 readFunc := makeReadFunc(store, &readCount) 393 394 // write an update every 5 years 3 times starting in Jan 1st 1970 and then silence 395 396 now := uint64(1533799046) 397 var epoch lookup.Epoch 398 399 var lastData *Data 400 for i := uint64(0); i < 5; i++ { 401 T := uint64(Year * 5 * i) // write an update every 5 years 3 times starting in Jan 1st 1970 and then silence 402 data := Data{ 403 Payload: T, //our "payload" will be the timestamp itself. 404 Time: T, 405 } 406 epoch = update(store, epoch, T, &data) 407 lastData = &data 408 } 409 410 // try to get the last value 411 412 value, err := lookup.Lookup(context.Background(), now, lookup.NoClue, readFunc) 413 if err != nil { 414 t.Fatal(err) 415 } 416 417 readCountWithoutHint := readCount 418 419 if value != lastData { 420 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 421 } 422 423 // reset the read count for the next test 424 readCount = 0 425 // Provide a hint to get a faster lookup. In particular, we give the exact location of the last update 426 value, err = lookup.Lookup(context.Background(), now, epoch, readFunc) 427 if err != nil { 428 t.Fatal(err) 429 } 430 431 if value != lastData { 432 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 433 } 434 435 if readCount > readCountWithoutHint { 436 t.Fatalf("Expected lookup to complete with fewer reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 437 } 438 439 } 440 441 // testG will hold precooked test results 442 // fields are abbreviated to reduce the size of the literal below 443 type testG struct { 444 e lookup.Epoch // last 445 n uint64 // next level 446 x uint8 // expected result 447 } 448 449 // test cases 450 var testGetNextLevelCases = []testG{{e: lookup.Epoch{Time: 989875233, Level: 12}, n: 989875233, x: 11}, {e: lookup.Epoch{Time: 995807650, Level: 18}, n: 995598156, x: 19}, {e: lookup.Epoch{Time: 969167082, Level: 0}, n: 968990357, x: 18}, {e: lookup.Epoch{Time: 993087628, Level: 14}, n: 992987044, x: 20}, {e: lookup.Epoch{Time: 963364631, Level: 20}, n: 963364630, x: 19}, {e: lookup.Epoch{Time: 963497510, Level: 16}, n: 963370732, x: 18}, {e: lookup.Epoch{Time: 955421349, Level: 22}, n: 955421348, x: 21}, {e: lookup.Epoch{Time: 968220379, Level: 15}, n: 968220378, x: 14}, {e: lookup.Epoch{Time: 939129014, Level: 6}, n: 939128771, x: 11}, {e: lookup.Epoch{Time: 907847903, Level: 6}, n: 907791833, x: 18}, {e: lookup.Epoch{Time: 910835564, Level: 15}, n: 910835564, x: 14}, {e: lookup.Epoch{Time: 913578333, Level: 22}, n: 881808431, x: 25}, {e: lookup.Epoch{Time: 895818460, Level: 3}, n: 895818132, x: 9}, {e: lookup.Epoch{Time: 903843025, Level: 24}, n: 895609561, x: 23}, {e: lookup.Epoch{Time: 877889433, Level: 13}, n: 877877093, x: 15}, {e: lookup.Epoch{Time: 901450396, Level: 10}, n: 901450058, x: 9}, {e: lookup.Epoch{Time: 925179910, Level: 3}, n: 925168393, x: 16}, {e: lookup.Epoch{Time: 913485477, Level: 21}, n: 913485476, x: 20}, {e: lookup.Epoch{Time: 924462991, Level: 18}, n: 924462990, x: 17}, {e: lookup.Epoch{Time: 941175128, Level: 13}, n: 941175127, x: 12}, {e: lookup.Epoch{Time: 920126583, Level: 3}, n: 920100782, x: 19}, {e: lookup.Epoch{Time: 932403200, Level: 9}, n: 932279891, x: 17}, {e: lookup.Epoch{Time: 948284931, Level: 2}, n: 948284921, x: 9}, {e: lookup.Epoch{Time: 953540997, Level: 7}, n: 950547986, x: 22}, {e: lookup.Epoch{Time: 926639837, Level: 18}, n: 918608882, x: 24}, {e: lookup.Epoch{Time: 954637598, Level: 1}, n: 954578761, x: 17}, {e: lookup.Epoch{Time: 943482981, Level: 10}, n: 942924151, x: 19}, {e: lookup.Epoch{Time: 963580771, Level: 7}, n: 963580771, x: 6}, {e: lookup.Epoch{Time: 993744930, Level: 7}, n: 993690858, x: 16}, {e: lookup.Epoch{Time: 1018890213, Level: 12}, n: 1018890212, x: 11}, {e: lookup.Epoch{Time: 1030309411, Level: 2}, n: 1030309227, x: 9}, {e: lookup.Epoch{Time: 1063204997, Level: 20}, n: 1063204996, x: 19}, {e: lookup.Epoch{Time: 1094340832, Level: 6}, n: 1094340633, x: 7}, {e: lookup.Epoch{Time: 1077880597, Level: 10}, n: 1075914292, x: 20}, {e: lookup.Epoch{Time: 1051114957, Level: 18}, n: 1051114957, x: 17}, {e: lookup.Epoch{Time: 1045649701, Level: 22}, n: 1045649700, x: 21}, {e: lookup.Epoch{Time: 1066198885, Level: 14}, n: 1066198884, x: 13}, {e: lookup.Epoch{Time: 1053231952, Level: 1}, n: 1053210845, x: 16}, {e: lookup.Epoch{Time: 1068763404, Level: 14}, n: 1068675428, x: 18}, {e: lookup.Epoch{Time: 1039042173, Level: 15}, n: 1038973110, x: 17}, {e: lookup.Epoch{Time: 1050747636, Level: 6}, n: 1050747364, x: 9}, {e: lookup.Epoch{Time: 1030034434, Level: 23}, n: 1030034433, x: 22}, {e: lookup.Epoch{Time: 1003783425, Level: 18}, n: 1003783424, x: 17}, {e: lookup.Epoch{Time: 988163976, Level: 15}, n: 988084064, x: 17}, {e: lookup.Epoch{Time: 1007222377, Level: 15}, n: 1007222377, x: 14}, {e: lookup.Epoch{Time: 1001211375, Level: 13}, n: 1001208178, x: 14}, {e: lookup.Epoch{Time: 997623199, Level: 8}, n: 997623198, x: 7}, {e: lookup.Epoch{Time: 1026283830, Level: 10}, n: 1006681704, x: 24}, {e: lookup.Epoch{Time: 1019421907, Level: 20}, n: 1019421906, x: 19}, {e: lookup.Epoch{Time: 1043154306, Level: 16}, n: 1043108343, x: 16}, {e: lookup.Epoch{Time: 1075643767, Level: 17}, n: 1075325898, x: 18}, {e: lookup.Epoch{Time: 1043726309, Level: 20}, n: 1043726308, x: 19}, {e: lookup.Epoch{Time: 1056415324, Level: 17}, n: 1056415324, x: 16}, {e: lookup.Epoch{Time: 1088650219, Level: 13}, n: 1088650218, x: 12}, {e: lookup.Epoch{Time: 1088551662, Level: 7}, n: 1088543355, x: 13}, {e: lookup.Epoch{Time: 1069667265, Level: 6}, n: 1069667075, x: 7}, {e: lookup.Epoch{Time: 1079145970, Level: 18}, n: 1079145969, x: 17}, {e: lookup.Epoch{Time: 1083338876, Level: 7}, n: 1083338875, x: 6}, {e: lookup.Epoch{Time: 1051581086, Level: 4}, n: 1051568869, x: 14}, {e: lookup.Epoch{Time: 1028430882, Level: 4}, n: 1028430864, x: 5}, {e: lookup.Epoch{Time: 1057356462, Level: 1}, n: 1057356417, x: 5}, {e: lookup.Epoch{Time: 1033104266, Level: 0}, n: 1033097479, x: 13}, {e: lookup.Epoch{Time: 1031391367, Level: 11}, n: 1031387304, x: 14}, {e: lookup.Epoch{Time: 1049781164, Level: 15}, n: 1049781163, x: 14}, {e: lookup.Epoch{Time: 1027271628, Level: 12}, n: 1027271627, x: 11}, {e: lookup.Epoch{Time: 1057270560, Level: 23}, n: 1057270560, x: 22}, {e: lookup.Epoch{Time: 1047501317, Level: 15}, n: 1047501317, x: 14}, {e: lookup.Epoch{Time: 1058349035, Level: 11}, n: 1045175573, x: 24}, {e: lookup.Epoch{Time: 1057396147, Level: 20}, n: 1057396147, x: 19}, {e: lookup.Epoch{Time: 1048906375, Level: 18}, n: 1039616919, x: 25}, {e: lookup.Epoch{Time: 1074294831, Level: 20}, n: 1074294831, x: 19}, {e: lookup.Epoch{Time: 1088946052, Level: 1}, n: 1088917364, x: 14}, {e: lookup.Epoch{Time: 1112337595, Level: 17}, n: 1111008110, x: 22}, {e: lookup.Epoch{Time: 1099990284, Level: 5}, n: 1099968370, x: 15}, {e: lookup.Epoch{Time: 1087036441, Level: 16}, n: 1053967855, x: 25}, {e: lookup.Epoch{Time: 1069225185, Level: 8}, n: 1069224660, x: 10}, {e: lookup.Epoch{Time: 1057505479, Level: 9}, n: 1057505170, x: 14}, {e: lookup.Epoch{Time: 1072381377, Level: 12}, n: 1065950959, x: 22}, {e: lookup.Epoch{Time: 1093887139, Level: 8}, n: 1093863305, x: 14}, {e: lookup.Epoch{Time: 1082366510, Level: 24}, n: 1082366510, x: 23}, {e: lookup.Epoch{Time: 1103231132, Level: 14}, n: 1102292201, x: 22}, {e: lookup.Epoch{Time: 1094502355, Level: 3}, n: 1094324652, x: 18}, {e: lookup.Epoch{Time: 1068488344, Level: 12}, n: 1067577330, x: 19}, {e: lookup.Epoch{Time: 1050278233, Level: 12}, n: 1050278232, x: 11}, {e: lookup.Epoch{Time: 1047660768, Level: 5}, n: 1047652137, x: 17}, {e: lookup.Epoch{Time: 1060116167, Level: 11}, n: 1060114091, x: 12}, {e: lookup.Epoch{Time: 1068149392, Level: 21}, n: 1052074801, x: 24}, {e: lookup.Epoch{Time: 1081934120, Level: 6}, n: 1081933847, x: 8}, {e: lookup.Epoch{Time: 1107943693, Level: 16}, n: 1107096139, x: 25}, {e: lookup.Epoch{Time: 1131571649, Level: 9}, n: 1131570428, x: 11}, {e: lookup.Epoch{Time: 1123139367, Level: 0}, n: 1122912198, x: 20}, {e: lookup.Epoch{Time: 1121144423, Level: 6}, n: 1120568289, x: 20}, {e: lookup.Epoch{Time: 1089932411, Level: 17}, n: 1089932410, x: 16}, {e: lookup.Epoch{Time: 1104899012, Level: 22}, n: 1098978789, x: 22}, {e: lookup.Epoch{Time: 1094588059, Level: 21}, n: 1094588059, x: 20}, {e: lookup.Epoch{Time: 1114987438, Level: 24}, n: 1114987437, x: 23}, {e: lookup.Epoch{Time: 1084186305, Level: 7}, n: 1084186241, x: 6}, {e: lookup.Epoch{Time: 1058827111, Level: 8}, n: 1058826504, x: 9}, {e: lookup.Epoch{Time: 1090679810, Level: 12}, n: 1090616539, x: 17}, {e: lookup.Epoch{Time: 1084299475, Level: 23}, n: 1084299475, x: 22}} 451 452 func TestGetNextLevel(t *testing.T) { 453 454 // First, test well-known cases 455 last := lookup.Epoch{ 456 Time: 1533799046, 457 Level: 5, 458 } 459 460 level := lookup.GetNextLevel(last, last.Time) 461 expected := uint8(4) 462 if level != expected { 463 t.Fatalf("Expected GetNextLevel to return %d for same-time updates at a nonzero level, got %d", expected, level) 464 } 465 466 level = lookup.GetNextLevel(last, last.Time+(1<<lookup.HighestLevel)+3000) 467 expected = lookup.HighestLevel 468 if level != expected { 469 t.Fatalf("Expected GetNextLevel to return %d for updates set 2^lookup.HighestLevel seconds away, got %d", expected, level) 470 } 471 472 level = lookup.GetNextLevel(last, last.Time+(1<<last.Level)) 473 expected = last.Level 474 if level != expected { 475 t.Fatalf("Expected GetNextLevel to return %d for updates set 2^last.Level seconds away, got %d", expected, level) 476 } 477 478 last.Level = 0 479 level = lookup.GetNextLevel(last, last.Time) 480 expected = 0 481 if level != expected { 482 t.Fatalf("Expected GetNextLevel to return %d for same-time updates at a zero level, got %d", expected, level) 483 } 484 485 // run a batch of 100 cooked tests 486 for _, s := range testGetNextLevelCases { 487 level := lookup.GetNextLevel(s.e, s.n) 488 if level != s.x { 489 t.Fatalf("Expected GetNextLevel to return %d for last=%s when now=%d, got %d", s.x, s.e.String(), s.n, level) 490 } 491 } 492 493 } 494 495 // cookGetNextLevelTests is used to generate a deterministic 496 // set of cases for TestGetNextLevel and thus "freeze" its current behavior 497 func CookGetNextLevelTests(t *testing.T) { 498 st := "" 499 var last lookup.Epoch 500 last.Time = 1000000000 501 var now uint64 502 var expected uint8 503 for i := 0; i < 100; i++ { 504 last.Time += uint64(rand.Intn(1<<26)) - (1 << 25) 505 last.Level = uint8(rand.Intn(25)) 506 v := last.Level + uint8(rand.Intn(lookup.HighestLevel)) 507 if v > lookup.HighestLevel { 508 v = 0 509 } 510 now = last.Time + uint64(rand.Intn(1<<v+1)) - (1 << v) 511 expected = lookup.GetNextLevel(last, now) 512 st = fmt.Sprintf("%s,testG{e:lookup.Epoch{Time:%d, Level:%d}, n:%d, x:%d}", st, last.Time, last.Level, now, expected) 513 } 514 fmt.Println(st) 515 }