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>
94 lines
3.1 KiB
Go
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"))
|
|
}
|
|
}
|