Force ::Collation objects to be serialized en bloc, "fixing" GC.
[scpubgit/stemmatology.git] / t / text_tradition_directory.t
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Test::More 'no_plan';
5 $| = 1;
6
7
8
9 # =begin testing
10 use TryCatch;
11 use File::Temp;
12 use Text::Tradition;
13 use_ok 'Text::Tradition::Directory';
14
15 my $fh = File::Temp->new();
16 my $file = $fh->filename;
17 if ($ARGV[0] eq 'test.db') { unlink($file = 'test.db') }
18 $fh->close;
19 my $dsn = "dbi:SQLite:dbname=$file";
20 my $uuid;
21 my $t = Text::Tradition->new( 
22         'name'  => 'inline', 
23         'input' => 'Tabular',
24         'file'  => 't/data/simple.txt',
25         );
26 my $obj_dbh = DBI->connect($dsn);
27
28 sub get_counts {
29   map @$_, @{$obj_dbh->selectall_arrayref(
30     'SELECT class, COUNT(*) FROM entries GROUP BY class'
31   )};
32 }
33
34 {
35         my $d = Text::Tradition::Directory->new( 'dsn' => $dsn,
36                 'extra_args' => { 'create' => 1 } );
37         is( ref $d, 'Text::Tradition::Directory', "Got directory object" );
38         
39         my $scope = $d->new_scope;
40         $uuid = $d->save( $t );
41         ok( $uuid, "Saved test tradition" );
42         
43         my $s = $t->add_stemma( dotfile => 't/data/simple.dot' );
44         ok( $d->save( $t ), "Updated tradition with stemma" );
45         is( $d->tradition( $uuid ), $t, "Correct tradition returned for id" );
46         is( $d->tradition( $uuid )->stemma(0), $s, "...and it has the correct stemma" );
47         try {
48                 $d->save( $s );
49         } catch( Text::Tradition::Error $e ) {
50                 is( $e->ident, 'database error', "Got exception trying to save stemma directly" );
51                 like( $e->message, qr/Cannot directly save non-Tradition object/, 
52                         "Exception has correct message" );
53         }
54 }
55
56 my %first_counts = get_counts();
57
58 my $nt = Text::Tradition->new(
59         'name' => 'CX',
60         'input' => 'CollateX',
61         'file' => 't/data/Collatex-16.xml',
62         );
63 is( ref( $nt ), 'Text::Tradition', "Made new tradition" );
64
65 my %second_counts;
66
67 {
68         my $f = Text::Tradition::Directory->new( 'dsn' => $dsn );
69         my $scope = $f->new_scope;
70         is( scalar $f->traditionlist, 1, "Directory index has our tradition" );
71         my $nuuid = $f->save( $nt );
72         ok( $nuuid, "Stored second tradition" );
73         my @tlist = $f->traditionlist;
74         is( scalar @tlist, 2, "Directory index has both traditions" );
75         my $tf = $f->tradition( $uuid );
76         my( $tlobj ) = grep { $_->{'id'} eq $uuid } @tlist;
77         is( $tlobj->{'name'}, $tf->name, "Directory index has correct tradition name" );
78         is( $tf->name, $t->name, "Retrieved the tradition from a new directory" );
79         my $sid = $f->object_to_id( $tf->stemma(0) );
80         try {
81                 $f->tradition( $sid );
82         } catch( Text::Tradition::Error $e ) {
83                 is( $e->ident, 'database error', "Got exception trying to fetch stemma directly" );
84                 like( $e->message, qr/not a Text::Tradition/, "Exception has correct message" );
85         }
86         try {
87                 $f->delete( $sid );
88         } catch( Text::Tradition::Error $e ) {
89                 is( $e->ident, 'database error', "Got exception trying to delete stemma directly" );
90                 like( $e->message, qr/Cannot directly delete non-Tradition object/, 
91                         "Exception has correct message" );
92         }
93
94         %second_counts = get_counts;
95         
96         $f->delete( $uuid );
97         ok( !$f->exists( $uuid ), "Object is deleted from DB" );
98         ok( !$f->exists( $sid ), "Object stemma also deleted from DB" );
99         is( scalar $f->traditionlist, 1, "Object is deleted from index" );
100 }
101
102 {
103         my $g = Text::Tradition::Directory->new( 'dsn' => $dsn );
104         my $scope = $g->new_scope;
105         is( scalar $g->traditionlist, 1, "Now one object in new directory index" );
106         my $ntobj = $g->tradition( 'CX' );
107         my @w1 = sort { $a->sigil cmp $b->sigil } $ntobj->witnesses;
108         my @w2 = sort{ $a->sigil cmp $b->sigil } $nt->witnesses;
109         is_deeply( \@w1, \@w2, "Looked up remaining tradition by name" );
110
111         is_deeply(
112             [ sort keys %{$nt->collation->{readings}} ],
113             [ sort keys %{$ntobj->collation->{readings}} ],
114             'Same reading keys between original and re-look-up'
115         );
116 }
117
118 my %final_counts = get_counts();
119
120 foreach my $class (sort keys %final_counts) {
121   my ($first, $second, $final) = map $_->{$class}, (
122     \%first_counts, \%second_counts, \%final_counts
123   );
124   cmp_ok(
125     $final, '==', ($second - $first),
126     "Final count for ${class} is $final ($second - $first)"
127   );
128 }
129
130 1;