std.t: create_file(): Use `>` as separate parameter in open()
[sunny256-utils.git] / tests / sort-sqlite.t
blob6e37f893b7dc93cfc9fde553b88dd4ed982e9b89
1 #!/usr/bin/env perl
3 #=======================================================================
4 # sort-sqlite.t
5 # File ID: b5f7d80e-70ff-11e5-96fa-fefdb24f8e10
7 # Test suite for sort-sqlite(1).
9 # Character set: UTF-8
10 # ©opyleft 2015– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of
12 # file for legal stuff.
13 #=======================================================================
15 use strict;
16 use warnings;
18 BEGIN {
19 use Test::More qw{no_plan};
20 # use_ok() goes here
23 use Getopt::Long;
24 use IPC::Open3;
26 local $| = 1;
28 our $CMD_BASENAME = "sort-sqlite";
29 our $CMD = "../$CMD_BASENAME";
30 our $SQLITE = "sqlite3";
32 our %Opt = (
34 'all' => 0,
35 'help' => 0,
36 'quiet' => 0,
37 'todo' => 0,
38 'verbose' => 0,
39 'version' => 0,
43 our $progname = $0;
44 $progname =~ s/^.*\/(.*?)$/$1/;
45 our $VERSION = '0.0.0';
47 my %descriptions = ();
49 Getopt::Long::Configure('bundling');
50 GetOptions(
52 'all|a' => \$Opt{'all'},
53 'help|h' => \$Opt{'help'},
54 'quiet|q+' => \$Opt{'quiet'},
55 'todo|t' => \$Opt{'todo'},
56 'verbose|v+' => \$Opt{'verbose'},
57 'version' => \$Opt{'version'},
59 ) || die("$progname: Option error. Use -h for help.\n");
61 $Opt{'verbose'} -= $Opt{'quiet'};
62 $Opt{'help'} && usage(0);
63 if ($Opt{'version'}) {
64 print_version();
65 exit(0);
68 my $sql_error = 0;
70 exit(main());
72 sub main {
73 # {{{
74 my $Retval = 0;
76 diag(sprintf('========== Executing %s v%s ==========',
77 $progname, $VERSION));
79 if ($Opt{'todo'} && !$Opt{'all'}) {
80 goto todo_section;
83 =pod
85 testcmd("$CMD command", # {{{
86 <<'END',
87 [expected stdout]
88 END
89 '',
91 'description',
94 # }}}
96 =cut
98 diag('Testing -h (--help) option...');
99 likecmd("$CMD -h", # {{{
100 '/ Show this help/i',
101 '/^$/',
103 'Option -h prints help screen',
106 # }}}
107 diag('Testing -v (--verbose) option...');
108 likecmd("$CMD -hv", # {{{
109 '/^\n\S+ \d+\.\d+\.\d+/s',
110 '/^$/',
112 'Option -v with -h returns version number and help screen',
115 # }}}
116 diag('Testing --version option...');
117 likecmd("$CMD --version", # {{{
118 '/^\S+ \d+\.\d+\.\d+/',
119 '/^$/',
121 'Option --version returns version number',
124 # }}}
125 ok(chdir("sort-sqlite-files"), "chdir sort-sqlite-files");
126 $CMD = "../$CMD";
127 testcmd("tar xzf sqlite-dbs.tar.gz", # {{{
131 "Untar sqlite-dbs.tar.gz",
134 # }}}
135 ok(chdir("sqlite-dbs"), "chdir sqlite-dbs");
136 $CMD = "../$CMD";
137 testcmd("$CMD -c abc.def non-existing.sqlite", # {{{
139 "sort-sqlite: non-existing.sqlite: File is not readable by you or is not a regular file\n",
141 "Try to open a non-existing file",
144 # }}}
145 testcmd("$CMD unsorted1.sqlite", # {{{
147 "sort-sqlite: Missing -c/--column option\n",
149 "Missing -c/--column option",
152 # }}}
153 likecmd("$CMD -c non.existing unsorted1.sqlite", # {{{
154 '/^$/',
155 '/^.*sort-sqlite: unsorted1.sqlite: sqlite3 error, aborting\n$/s',
157 "Try to sort unsorted1.sqlite with unknown table and column",
160 # }}}
161 is(sqlite_dump("unsorted1.sqlite"), # {{{
162 <<END,
163 CREATE TABLE t (
164 a TEXT
171 "unsorted1.sqlite is not modified",
174 # }}}
175 testcmd("$CMD -c t.a unsorted1.sqlite", # {{{
179 "Sort unsorted1.sqlite",
182 # }}}
183 is(sqlite_dump("unsorted1.sqlite"), # {{{
184 <<END,
185 CREATE TABLE t (
186 a TEXT
193 "unsorted1.sqlite looks ok",
196 # }}}
197 ok(-f "unsorted1.sqlite.20151012T164244Z.bck", "Backup file 1 exists");
198 testcmd("$CMD -v --column t.a -c u.a unsorted2.sqlite " .
199 "unsorted3.sqlite", # {{{
201 "sort-sqlite: Sorting unsorted2.sqlite\n" .
202 "sort-sqlite: Sorting unsorted3.sqlite\n",
204 "Sort several tables in unsorted2.sqlite",
207 # }}}
208 is(sqlite_dump("unsorted2.sqlite"), # {{{
209 <<END,
210 CREATE TABLE u (
211 a TEXT
213 CREATE TABLE t (
214 a TEXT
223 u|aa
224 u|→
226 "unsorted2.sqlite looks ok",
229 # }}}
230 is(sqlite_dump("unsorted3.sqlite"), # {{{
231 <<END,
232 CREATE TABLE u (
233 a TEXT
235 CREATE TABLE one (
236 single TEXT
238 CREATE TABLE t (
239 a TEXT
241 one|z
249 u|aa
250 u|→
252 "unsorted3.sqlite looks ok",
255 # }}}
256 testcmd("$CMD -c t.a unsorted4.sqlite --column u.a", # {{{
260 "Sort unsorted4.sqlite, entries have several lines",
263 # }}}
264 ok(-f "unsorted4.sqlite.20161103T235439Z.bck", "Backup file 4 exists");
265 is(sqlite_dump("unsorted4.sqlite"), # {{{
266 <<END,
267 CREATE TABLE u (
268 a TEXT
270 CREATE TABLE t (
271 a TEXT
273 t|\n\nanother\n\nmulti\nline\n
279 u|aa
280 u|multi\nline\nhere
281 u|→
283 "unsorted4.sqlite looks ok",
286 # }}}
287 ok(-f "unsorted2.sqlite.20151012T164437Z.bck", "Backup file 2 exists");
288 ok(-f "unsorted3.sqlite.20151012T181141Z.bck", "Backup file 3 exists");
289 ok(unlink("unsorted1.sqlite"), "Delete unsorted1.sqlite");
290 ok(unlink("unsorted2.sqlite"), "Delete unsorted2.sqlite");
291 ok(unlink("unsorted3.sqlite"), "Delete unsorted3.sqlite");
292 ok(unlink("unsorted4.sqlite"), "Delete unsorted4.sqlite");
293 ok(unlink("unsorted1.sqlite.20151012T164244Z.bck"), "Delete backup 1");
294 ok(unlink("unsorted2.sqlite.20151012T164437Z.bck"), "Delete backup 2");
295 ok(unlink("unsorted3.sqlite.20151012T181141Z.bck"), "Delete backup 3");
296 ok(unlink("unsorted4.sqlite.20161103T235439Z.bck"), "Delete backup 4");
297 ok(chdir(".."), "chdir ..");
298 ok(rmdir("sqlite-dbs"), "rmdir sqlite-dbs");
300 todo_section:
303 if ($Opt{'all'} || $Opt{'todo'}) {
304 diag('Running TODO tests...'); # {{{
306 TODO: {
308 local $TODO = '';
309 # Insert TODO tests here.
312 # TODO tests }}}
315 diag('Testing finished.');
316 return $Retval;
317 # }}}
318 } # main()
320 sub sql {
321 # {{{
322 my ($db, $sql) = @_;
323 my @retval = ();
325 msg(5, "sql(): db = '$db'");
326 local(*CHLD_IN, *CHLD_OUT, *CHLD_ERR);
328 my $pid = open3(*CHLD_IN, *CHLD_OUT, *CHLD_ERR, $SQLITE, $db) or (
329 $sql_error = 1,
330 msg(0, "sql(): open3() error: $!"),
331 return("sql() error"),
333 msg(5, "sql(): sql = '$sql'");
334 print(CHLD_IN "$sql\n") or msg(0, "sql(): print CHLD_IN error: $!");
335 close(CHLD_IN);
336 @retval = <CHLD_OUT>;
337 msg(5, "sql(): retval = '" . join('|', @retval) . "'");
338 my @child_stderr = <CHLD_ERR>;
339 if (scalar(@child_stderr)) {
340 msg(1, "$SQLITE error: " . join('', @child_stderr));
341 $sql_error = 1;
343 return(join('', @retval));
344 # }}}
345 } # sql()
347 sub sqlite_dump {
348 # Return contents of database file {{{
349 my $File = shift;
351 return sql($File, <<END);
352 .nullvalue NULL
353 .schema
354 SELECT 'one', * FROM one;
355 SELECT 't', * FROM t;
356 SELECT 'u', * FROM u;
358 # }}}
359 } # sqlite_dump()
361 sub testcmd {
362 # {{{
363 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
364 defined($descriptions{$Desc}) &&
365 BAIL_OUT("testcmd(): '$Desc' description is used twice");
366 $descriptions{$Desc} = 1;
367 my $stderr_cmd = '';
368 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
369 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
370 my $TMP_STDERR = "$CMD_BASENAME-stderr.tmp";
371 my $retval = 1;
373 if (defined($Exp_stderr)) {
374 $stderr_cmd = " 2>$TMP_STDERR";
376 $retval &= is(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
377 my $ret_val = $?;
378 if (defined($Exp_stderr)) {
379 $retval &= is(file_data($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
380 unlink($TMP_STDERR);
381 } else {
382 diag("Warning: stderr not defined for '$Txt'");
384 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
386 return $retval;
387 # }}}
388 } # testcmd()
390 sub likecmd {
391 # {{{
392 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
393 defined($descriptions{$Desc}) &&
394 BAIL_OUT("likecmd(): '$Desc' description is used twice");
395 $descriptions{$Desc} = 1;
396 my $stderr_cmd = '';
397 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
398 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
399 my $TMP_STDERR = "$CMD_BASENAME-stderr.tmp";
400 my $retval = 1;
402 if (defined($Exp_stderr)) {
403 $stderr_cmd = " 2>$TMP_STDERR";
405 $retval &= like(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
406 my $ret_val = $?;
407 if (defined($Exp_stderr)) {
408 $retval &= like(file_data($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
409 unlink($TMP_STDERR);
410 } else {
411 diag("Warning: stderr not defined for '$Txt'");
413 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
415 return $retval;
416 # }}}
417 } # likecmd()
419 sub file_data {
420 # Return file content as a string {{{
421 my $File = shift;
422 my $Txt;
424 open(my $fp, '<', $File) or return undef;
425 local $/ = undef;
426 $Txt = <$fp>;
427 close($fp);
428 return $Txt;
429 # }}}
430 } # file_data()
432 sub print_version {
433 # Print program version {{{
434 print("$progname $VERSION\n");
435 return;
436 # }}}
437 } # print_version()
439 sub usage {
440 # Send the help message to stdout {{{
441 my $Retval = shift;
443 if ($Opt{'verbose'}) {
444 print("\n");
445 print_version();
447 print(<<"END");
449 Usage: $progname [options]
451 Contains tests for the $CMD_BASENAME(1) program.
453 Options:
455 -a, --all
456 Run all tests, also TODOs.
457 -h, --help
458 Show this help.
459 -q, --quiet
460 Be more quiet. Can be repeated to increase silence.
461 -t, --todo
462 Run only the TODO tests.
463 -v, --verbose
464 Increase level of verbosity. Can be repeated.
465 --version
466 Print version information.
469 exit($Retval);
470 # }}}
471 } # usage()
473 sub msg {
474 # Print a status message to stderr based on verbosity level {{{
475 my ($verbose_level, $Txt) = @_;
477 $verbose_level > $Opt{'verbose'} && return;
478 print(STDERR "$progname: $Txt\n");
479 return;
480 # }}}
481 } # msg()
483 __END__
485 # This program is free software; you can redistribute it and/or modify
486 # it under the terms of the GNU General Public License as published by
487 # the Free Software Foundation; either version 2 of the License, or (at
488 # your option) any later version.
490 # This program is distributed in the hope that it will be useful, but
491 # WITHOUT ANY WARRANTY; without even the implied warranty of
492 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
493 # See the GNU General Public License for more details.
495 # You should have received a copy of the GNU General Public License
496 # along with this program.
497 # If not, see L<http://www.gnu.org/licenses/>.
499 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :