init
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package adminapi
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/iceBear67/simplepages/api"
|
||||
)
|
||||
|
||||
func TestCheckProjectName(t *testing.T) {
|
||||
valid := []string{
|
||||
"a", "0", "demo", "demo-site", "demo_site", "demo.site", "a1.b-c_d",
|
||||
strings.Repeat("z", 63),
|
||||
}
|
||||
for _, name := range valid {
|
||||
if err := checkProjectName(name); err != nil {
|
||||
t.Errorf("checkProjectName(%q) = %v, want nil", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Everything that could become a path separator, a traversal or a hidden
|
||||
// file once the name is turned into a "~name" entry in $WEBROOT.
|
||||
invalid := []string{
|
||||
"", ".", "..", "./x", "../x", "/demo", "demo/", "a/b", `a\b`,
|
||||
".hidden", "-lead", "_lead", "Demo", "DEMO", "démo", "demo ",
|
||||
" demo", "de mo", "demo\t", "demo\n", "demo\x00", "~demo", "demo%2f",
|
||||
strings.Repeat("z", 64),
|
||||
}
|
||||
for _, name := range invalid {
|
||||
err := checkProjectName(name)
|
||||
if err == nil {
|
||||
t.Errorf("checkProjectName(%q) = nil, want an error", name)
|
||||
continue
|
||||
}
|
||||
if got := api.CodeOf(err); got != api.CodeInvalidProjectName {
|
||||
t.Errorf("checkProjectName(%q) code = %q, want %q", name, got, api.CodeInvalidProjectName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckSitePath(t *testing.T) {
|
||||
valid := []string{
|
||||
"index.html", "404.html", "a/b/c.html", "a.b/c", "_next/index.html",
|
||||
"страница.html", strings.Repeat("a", maxSitePathLen),
|
||||
}
|
||||
for _, p := range valid {
|
||||
if err := checkSitePath("index_file", p); err != nil {
|
||||
t.Errorf("checkSitePath(%q) = %v, want nil", p, err)
|
||||
}
|
||||
}
|
||||
|
||||
invalid := []string{
|
||||
"", ".", "..", "/index.html", "index.html/", "a//b", "a/./b", "a/../b",
|
||||
"../../etc/passwd", `a\b`, "a\x00b", "a\nb", "a\x7fb",
|
||||
strings.Repeat("a", maxSitePathLen+1),
|
||||
}
|
||||
for _, p := range invalid {
|
||||
err := checkSitePath("index_file", p)
|
||||
if err == nil {
|
||||
t.Errorf("checkSitePath(%q) = nil, want an error", p)
|
||||
continue
|
||||
}
|
||||
if got := api.CodeOf(err); got != api.CodeInvalidPath {
|
||||
t.Errorf("checkSitePath(%q) code = %q, want %q", p, got, api.CodeInvalidPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckHeaderValue(t *testing.T) {
|
||||
valid := []string{
|
||||
"", "public, max-age=0, must-revalidate", "no-store",
|
||||
"public,\tmax-age=31536000, immutable", strings.Repeat("a", maxCacheControlLen),
|
||||
}
|
||||
for _, v := range valid {
|
||||
if err := checkHeaderValue("cache_control", v); err != nil {
|
||||
t.Errorf("checkHeaderValue(%q) = %v, want nil", v, err)
|
||||
}
|
||||
}
|
||||
|
||||
// A CR or LF here would let a project append headers of its own to every
|
||||
// response it serves, on an origin it shares with every other project.
|
||||
invalid := []string{
|
||||
"public\r\nX-Evil: 1", "public\nX-Evil: 1", "public\r", "public\x00",
|
||||
"public\x7f", "public é", strings.Repeat("a", maxCacheControlLen+1),
|
||||
}
|
||||
for _, v := range invalid {
|
||||
if err := checkHeaderValue("cache_control", v); err == nil {
|
||||
t.Errorf("checkHeaderValue(%q) = nil, want an error", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckText(t *testing.T) {
|
||||
// Free text is allowed to be anything printable, including non-ASCII: it is
|
||||
// a display name, not a header value.
|
||||
valid := []string{"", "Demo Site", "デモ", "a — b", strings.Repeat("x", maxDisplayNameLen)}
|
||||
for _, v := range valid {
|
||||
if err := checkText("display_name", v, maxDisplayNameLen); err != nil {
|
||||
t.Errorf("checkText(%q) = %v, want nil", v, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Control characters are not: these strings are printed to operator
|
||||
// terminals and written into structured logs.
|
||||
invalid := []string{
|
||||
"a\x1b[31mred", "line\nbreak", "car\rriage", "nul\x00", "del\x7f", "tab\there",
|
||||
strings.Repeat("x", maxDisplayNameLen+1),
|
||||
}
|
||||
for _, v := range invalid {
|
||||
if err := checkText("display_name", v, maxDisplayNameLen); err == nil {
|
||||
t.Errorf("checkText(%q) = nil, want an error", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user