http3_transport_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. //go:build with_quic
  2. package httpclient
  3. import (
  4. "testing"
  5. "time"
  6. )
  7. func TestHTTP3BrokenAuthorityIsolation(t *testing.T) {
  8. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  9. transport.markH3Broken("a.example:443")
  10. if !transport.h3Broken("a.example:443") {
  11. t.Fatal("a.example:443 should be broken after mark")
  12. }
  13. if transport.h3Broken("b.example:443") {
  14. t.Fatal("b.example:443 must not be affected by marking a.example")
  15. }
  16. }
  17. func TestHTTP3BrokenBackoffPerAuthority(t *testing.T) {
  18. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  19. transport.markH3Broken("a.example:443")
  20. if transport.broken["a.example:443"].backoff != 5*time.Minute {
  21. t.Fatalf("first mark should set backoff to 5m, got %v", transport.broken["a.example:443"].backoff)
  22. }
  23. transport.markH3Broken("a.example:443")
  24. if transport.broken["a.example:443"].backoff != 10*time.Minute {
  25. t.Fatalf("second mark should double backoff to 10m, got %v", transport.broken["a.example:443"].backoff)
  26. }
  27. transport.markH3Broken("a.example:443")
  28. if transport.broken["a.example:443"].backoff != 20*time.Minute {
  29. t.Fatalf("third mark should double to 20m, got %v", transport.broken["a.example:443"].backoff)
  30. }
  31. if _, found := transport.broken["b.example:443"]; found {
  32. t.Fatal("marking a.example must not leak into b.example backoff state")
  33. }
  34. transport.markH3Broken("b.example:443")
  35. if transport.broken["b.example:443"].backoff != 5*time.Minute {
  36. t.Fatalf("b.example first mark should start at 5m independent of a.example, got %v", transport.broken["b.example:443"].backoff)
  37. }
  38. }
  39. func TestHTTP3BrokenBackoffCap(t *testing.T) {
  40. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  41. transport.broken["a.example:443"] = http3BrokenEntry{backoff: 48 * time.Hour, until: time.Now().Add(48 * time.Hour)}
  42. transport.markH3Broken("a.example:443")
  43. if transport.broken["a.example:443"].backoff != 48*time.Hour {
  44. t.Fatalf("backoff must cap at 48h, got %v", transport.broken["a.example:443"].backoff)
  45. }
  46. }
  47. func TestHTTP3BrokenClearDeletesEntry(t *testing.T) {
  48. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  49. transport.markH3Broken("a.example:443")
  50. transport.markH3Broken("b.example:443")
  51. transport.clearH3Broken("a.example:443")
  52. if _, found := transport.broken["a.example:443"]; found {
  53. t.Fatal("clearH3Broken must delete the entry")
  54. }
  55. if !transport.h3Broken("b.example:443") {
  56. t.Fatal("clearing a.example must not affect b.example")
  57. }
  58. }
  59. func TestHTTP3BrokenExpiredEntryGarbageCollected(t *testing.T) {
  60. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  61. transport.broken["a.example:443"] = http3BrokenEntry{
  62. backoff: 5 * time.Minute,
  63. until: time.Now().Add(-time.Second),
  64. }
  65. if transport.h3Broken("a.example:443") {
  66. t.Fatal("expired entry must report not broken")
  67. }
  68. if _, found := transport.broken["a.example:443"]; found {
  69. t.Fatal("expired entry must be garbage-collected on read")
  70. }
  71. }
  72. func TestHTTP3BrokenEmptyAuthorityNoOp(t *testing.T) {
  73. transport := &http3FallbackTransport{broken: make(map[string]http3BrokenEntry)}
  74. transport.markH3Broken("")
  75. if len(transport.broken) != 0 {
  76. t.Fatalf("markH3Broken must ignore empty authority, got %d entries", len(transport.broken))
  77. }
  78. if transport.h3Broken("") {
  79. t.Fatal("h3Broken must return false for empty authority")
  80. }
  81. transport.clearH3Broken("")
  82. }