blob: ae1ef96750c4b9c571f5ee61ee9c16a223f742d0 [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"reflect"
"strings"
"testing"
)
func newFileSet(kv ...string) *fileSet {
fs := new(fileSet)
if kv[0] == "prog.go!implicit" {
fs.noHeader = true
kv[0] = "prog.go"
}
for len(kv) > 0 {
fs.AddFile(kv[0], []byte(kv[1]))
kv = kv[2:]
}
return fs
}
func TestSplitFiles(t *testing.T) {
for _, tt := range []struct {
name string
in string
want *fileSet
wantErr string
}{
{
name: "classic",
in: "package main",
want: newFileSet("prog.go!implicit", "package main\n"),
},
{
name: "implicit prog.go",
in: "package main\n-- two.go --\nsecond",
want: newFileSet(
"prog.go!implicit", "package main\n",
"two.go", "second\n",
),
},
{
name: "basic txtar",
in: "-- main.go --\npackage main\n-- foo.go --\npackage main\n",
want: newFileSet(
"main.go", "package main\n",
"foo.go", "package main\n",
),
},
{
name: "reject dotdot 1",
in: "-- ../foo --\n",
wantErr: `invalid file name "../foo"`,
},
{
name: "reject dotdot 2",
in: "-- .. --\n",
wantErr: `invalid file name ".."`,
},
{
name: "reject dotdot 3",
in: "-- bar/../foo --\n",
wantErr: `invalid file name "bar/../foo"`,
},
{
name: "reject long",
in: "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --\n",
wantErr: `file name too long`,
},
{
name: "reject deep",
in: "-- x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x --\n",
wantErr: `file name "x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x" too deep`,
},
{
name: "reject abs",
in: "-- /etc/passwd --\n",
wantErr: `invalid file name "/etc/passwd"`,
},
{
name: "reject backslash",
in: "-- foo\\bar --\n",
wantErr: `invalid file name "foo\\bar"`,
},
{
name: "reject binary null",
in: "-- foo\x00bar --\n",
wantErr: `invalid file name "foo\x00bar"`,
},
{
name: "reject binary low",
in: "-- foo\x1fbar --\n",
wantErr: `invalid file name "foo\x1fbar"`,
},
{
name: "reject dup",
in: "-- foo.go --\n-- foo.go --\n",
wantErr: `duplicate file name "foo.go"`,
},
{
name: "reject implicit dup",
in: "package main\n-- prog.go --\n",
wantErr: `duplicate file name "prog.go"`,
},
{
name: "skip leading whitespace comment",
in: "\n \n\n \n\n-- f.go --\ncontents",
want: newFileSet("f.go", "contents\n"),
},
{
name: "reject many files",
in: strings.Repeat("-- x.go --\n", 50),
wantErr: `too many files in txtar archive (50 exceeds limit of 20)`,
},
} {
got, err := splitFiles([]byte(tt.in))
var gotErr string
if err != nil {
gotErr = err.Error()
}
if gotErr != tt.wantErr {
if tt.wantErr == "" {
t.Errorf("%s: unexpected error: %v", tt.name, err)
continue
}
t.Errorf("%s: error = %#q; want error %#q", tt.name, err, tt.wantErr)
continue
}
if err != nil {
continue
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("%s: wrong files\n got:\n%s\nwant:\n%s", tt.name, filesAsString(got), filesAsString(tt.want))
}
}
}
func filesAsString(fs *fileSet) string {
var sb strings.Builder
for i, f := range fs.files {
var implicit string
if i == 0 && f == progName && fs.noHeader {
implicit = " (implicit)"
}
fmt.Fprintf(&sb, "[file %q%s]: %q\n", f, implicit, fs.m[f])
}
return sb.String()
}