Files
Mitchell-JohnsonandClaude Opus 5.5 d5c16540a1 files: video previews are made on the Transcode device too
The setting's device makes every video preview: on the file's own machine
when it is there (the hub tells it by header), else on the device's machine,
which reads the file through the hub by a one-file token, and the preview is
kept in the file's machine's own cache (PUT /api/files/thumb, refused if the
file changed). Images and covers stay on the file's machine's CPU. If the
device's machine can't, the file's makes it as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 16:07:00 -07:00

94 lines
3.1 KiB
Go

package api
import (
"fmt"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"hamlab/internal/config"
"hamlab/internal/files"
)
// The file a machine transcodes from another is read through the hub by a token naming that
// one file: ranges pass through, the query can't point it anywhere else, and an unknown token
// is nothing.
func TestPlaySrc(t *testing.T) {
dir := t.TempDir()
p := filepath.Join(dir, "film.mp4")
if err := os.WriteFile(p, []byte("0123456789"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "other.mp4"), []byte("secret"), 0o644); err != nil {
t.Fatal(err)
}
s := &Server{fsLocal: files.Local{}, cfg: &config.Config{Listen: "10.0.0.234:8100"}}
u, err := s.srcURL("", "", p, false)
if err != nil || !strings.HasPrefix(u, "http://10.0.0.234:8100/api/play-src/") {
t.Fatalf("url %q %v", u, err)
}
tok := strings.TrimPrefix(u, "http://10.0.0.234:8100/api/play-src/")
get := func(tok, query, rng string) *httptest.ResponseRecorder {
r := httptest.NewRequest("GET", "/api/play-src/"+tok+query, nil)
r.SetPathValue("token", tok)
if rng != "" {
r.Header.Set("Range", rng)
}
w := httptest.NewRecorder()
s.playSrc(w, r)
return w
}
if w := get(tok, "", "bytes=2-4"); w.Code != 206 || w.Body.String() != "234" {
t.Fatalf("range: %d %q", w.Code, w.Body)
}
if w := get(tok, "?path="+filepath.Join(dir, "other.mp4"), ""); w.Body.String() != "0123456789" {
t.Fatalf("the query moved it: %q", w.Body)
}
if w := get("nope", "", ""); w.Code != 404 {
t.Fatalf("unknown token: %d", w.Code)
}
}
// A preview made on another machine is kept by the file's own: only while the file is still
// the one it was made of, and a failure is kept as a failure.
func TestThumbPut(t *testing.T) {
dir := t.TempDir()
p := filepath.Join(dir, "film.mp4")
if err := os.WriteFile(p, []byte("0123456789"), 0o644); err != nil {
t.Fatal(err)
}
fi, _ := os.Stat(p)
s := &Server{fsLocal: files.Local{}, thumbs: newThumbSvc(dir, "")}
v := fmt.Sprintf("%d-%d", fi.ModTime().UnixMilli(), fi.Size())
put := func(v string, body string, hdr map[string]string) int {
r := httptest.NewRequest("PUT", "/api/files/thumb?path="+url.QueryEscape(p)+"&v="+v, strings.NewReader(body))
for k, x := range hdr {
r.Header.Set(k, x)
}
w := httptest.NewRecorder()
s.thumbPut(w, r)
return w.Code
}
get := func() *httptest.ResponseRecorder {
r := httptest.NewRequest("GET", "/api/files/thumb?cached=1&path="+url.QueryEscape(p)+"&v="+v, nil)
w := httptest.NewRecorder()
s.filesThumb(w, r)
return w
}
if w := get(); w.Code != 404 {
t.Fatalf("cached=1 before anything: %d", w.Code)
}
if c := put("1-10", "jpeg", nil); c != 409 {
t.Fatalf("a changed file: %d", c)
}
if c := put(v, "jpeg-bytes", map[string]string{"X-Hamlab-Thumb": "grid vaapi:/dev/dri/renderD129"}); c != 204 {
t.Fatalf("put: %d", c)
}
if w := get(); w.Code != 200 || w.Body.String() != "jpeg-bytes" || !strings.Contains(w.Header().Get("X-Hamlab-Thumb"), "grid") {
t.Fatalf("kept: %d %q %q", w.Code, w.Body, w.Header().Get("X-Hamlab-Thumb"))
}
}