github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/feed/lookup/lookup_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:44</date> 10 //</624450119214829568> 11 12 13 package lookup_test 14 15 import ( 16 "fmt" 17 "math/rand" 18 "testing" 19 20 "github.com/ethereum/go-ethereum/swarm/log" 21 "github.com/ethereum/go-ethereum/swarm/storage/feed/lookup" 22 ) 23 24 type Data struct { 25 Payload uint64 26 Time uint64 27 } 28 29 type Store map[lookup.EpochID]*Data 30 31 func write(store Store, epoch lookup.Epoch, value *Data) { 32 log.Debug("Write: %d-%d, value='%d'\n", epoch.Base(), epoch.Level, value.Payload) 33 store[epoch.ID()] = value 34 } 35 36 func update(store Store, last lookup.Epoch, now uint64, value *Data) lookup.Epoch { 37 epoch := lookup.GetNextEpoch(last, now) 38 39 write(store, epoch, value) 40 41 return epoch 42 } 43 44 const Day = 60 * 60 * 24 45 const Year = Day * 365 46 const Month = Day * 30 47 48 func makeReadFunc(store Store, counter *int) lookup.ReadFunc { 49 return func(epoch lookup.Epoch, now uint64) (interface{}, error) { 50 *counter++ 51 data := store[epoch.ID()] 52 var valueStr string 53 if data != nil { 54 valueStr = fmt.Sprintf("%d", data.Payload) 55 } 56 log.Debug("Read: %d-%d, value='%s'\n", epoch.Base(), epoch.Level, valueStr) 57 if data != nil && data.Time <= now { 58 return data, nil 59 } 60 return nil, nil 61 } 62 } 63 64 func TestLookup(t *testing.T) { 65 66 store := make(Store) 67 readCount := 0 68 readFunc := makeReadFunc(store, &readCount) 69 70 //3年前12个月每月更新一次,然后沉默两年。 71 now := uint64(1533799046) 72 var epoch lookup.Epoch 73 74 var lastData *Data 75 for i := uint64(0); i < 12; i++ { 76 t := uint64(now - Year*3 + i*Month) 77 data := Data{ 78 Payload: t, //我们的“有效载荷”将是时间戳本身。 79 Time: t, 80 } 81 epoch = update(store, epoch, t, &data) 82 lastData = &data 83 } 84 85 //尝试获取最后一个值 86 87 value, err := lookup.Lookup(now, lookup.NoClue, readFunc) 88 if err != nil { 89 t.Fatal(err) 90 } 91 92 readCountWithoutHint := readCount 93 94 if value != lastData { 95 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 96 } 97 98 //重置下次测试的读取计数 99 readCount = 0 100 //提供提示以加快查找速度。特别是,我们给出了最后一次更新的确切位置 101 value, err = lookup.Lookup(now, epoch, readFunc) 102 if err != nil { 103 t.Fatal(err) 104 } 105 106 if value != lastData { 107 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 108 } 109 110 if readCount > readCountWithoutHint { 111 t.Fatalf("Expected lookup to complete with fewer or same reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 112 } 113 114 //尝试获取中间值 115 //如果我们在现在-年*3+6*月内寻找一个值,我们应该得到这个值 116 //因为“有效载荷”是时间戳本身,所以我们可以检查它。 117 118 expectedTime := now - Year*3 + 6*Month 119 120 value, err = lookup.Lookup(expectedTime, lookup.NoClue, readFunc) 121 if err != nil { 122 t.Fatal(err) 123 } 124 125 data, ok := value.(*Data) 126 127 if !ok { 128 t.Fatal("Expected value to contain data") 129 } 130 131 if data.Time != expectedTime { 132 t.Fatalf("Expected value timestamp to be %d, got %d", data.Time, expectedTime) 133 } 134 135 } 136 137 func TestOneUpdateAt0(t *testing.T) { 138 139 store := make(Store) 140 readCount := 0 141 142 readFunc := makeReadFunc(store, &readCount) 143 now := uint64(1533903729) 144 145 var epoch lookup.Epoch 146 data := Data{ 147 Payload: 79, 148 Time: 0, 149 } 150 update(store, epoch, 0, &data) 151 152 value, err := lookup.Lookup(now, lookup.NoClue, readFunc) 153 if err != nil { 154 t.Fatal(err) 155 } 156 if value != &data { 157 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", data, value) 158 } 159 } 160 161 //测试即使给出错误提示也会找到更新 162 func TestBadHint(t *testing.T) { 163 164 store := make(Store) 165 readCount := 0 166 167 readFunc := makeReadFunc(store, &readCount) 168 now := uint64(1533903729) 169 170 var epoch lookup.Epoch 171 data := Data{ 172 Payload: 79, 173 Time: 0, 174 } 175 176 //更新t=1200 177 update(store, epoch, 1200, &data) 178 179 //想出一些邪恶的暗示 180 badHint := lookup.Epoch{ 181 Level: 18, 182 Time: 1200000000, 183 } 184 185 value, err := lookup.Lookup(now, badHint, readFunc) 186 if err != nil { 187 t.Fatal(err) 188 } 189 if value != &data { 190 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", data, value) 191 } 192 } 193 194 func TestLookupFail(t *testing.T) { 195 196 store := make(Store) 197 readCount := 0 198 199 readFunc := makeReadFunc(store, &readCount) 200 now := uint64(1533903729) 201 202 //不要写任何东西,试着抬头看看。 203 //我们在测试我们不会陷入循环 204 205 value, err := lookup.Lookup(now, lookup.NoClue, readFunc) 206 if err != nil { 207 t.Fatal(err) 208 } 209 if value != nil { 210 t.Fatal("Expected value to be nil, since the update should've failed") 211 } 212 213 expectedReads := now/(1<<lookup.HighestLevel) + 1 214 if uint64(readCount) != expectedReads { 215 t.Fatalf("Expected lookup to fail after %d reads. Did %d reads.", expectedReads, readCount) 216 } 217 } 218 219 func TestHighFreqUpdates(t *testing.T) { 220 221 store := make(Store) 222 readCount := 0 223 224 readFunc := makeReadFunc(store, &readCount) 225 now := uint64(1533903729) 226 227 //在过去的1000秒内,每秒写一次更新 228 var epoch lookup.Epoch 229 230 var lastData *Data 231 for i := uint64(0); i <= 994; i++ { 232 T := uint64(now - 1000 + i) 233 data := Data{ 234 Payload: T, //我们的“有效载荷”将是时间戳本身。 235 Time: T, 236 } 237 epoch = update(store, epoch, T, &data) 238 lastData = &data 239 } 240 241 value, err := lookup.Lookup(lastData.Time, lookup.NoClue, readFunc) 242 if err != nil { 243 t.Fatal(err) 244 } 245 246 if value != lastData { 247 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 248 } 249 250 readCountWithoutHint := readCount 251 //重置下次测试的读取计数 252 readCount = 0 253 //提供提示以加快查找速度。特别是,我们给出了最后一次更新的确切位置 254 value, err = lookup.Lookup(now, epoch, readFunc) 255 if err != nil { 256 t.Fatal(err) 257 } 258 259 if value != lastData { 260 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 261 } 262 263 if readCount > readCountWithoutHint { 264 t.Fatalf("Expected lookup to complete with fewer or equal reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 265 } 266 267 for i := uint64(0); i <= 994; i++ { 268 T := uint64(now - 1000 + i) //最近1000秒每秒钟更新一次 269 value, err := lookup.Lookup(T, lookup.NoClue, readFunc) 270 if err != nil { 271 t.Fatal(err) 272 } 273 data, _ := value.(*Data) 274 if data == nil { 275 t.Fatalf("Expected lookup to return %d, got nil", T) 276 } 277 if data.Payload != T { 278 t.Fatalf("Expected lookup to return %d, got %d", T, data.Time) 279 } 280 } 281 } 282 283 func TestSparseUpdates(t *testing.T) { 284 285 store := make(Store) 286 readCount := 0 287 readFunc := makeReadFunc(store, &readCount) 288 289 //从1970年1月1日开始每5年写3次更新,然后沉默 290 291 now := uint64(1533799046) 292 var epoch lookup.Epoch 293 294 var lastData *Data 295 for i := uint64(0); i < 5; i++ { 296 T := uint64(Year * 5 * i) //从1970年1月1日开始每5年写3次更新,然后沉默 297 data := Data{ 298 Payload: T, //我们的“有效载荷”将是时间戳本身。 299 Time: T, 300 } 301 epoch = update(store, epoch, T, &data) 302 lastData = &data 303 } 304 305 //尝试获取最后一个值 306 307 value, err := lookup.Lookup(now, lookup.NoClue, readFunc) 308 if err != nil { 309 t.Fatal(err) 310 } 311 312 readCountWithoutHint := readCount 313 314 if value != lastData { 315 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 316 } 317 318 //重置下次测试的读取计数 319 readCount = 0 320 //提供提示以加快查找速度。特别是,我们给出了最后一次更新的确切位置 321 value, err = lookup.Lookup(now, epoch, readFunc) 322 if err != nil { 323 t.Fatal(err) 324 } 325 326 if value != lastData { 327 t.Fatalf("Expected lookup to return the last written value: %v. Got %v", lastData, value) 328 } 329 330 if readCount > readCountWithoutHint { 331 t.Fatalf("Expected lookup to complete with fewer reads than %d since we provided a hint. Did %d reads.", readCountWithoutHint, readCount) 332 } 333 334 } 335 336 //TESTG将保存预煮的测试结果 337 //字段被缩写为减小以下文本的大小 338 type testG struct { 339 e lookup.Epoch //最后的 340 n uint64 //下一级 341 x uint8 //预期结果 342 } 343 344 //测试用例 345 var testGetNextLevelCases []testG = []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}} 346 347 func TestGetNextLevel(t *testing.T) { 348 349 //首先,测试知名案例 350 last := lookup.Epoch{ 351 Time: 1533799046, 352 Level: 5, 353 } 354 355 level := lookup.GetNextLevel(last, last.Time) 356 expected := uint8(4) 357 if level != expected { 358 t.Fatalf("Expected GetNextLevel to return %d for same-time updates at a nonzero level, got %d", expected, level) 359 } 360 361 level = lookup.GetNextLevel(last, last.Time+(1<<lookup.HighestLevel)+3000) 362 expected = lookup.HighestLevel 363 if level != expected { 364 t.Fatalf("Expected GetNextLevel to return %d for updates set 2^lookup.HighestLevel seconds away, got %d", expected, level) 365 } 366 367 level = lookup.GetNextLevel(last, last.Time+(1<<last.Level)) 368 expected = last.Level 369 if level != expected { 370 t.Fatalf("Expected GetNextLevel to return %d for updates set 2^last.Level seconds away, got %d", expected, level) 371 } 372 373 last.Level = 0 374 level = lookup.GetNextLevel(last, last.Time) 375 expected = 0 376 if level != expected { 377 t.Fatalf("Expected GetNextLevel to return %d for same-time updates at a zero level, got %d", expected, level) 378 } 379 380 //进行一批100次煮熟试验 381 for _, s := range testGetNextLevelCases { 382 level := lookup.GetNextLevel(s.e, s.n) 383 if level != s.x { 384 t.Fatalf("Expected GetNextLevel to return %d for last=%s when now=%d, got %d", s.x, s.e.String(), s.n, level) 385 } 386 } 387 388 } 389 390 //CookGetNextletvelTests用于生成确定性 391 //testGetNextLevel的一组事例,从而“冻结”其当前行为 392 func CookGetNextLevelTests(t *testing.T) { 393 st := "" 394 var last lookup.Epoch 395 last.Time = 1000000000 396 var now uint64 397 var expected uint8 398 for i := 0; i < 100; i++ { 399 last.Time += uint64(rand.Intn(1<<26)) - (1 << 25) 400 last.Level = uint8(rand.Intn(25)) 401 v := last.Level + uint8(rand.Intn(lookup.HighestLevel)) 402 if v > lookup.HighestLevel { 403 v = 0 404 } 405 now = last.Time + uint64(rand.Intn(1<<v+1)) - (1 << v) 406 expected = lookup.GetNextLevel(last, now) 407 st = fmt.Sprintf("%s,testG{e:lookup.Epoch{Time:%d, Level:%d}, n:%d, x:%d}", st, last.Time, last.Level, now, expected) 408 } 409 fmt.Println(st) 410 } 411