golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/txtar_test.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  func newFileSet(kv ...string) *fileSet {
    15  	fs := new(fileSet)
    16  	if kv[0] == "prog.go!implicit" {
    17  		fs.noHeader = true
    18  		kv[0] = "prog.go"
    19  	}
    20  	for len(kv) > 0 {
    21  		fs.AddFile(kv[0], []byte(kv[1]))
    22  		kv = kv[2:]
    23  	}
    24  	return fs
    25  }
    26  
    27  func TestSplitFiles(t *testing.T) {
    28  	for _, tt := range []struct {
    29  		name    string
    30  		in      string
    31  		want    *fileSet
    32  		wantErr string
    33  	}{
    34  		{
    35  			name: "classic",
    36  			in:   "package main",
    37  			want: newFileSet("prog.go!implicit", "package main\n"),
    38  		},
    39  		{
    40  			name: "implicit prog.go",
    41  			in:   "package main\n-- two.go --\nsecond",
    42  			want: newFileSet(
    43  				"prog.go!implicit", "package main\n",
    44  				"two.go", "second\n",
    45  			),
    46  		},
    47  		{
    48  			name: "basic txtar",
    49  			in:   "-- main.go --\npackage main\n-- foo.go --\npackage main\n",
    50  			want: newFileSet(
    51  				"main.go", "package main\n",
    52  				"foo.go", "package main\n",
    53  			),
    54  		},
    55  		{
    56  			name:    "reject dotdot 1",
    57  			in:      "-- ../foo --\n",
    58  			wantErr: `invalid file name "../foo"`,
    59  		},
    60  		{
    61  			name:    "reject dotdot 2",
    62  			in:      "-- .. --\n",
    63  			wantErr: `invalid file name ".."`,
    64  		},
    65  		{
    66  			name:    "reject dotdot 3",
    67  			in:      "-- bar/../foo --\n",
    68  			wantErr: `invalid file name "bar/../foo"`,
    69  		},
    70  		{
    71  			name:    "reject long",
    72  			in:      "-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --\n",
    73  			wantErr: `file name too long`,
    74  		},
    75  		{
    76  			name:    "reject deep",
    77  			in:      "-- x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x --\n",
    78  			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`,
    79  		},
    80  		{
    81  			name:    "reject abs",
    82  			in:      "-- /etc/passwd --\n",
    83  			wantErr: `invalid file name "/etc/passwd"`,
    84  		},
    85  		{
    86  			name:    "reject backslash",
    87  			in:      "-- foo\\bar --\n",
    88  			wantErr: `invalid file name "foo\\bar"`,
    89  		},
    90  		{
    91  			name:    "reject binary null",
    92  			in:      "-- foo\x00bar --\n",
    93  			wantErr: `invalid file name "foo\x00bar"`,
    94  		},
    95  		{
    96  			name:    "reject binary low",
    97  			in:      "-- foo\x1fbar --\n",
    98  			wantErr: `invalid file name "foo\x1fbar"`,
    99  		},
   100  		{
   101  			name:    "reject dup",
   102  			in:      "-- foo.go --\n-- foo.go --\n",
   103  			wantErr: `duplicate file name "foo.go"`,
   104  		},
   105  		{
   106  			name:    "reject implicit dup",
   107  			in:      "package main\n-- prog.go --\n",
   108  			wantErr: `duplicate file name "prog.go"`,
   109  		},
   110  		{
   111  			name: "skip leading whitespace comment",
   112  			in:   "\n    \n\n   \n\n-- f.go --\ncontents",
   113  			want: newFileSet("f.go", "contents\n"),
   114  		},
   115  		{
   116  			name:    "reject many files",
   117  			in:      strings.Repeat("-- x.go --\n", 50),
   118  			wantErr: `too many files in txtar archive (50 exceeds limit of 20)`,
   119  		},
   120  	} {
   121  		got, err := splitFiles([]byte(tt.in))
   122  		var gotErr string
   123  		if err != nil {
   124  			gotErr = err.Error()
   125  		}
   126  		if gotErr != tt.wantErr {
   127  			if tt.wantErr == "" {
   128  				t.Errorf("%s: unexpected error: %v", tt.name, err)
   129  				continue
   130  			}
   131  			t.Errorf("%s: error = %#q; want error %#q", tt.name, err, tt.wantErr)
   132  			continue
   133  		}
   134  		if err != nil {
   135  			continue
   136  		}
   137  		if !reflect.DeepEqual(got, tt.want) {
   138  			t.Errorf("%s: wrong files\n got:\n%s\nwant:\n%s", tt.name, filesAsString(got), filesAsString(tt.want))
   139  		}
   140  	}
   141  }
   142  
   143  func filesAsString(fs *fileSet) string {
   144  	var sb strings.Builder
   145  	for i, f := range fs.files {
   146  		var implicit string
   147  		if i == 0 && f == progName && fs.noHeader {
   148  			implicit = " (implicit)"
   149  		}
   150  		fmt.Fprintf(&sb, "[file %q%s]: %q\n", f, implicit, fs.Data(f))
   151  	}
   152  	return sb.String()
   153  }