-
Notifications
You must be signed in to change notification settings - Fork 34
/
commands_display_test.go
313 lines (283 loc) · 10.2 KB
/
commands_display_test.go
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
package main
import (
"bytes"
"fmt"
"runtime"
"strings"
"testing"
"github.com/fatih/color"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var ansiColor = func() (c *color.Color) {
c = color.New(color.FgCyan)
c.EnableColor()
return
}()
var colored = ansiColor.SprintFunc()
func TestDisplayWriter(t *testing.T) {
flags, noAnsiFlags := commandLineFlags{}, commandLineFlags{noAnsi: true}
buffer := bytes.Buffer{}
write := func(clf commandLineFlags, v ...any) string {
buffer.Reset()
out, closer := displayWriter(&buffer, clf)
out(v...)
closer()
return buffer.String()
}
t.Run("write-plain", func(t *testing.T) {
actual := write(flags, "hello %s %d")
assert.Equal(t, "hello %s %d", actual)
})
t.Run("write-with-format", func(t *testing.T) {
actual := write(flags, "hello %s %02d", "world", 5)
assert.Equal(t, "hello world 05", actual)
})
t.Run("write-tabs", func(t *testing.T) {
actual := write(flags, "col1\tcol2\tcol3\nvalue1\tvalue2\tvalue3")
assert.Equal(t, "col1 col2 col3\nvalue1 value2 value3", actual)
})
t.Run("no-ansi", func(t *testing.T) {
actual := write(flags, colored("test"))
assert.Equal(t, colored("test"), actual)
actual = write(noAnsiFlags, colored("test"))
assert.Equal(t, "test", actual)
})
}
func TestLineLengthWriter(t *testing.T) {
tests := []struct {
input, expected string
chunks, scale int
}{
// test non-breakable
{input: strings.Repeat("-", 50), expected: strings.Repeat("-", 50), chunks: 15},
// test breakable without columns
{
input: strings.Repeat("word ", 20),
expected: "" +
strings.TrimSpace(strings.Repeat("word ", 8)) + "\n" +
strings.TrimSpace(strings.Repeat("word ", 8)) + "\n" +
strings.Repeat("word ", 4),
chunks: 5, scale: 6,
},
// test breakable with ANSI color
{
input: strings.Repeat(colored("word "), 20),
expected: "" +
strings.Repeat(colored("word "), 7) + colored("word\n") +
strings.Repeat(colored("word "), 7) + colored("word\n") +
strings.Repeat(colored("word "), 4),
},
// test breakable with 2 columns
{
input: "word word word word " +
strings.Repeat("word ", 20),
expected: "" +
"word word word word " +
"word word word\n" +
strings.Repeat(" word word word\n", 5) +
" word word ",
chunks: 3, scale: 15,
},
// test breakable with 2 columns and ANSI color
{
input: colored("word word word word ") +
strings.Repeat(colored("word "), 20),
expected: "" +
colored("word word word word ") +
colored("word ") + colored("word ") + colored("word\n ") +
strings.Repeat(colored("word ")+colored("word ")+colored("word\n "), 5) +
colored("word ") + colored("word "),
},
// test real-world content
{
input: `
Usage of resticprofile:
resticprofile [resticprofile flags] [profile name.][restic command] [restic flags]
resticprofile [resticprofile flags] [profile name.][resticprofile command] [command specific flags]
resticprofile flags:
-c, --config string configuration file (default "profiles")
--dry-run display the restic commands instead of running them
-f, --format string file format of the configuration (default is to use the file extension)
-h, --help display this help
--lock-wait duration wait up to duration to acquire a lock (syntax "1h5m30s")
-l, --log string logs to a target instead of the console
-n, --name string profile name (default "default")
--no-ansi disable ansi control characters (disable console colouring)
--no-lock skip profile lock file
--no-prio don't set any priority on load: used when started from a service that has already set the priority
-q, --quiet display only warnings and errors
--theme string console colouring theme (dark, light, none) (default "light")
--trace display even more debugging information
-v, --verbose display some debugging information
-w, --wait wait at the end until the user presses the enter key
resticprofile own commands:
help display help (run in verbose mode for detailed information)
version display version (run in verbose mode for detailed information)
self-update update to latest resticprofile (use -q/--quiet flag to update without confirmation)
profiles display profile names from the configuration file
show show all the details of the current profile
schedule schedule jobs from a profile (use --all flag to schedule all jobs of all profiles)
unschedule remove scheduled jobs of a profile (use --all flag to unschedule all profiles)
status display the status of scheduled jobs (use --all flag for all profiles)
generate generate resources (--random-key [size], --bash-completion & --zsh-completion)
Documentation available at https://creativeprojects.github.io/resticprofile/
`,
expected: `
Usage of resticprofile:
resticprofile [resticprofile flags]
[profile name.][restic command]
[restic flags]
resticprofile [resticprofile flags]
[profile name.][resticprofile
command] [command specific flags]
resticprofile flags:
-c, --config string
configuration
file (default
"profiles")
--dry-run display
the restic
commands
instead of
running them
-f, --format string file
format of the
configuration
(default is to
use the file
extension)
-h, --help display
this help
--lock-wait duration wait up to
duration to acquire a lock
(syntax "1h5m30s")
-l, --log string logs to a
target instead
of the console
-n, --name string profile
name (default
"default")
--no-ansi disable
ansi control
characters
(disable
console
colouring)
--no-lock skip
profile lock
file
--no-prio don't set
any priority
on load: used
when started
from a service
that has
already set
the priority
-q, --quiet display
only warnings
and errors
--theme string console
colouring
theme (dark,
light, none)
(default
"light")
--trace display
even more
debugging
information
-v, --verbose display
some debugging
information
-w, --wait wait at
the end until
the user
presses the
enter key
resticprofile own commands:
help display help (run in
verbose mode for
detailed information)
version display version (run
in verbose mode for
detailed information)
self-update update to latest
resticprofile (use
-q/--quiet flag to
update without
confirmation)
profiles display profile names
from the configuration
file
show show all the details
of the current profile
schedule schedule jobs from a
profile (use --all
flag to schedule all
jobs of all profiles)
unschedule remove scheduled jobs
of a profile (use
--all flag to
unschedule all
profiles)
status display the status of
scheduled jobs (use
--all flag for all
profiles)
generate generate resources
(--random-key [size],
--bash-completion &
--zsh-completion)
Documentation available at
https://creativeprojects.github.io/resticprofile/
`,
},
}
for i, test := range tests {
if test.scale == 0 {
test.scale = 1
}
for chunkSize := 0; chunkSize <= test.chunks; chunkSize++ {
t.Run(fmt.Sprintf("%d-%d", i, chunkSize), func(t *testing.T) {
buffer := bytes.Buffer{}
writer := newLineLengthWriter(&buffer, 40)
input := []byte(test.input)
var (
n int
err error
)
switch chunkSize {
case 0:
n, err = writer.Write(input)
assert.Equal(t, len(input), n)
default:
for len(input) > 0 && err == nil {
length := test.scale * chunkSize
if length > len(input) {
length = len(input)
}
n, err = writer.Write(input[:length])
assert.Equal(t, length, n)
input = input[length:]
}
}
assert.Nil(t, err)
assert.Equal(t, test.expected, buffer.String())
})
}
}
}
func TestDisplayVersionVerbose1(t *testing.T) {
buffer := &bytes.Buffer{}
err := displayVersion(buffer, commandContext{Context: Context{flags: commandLineFlags{verbose: true}}})
require.NoError(t, err)
assert.True(t, strings.Contains(buffer.String(), runtime.GOOS))
}
func TestDisplayVersionVerbose2(t *testing.T) {
buffer := &bytes.Buffer{}
err := displayVersion(buffer, commandContext{Context: Context{request: Request{arguments: []string{"-v"}}}})
require.NoError(t, err)
assert.True(t, strings.Contains(buffer.String(), runtime.GOOS))
}