github.com/TeaOSLab/EdgeNode@v1.3.8/internal/caches/storage_file_test.go (about) 1 package caches 2 3 import ( 4 "bytes" 5 "errors" 6 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" 7 "github.com/TeaOSLab/EdgeNode/internal/utils" 8 "github.com/TeaOSLab/EdgeNode/internal/utils/testutils" 9 "github.com/iwind/TeaGo/Tea" 10 _ "github.com/iwind/TeaGo/bootstrap" 11 "github.com/iwind/TeaGo/logs" 12 "io" 13 "net/http" 14 "runtime" 15 "strconv" 16 "sync" 17 "testing" 18 "time" 19 ) 20 21 func TestFileStorage_Init(t *testing.T) { 22 if !testutils.IsSingleTesting() { 23 return 24 } 25 26 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 27 Id: 1, 28 IsOn: true, 29 Options: map[string]interface{}{ 30 "dir": Tea.Root + "/caches", 31 }, 32 }) 33 34 defer storage.Stop() 35 36 err := storage.Init() 37 if err != nil { 38 t.Fatal(err) 39 } 40 //t.Log(storage.list.m) 41 42 /**err = storage.Write("c", bytes.NewReader([]byte("i am c")), 4, "second") 43 if err != nil { 44 t.Fatal(err) 45 }**/ 46 //logs.PrintAsJSON(storage.list.m, t) 47 48 time.Sleep(2 * time.Second) 49 storage.purgeLoop() 50 t.Log(storage.list.(*SQLiteFileList).Stat(func(hash string) bool { 51 return true 52 })) 53 } 54 55 func TestFileStorage_OpenWriter(t *testing.T) { 56 if !testutils.IsSingleTesting() { 57 return 58 } 59 60 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 61 Id: 1, 62 IsOn: true, 63 Options: map[string]interface{}{ 64 "dir": Tea.Root + "/caches", 65 }, 66 }) 67 68 defer storage.Stop() 69 70 err := storage.Init() 71 if err != nil { 72 t.Fatal(err) 73 } 74 now := time.Now() 75 defer func() { 76 t.Log(time.Since(now).Seconds()*1000, "ms") 77 }() 78 79 header := []byte("Header") 80 body := []byte("This is Body") 81 writer, err := storage.OpenWriter("my-key", time.Now().Unix()+86400, 200, -1, -1, -1, false) 82 if err != nil { 83 t.Fatal(err) 84 } 85 t.Log(writer) 86 87 _, err = writer.WriteHeader(header) 88 if err != nil { 89 t.Fatal(err) 90 } 91 92 _, err = writer.Write(body) 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 err = writer.Close() 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 t.Log("header:", writer.HeaderSize(), "body:", writer.BodySize()) 103 t.Log("ok") 104 } 105 106 func TestFileStorage_OpenWriter_Partial(t *testing.T) { 107 if !testutils.IsSingleTesting() { 108 return 109 } 110 111 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 112 Id: 2, 113 IsOn: true, 114 Options: map[string]interface{}{ 115 "dir": Tea.Root + "/caches", 116 }, 117 }) 118 119 defer storage.Stop() 120 121 err := storage.Init() 122 if err != nil { 123 t.Fatal(err) 124 } 125 126 writer, err := storage.OpenWriter("my-key", time.Now().Unix()+86400, 200, -1, -1, -1, true) 127 if err != nil { 128 t.Fatal(err) 129 } 130 131 _, err = writer.WriteHeader([]byte("Content-Type:text/html; charset=utf-8")) 132 if err != nil { 133 t.Fatal(err) 134 } 135 136 err = writer.WriteAt(0, []byte("Hello, World")) 137 if err != nil { 138 t.Fatal(err) 139 } 140 141 err = writer.Close() 142 if err != nil { 143 t.Fatal(err) 144 } 145 t.Log(writer) 146 } 147 148 func TestFileStorage_OpenWriter_HTTP(t *testing.T) { 149 if !testutils.IsSingleTesting() { 150 return 151 } 152 153 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 154 Id: 1, 155 IsOn: true, 156 Options: map[string]interface{}{ 157 "dir": Tea.Root + "/caches", 158 }, 159 }) 160 161 defer storage.Stop() 162 163 err := storage.Init() 164 if err != nil { 165 t.Fatal(err) 166 } 167 now := time.Now() 168 defer func() { 169 t.Log(time.Since(now).Seconds()*1000, "ms") 170 }() 171 172 writer, err := storage.OpenWriter("my-http-response", time.Now().Unix()+86400, 200, -1, -1, -1, false) 173 if err != nil { 174 t.Fatal(err) 175 } 176 t.Log(writer) 177 178 resp := &http.Response{ 179 StatusCode: http.StatusOK, 180 Header: http.Header{ 181 "Content-Type": []string{"text/html; charset=utf-8"}, 182 "Last-Modified": []string{"Wed, 06 Jan 2021 10:03:29 GMT"}, 183 "Server": []string{"CDN-Server"}, 184 }, 185 Body: io.NopCloser(bytes.NewBuffer([]byte("THIS IS HTTP BODY"))), 186 } 187 188 for k, v := range resp.Header { 189 for _, v1 := range v { 190 _, err = writer.WriteHeader([]byte(k + ":" + v1 + "\n")) 191 if err != nil { 192 t.Fatal(err) 193 } 194 } 195 } 196 197 buf := make([]byte, 1024) 198 for { 199 n, err := resp.Body.Read(buf) 200 if n > 0 { 201 _, err = writer.Write(buf[:n]) 202 if err != nil { 203 t.Fatal(err) 204 } 205 } 206 if err != nil { 207 break 208 } 209 } 210 211 err = writer.Close() 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 t.Log("header:", writer.HeaderSize(), "body:", writer.BodySize()) 217 t.Log("ok") 218 } 219 220 func TestFileStorage_Concurrent_Open_DifferentFile(t *testing.T) { 221 if !testutils.IsSingleTesting() { 222 return 223 } 224 225 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 226 Id: 1, 227 IsOn: true, 228 Options: map[string]interface{}{ 229 "dir": Tea.Root + "/caches", 230 }, 231 }) 232 233 defer storage.Stop() 234 235 err := storage.Init() 236 if err != nil { 237 t.Fatal(err) 238 } 239 now := time.Now() 240 defer func() { 241 t.Log(time.Since(now).Seconds()*1000, "ms") 242 }() 243 244 wg := sync.WaitGroup{} 245 count := 100 246 wg.Add(count) 247 248 for i := 0; i < count; i++ { 249 go func(i int) { 250 defer wg.Done() 251 252 writer, err := storage.OpenWriter("abc"+strconv.Itoa(i), time.Now().Unix()+3600, 200, -1, -1, -1, false) 253 if err != nil { 254 if errors.Is(err, ErrFileIsWriting) { 255 t.Error(err) 256 return 257 } 258 return 259 } 260 //t.Log(writer) 261 262 _, err = writer.Write([]byte("Hello,World")) 263 if err != nil { 264 t.Error(err) 265 return 266 } 267 268 // 故意造成慢速写入 269 time.Sleep(1 * time.Second) 270 271 err = writer.Close() 272 if err != nil { 273 t.Error(err) 274 return 275 } 276 }(i) 277 } 278 279 wg.Wait() 280 } 281 282 func TestFileStorage_Concurrent_Open_SameFile(t *testing.T) { 283 if !testutils.IsSingleTesting() { 284 return 285 } 286 287 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 288 Id: 1, 289 IsOn: true, 290 Options: map[string]interface{}{ 291 "dir": Tea.Root + "/caches", 292 }, 293 }) 294 295 defer storage.Stop() 296 297 err := storage.Init() 298 if err != nil { 299 t.Fatal(err) 300 } 301 now := time.Now() 302 defer func() { 303 t.Log(time.Since(now).Seconds()*1000, "ms") 304 }() 305 306 wg := sync.WaitGroup{} 307 count := 100 308 wg.Add(count) 309 310 for i := 0; i < count; i++ { 311 go func(i int) { 312 defer wg.Done() 313 314 writer, err := storage.OpenWriter("abc"+strconv.Itoa(0), time.Now().Unix()+3600, 200, -1, -1, -1, false) 315 if err != nil { 316 if errors.Is(err, ErrFileIsWriting) { 317 t.Error(err) 318 return 319 } 320 return 321 } 322 //t.Log(writer) 323 324 t.Log("writing") 325 _, err = writer.Write([]byte("Hello,World")) 326 if err != nil { 327 t.Error(err) 328 return 329 } 330 331 // 故意造成慢速写入 332 time.Sleep(time.Duration(1) * time.Second) 333 334 err = writer.Close() 335 if err != nil { 336 t.Error(err) 337 return 338 } 339 }(i) 340 } 341 342 wg.Wait() 343 } 344 345 func TestFileStorage_Read(t *testing.T) { 346 if !testutils.IsSingleTesting() { 347 return 348 } 349 350 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 351 Id: 1, 352 IsOn: true, 353 Options: map[string]interface{}{ 354 "dir": Tea.Root + "/caches", 355 }, 356 }) 357 358 defer storage.Stop() 359 360 err := storage.Init() 361 if err != nil { 362 t.Fatal(err) 363 } 364 now := time.Now() 365 reader, err := storage.OpenReader("my-key", false, false) 366 if err != nil { 367 t.Fatal(err) 368 } 369 buf := make([]byte, 6) 370 t.Log(reader.Status()) 371 err = reader.ReadHeader(buf, func(n int) (goNext bool, err error) { 372 t.Log("header:", string(buf[:n])) 373 return true, nil 374 }) 375 if err != nil { 376 t.Fatal(err) 377 } 378 err = reader.ReadBody(buf, func(n int) (goNext bool, err error) { 379 t.Log("body:", string(buf[:n])) 380 return true, nil 381 }) 382 if err != nil { 383 t.Fatal(err) 384 } 385 t.Log(time.Since(now).Seconds()*1000, "ms") 386 } 387 388 func TestFileStorage_Read_HTTP_Response(t *testing.T) { 389 if !testutils.IsSingleTesting() { 390 return 391 } 392 393 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 394 Id: 1, 395 IsOn: true, 396 Options: map[string]interface{}{ 397 "dir": Tea.Root + "/caches", 398 }, 399 }) 400 401 defer storage.Stop() 402 403 err := storage.Init() 404 if err != nil { 405 t.Fatal(err) 406 } 407 now := time.Now() 408 reader, err := storage.OpenReader("my-http-response", false, false) 409 if err != nil { 410 t.Fatal(err) 411 } 412 buf := make([]byte, 32) 413 t.Log(reader.Status()) 414 415 headerBuf := []byte{} 416 err = reader.ReadHeader(buf, func(n int) (goNext bool, err error) { 417 headerBuf = append(headerBuf, buf...) 418 for { 419 nIndex := bytes.Index(headerBuf, []byte{'\n'}) 420 if nIndex >= 0 { 421 row := headerBuf[:nIndex] 422 spaceIndex := bytes.Index(row, []byte{':'}) 423 if spaceIndex <= 0 { 424 return false, errors.New("invalid header") 425 } 426 427 t.Log("header row:", string(row[:spaceIndex]), string(row[spaceIndex+1:])) 428 headerBuf = headerBuf[nIndex+1:] 429 } else { 430 break 431 } 432 } 433 return true, nil 434 }) 435 if err != nil { 436 t.Fatal(err) 437 } 438 err = reader.ReadBody(buf, func(n int) (goNext bool, err error) { 439 t.Log("body:", string(buf[:n])) 440 return true, nil 441 }) 442 if err != nil { 443 t.Fatal(err) 444 } 445 t.Log(time.Since(now).Seconds()*1000, "ms") 446 } 447 448 func TestFileStorage_Read_NotFound(t *testing.T) { 449 if !testutils.IsSingleTesting() { 450 return 451 } 452 453 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 454 Id: 1, 455 IsOn: true, 456 Options: map[string]interface{}{ 457 "dir": Tea.Root + "/caches", 458 }, 459 }) 460 461 defer storage.Stop() 462 463 err := storage.Init() 464 if err != nil { 465 t.Fatal(err) 466 } 467 now := time.Now() 468 buf := make([]byte, 6) 469 reader, err := storage.OpenReader("my-key-10000", false, false) 470 if err != nil { 471 if err == ErrNotFound { 472 t.Log("cache not fund") 473 return 474 } 475 t.Fatal(err) 476 } 477 478 err = reader.ReadBody(buf, func(n int) (goNext bool, err error) { 479 t.Log("body:", string(buf[:n])) 480 return true, nil 481 }) 482 if err != nil { 483 t.Fatal(err) 484 } 485 t.Log(time.Since(now).Seconds()*1000, "ms") 486 } 487 488 func TestFileStorage_Delete(t *testing.T) { 489 if !testutils.IsSingleTesting() { 490 return 491 } 492 493 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 494 Id: 1, 495 IsOn: true, 496 Options: map[string]interface{}{ 497 "dir": Tea.Root + "/caches", 498 }, 499 }) 500 501 defer storage.Stop() 502 503 err := storage.Init() 504 if err != nil { 505 t.Fatal(err) 506 } 507 err = storage.Delete("my-key") 508 if err != nil { 509 t.Fatal(err) 510 } 511 t.Log("ok") 512 } 513 514 func TestFileStorage_Stat(t *testing.T) { 515 if !testutils.IsSingleTesting() { 516 return 517 } 518 519 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 520 Id: 1, 521 IsOn: true, 522 Options: map[string]interface{}{ 523 "dir": Tea.Root + "/caches", 524 }, 525 }) 526 527 defer storage.Stop() 528 529 err := storage.Init() 530 if err != nil { 531 t.Fatal(err) 532 } 533 534 before := time.Now() 535 defer func() { 536 t.Log(time.Since(before).Seconds()*1000, "ms") 537 }() 538 539 stat, err := storage.Stat() 540 if err != nil { 541 t.Fatal(err) 542 } 543 logs.PrintAsJSON(stat, t) 544 } 545 546 func TestFileStorage_CleanAll(t *testing.T) { 547 if !testutils.IsSingleTesting() { 548 return 549 } 550 551 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 552 Id: 1, 553 IsOn: true, 554 Options: map[string]interface{}{ 555 "dir": Tea.Root + "/caches", 556 }, 557 }) 558 559 defer storage.Stop() 560 561 err := storage.Init() 562 if err != nil { 563 t.Fatal(err) 564 } 565 566 before := time.Now() 567 defer func() { 568 t.Log(time.Since(before).Seconds()*1000, "ms") 569 }() 570 571 c, _ := storage.list.Count() 572 t.Log("before:", c) 573 574 err = storage.CleanAll() 575 if err != nil { 576 t.Fatal(err) 577 } 578 579 c, _ = storage.list.Count() 580 t.Log("after:", c) 581 t.Log("ok") 582 } 583 584 func TestFileStorage_Stop(t *testing.T) { 585 if !testutils.IsSingleTesting() { 586 return 587 } 588 589 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 590 Id: 1, 591 IsOn: true, 592 Options: map[string]interface{}{ 593 "dir": Tea.Root + "/caches", 594 }, 595 }) 596 597 defer storage.Stop() 598 599 err := storage.Init() 600 if err != nil { 601 t.Fatal(err) 602 } 603 storage.Stop() 604 } 605 606 func TestFileStorage_DecodeFile(t *testing.T) { 607 if !testutils.IsSingleTesting() { 608 return 609 } 610 611 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 612 Id: 1, 613 IsOn: true, 614 Options: map[string]interface{}{ 615 "dir": Tea.Root + "/caches", 616 }, 617 }) 618 619 defer storage.Stop() 620 621 err := storage.Init() 622 if err != nil { 623 t.Fatal(err) 624 } 625 _, path, _ := storage.keyPath("my-key") 626 t.Log(path) 627 } 628 629 func TestFileStorage_RemoveCacheFile(t *testing.T) { 630 if !testutils.IsSingleTesting() { 631 return 632 } 633 634 var storage = NewFileStorage(nil) 635 636 defer storage.Stop() 637 638 t.Log(storage.removeCacheFile("/Users/WorkSpace/EdgeProject/EdgeCache/p43/15/7e/157eba0dfc6dfb6fbbf20b1f9e584674.cache")) 639 } 640 641 func TestFileStorage_ScanGarbageCaches(t *testing.T) { 642 if !testutils.IsSingleTesting() { 643 return 644 } 645 646 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 647 Id: 43, 648 Options: map[string]any{"dir": "/Users/WorkSpace/EdgeProject/EdgeCache"}, 649 }) 650 err := storage.Init() 651 if err != nil { 652 t.Fatal(err) 653 } 654 655 err = storage.ScanGarbageCaches(func(path string) error { 656 t.Log(path, PartialRangesFilePath(path)) 657 return nil 658 }) 659 if err != nil { 660 t.Fatal(err) 661 } 662 } 663 664 func BenchmarkFileStorage_Read(b *testing.B) { 665 runtime.GOMAXPROCS(1) 666 667 _ = utils.SetRLimit(1 << 20) 668 669 var storage = NewFileStorage(&serverconfigs.HTTPCachePolicy{ 670 Id: 1, 671 IsOn: true, 672 Options: map[string]interface{}{ 673 "dir": Tea.Root + "/caches", 674 }, 675 }) 676 677 defer storage.Stop() 678 679 err := storage.Init() 680 if err != nil { 681 b.Fatal(err) 682 } 683 for i := 0; i < b.N; i++ { 684 reader, err := storage.OpenReader("my-key", false, false) 685 if err != nil { 686 b.Fatal(err) 687 } 688 buf := make([]byte, 1024) 689 _ = reader.ReadBody(buf, func(n int) (goNext bool, err error) { 690 return true, nil 691 }) 692 _ = reader.Close() 693 } 694 } 695 696 func BenchmarkFileStorage_KeyPath(b *testing.B) { 697 runtime.GOMAXPROCS(1) 698 699 var storage = &FileStorage{ 700 options: &serverconfigs.HTTPFileCacheStorage{}, 701 policy: &serverconfigs.HTTPCachePolicy{Id: 1}, 702 } 703 704 for i := 0; i < b.N; i++ { 705 _, _, _ = storage.keyPath(strconv.Itoa(i)) 706 } 707 }