96 lines
3.9 KiB
Go
96 lines
3.9 KiB
Go
package web_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Input that cannot be right is the caller's to fix: a 4xx, never a 500 (adversarial
|
|
// review F7). No cross-tenant oracle either way: unknown and foreign ids look the same.
|
|
|
|
func TestUploadRoutes_ANonUUIDIdIs404NotA500(t *testing.T) {
|
|
app, _ := newUploadApp(t, audioOK, 200<<20)
|
|
for _, path := range []string{"/uploads/not-a-uuid", "/uploads/not-a-uuid/status", "/uploads/not-a-uuid/chat", "/uploads/%00/status", "/uploads/1/status"} {
|
|
t.Run(path, func(t *testing.T) {
|
|
rec := do(t, app, get(path))
|
|
|
|
assert.Equal(t, http.StatusNotFound, rec.Code)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUploadPost_ATitleWithControlCharactersOrInvalidUTF8IsCleanedNotA500(t *testing.T) {
|
|
tests := []struct{ name, title, filename string }{
|
|
{"a NUL in the title", "Sprint\x00review", "a.m4a"},
|
|
{"invalid UTF-8 in the title", "Sprint \xff\xfe review", "a.m4a"},
|
|
{"a newline in the title", "Sprint\nreview", "a.m4a"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
app, sub := newUploadApp(t, audioOK, 200<<20)
|
|
|
|
rec := do(t, app, uploadReq(t, tt.title, tt.filename, []byte("synthetic audio bytes")))
|
|
|
|
require.Equal(t, http.StatusSeeOther, rec.Code, "bad bytes in a cosmetic title must not fail the upload: %s", body(t, rec))
|
|
require.Len(t, sub.jobs, 1)
|
|
var title string
|
|
require.NoError(t, rawPool(t).QueryRow(context.Background(), `SELECT title FROM uploaded_transcripts WHERE id = $1`, sub.jobs[0].UploadID).Scan(&title))
|
|
assert.NotContains(t, title, "\x00")
|
|
assert.NotContains(t, title, "\n")
|
|
assert.True(t, len(title) > 0, "a title is still shown")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUploadPost_AMalformedMultipartHeaderIsA400AndItsTextIsNotLogged(t *testing.T) {
|
|
// A control byte in the part's file name makes the multipart body malformed. It is the
|
|
// sender's to fix, and the parser's error quotes the header, which carries the name.
|
|
app, sub := newUploadApp(t, audioOK, 200<<20)
|
|
buf := &lockedBuf{}
|
|
app.Log = slog.New(slog.NewTextHandler(buf, nil))
|
|
|
|
rec := do(t, app, uploadReq(t, "", "zebrakaka\x00weekly.m4a", []byte("x")))
|
|
|
|
assert.Equal(t, http.StatusBadRequest, rec.Code)
|
|
assert.Empty(t, sub.jobs)
|
|
assert.NotContains(t, buf.String(), "zebrakaka", "a file name is private content")
|
|
}
|
|
|
|
func TestUploadPost_EveryBidirectionalControlCharacterIsStrippedFromATitle(t *testing.T) {
|
|
// U+202E reverses the text that follows it, so a title could render reversed on its
|
|
// owner's own page (second adversarial review). Every one of the twelve is pinned.
|
|
controls := []rune{0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x2066, 0x2067, 0x2068, 0x2069, 0x200E, 0x200F, 0x061C}
|
|
for _, c := range controls {
|
|
t.Run(fmt.Sprintf("U+%04X", c), func(t *testing.T) {
|
|
app, sub := newUploadApp(t, audioOK, 200<<20)
|
|
|
|
rec := do(t, app, uploadReq(t, "Sprint "+string(c)+"review", "a.m4a", []byte("x")))
|
|
|
|
require.Equal(t, http.StatusSeeOther, rec.Code)
|
|
var title string
|
|
require.NoError(t, rawPool(t).QueryRow(context.Background(), `SELECT title FROM uploaded_transcripts WHERE id = $1`, sub.jobs[0].UploadID).Scan(&title))
|
|
assert.Equal(t, "Sprintreview", title, "dropped, not replaced by a space: a space would leave a visible gap")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUploadPost_SwedishLettersAndEmojiSurviveTheTitleCleaning(t *testing.T) {
|
|
app, sub := newUploadApp(t, audioOK, 200<<20)
|
|
|
|
// Includes a ZWJ sequence (woman + ZWJ + laptop) and a ZWNJ: joiners are not direction controls.
|
|
rec := do(t, app, uploadReq(t, "Möte åäö 🎙️ 👩\u200d💻 a\u200cb", "a.m4a", []byte("x")))
|
|
|
|
require.Equal(t, http.StatusSeeOther, rec.Code)
|
|
var title string
|
|
require.NoError(t, rawPool(t).QueryRow(context.Background(), `SELECT title FROM uploaded_transcripts WHERE id = $1`, sub.jobs[0].UploadID).Scan(&title))
|
|
assert.Equal(t, "Möte åäö 🎙️ 👩\u200d💻 a\u200cb", title, "joiners and variation selectors belong to the text")
|
|
}
|