-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand_test.go
More file actions
167 lines (140 loc) · 5.47 KB
/
Copy pathcommand_test.go
File metadata and controls
167 lines (140 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package command_test
import (
"context"
"testing"
gloo "github.com/gloo-foo/framework"
command "github.com/gloo-foo/cmd-seq"
)
func collect(t *testing.T, src gloo.Source[[]byte]) []string {
t.Helper()
got, err := gloo.Collect(context.Background(), src.Stream(context.Background()))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
result := make([]string, len(got))
for i, b := range got {
result[i] = string(b)
}
return result
}
func assertStrings(t *testing.T, got, want []string) {
t.Helper()
if len(got) != len(want) {
t.Fatalf("got %d items %v, want %d items %v", len(got), got, len(want), want)
}
for i := range want {
if got[i] != want[i] {
t.Errorf("item %d: got %q, want %q", i, got[i], want[i])
}
}
}
func TestSeq_SingleArg(t *testing.T) {
assertStrings(t, collect(t, command.Seq(3)), []string{"1", "2", "3"})
}
func TestSeq_Range(t *testing.T) {
assertStrings(t, collect(t, command.Seq(2, 5)), []string{"2", "3", "4", "5"})
}
func TestSeq_Step(t *testing.T) {
assertStrings(t, collect(t, command.Seq(1, 2, 7)), []string{"1", "3", "5", "7"})
}
func TestSeq_EqualWidth(t *testing.T) {
got := collect(t, command.Seq(8, 11, command.SeqEqualWidth))
assertStrings(t, got, []string{"08", "09", "10", "11"})
}
func TestSeq_EqualWidthSingleDigits(t *testing.T) {
got := collect(t, command.Seq(1, 5, command.SeqEqualWidth))
assertStrings(t, got, []string{"1", "2", "3", "4", "5"})
}
func TestSeq_EqualWidthLargeRange(t *testing.T) {
got := collect(t, command.Seq(1, 100, command.SeqEqualWidth))
if got[0] != "001" {
t.Errorf("first item: got %q, want %q", got[0], "001")
}
if got[99] != "100" {
t.Errorf("last item: got %q, want %q", got[99], "100")
}
}
func TestSeq_Separator(t *testing.T) {
got := collect(t, command.Seq(1, 4, command.SeqSeparator(", ")))
assertStrings(t, got, []string{"1, 2, 3, 4"})
}
func TestSeq_SeparatorColon(t *testing.T) {
got := collect(t, command.Seq(1, 3, command.SeqSeparator(":")))
assertStrings(t, got, []string{"1:2:3"})
}
func TestSeq_EmptySeparatorJoinsWithNothing(t *testing.T) {
// seq -s '' 1 3 -> an explicitly empty separator still joins the whole run
// onto a single line, with nothing between the numbers.
got := collect(t, command.Seq(1, 3, command.SeqSeparator("")))
assertStrings(t, got, []string{"123"})
}
func TestSeq_UnknownOptionIsIgnored(t *testing.T) {
// A non-numeric argument of an unrecognized type is not a seq option; it is
// ignored and the sequence renders as if it were absent.
got := collect(t, command.Seq(1, 3, struct{}{}))
assertStrings(t, got, []string{"1", "2", "3"})
}
func TestSeq_Format(t *testing.T) {
got := collect(t, command.Seq(1, 3, command.SeqFormat("%05.2f")))
assertStrings(t, got, []string{"01.00", "02.00", "03.00"})
}
func TestSeq_FormatSimple(t *testing.T) {
got := collect(t, command.Seq(1, 3, command.SeqFormat("%.0f")))
assertStrings(t, got, []string{"1", "2", "3"})
}
func TestSeq_SeparatorAndFormat(t *testing.T) {
got := collect(t, command.Seq(1, 3, command.SeqSeparator(" "), command.SeqFormat("%02.0f")))
assertStrings(t, got, []string{"01 02 03"})
}
func TestSeq_DescendingNegativeStep(t *testing.T) {
// seq 5 -1 1 walks downward and is inclusive of last.
assertStrings(t, collect(t, command.Seq(5, -1, 1)), []string{"5", "4", "3", "2", "1"})
}
func TestSeq_NegativeStepLargerStride(t *testing.T) {
// seq 10 -2 1 stops at the last value not below 1.
assertStrings(t, collect(t, command.Seq(10, -2, 1)), []string{"10", "8", "6", "4", "2"})
}
func TestSeq_DescendingWithoutNegativeStepIsEmpty(t *testing.T) {
// seq 3 1 with the default +1 step never reaches a value <= 1, so GNU emits
// nothing.
assertStrings(t, collect(t, command.Seq(3, 1)), []string{})
}
func TestSeq_ZeroStepIsEmpty(t *testing.T) {
// A zero step can never advance; rather than loop forever, the walk is empty.
assertStrings(t, collect(t, command.Seq(1.0, 0.0, 5.0)), []string{})
}
func TestSeq_FloatIncrement(t *testing.T) {
// seq 1 0.5 2.5 -> fractional steps render with %g by default.
assertStrings(t, collect(t, command.Seq(1.0, 0.5, 2.5)), []string{"1", "1.5", "2", "2.5"})
}
func TestSeq_EqualWidthFractional(t *testing.T) {
// seq -w 8 0.5 10 -> a fixed one-decimal precision, zero-padded to width 4,
// matching GNU exactly (08.0 .. 10.0).
got := collect(t, command.Seq(8.0, 0.5, 10.0, command.SeqEqualWidth))
assertStrings(t, got, []string{"08.0", "08.5", "09.0", "09.5", "10.0"})
}
func TestSeq_EqualWidthNegativeFractional(t *testing.T) {
// seq -w -1 0.5 1 -> zero padding lands after the sign: -1.0, ..., 00.0, 01.0.
got := collect(t, command.Seq(-1.0, 0.5, 1.0, command.SeqEqualWidth))
assertStrings(t, got, []string{"-1.0", "-0.5", "00.0", "00.5", "01.0"})
}
func TestSeq_NoEqualWidthMatchesDefault(t *testing.T) {
// The disabled -w form behaves exactly like passing no flag.
got := collect(t, command.Seq(8, 11, command.SeqNoEqualWidth))
assertStrings(t, got, []string{"8", "9", "10", "11"})
}
// TestSeq_DiscardStopsProducer pulls a single item and then discards the stream.
// The framework's generator uses an unbuffered channel, so the producer blocks
// on the next send; the discard makes that send report false, exercising the
// early-return path in emit.
func TestSeq_DiscardStopsProducer(t *testing.T) {
stream := command.Seq(1, 1000).Stream(context.Background())
first := <-stream.Chan()
if first.Error != nil {
t.Fatalf("unexpected error: %v", first.Error)
}
if got := string(first.Value); got != "1" {
t.Fatalf("first item: got %q, want %q", got, "1")
}
stream.Discard()
}