123 lines
3.5 KiB
Go
123 lines
3.5 KiB
Go
package server_test
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"net/url"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"g.fc.run/misc/byre/internal/api"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestTaskFiles(t *testing.T) {
|
||
|
|
h := newHarness(t)
|
||
|
|
p := h.createProject("demo")
|
||
|
|
task := api.Task{}
|
||
|
|
h.do("POST", "/api/projects/"+p.Id+"/tasks", api.TaskCreate{Title: "files"}, &task)
|
||
|
|
wt := task.WorktreePath
|
||
|
|
|
||
|
|
outside := t.TempDir()
|
||
|
|
writeFile(t, filepath.Join(outside, "secret"), "secret\n")
|
||
|
|
err := os.Mkdir(filepath.Join(wt, "src"), 0o755)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("mkdir: %v", err)
|
||
|
|
}
|
||
|
|
writeFile(t, filepath.Join(wt, "src", "main.go"), "package main\n")
|
||
|
|
writeFile(t, filepath.Join(wt, "src", "main.o"), "obj")
|
||
|
|
writeFile(t, filepath.Join(wt, ".gitignore"), "*.o\n/out/\n")
|
||
|
|
err = os.Mkdir(filepath.Join(wt, "out"), 0o755)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("mkdir: %v", err)
|
||
|
|
}
|
||
|
|
writeFile(t, filepath.Join(wt, "out", "app"), "bin")
|
||
|
|
writeFile(t, filepath.Join(wt, "blob.bin"), "a\x00b")
|
||
|
|
writeFile(t, filepath.Join(wt, "big.txt"), strings.Repeat("é", 200_000))
|
||
|
|
for name, target := range map[string]string{
|
||
|
|
"inlink": "src",
|
||
|
|
"outlink": filepath.Join(outside, "secret"),
|
||
|
|
"outdir": outside,
|
||
|
|
"dangling": "nope",
|
||
|
|
} {
|
||
|
|
err = os.Symlink(target, filepath.Join(wt, name))
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("symlink: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
dir := func(path string) (api.DirListing, int) {
|
||
|
|
l := api.DirListing{}
|
||
|
|
code := h.do("GET", "/api/tasks/"+task.Id+"/dir?path="+url.QueryEscape(path), nil, &l)
|
||
|
|
return l, code
|
||
|
|
}
|
||
|
|
file := func(path string) (api.FileContent, int) {
|
||
|
|
f := api.FileContent{}
|
||
|
|
code := h.do("GET", "/api/tasks/"+task.Id+"/file?path="+url.QueryEscape(path), nil, &f)
|
||
|
|
return f, code
|
||
|
|
}
|
||
|
|
|
||
|
|
root, code := dir("")
|
||
|
|
if code != http.StatusOK {
|
||
|
|
t.Fatalf("list root: %d", code)
|
||
|
|
}
|
||
|
|
names := func(l api.DirListing) string {
|
||
|
|
got := []string{}
|
||
|
|
for _, e := range l.Entries {
|
||
|
|
s := string(e.Type) + ":" + e.Name
|
||
|
|
if e.Ignored {
|
||
|
|
s += "!"
|
||
|
|
}
|
||
|
|
got = append(got, s)
|
||
|
|
}
|
||
|
|
return strings.Join(got, " ")
|
||
|
|
}
|
||
|
|
want := "dir:inlink dir:out! dir:src file:.gitignore file:README file:big.txt file:blob.bin other:dangling other:outdir other:outlink"
|
||
|
|
if names(root) != want {
|
||
|
|
t.Fatalf("root listing %q, want %q", names(root), want)
|
||
|
|
}
|
||
|
|
|
||
|
|
for path, want := range map[string]string{
|
||
|
|
"src": "file:main.go file:main.o!",
|
||
|
|
"inlink": "file:main.go file:main.o!",
|
||
|
|
"out": "file:app!",
|
||
|
|
} {
|
||
|
|
sub, code := dir(path)
|
||
|
|
if code != http.StatusOK || sub.Path != path || names(sub) != want {
|
||
|
|
t.Fatalf("list %s: %d %q, want %q", path, code, names(sub), want)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
f, code := file("src/main.go")
|
||
|
|
if code != http.StatusOK || f.Text != "package main\n" || f.Binary || f.Truncated {
|
||
|
|
t.Fatalf("read text: %d %+v", code, f)
|
||
|
|
}
|
||
|
|
|
||
|
|
f, code = file("blob.bin")
|
||
|
|
if code != http.StatusOK || !f.Binary || f.Text != "" || f.Size != 3 {
|
||
|
|
t.Fatalf("read binary: %d %+v", code, f)
|
||
|
|
}
|
||
|
|
|
||
|
|
f, code = file("big.txt")
|
||
|
|
if code != http.StatusOK || f.Binary || !f.Truncated || f.Size != 400_000 || len(f.Text) != 256<<10 {
|
||
|
|
t.Fatalf("read big: %d binary=%v truncated=%v size=%d len=%d", code, f.Binary, f.Truncated, f.Size, len(f.Text))
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, path := range []string{"../secret", "/etc/passwd", "src/../../x", "outlink", "outdir/secret", ".git", "src"} {
|
||
|
|
_, code = file(path)
|
||
|
|
if code != http.StatusBadRequest {
|
||
|
|
t.Fatalf("read %s: want 400, got %d", path, code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for _, path := range []string{"..", "outdir", "README"} {
|
||
|
|
_, code = dir(path)
|
||
|
|
if code != http.StatusBadRequest {
|
||
|
|
t.Fatalf("list %s: want 400, got %d", path, code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_, code = file("missing")
|
||
|
|
if code != http.StatusNotFound {
|
||
|
|
t.Fatalf("read missing: want 404, got %d", code)
|
||
|
|
}
|
||
|
|
}
|