README.md
1# Archive-Zip Tests
2
3This document provides some information on writing tests for the
4Archive::Zip module. Note that the tests have been evolving
5rather organically over a long time and may contain old-fashioned
6Perl.
7
8
9## General Guidelines
10
11- To keep test headers somewhat uniform, use a header along the
12 following lines:
13
14 ```perl
15 #!/usr/bin/perl
16
17 # See https://github.com/redhotpenguin/perl-Archive-Zip/blob/master/t/README.md
18 # for a short documentation on the Archive::Zip test infrastructure.
19
20 use strict;
21
22 BEGIN { $^W = 1; }
23
24 use Test::More;
25
26 use Archive::Zip qw();
27
28 use lib 't';
29 use common;
30 ```
31
32- Use `BEGIN { $^W = 1; }` in the test headers instead of the
33 usually preferred `use warnings;` since that way the
34 Archive::Zip module itself and its descendants get executed
35 with warnings, too. Which, unfortunately, otherwise would
36 not be the case.
37
38- Keep test data below directory `t/data` without any
39 additional subdirectories and access it by means of function
40 `dataPath`.
41
42- Create temporary results only in directory `TESTDIR` and in
43 files `INPUTZIP` and `OUTPUTZIP` to avoid race conditions
44 when tests are executed in parallel. Access directory
45 `TESTDIR` and any paths below it by means of function
46 `testPath`.
47
48
49## Constants Provided by Package common
50
51Package common, included by `use lib 't'; use common;` in a test
52header, provides the following constants (which are all exported
53by default):
54
55- `TESTDIR`
56
57 Relative path to a unique (per test program) temporary test
58 directory located below the build directory of this module.
59 Better use function `testPath` to access that directory than
60 this constant.
61
62- `INPUTZIP`, `OUTPUTZIP`
63
64 Absolute paths to unique (per test program) temporary files
65 with extension `.zip` that could be used arbitrarily by
66 tests. Except above facts tests should assume nothing about
67 these files.
68
69- `TESTSTRING`, `TESTSTRINGLENGTH`, `TESTSTRINGCRC`
70
71 A somewhat harmless, ASCII-only-but-multi-line test string,
72 its length, and CRC.
73
74- `PATH_REL`, `PATH_ABS`, `PATH_ZIPFILE`, `PATH_ZIPDIR`, `PATH_ZIPABS`
75
76 Enumerators used by functions `dataPath` and `testPath`,
77 which see.
78
79
80## Functions Provided by Package common
81
82Package common provides the following auxilliary functions (which
83are all exported by default):
84
85- `passThrough( $fromFile, $toFile, $action );`
86
87 Reads archive `$fromFile`, executes `$action` on every member
88 (or does nothing if `$action` is false), writes the resulting
89 archive to `$toFile`.
90
91- `my $data = readFile( $file );`
92
93 The ubiquitous file slurping function.
94
95- `my ( $outErr, $exitVal ) = execProc( $command );`
96
97 The likewise ubiquitous process execution function. Even if
98 this function is exceedingly simple, please use it in favor
99 of direct `qx{...}` or other constructs to have one
100 consistent API.
101
102- `my ( $outErr, $exitVal ) = execPerl( @args );`
103
104 Executes the Perl running the current test program with the
105 specified arguments.
106
107- `my $file = dataPath( "simple" );`
108 `my $file = dataPath( "simple.zip" );`
109 `my $file = dataPath( "t/data/simple.zip" );`
110
111 Returns the path to the specified file below the `t/data`
112 directory located below the build directory of this module
113 ...
114
115 `my $file = dataPath( "simple.zip", PATH_REL );`
116
117 ... relative to the build directory with OS-specific path
118 item separators (the default),
119
120 `my $file = dataPath( "simple.zip", PATH_ABS );`
121
122 ... as absolute path with OS-specific path item separators,
123
124 `my $file = dataPath( "simple.zip", PATH_ZIPFILE );`
125
126 ... relative to the build directory in Zip (internal) file
127 name format, that is, always with forward slashes as path
128 item separators,
129
130 `my $file = dataPath( "simple.zip", PATH_ZIPDIR );`
131
132 ... relative to the build directory in Zip (internal) file
133 name format and with a final trailing slash,
134
135 `my $file = dataPath( "simple.zip", PATH_ZIPABS );`
136
137 ... as absolute path but with any volume specifier stripped
138 and in Zip (internal) file name format.
139
140- `my $file = testPath( @pathItems, $pathType );`
141
142 Returns the path to the specified file below the directory
143 denoted by `TESTDIR` in the format specified by the optional
144 path type, which is one of `PATH_REL` (the default),
145 `PATH_ABS`, `PATH_ZIPFILE`, `PATH_ZIPDIR`, or `PATH_ZIPABS`,
146 see above.
147
148
149## Test Functions Provided by Package common
150
151Package common provides below test functions (which are all
152exported by default). "Test functions" means that these
153functions generate valid TAP and could (and should) be used
154instead of Test::More functions where appropriate.
155
156Note that some of the test functions rely on a particular
157`$Archive::Zip::Errorhandler` being in place, so avoid using your
158own handler unless you know what you are doing.
159
160As usual, specification of the test name is optional.
161
162- `azbinis( $got, $expected, $name );`
163
164 Test that succeeds like `is` from Test::More, but which
165 provides additional diagnostics when comparison of lengthy
166 binary `$got` and `$expected` fails. Does not return any
167 meaningful value.
168
169- `my $ok = azok( $status, $name );`
170
171 Test that succeeds if `$status` equals `AZ_OK` and fails
172 otherwise. Provides built-in diagnostics in case of test
173 failure and returns the test verdict.
174
175- `my $ok = azis( $status, $expectedStatus, $name );`
176 `my $ok = azis( $status, qr/$errorMatchingRegexp/, $name );`
177 `my $ok = azis( $status, $expectedStatus, qr/$errorMatchingRegexp/, $name );`
178
179 Test that succeeds if the specified status equals the
180 expected status (one of the `:ERROR_CODES` constants) and/or,
181 if an error has been generated, if the error message matches
182 the specified regexp. Provides built-in diagnostics in case
183 of test failure and returns the test verdict.
184
185- `my $fileHandle = azopen( $file )`
186
187 Creates and returns a file handle to write to the specified
188 file (defaulting to `OUTPUTZIP`). If possible, a piped file
189 handle, otherwise a regular one. Returns the undefined value
190 on failure.
191
192- ```
193 my $ok = azuztok( [['file' =>] $file,]
194 ['name' => $name] );
195 ```
196
197 Test that succeeds if `unzip -t` on the specified file
198 (defaulting to `OUTPUTZIP`) returns exit value zero. This
199 function provides built-in diagnostics in case of test
200 failure and returns the test verdict regardless of the
201 specific calling syntax.
202
203- ```
204 my $ok = azuztok( [['file' =>] $file,]
205 'refzip' => $refzip,
206 ['name' => $name] );
207 ```
208
209 Test that succeeds if `unzip -t` on the specified file
210 returns the same exit value as `unzip -t` on the specified
211 reference zip file.
212
213- ```
214 my $ok = azuztok( [['file' =>] $file,]
215 'xppats' => $xppats,
216 ['name' => $name] );
217 ```
218
219 Test that succeeds depending on the exit value of `unzip -t`
220 on the specified file, its STDOUT and STDERR, and the
221 operating system the test is running on.
222
223 The expected patterns `$xppats` must be specified as a list
224 of triples `[$exitVal, $outerrRegexp, $osName]`, like this:
225
226 ```
227 my $ok = azuztok( "emptyzip.zip",
228 'xppats' => [[0, undef, 'freebsd'],
229 [0, undef, 'netbsd'],
230 [undef, qr/\bempty\b/, undef]] );
231 ```
232
233 Meaning: Expect exit value zero on FreeBSD and NetBSD
234 (disregarding STDOUT and STDERR on these), and expect STDOUT
235 and STDERR matching `/\bempty\b/` on all other operating
236 systems (disregarding exit value on these).
237
238- `azwok( $zip, %params )`
239
240 Test (actually 6 of them) that succeeds if the specified
241 archive can be written (both using a plain and a piped file
242 handle) and tested using `unzip -t`.
243
244 Accepts a hash of optional parameters `file`, `refzip`,
245 `xppats`, `name`, which are processed as explained for
246 function `azuztok`. Does not return any meaningful value.
247