github.com/rogpeppe/go-internal@v1.12.1-0.20240509064211-c8567cf8e95f/txtar/archive_test.go (about)

     1  // Copyright 2018 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 txtar
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  var tests = []struct {
    15  	name   string
    16  	text   string
    17  	parsed *Archive
    18  }{
    19  	// General test
    20  	{
    21  		name: "basic",
    22  		text: `comment1
    23  comment2
    24  -- file1 --
    25  File 1 text.
    26  -- foo ---
    27  More file 1 text.
    28  -- file 2 --
    29  File 2 text.
    30  -- empty --
    31  -- noNL --
    32  hello world`,
    33  		parsed: &Archive{
    34  			Comment: []byte("comment1\ncomment2\n"),
    35  			Files: []File{
    36  				{"file1", []byte("File 1 text.\n-- foo ---\nMore file 1 text.\n")},
    37  				{"file 2", []byte("File 2 text.\n")},
    38  				{"empty", []byte{}},
    39  				{"noNL", []byte("hello world\n")},
    40  			},
    41  		},
    42  	},
    43  	// Test CRLF input
    44  	{
    45  		name: "basicCRLF",
    46  		text: "blah\r\n-- hello --\r\nhello\r\n",
    47  		parsed: &Archive{
    48  			Comment: []byte("blah\r\n"),
    49  			Files: []File{
    50  				{"hello", []byte("hello\r\n")},
    51  			},
    52  		},
    53  	},
    54  }
    55  
    56  func Test(t *testing.T) {
    57  	for _, tt := range tests {
    58  		t.Run(tt.name, func(t *testing.T) {
    59  			a := Parse([]byte(tt.text))
    60  			if !reflect.DeepEqual(a, tt.parsed) {
    61  				t.Fatalf("Parse: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed))
    62  			}
    63  			text := Format(a)
    64  			a = Parse(text)
    65  			if !reflect.DeepEqual(a, tt.parsed) {
    66  				t.Fatalf("Parse after Format: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed))
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  func shortArchive(a *Archive) string {
    73  	var buf bytes.Buffer
    74  	fmt.Fprintf(&buf, "comment: %q\n", a.Comment)
    75  	for _, f := range a.Files {
    76  		fmt.Fprintf(&buf, "file %q: %q\n", f.Name, f.Data)
    77  	}
    78  	return buf.String()
    79  }
    80  
    81  func TestWrite(t *testing.T) {
    82  	td := t.TempDir()
    83  
    84  	good := &Archive{Files: []File{File{Name: "good.txt"}}}
    85  	if err := Write(good, td); err != nil {
    86  		t.Fatalf("expected no error; got %v", err)
    87  	}
    88  
    89  	badRel := &Archive{Files: []File{File{Name: "../bad.txt"}}}
    90  	want := `"../bad.txt": outside parent directory`
    91  	if err := Write(badRel, td); err == nil || err.Error() != want {
    92  		t.Fatalf("expected %v; got %v", want, err)
    93  	}
    94  
    95  	badAbs := &Archive{Files: []File{File{Name: "/bad.txt"}}}
    96  	want = `"/bad.txt": outside parent directory`
    97  	if err := Write(badAbs, td); err == nil || err.Error() != want {
    98  		t.Fatalf("expected %v; got %v", want, err)
    99  	}
   100  }
   101  
   102  var unquoteErrorTests = []struct {
   103  	testName    string
   104  	data        string
   105  	expectError string
   106  }{{
   107  	testName:    "no final newline",
   108  	data:        ">hello",
   109  	expectError: `data does not appear to be quoted`,
   110  }, {
   111  	testName:    "no initial >",
   112  	data:        "hello\n",
   113  	expectError: `data does not appear to be quoted`,
   114  }}
   115  
   116  func TestUnquote(t *testing.T) {
   117  	for _, test := range unquoteErrorTests {
   118  		t.Run(test.testName, func(t *testing.T) {
   119  			_, err := Unquote([]byte(test.data))
   120  			if err == nil {
   121  				t.Fatalf("unexpected success")
   122  			}
   123  			if err.Error() != test.expectError {
   124  				t.Fatalf("unexpected error; got %q want %q", err, test.expectError)
   125  			}
   126  		})
   127  	}
   128  }
   129  
   130  var quoteTests = []struct {
   131  	testName    string
   132  	data        string
   133  	expect      string
   134  	expectError string
   135  }{{
   136  	testName: "empty",
   137  	data:     "",
   138  	expect:   "",
   139  }, {
   140  	testName: "one line",
   141  	data:     "foo\n",
   142  	expect:   ">foo\n",
   143  }, {
   144  	testName: "several lines",
   145  	data:     "foo\nbar\n-- baz --\n",
   146  	expect:   ">foo\n>bar\n>-- baz --\n",
   147  }, {
   148  	testName:    "bad data",
   149  	data:        "foo\xff\n",
   150  	expectError: `data contains non-UTF-8 characters`,
   151  }, {
   152  	testName:    "no final newline",
   153  	data:        "foo",
   154  	expectError: `data has no final newline`,
   155  }}
   156  
   157  func TestQuote(t *testing.T) {
   158  	for _, test := range quoteTests {
   159  		t.Run(test.testName, func(t *testing.T) {
   160  			got, err := Quote([]byte(test.data))
   161  			if test.expectError != "" {
   162  				if err == nil {
   163  					t.Fatalf("unexpected success")
   164  				}
   165  				if err.Error() != test.expectError {
   166  					t.Fatalf("unexpected error; got %q want %q", err, test.expectError)
   167  				}
   168  				return
   169  			}
   170  			if err != nil {
   171  				t.Fatalf("quote error: %v", err)
   172  			}
   173  			if string(got) != test.expect {
   174  				t.Fatalf("unexpected result; got %q want %q", got, test.expect)
   175  			}
   176  			orig, err := Unquote(got)
   177  			if err != nil {
   178  				t.Fatal(err)
   179  			}
   180  			if string(orig) != test.data {
   181  				t.Fatalf("round trip failed; got %q want %q", orig, test.data)
   182  			}
   183  		})
   184  	}
   185  }