-
Notifications
You must be signed in to change notification settings - Fork 4
/
unittest_inttest.sh
690 lines (566 loc) · 16.3 KB
/
unittest_inttest.sh
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
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
#! __SHTK_SHELL__
# Copyright 2014 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of Google Inc. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Bootstrap and integration tests for the "unittest" module.
#
# This file implements a bunch of rudimentary tests for the "unittest"
# module and serve two purposes: first, that test programs using "unittest"
# and built via shtk are runnable and execute all defined test cases; and,
# second, that the pass/fail code of the test program matches the results
# of the individual test cases.
#
# This test program is purposely not written using shtk's modules at all
# precisely to ensure that the shtk+unittest combination works. Only once
# we have certain confidence in the behavior of shtk-based test programs,
# we can trust the results yielded by the more complex and detailed tests
# in unittest_test.sh.
# The program name for error-reporting purposes.
_ProgName="${0##*/}"
# Logs an error and fails the test program.
#
# \param ... Error message. Multiple arguments are concatenated using a
# single whitespace character.
fail() {
echo "${_ProgName}: ${*}" 1>&2
exit 1
}
# Executes a command and validates its exit code and its output.
#
# \param expected_exit_code Expected code that the command should return.
# \param expected_stdout_file Path to a file containing the expected stdout.
# \param expected_stderr_file Path to a file containing the expected stderr.
# \param ... The command to execute.
#
# \return True if the command's execution matches the expected conditions;
# false otherwise.
check() {
local expected_exit_code="${1}"; shift
local expected_stdout_file="${1}"; shift
local expected_stderr_file="${1}"; shift
local exit_code=0
"${@}" >out 2>err || exit_code="${?}"
local failed=no
[ "${exit_code}" -eq "${expected_exit_code}" ] || failed=yes
cmp -s "${expected_stdout_file}" out || failed=yes
cmp -s "${expected_stderr_file}" err || failed=yes
if [ "${failed}" = yes ]; then
echo "${@} failed"
echo "Expected exit code ${expected_exit_code}, got ${exit_code}"
diff -u "${expected_stdout_file}" out
diff -u "${expected_stderr_file}" err
return 1
fi
}
one_test__always_passes() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test always_passes
always_passes_test() {
echo "Hello"
}
EOF
cat >expout <<EOF
Hello
EOF
cat >experr <<EOF
program: I: Testing always_passes...
program: I: Testing always_passes... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
one_test__always_fails() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test always_fails
always_fails_test() {
echo "Hello"
fail "Oops! Explicitly failing"
echo "Bye"
}
EOF
cat >expout <<EOF
Hello
EOF
cat >experr <<EOF
program: I: Testing always_fails...
program: E: Oops! Explicitly failing
program: W: Testing always_fails... FAILED
program: W: Ran 1 tests; 1 FAILED
EOF
check 1 expout experr ./program || return 1
}
some_tests__all_pass() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() { echo "First"; }
shtk_unittest_add_test second
second_test() { set_expect_failure; fail "Second"; echo "not reached"; }
shtk_unittest_add_test third
third_test() { echo "Third"; }
EOF
cat >expout <<EOF
First
Third
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Testing second...
program: E: Expected failure: Second
program: I: Testing second... EXPECTED FAILURE
program: I: Testing third...
program: I: Testing third... PASSED
program: I: Ran 3 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
some_tests__some_fail() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() { echo "First"; }
shtk_unittest_add_test second
second_test() { echo "Second"; fail "Bailing out"; echo "Second bis"; }
shtk_unittest_add_test third
third_test() { echo "Third"; }
EOF
cat >expout <<EOF
First
Second
Third
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Testing second...
program: E: Bailing out
program: W: Testing second... FAILED
program: I: Testing third...
program: I: Testing third... PASSED
program: W: Ran 3 tests; 1 FAILED
EOF
check 1 expout experr ./program || return 1
}
fixtures() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_fixture first
first_fixture() {
setup() { echo "Shared setup"; }
teardown() { echo "Shared teardown"; }
shtk_unittest_add_test first
first_test() { echo "First in first fixture"; }
shtk_unittest_add_test second
second_test() { echo "Second in first fixture"; fail "Leave 1"; }
}
shtk_unittest_add_fixture second
second_fixture() {
shtk_unittest_add_test first
first_test() { echo "First in second fixture"; fail "Leave 2"; }
shtk_unittest_add_test second
second_test() { echo "Second in second fixture"; }
}
shtk_unittest_add_test standalone
standalone_test() {
echo "Runs outside of the fixtures"
}
EOF
cat >expout <<EOF
Runs outside of the fixtures
Shared setup
First in first fixture
Shared teardown
Shared setup
Second in first fixture
Shared teardown
First in second fixture
Second in second fixture
EOF
cat >experr <<EOF
program: I: Testing standalone...
program: I: Testing standalone... PASSED
program: I: Testing first__first...
program: I: Testing first__first... PASSED
program: I: Testing first__second...
program: E: Leave 1
program: W: Testing first__second... FAILED
program: I: Testing second__first...
program: E: Leave 2
program: W: Testing second__first... FAILED
program: I: Testing second__second...
program: I: Testing second__second... PASSED
program: W: Ran 5 tests; 2 FAILED
EOF
check 1 expout experr ./program || return 1
}
assert_command__ok() {
cat >command.sh <<EOF
echo "some contents to stdout"
echo "some contents to stderr" 1>&2
exit 42
EOF
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
echo "some contents to stdout" >expout
echo "some contents to stderr" >experr
assert_command -s exit:42 -o file:expout -e file:experr sh $(pwd)/command.sh
echo "reached"
}
EOF
cat >expout <<EOF
Running checked command: sh $(pwd)/command.sh
reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
assert_command__fail() {
cat >command.sh <<EOF
echo "some contents to stdout"
echo "some contents to stderr" 1>&2
exit 42
EOF
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
assert_command -s exit:42 sh $(pwd)/command.sh
echo "not reached"
}
EOF
cat >expout <<EOF
Running checked command: sh $(pwd)/command.sh
Expected standard output to be empty; found:
some contents to stdout
Expected standard error to be empty; found:
some contents to stderr
EOF
cat >experr <<EOF
program: I: Testing first...
program: E: Check of 'sh $(pwd)/command.sh' failed; see stdout for details
program: W: Testing first... FAILED
program: W: Ran 1 tests; 1 FAILED
EOF
check 1 expout experr ./program || return 1
}
expect_command__ok() {
cat >command.sh <<EOF
echo "some contents to stdout"
echo "some contents to stderr" 1>&2
exit 42
EOF
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
echo "some contents to stdout" >expout
echo "some contents to stderr" >experr
expect_command -s exit:42 -o file:expout -e file:experr sh $(pwd)/command.sh
echo "reached"
}
EOF
cat >expout <<EOF
Running checked command: sh $(pwd)/command.sh
reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
expect_command__fail() {
cat >command.sh <<EOF
echo "some contents to stdout"
echo "some contents to stderr" 1>&2
exit 42
EOF
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
expect_command -s exit:42 sh $(pwd)/command.sh
echo "reached"
expect_command sh $(pwd)/command.sh
echo "also reached"
}
EOF
cat >expout <<EOF
Running checked command: sh $(pwd)/command.sh
Expected standard output to be empty; found:
some contents to stdout
Expected standard error to be empty; found:
some contents to stderr
reached
Running checked command: sh $(pwd)/command.sh
Expected exit code 0 != actual exit code 42
stdout: some contents to stdout
stderr: some contents to stderr
also reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: W: Delayed failure: Check of 'sh $(pwd)/command.sh' failed; see stdout for details
program: W: Delayed failure: Check of 'sh $(pwd)/command.sh' failed; see stdout for details
program: W: Testing first... FAILED (2 delayed failures)
program: W: Ran 1 tests; 1 FAILED
EOF
check 1 expout experr ./program || return 1
}
assert_file__ok() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
touch actual
assert_file empty actual
echo "foo" >>actual
echo "bar" >>actual
assert_file not-empty actual
assert_file inline:"foo\nbar\n" actual
assert_file file:actual actual
assert_file stdin actual <actual
echo "reached"
}
EOF
cat >expout <<EOF
reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
assert_file__fail() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
touch actual
assert_file not-empty actual
echo reached
}
shtk_unittest_add_test second
second_test() {
echo "foo" >actual
assert_file empty actual
echo reached
}
shtk_unittest_add_test third
third_test() {
echo "foo" >actual
assert_file match:"foobar" actual
echo reached
}
EOF
cat >expout <<EOF
Expected actual to not be empty
Expected actual to be empty; found:
foo
Expected regexp 'foobar' not found in actual:
foo
EOF
cat >experr <<EOF
program: I: Testing first...
program: E: Failed to validate contents of file actual
program: W: Testing first... FAILED
program: I: Testing second...
program: E: Failed to validate contents of file actual
program: W: Testing second... FAILED
program: I: Testing third...
program: E: Failed to validate contents of file actual
program: W: Testing third... FAILED
program: W: Ran 3 tests; 3 FAILED
EOF
check 1 expout experr ./program || return 1
}
expect_file__ok() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
touch actual
expect_file empty actual
echo "foo" >>actual
echo "bar" >>actual
expect_file not-empty actual
expect_file inline:"foo\nbar\n" actual
expect_file file:actual actual
expect_file stdin actual <actual
echo "reached"
}
EOF
cat >expout <<EOF
reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: I: Testing first... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program || return 1
}
expect_file__fail() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_test first
first_test() {
touch actual
expect_file not-empty actual
echo "foo" >>actual
echo "bar" >>actual
expect_file empty actual
expect_file match:foobar actual
echo "reached"
}
EOF
cat >expout <<EOF
Expected actual to not be empty
Expected actual to be empty; found:
foo
bar
Expected regexp 'foobar' not found in actual:
foo
bar
reached
EOF
cat >experr <<EOF
program: I: Testing first...
program: W: Delayed failure: Failed to validate contents of file actual
program: W: Delayed failure: Failed to validate contents of file actual
program: W: Delayed failure: Failed to validate contents of file actual
program: W: Testing first... FAILED (3 delayed failures)
program: W: Ran 1 tests; 1 FAILED
EOF
check 1 expout experr ./program || return 1
}
filter() {
shtk build -m shtk_unittest_main -o program - <<EOF
shtk_import unittest
shtk_unittest_add_fixture first
first_fixture() {
setup() { echo "Shared setup"; }
teardown() { echo "Shared teardown"; }
shtk_unittest_add_test first
first_test() { echo "First in first fixture"; }
shtk_unittest_add_test second
second_test() { echo "Second in first fixture"; fail "Leave 1"; }
}
shtk_unittest_add_fixture second
second_fixture() {
shtk_unittest_add_test first
first_test() { echo "First in second fixture"; fail "Leave 2"; }
shtk_unittest_add_test second
second_test() { echo "Second in second fixture"; }
}
shtk_unittest_add_test standalone
standalone_test() {
echo "Runs outside of the fixtures"
}
EOF
cat >expout <<EOF
Runs outside of the fixtures
EOF
cat >experr <<EOF
program: I: Testing standalone...
program: I: Testing standalone... PASSED
program: I: Ran 1 tests; ALL PASSED
EOF
check 0 expout experr ./program -t standalone || return 1
cat >expout <<EOF
Shared setup
Second in first fixture
Shared teardown
EOF
cat >experr <<EOF
program: I: Testing first__second...
program: E: Leave 1
program: W: Testing first__second... FAILED
program: W: Ran 1 tests; 1 FAILED
EOF
check 1 expout experr ./program -t first__second || return 1
cat >expout <<EOF
Runs outside of the fixtures
Second in second fixture
EOF
cat >experr <<EOF
program: I: Testing standalone...
program: I: Testing standalone... PASSED
program: I: Testing second__second...
program: I: Testing second__second... PASSED
program: I: Ran 2 tests; ALL PASSED
EOF
check 0 expout experr ./program -t second__second -t standalone || return 1
cat >expout <<EOF
EOF
cat >experr <<EOF
program: E: No tests were run
EOF
check 1 expout experr ./program -t unknown-test || return 1
}
main() {
for name in \
one_test__always_passes \
one_test__always_fails \
some_tests__all_pass \
some_tests__some_fail \
fixtures \
assert_command__ok \
assert_command__fail \
expect_command__ok \
expect_command__fail \
assert_file__ok \
assert_file__fail \
expect_file__ok \
expect_file__fail \
filter
do
local failed=no
echo "Running test ${name}"
(
mkdir work
cd work
"${name}"
) || failed=yes
rm -rf work
[ "${failed}" = no ] || fail "unittest is severely broken; aborting!"
done
echo "OK!"
}
main "${@}"