datefmt: Define 1 year as 365.2425 days instead of 365.25
[sunny256-utils.git] / tests / edit-sqlite3.t
blob6f5b5d84fdcf2a56a28fd168eed2e4cc30d8b3d3
1 #!/usr/bin/env perl
3 #=======================================================================
4 # edit-sqlite3.t
5 # File ID: dd33f796-6a8c-11e5-8a5b-fefdb24f8e10
7 # Test suite for edit-sqlite3(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;
25 local $| = 1;
27 our $CMDB = "edit-sqlite3";
28 our $CMD = "../$CMDB";
30 our %Opt = (
32 'all' => 0,
33 'help' => 0,
34 'quiet' => 0,
35 'todo' => 0,
36 'verbose' => 0,
37 'version' => 0,
41 our $progname = $0;
42 $progname =~ s/^.*\/(.*?)$/$1/;
43 our $VERSION = '0.0.0';
45 my %descriptions = ();
47 Getopt::Long::Configure('bundling');
48 GetOptions(
50 'all|a' => \$Opt{'all'},
51 'help|h' => \$Opt{'help'},
52 'quiet|q+' => \$Opt{'quiet'},
53 'todo|t' => \$Opt{'todo'},
54 'verbose|v+' => \$Opt{'verbose'},
55 'version' => \$Opt{'version'},
57 ) || die("$progname: Option error. Use -h for help.\n");
59 $Opt{'verbose'} -= $Opt{'quiet'};
60 $Opt{'help'} && usage(0);
61 if ($Opt{'version'}) {
62 print_version();
63 exit(0);
66 exit(main());
68 sub main {
69 # {{{
70 my $Retval = 0;
72 diag(sprintf('========== Executing %s v%s ==========',
73 $progname, $VERSION));
75 $ENV{'EDITOR'} = 'cat';
77 if ($Opt{'todo'} && !$Opt{'all'}) {
78 goto todo_section;
81 =pod
83 testcmd("$CMD command", # {{{
84 <<'END',
85 [expected stdout]
86 END
87 '',
89 'description',
92 # }}}
94 =cut
96 diag('Testing -h (--help) option...');
97 likecmd("$CMD -h", # {{{
98 '/ Show this help/i',
99 '/^$/',
101 'Option -h prints help screen',
104 # }}}
105 diag('Testing -v (--verbose) option...');
106 likecmd("$CMD -h -v", # {{{
107 '/^\n\S+ \d+\.\d+\.\d+/s',
108 '/^$/',
110 'Option -v with -h returns version number and help screen',
113 # }}}
114 diag('Testing --version option...');
115 likecmd("$CMD --version", # {{{
116 '/^\S+ \d+\.\d+\.\d+/',
117 '/^$/',
119 'Option --version returns version number',
122 # }}}
123 likecmd('sqlite3 --version', # {{{
124 '/^\d+\.\d+.+/',
125 '/^$/',
127 'sqlite3 is available',
128 ) || BAIL_OUT('sqlite3 is not available');
130 # }}}
131 ok(chdir('edit-sqlite3-files'), 'chdir edit-sqlite3-files');
132 testcmd("tar xzf sqlite-databases.tar.gz", # {{{
136 'Untar sqlite-databases.tar.gz',
139 # }}}
140 $CMD = "../$CMD";
141 testcmd("$CMD", # {{{
143 "edit-sqlite3: No SQLite database specified\n",
145 'No database specified',
148 # }}}
149 testcmd("$CMD nonexisting_db", # {{{
151 "edit-sqlite3: nonexisting_db: File not found or is not a regular file\n",
153 'Non-existing database specified',
156 # }}}
157 testcmd("$CMD sqlite-databases", # {{{
159 "edit-sqlite3: sqlite-databases: File not found or is not a regular file\n",
161 'Specify directory as SQLite database',
164 # }}}
165 ok(chdir('sqlite-databases'), 'chdir sqlite-databases');
166 $CMD = "../$CMD";
167 testcmd("$CMD -n ok.sqlite", # {{{
168 "ok\n",
169 "edit-sqlite3: ok.sqlite: File would be edited\n",
171 'Specify valid SQLite database with -n',
174 # }}}
175 likecmd("$CMD --dry-run invalid.sqlite", # {{{
176 '/^$/',
177 '/edit-sqlite3: invalid\.sqlite: SQLite database contains errors/',
179 'Specify invalid SQLite db with --dry-run',
182 # }}}
183 diag('Test file permissions...');
184 SKIP: {
185 skip("Running tests as root", 13) unless ($<);
186 ok(chmod(0444, 'ok.sqlite'), 'Make ok.sqlite read-only');
187 testcmd("$CMD ok.sqlite", # {{{
189 "edit-sqlite3: ok.sqlite: File is not writable by you\n",
191 'File is not writable, abort',
194 # }}}
195 ok(chmod(0222, 'ok.sqlite'), 'Make ok.sqlite unreadable');
196 testcmd("$CMD ok.sqlite", # {{{
198 "edit-sqlite3: ok.sqlite: File is not readable by you\n",
200 'File is not readable, abort',
203 # }}}
204 ok(chmod(0000, 'ok.sqlite'),
205 'Make ok.sqlite unreadable and unwritable');
206 testcmd("$CMD ok.sqlite", # {{{
208 "edit-sqlite3: ok.sqlite: File is not readable by you\n",
210 'File is not readable nor writable, abort',
213 # }}}
214 ok(chmod(0644, 'ok.sqlite'), 'Restore permissions of ok.sqlite');
216 diag('Abort if the file is a symlink...');
217 ok(symlink('ok.sqlite', 'symlink-to-file.sqlite'), 'Create symlink to ok.sqlite');
218 testcmd("$CMD -n symlink-to-file.sqlite", # {{{
220 "edit-sqlite3: symlink-to-file.sqlite: File is a symlink\n",
222 'File is a symlink to a regular file, abort',
225 # }}}
226 ok(unlink('symlink-to-file.sqlite'), 'Delete symlink-to-file.sqlite');
227 ok(symlink('.', 'symlink-to-dir.sqlite'), 'Create symlink to \'.\'');
228 testcmd("$CMD --dry-run symlink-to-dir.sqlite", # {{{
230 "edit-sqlite3: symlink-to-dir.sqlite: File is a symlink\n",
232 'File is a symlink to a directory, abort',
235 # }}}
236 ok(unlink('symlink-to-dir.sqlite'), 'Delete symlink-to-dir.sqlite');
237 ok(symlink('nonexisting', 'symlink-to-nonexisting.sqlite'), 'Create symlink to nonexisting');
238 testcmd("$CMD --dry-run symlink-to-nonexisting.sqlite", # {{{
240 "edit-sqlite3: symlink-to-nonexisting.sqlite: File is a symlink\n",
242 'File is a symlink to a non-existing file, abort',
245 # }}}
246 ok(unlink('symlink-to-nonexisting.sqlite'), 'Delete symlink-to-nonexisting.sqlite');
247 diag('Test empty and undefined $EDITOR environment variable...');
248 $ENV{'EDITOR'} = '';
249 testcmd("$CMD ok.sqlite", # {{{
251 "edit-sqlite3: \$EDITOR environment variable is not defined\n",
253 '$EDITOR environment variable is empty',
256 # }}}
257 $ENV{'EDITOR'} = undef;
258 testcmd("$CMD ok.sqlite", # {{{
260 "edit-sqlite3: \$EDITOR environment variable is not defined\n",
262 '$EDITOR environment variable is undefined',
265 # }}}
266 diag('Test without --dry-run...');
267 $ENV{'EDITOR'} = 'cat';
268 likecmd("$CMD invalid.sqlite", # {{{
269 '/^$/',
270 '/edit-sqlite3: invalid\.sqlite: SQLite database contains errors/',
272 'Specify invalid SQLite db without --dry-run',
275 # }}}
276 testcmd("$CMD ok.sqlite", # {{{
277 <<'END',
279 PRAGMA foreign_keys=OFF;
280 BEGIN TRANSACTION;
281 CREATE TABLE t (a integer);
282 COMMIT;
286 'Valid db without --dry-run',
289 # }}}
290 my $bckfile = glob("ok.sqlite.2*.bck");
291 testcmd("sqlite3 $bckfile .dump", # {{{
292 <<END,
293 PRAGMA foreign_keys=OFF;
294 BEGIN TRANSACTION;
295 CREATE TABLE t (a integer);
296 COMMIT;
300 'Data of backup file is identical to ok.sqlite',
303 # }}}
304 ok(unlink($bckfile), 'Remove backup file');
305 create_file('ok.sqlite.sql', <<END); # {{{
306 PRAGMA foreign_keys=OFF;
307 BEGIN TRANSACTION;
308 dCREATE TABLE t (a integer);
309 COMMIT;
312 # }}}
313 likecmd("echo q | $CMD ok.sqlite", # {{{
314 '/^'
315 . 'ok\n'
316 . 'PRAGMA foreign_keys=OFF;\n'
317 . 'BEGIN TRANSACTION;\n'
318 . 'dCREATE TABLE t \(a integer\);\n'
319 . 'COMMIT;\n'
320 . '$/',
321 '/^'
322 . '.*dCREATE.*\n'
323 . 'edit-sqlite3: Press Enter to edit again, or q to abort\.\.\.'
324 . '$/s',
326 'Display "edit again" message if invalid SQL',
329 # }}}
330 diag('Clean up...');
331 ok(unlink('ok.sqlite.sql'), 'Delete ok.sqlite.sql');
332 ok(unlink(glob("ok.sqlite.2*.bck")), 'Delete backup file');
333 ok(unlink('invalid.sqlite'), 'Delete invalid.sqlite');
334 ok(unlink('ok.sqlite'), 'Delete ok.sqlite');
335 ok(chdir('..'), 'chdir ..');
336 ok(rmdir('sqlite-databases'), 'rmdir sqlite-databases');
338 todo_section:
341 if ($Opt{'all'} || $Opt{'todo'}) {
342 diag('Running TODO tests...'); # {{{
344 TODO: {
346 local $TODO = '';
347 # Insert TODO tests here.
350 # TODO tests }}}
353 diag('Testing finished.');
354 return $Retval;
355 # }}}
356 } # main()
358 sub testcmd {
359 # {{{
360 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
361 defined($descriptions{$Desc}) &&
362 BAIL_OUT("testcmd(): '$Desc' description is used twice");
363 $descriptions{$Desc} = 1;
364 my $stderr_cmd = '';
365 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
366 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
367 my $TMP_STDERR = "$CMDB-stderr.tmp";
368 my $retval = 1;
370 if (defined($Exp_stderr)) {
371 $stderr_cmd = " 2>$TMP_STDERR";
373 $retval &= is(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
374 my $ret_val = $?;
375 if (defined($Exp_stderr)) {
376 $retval &= is(file_data($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
377 unlink($TMP_STDERR);
378 } else {
379 diag("Warning: stderr not defined for '$Txt'");
381 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
383 return $retval;
384 # }}}
385 } # testcmd()
387 sub likecmd {
388 # {{{
389 my ($Cmd, $Exp_stdout, $Exp_stderr, $Exp_retval, $Desc) = @_;
390 defined($descriptions{$Desc}) &&
391 BAIL_OUT("likecmd(): '$Desc' description is used twice");
392 $descriptions{$Desc} = 1;
393 my $stderr_cmd = '';
394 my $cmd_outp_str = $Opt{'verbose'} >= 1 ? "\"$Cmd\" - " : '';
395 my $Txt = join('', $cmd_outp_str, defined($Desc) ? $Desc : '');
396 my $TMP_STDERR = "$CMDB-stderr.tmp";
397 my $retval = 1;
399 if (defined($Exp_stderr)) {
400 $stderr_cmd = " 2>$TMP_STDERR";
402 $retval &= like(`$Cmd$stderr_cmd`, $Exp_stdout, "$Txt (stdout)");
403 my $ret_val = $?;
404 if (defined($Exp_stderr)) {
405 $retval &= like(file_data($TMP_STDERR), $Exp_stderr, "$Txt (stderr)");
406 unlink($TMP_STDERR);
407 } else {
408 diag("Warning: stderr not defined for '$Txt'");
410 $retval &= is($ret_val >> 8, $Exp_retval, "$Txt (retval)");
412 return $retval;
413 # }}}
414 } # likecmd()
416 sub file_data {
417 # Return file content as a string {{{
418 my $File = shift;
419 my $Txt;
421 open(my $fp, '<', $File) or return undef;
422 local $/ = undef;
423 $Txt = <$fp>;
424 close($fp);
425 return $Txt;
426 # }}}
427 } # file_data()
429 sub create_file {
430 # Create new file and fill it with data {{{
431 my ($file, $text) = @_;
432 my $retval = 0;
433 if (open(my $fp, ">$file")) {
434 print($fp $text);
435 close($fp);
436 $retval = is(
437 file_data($file),
438 $text,
439 "$file was successfully created",
442 return($retval); # 0 if error, 1 if ok
443 # }}}
444 } # create_file()
446 sub print_version {
447 # Print program version {{{
448 print("$progname $VERSION\n");
449 return;
450 # }}}
451 } # print_version()
453 sub usage {
454 # Send the help message to stdout {{{
455 my $Retval = shift;
457 if ($Opt{'verbose'}) {
458 print("\n");
459 print_version();
461 print(<<"END");
463 Usage: $progname [options]
465 Contains tests for the $CMDB(1) program.
467 Options:
469 -a, --all
470 Run all tests, also TODOs.
471 -h, --help
472 Show this help.
473 -q, --quiet
474 Be more quiet. Can be repeated to increase silence.
475 -t, --todo
476 Run only the TODO tests.
477 -v, --verbose
478 Increase level of verbosity. Can be repeated.
479 --version
480 Print version information.
483 exit($Retval);
484 # }}}
485 } # usage()
487 sub msg {
488 # Print a status message to stderr based on verbosity level {{{
489 my ($verbose_level, $Txt) = @_;
491 $verbose_level > $Opt{'verbose'} && return;
492 print(STDERR "$progname: $Txt\n");
493 return;
494 # }}}
495 } # msg()
497 __END__
499 # This program is free software; you can redistribute it and/or modify
500 # it under the terms of the GNU General Public License as published by
501 # the Free Software Foundation; either version 2 of the License, or (at
502 # your option) any later version.
504 # This program is distributed in the hope that it will be useful, but
505 # WITHOUT ANY WARRANTY; without even the implied warranty of
506 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
507 # See the GNU General Public License for more details.
509 # You should have received a copy of the GNU General Public License
510 # along with this program.
511 # If not, see L<http://www.gnu.org/licenses/>.
513 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :