1package pflag
2
3import (
4	"fmt"
5	"strconv"
6	"strings"
7	"testing"
8)
9
10func setUpBSFlagSet(bsp *[]bool) *FlagSet {
11	f := NewFlagSet("test", ContinueOnError)
12	f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!")
13	return f
14}
15
16func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet {
17	f := NewFlagSet("test", ContinueOnError)
18	f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!")
19	return f
20}
21
22func TestEmptyBS(t *testing.T) {
23	var bs []bool
24	f := setUpBSFlagSet(&bs)
25	err := f.Parse([]string{})
26	if err != nil {
27		t.Fatal("expected no error; got", err)
28	}
29
30	getBS, err := f.GetBoolSlice("bs")
31	if err != nil {
32		t.Fatal("got an error from GetBoolSlice():", err)
33	}
34	if len(getBS) != 0 {
35		t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS))
36	}
37}
38
39func TestBS(t *testing.T) {
40	var bs []bool
41	f := setUpBSFlagSet(&bs)
42
43	vals := []string{"1", "F", "TRUE", "0"}
44	arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
45	err := f.Parse([]string{arg})
46	if err != nil {
47		t.Fatal("expected no error; got", err)
48	}
49	for i, v := range bs {
50		b, err := strconv.ParseBool(vals[i])
51		if err != nil {
52			t.Fatalf("got error: %v", err)
53		}
54		if b != v {
55			t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v)
56		}
57	}
58	getBS, err := f.GetBoolSlice("bs")
59	if err != nil {
60		t.Fatalf("got error: %v", err)
61	}
62	for i, v := range getBS {
63		b, err := strconv.ParseBool(vals[i])
64		if err != nil {
65			t.Fatalf("got error: %v", err)
66		}
67		if b != v {
68			t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v)
69		}
70	}
71}
72
73func TestBSDefault(t *testing.T) {
74	var bs []bool
75	f := setUpBSFlagSetWithDefault(&bs)
76
77	vals := []string{"false", "T"}
78
79	err := f.Parse([]string{})
80	if err != nil {
81		t.Fatal("expected no error; got", err)
82	}
83	for i, v := range bs {
84		b, err := strconv.ParseBool(vals[i])
85		if err != nil {
86			t.Fatalf("got error: %v", err)
87		}
88		if b != v {
89			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
90		}
91	}
92
93	getBS, err := f.GetBoolSlice("bs")
94	if err != nil {
95		t.Fatal("got an error from GetBoolSlice():", err)
96	}
97	for i, v := range getBS {
98		b, err := strconv.ParseBool(vals[i])
99		if err != nil {
100			t.Fatal("got an error from GetBoolSlice():", err)
101		}
102		if b != v {
103			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
104		}
105	}
106}
107
108func TestBSWithDefault(t *testing.T) {
109	var bs []bool
110	f := setUpBSFlagSetWithDefault(&bs)
111
112	vals := []string{"FALSE", "1"}
113	arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
114	err := f.Parse([]string{arg})
115	if err != nil {
116		t.Fatal("expected no error; got", err)
117	}
118	for i, v := range bs {
119		b, err := strconv.ParseBool(vals[i])
120		if err != nil {
121			t.Fatalf("got error: %v", err)
122		}
123		if b != v {
124			t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v)
125		}
126	}
127
128	getBS, err := f.GetBoolSlice("bs")
129	if err != nil {
130		t.Fatal("got an error from GetBoolSlice():", err)
131	}
132	for i, v := range getBS {
133		b, err := strconv.ParseBool(vals[i])
134		if err != nil {
135			t.Fatalf("got error: %v", err)
136		}
137		if b != v {
138			t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
139		}
140	}
141}
142
143func TestBSCalledTwice(t *testing.T) {
144	var bs []bool
145	f := setUpBSFlagSet(&bs)
146
147	in := []string{"T,F", "T"}
148	expected := []bool{true, false, true}
149	argfmt := "--bs=%s"
150	arg1 := fmt.Sprintf(argfmt, in[0])
151	arg2 := fmt.Sprintf(argfmt, in[1])
152	err := f.Parse([]string{arg1, arg2})
153	if err != nil {
154		t.Fatal("expected no error; got", err)
155	}
156	for i, v := range bs {
157		if expected[i] != v {
158			t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v)
159		}
160	}
161}
162
163func TestBSAsSliceValue(t *testing.T) {
164	var bs []bool
165	f := setUpBSFlagSet(&bs)
166
167	in := []string{"true", "false"}
168	argfmt := "--bs=%s"
169	arg1 := fmt.Sprintf(argfmt, in[0])
170	arg2 := fmt.Sprintf(argfmt, in[1])
171	err := f.Parse([]string{arg1, arg2})
172	if err != nil {
173		t.Fatal("expected no error; got", err)
174	}
175
176	f.VisitAll(func(f *Flag) {
177		if val, ok := f.Value.(SliceValue); ok {
178			_ = val.Replace([]string{"false"})
179		}
180	})
181	if len(bs) != 1 || bs[0] != false {
182		t.Fatalf("Expected ss to be overwritten with 'false', but got: %v", bs)
183	}
184}
185
186func TestBSBadQuoting(t *testing.T) {
187
188	tests := []struct {
189		Want    []bool
190		FlagArg []string
191	}{
192		{
193			Want:    []bool{true, false, true},
194			FlagArg: []string{"1", "0", "true"},
195		},
196		{
197			Want:    []bool{true, false},
198			FlagArg: []string{"True", "F"},
199		},
200		{
201			Want:    []bool{true, false},
202			FlagArg: []string{"T", "0"},
203		},
204		{
205			Want:    []bool{true, false},
206			FlagArg: []string{"1", "0"},
207		},
208		{
209			Want:    []bool{true, false, false},
210			FlagArg: []string{"true,false", "false"},
211		},
212		{
213			Want:    []bool{true, false, false, true, false, true, false},
214			FlagArg: []string{`"true,false,false,1,0,     T"`, " false "},
215		},
216		{
217			Want:    []bool{false, false, true, false, true, false, true},
218			FlagArg: []string{`"0, False,  T,false  , true,F"`, "true"},
219		},
220	}
221
222	for i, test := range tests {
223
224		var bs []bool
225		f := setUpBSFlagSet(&bs)
226
227		if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
228			t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v",
229				err, test.FlagArg, test.Want[i])
230		}
231
232		for j, b := range bs {
233			if b != test.Want[j] {
234				t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b)
235			}
236		}
237	}
238}
239