1 package httpreaderat 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "embed" 7 "errors" 8 "io" 9 "io/fs" 10 "net/http" 11 "net/http/httptest" 12 "testing" 13 "time" 14 ) 15 16 //go:embed httpreaderat_test.go 17 var f embed.FS 18 19 func TestHTTPReaderAt(t *testing.T) { 20 b, _ := f.ReadFile("httpreaderat_test.go") 21 srv := httptest.NewServer(http.FileServerFS(f)) 22 23 r, err := NewRequest(srv.URL + "/httpreaderat_test.go") 24 if err != nil { 25 t.Fatalf("unexpected error: %s", err) 26 } else if r.Length() != int64(len(b)) { 27 t.Errorf("expecting length %d, got %d", len(b), r.Length()) 28 } 29 30 buf := make([]byte, 16) 31 32 if n, err := r.ReadAt(buf[:12], -1); !errors.Is(err, fs.ErrInvalid) { 33 t.Errorf("expecting error ErrInvalid, got %v", err) 34 } else if n != 0 { 35 t.Errorf("expecting to read %d bytes, read %d", 0, n) 36 } 37 38 if n, err := r.ReadAt(buf[:12], 8); err != nil { 39 t.Errorf("unexpected error: %s", err) 40 } else if n != 12 { 41 t.Errorf("expecting to read %d bytes, read %d", 12, n) 42 } else if string(buf[:12]) != "httpreaderat" { 43 t.Errorf("expecting to read string %q, read %q", "httpreaderat", buf[:12]) 44 } 45 46 if n, err := r.ReadAt(buf[:7], 0); err != nil { 47 t.Errorf("unexpected error: %s", err) 48 } else if n != 7 { 49 t.Errorf("expecting to read %d bytes, read %d", 7, n) 50 } else if string(buf[:7]) != "package" { 51 t.Errorf("expecting to read string %q, read %q", "package", buf[:7]) 52 } 53 54 if n, err := r.ReadAt(buf[:7], 1<<32); !errors.Is(err, io.EOF) { 55 t.Errorf("expecting error EOF, got %v", err) 56 } else if n != 0 { 57 t.Errorf("expecting to read %d bytes, read %d", 0, n) 58 } 59 } 60 61 func TestSetLength(t *testing.T) { 62 r, err := NewRequest("") 63 if err == nil { 64 t.Errorf("expecting error, got %v", err) 65 } else if r != nil { 66 t.Errorf("expecting nil request, got %v", r) 67 } 68 69 r, err = NewRequest("", SetLength(10)) 70 if err != nil { 71 t.Fatalf("unexpected error: %s", err) 72 } else if r.Length() != 10 { 73 t.Errorf("expecting length %d, got %d", 10, r.Length()) 74 } 75 } 76 77 type FS []byte 78 79 func (f FS) Open(file string) (fs.File, error) { 80 return &File{name: file, Reader: bytes.NewReader(f)}, nil 81 } 82 83 type File struct { 84 name string 85 *bytes.Reader 86 } 87 88 func (File) Close() error { return nil } 89 func (f *File) Stat() (fs.FileInfo, error) { return f, nil } 90 func (f *File) Name() string { return f.name } 91 func (File) IsDir() bool { return false } 92 func (File) ModTime() time.Time { return time.Now() } 93 func (File) Mode() fs.FileMode { return fs.ModePerm } 94 func (f *File) Sys() any { return f } 95 96 type requestCounter struct { 97 count int 98 http.Handler 99 } 100 101 func (rc *requestCounter) ServeHTTP(w http.ResponseWriter, r *http.Request) { 102 rc.count++ 103 104 rc.Handler.ServeHTTP(w, r) 105 } 106 107 func (rc *requestCounter) GetCount() int { 108 c := rc.count 109 110 rc.count = 0 111 112 return c 113 } 114 115 func TestLarge(t *testing.T) { 116 data := make(FS, 256) 117 118 n, err := rand.Read(data) 119 if err != nil { 120 t.Fatalf("unexpected error: %s", err) 121 } else if n != len(data) { 122 t.Fatalf("only read %d random bytes", n) 123 } 124 125 rc := &requestCounter{Handler: http.FileServerFS(data)} 126 127 srv := httptest.NewServer(rc) 128 129 r, err := NewRequest(srv.URL + "/httpreaderat_test.go") 130 if err != nil { 131 t.Fatalf("unexpected error: %s", err) 132 } else if r.Length() != int64(len(data)) { 133 t.Errorf("expecting length %d, got %d", len(data), r.Length()) 134 } else if count := rc.GetCount(); count != 1 { 135 t.Errorf("expecting 1 request, had %d", count) 136 } 137 138 r.blockSize = 10 139 140 testRead(t, data, r, rc, 0, 1, 1) // 0 141 testRead(t, data, r, rc, 0, 1, 0) // 0 142 testRead(t, data, r, rc, 0, 9, 0) // 0 143 testRead(t, data, r, rc, 0, 10, 0) // 0 144 testRead(t, data, r, rc, 1, 10, 1) // 1,2 145 testRead(t, data, r, rc, 11, 10, 1) // 2,3 146 testRead(t, data, r, rc, 38, 14, 1) // 3, 4, 5 147 testRead(t, data, r, rc, 71, 1, 1) // 7 148 testRead(t, data, r, rc, 68, 14, 1) // 6, 7, 8 149 } 150 151 func testRead(t *testing.T, data FS, r *Request, rc *requestCounter, start, length int64, requests int) { 152 t.Helper() 153 154 buf := make([]byte, length) 155 156 if n, err := r.ReadAt(buf, start); err != nil { 157 t.Errorf("unexpected error: %s", err) 158 } else if int64(n) != length { 159 t.Errorf("expected to read %d byte(s), read %d", length, n) 160 } else if count := rc.GetCount(); count != requests { 161 t.Errorf("expecting %d request(s), had %d", requests, count) 162 } else if string(buf) != string(data[start:start+length]) { 163 t.Errorf("expected to read %q, read %q", data[start:start+length], buf) 164 } 165 } 166