1// Copyright 2020 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
5package quoted
6
7import (
8	"reflect"
9	"strings"
10	"testing"
11)
12
13func TestSplit(t *testing.T) {
14	for _, test := range []struct {
15		name    string
16		value   string
17		want    []string
18		wantErr string
19	}{
20		{name: "empty", value: "", want: nil},
21		{name: "space", value: " ", want: nil},
22		{name: "one", value: "a", want: []string{"a"}},
23		{name: "leading_space", value: " a", want: []string{"a"}},
24		{name: "trailing_space", value: "a ", want: []string{"a"}},
25		{name: "two", value: "a b", want: []string{"a", "b"}},
26		{name: "two_multi_space", value: "a  b", want: []string{"a", "b"}},
27		{name: "two_tab", value: "a\tb", want: []string{"a", "b"}},
28		{name: "two_newline", value: "a\nb", want: []string{"a", "b"}},
29		{name: "quote_single", value: `'a b'`, want: []string{"a b"}},
30		{name: "quote_double", value: `"a b"`, want: []string{"a b"}},
31		{name: "quote_both", value: `'a '"b "`, want: []string{"a ", "b "}},
32		{name: "quote_contains", value: `'a "'"'b"`, want: []string{`a "`, `'b`}},
33		{name: "escape", value: `\'`, want: []string{`\'`}},
34		{name: "quote_unclosed", value: `'a`, wantErr: "unterminated ' string"},
35	} {
36		t.Run(test.name, func(t *testing.T) {
37			got, err := Split(test.value)
38			if err != nil {
39				if test.wantErr == "" {
40					t.Fatalf("unexpected error: %v", err)
41				} else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) {
42					t.Fatalf("error %q does not contain %q", errMsg, test.wantErr)
43				}
44				return
45			}
46			if test.wantErr != "" {
47				t.Fatalf("unexpected success; wanted error containing %q", test.wantErr)
48			}
49			if !reflect.DeepEqual(got, test.want) {
50				t.Errorf("got %q; want %q", got, test.want)
51			}
52		})
53	}
54}
55
56func TestJoin(t *testing.T) {
57	for _, test := range []struct {
58		name          string
59		args          []string
60		want, wantErr string
61	}{
62		{name: "empty", args: nil, want: ""},
63		{name: "one", args: []string{"a"}, want: "a"},
64		{name: "two", args: []string{"a", "b"}, want: "a b"},
65		{name: "space", args: []string{"a ", "b"}, want: "'a ' b"},
66		{name: "newline", args: []string{"a\n", "b"}, want: "'a\n' b"},
67		{name: "quote", args: []string{`'a `, "b"}, want: `"'a " b`},
68		{name: "unquoteable", args: []string{`'"`}, wantErr: "contains both single and double quotes and cannot be quoted"},
69	} {
70		t.Run(test.name, func(t *testing.T) {
71			got, err := Join(test.args)
72			if err != nil {
73				if test.wantErr == "" {
74					t.Fatalf("unexpected error: %v", err)
75				} else if errMsg := err.Error(); !strings.Contains(errMsg, test.wantErr) {
76					t.Fatalf("error %q does not contain %q", errMsg, test.wantErr)
77				}
78				return
79			}
80			if test.wantErr != "" {
81				t.Fatalf("unexpected success; wanted error containing %q", test.wantErr)
82			}
83			if got != test.want {
84				t.Errorf("got %s; want %s", got, test.want)
85			}
86		})
87	}
88}
89