| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package controller
- import (
- "bytes"
- "errors"
- "io"
- "io/fs"
- "net/http"
- "net/http/httptest"
- "testing"
- "testing/fstest"
- "git.aetherial.dev/aeth/keiji/pkg/storage"
- "github.com/gin-gonic/gin"
- )
- type trackedImageStream struct {
- *bytes.Reader
- closed bool
- }
- func (s *trackedImageStream) Close() error { s.closed = true; return nil }
- type streamingRepo struct {
- *mediaRepo
- stream *trackedImageStream
- err error
- }
- func (r *streamingRepo) OpenImage(id storage.Identifier) (storage.Image, storage.ReadSeekCloser, error) {
- return storage.Image{MediaType: "video/webm"}, r.stream, r.err
- }
- func TestServeImageStream(t *testing.T) {
- gin.SetMode(gin.TestMode)
- for _, tc := range []struct {
- method, rangeHeader string
- status int
- body string
- }{
- {"GET", "bytes=2-5", 206, "2345"}, {"HEAD", "", 200, ""}, {"GET", "bytes=20-30", 416, ""},
- } {
- stream := &trackedImageStream{Reader: bytes.NewReader([]byte("0123456789"))}
- repo := &streamingRepo{mediaRepo: &mediaRepo{}, stream: stream}
- router := gin.New()
- c := &Controller{database: repo}
- router.Handle(tc.method, "/images/:file", c.ServeImage)
- req := httptest.NewRequest(tc.method, "/images/x", nil)
- req.Header.Set("Range", tc.rangeHeader)
- res := httptest.NewRecorder()
- router.ServeHTTP(res, req)
- if res.Code != tc.status || (tc.status != 416 && res.Body.String() != tc.body) || !stream.closed {
- t.Fatalf("%s %d %q closed=%v", tc.method, res.Code, res.Body.String(), stream.closed)
- }
- }
- }
- type trackingFS struct{ file *trackingFile }
- func (f trackingFS) Open(name string) (fs.File, error) { return f.file, nil }
- type trackingFile struct {
- fs.File
- closed bool
- fail bool
- }
- func (f *trackingFile) Close() error { f.closed = true; return f.File.Close() }
- func (f *trackingFile) Read(b []byte) (int, error) {
- if f.fail {
- return 0, errors.New("read failed")
- }
- return f.File.Read(b)
- }
- func TestServeGenericClosesFile(t *testing.T) {
- gin.SetMode(gin.TestMode)
- for _, fail := range []bool{false, true} {
- f, err := (fstest.MapFS{"cdn/a.js": &fstest.MapFile{Data: []byte("test")}}).Open("cdn/a.js")
- if err != nil {
- t.Fatal(err)
- }
- tf := &trackingFile{File: f, fail: fail}
- c := &Controller{FileIO: trackingFS{tf}}
- router := gin.New()
- router.GET("/cdn/:file", c.ServeGeneric)
- res := httptest.NewRecorder()
- router.ServeHTTP(res, httptest.NewRequest(http.MethodGet, "/cdn/a.js", nil))
- want := 200
- if fail {
- want = 500
- }
- if res.Code != want || !tf.closed {
- t.Fatalf("status %d closed %v", res.Code, tf.closed)
- }
- }
- }
- var _ io.ReadSeeker = (*trackedImageStream)(nil)
|