3 # Test suite for krb5-strength-wordlist SQLite database generation
5 # Written by Russ Allbery <eagle@eyrie.org>
7 # The Board of Trustees of the Leland Stanford Junior University
9 # See LICENSE for licensing terms.
15 use lib "$ENV{SOURCE}/tap/perl";
18 use Test::RRA qw(use_prereq);
19 use Test::RRA::Automake qw(automake_setup test_file_path test_tmpdir);
21 # Load prerequisite modules.
23 use_prereq('DBD::SQLite');
24 use_prereq('IPC::Run', 'run');
25 use_prereq('Perl6::Slurp', 'slurp');
27 # Set up for testing of an Automake project.
30 # Run krb5-strength-wordlist on the given word list, generating a SQLite
31 # dictionary in a temporary directory and returning its path. Ensure that
32 # krb5-strength exits successfully with no output. For planning purposes,
33 # this function will report three tests. Calls BAIL_OUT if the output file
34 # already exists and can't be deleted.
36 # $input - Input wordlist file, used to form the output file name
38 # Returns: Path to new temporary SQLite dictionary
41 my $output = test_tmpdir() . '/wordlist.sqlite';
43 # Find the krb5-strength-wordlist program in the distribution.
44 my $wordlist = test_file_path('../tools/krb5-strength-wordlist');
46 # Ensure the output file does not exist.
48 unlnk($output) or BAIL_OUT("cannot delete $output: $!");
51 # Run the program, capturing its output and status.
53 run([$wordlist, '-s', $output, $input], \undef, \$out, \$err);
54 my $status = ($? >> 8);
57 is($status, 0, 'krb5-strength-wordlist -s');
58 is($out, q{}, '...with no output');
59 is($err, q{}, '...and no errors');
61 # Return the newly-created database.
65 # Read the word list that we'll use for testing so that we can validate the
66 # contents of the generated SQLite database.
67 my $wordlist = test_file_path('data/wordlist');
68 my @words = slurp($wordlist);
71 # Declare the plan now that we know how many tests there will be. There is
72 # one test for each word, plus four for creating the database and another for
73 # checking that it contains the right passwords.
74 plan tests => 5 + scalar(@words);
76 # Build the SQLite database.
77 my $dictionary = run_wordlist($wordlist);
79 # Ensure that we can open the result as a SQLite database.
80 my $options = { PrintError => 1, RaiseError => 1, AutoCommit => 1 };
81 my $dbh = DBI->connect("dbi:SQLite:dbname=$dictionary", q{}, q{}, $options);
82 ok(defined($dbh), 'Opening SQLite database succeeded');
84 # Walk through every row in the passwords table and ensure that the drowssap
85 # column is the reverse of the password column. Accumulate the passwords so
86 # that we can check against the contents of the word list.
87 my $sql = 'SELECT PASSWORD, DROWSSAP FROM PASSWORDS';
88 my $data_ref = $dbh->selectall_arrayref($sql);
90 for my $row (@{$data_ref}) {
91 my ($password, $drowssap) = @{$row};
92 push(@got, $password);
93 is($drowssap, scalar(reverse($password)), "Reversal for $password");
97 # Ensure that the list of passwords in the database are what we expected.
98 is_deeply(\@got, \@words, 'Passwords in dictionary');
100 # Remove the files created by the test.