Files
CHFS-NG/chfs-ng/internal/api/share_archive_test.go
T

96 lines
2.9 KiB
Go

package api
import (
"archive/zip"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"chfs-ng/internal/auth"
"chfs-ng/internal/storage"
)
func TestSharedRoutesMatchCHFS(t *testing.T) {
root := t.TempDir()
if err := os.WriteFile(filepath.Join(root, "hello.txt"), []byte("hello"), 0o644); err != nil {
t.Fatal(err)
}
s := &Server{Store: storage.Local{Root: root}, Auth: &auth.Manager{Accounts: map[string]*auth.Account{}, Guest: &auth.Account{Mask: auth.Read | auth.Write | auth.Delete}}}
r := httptest.NewRequest(http.MethodGet, "/chfs/shared?file=hello.txt", nil)
w := httptest.NewRecorder()
s.Handler().ServeHTTP(w, r)
if w.Code != http.StatusMovedPermanently || w.Header().Get("Location") != "shared/?file=hello.txt" {
t.Fatalf("shared redirect: status=%d location=%q", w.Code, w.Header().Get("Location"))
}
r = httptest.NewRequest(http.MethodGet, "/chfs/shared/hello.txt", nil)
w = httptest.NewRecorder()
s.Handler().ServeHTTP(w, r)
if w.Code != http.StatusOK || w.Header().Get("Content-Disposition") != `attachment;filename="hello.txt"` {
t.Fatalf("shared file: status=%d disposition=%q", w.Code, w.Header().Get("Content-Disposition"))
}
body, _ := io.ReadAll(w.Result().Body)
if string(body) != "hello" {
t.Fatalf("shared body=%q", body)
}
}
func TestDownloadDirArchiveHeadersAndEntries(t *testing.T) {
root := t.TempDir()
dir := filepath.Join(root, "pack")
if err := os.Mkdir(dir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "a.txt"), []byte("abc"), 0o644); err != nil {
t.Fatal(err)
}
s := &Server{Store: storage.Local{Root: root}, Auth: &auth.Manager{Accounts: map[string]*auth.Account{}, Guest: &auth.Account{Mask: auth.Read | auth.Write | auth.Delete}}}
r := httptest.NewRequest(http.MethodGet, "/chfs/downloaddir/pack", nil)
w := httptest.NewRecorder()
s.Handler().ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("archive status=%d body=%s", w.Code, w.Body.String())
}
if got := w.Header().Get("Content-Type"); got != "application/zip" {
t.Fatalf("archive content type=%q", got)
}
if got := w.Header().Get("Content-Disposition"); got != "" {
t.Fatalf("CHFS archive must not emit Content-Disposition, got %q", got)
}
zr, err := zip.NewReader(bytesReaderAt{r: w.Body.Bytes()}, int64(w.Body.Len()))
if err != nil {
t.Fatalf("open archive: %v", err)
}
if len(zr.File) != 1 || zr.File[0].Name != "a.txt" {
t.Fatalf("archive entries=%v", archiveNames(zr.File))
}
if zr.File[0].UncompressedSize64 != 3 {
t.Fatalf("archive size=%d", zr.File[0].UncompressedSize64)
}
}
type bytesReaderAt struct{ r []byte }
func (b bytesReaderAt) ReadAt(p []byte, off int64) (int, error) {
if off >= int64(len(b.r)) {
return 0, io.EOF
}
n := copy(p, b.r[off:])
if n < len(p) {
return n, io.EOF
}
return n, nil
}
func archiveNames(files []*zip.File) []string {
n := make([]string, 0, len(files))
for _, f := range files {
n = append(n, f.Name)
}
return n
}