File: 01-simple.t

package info (click to toggle)
libtangram-perl 2.10-1.1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 1,064 kB
  • ctags: 703
  • sloc: perl: 9,665; makefile: 35
file content (249 lines) | stat: -rw-r--r-- 6,450 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# -*- perl -*-

# test script for the Persistathon - set TANGRAM_TRACE=1 in the
# environment for a nice log of what queries Tangram is running.

use lib "t/musicstore";
use Prerequisites;
use strict;

use Test::More tests => 24;
use Tangram::Storage;

# various items that will "persist" between test blocks
use vars qw($storage);
my ($oid, $id, $r_cd, $r_artist, $band, $row, $join, $filter);

# open a storage connection - this will be
# Tangram::Relational->connect(), etc.
$storage = DBConfig->dialect->connect(MusicStore->schema, DBConfig->cparm);

{

    # 1. create a new database object of each type in the schema
    my ($cd, @songs, $band, @people);
    $band = CD::Band->new
	({ name => "The Upbeats",
	  popularity => "World Famous in New Zealand",
	  cds => Set::Object->new
	  (
	   $cd=
	   CD->new({title => "The Upbeats",
		    publishdate => iso('2004-04-01'),
		    songs => [
			      @songs=
			      CD::Song->new({name => "Hello"}),
			      CD::Song->new({name => "Drizzle"}),
			      CD::Song->new({name => "From the Deep"}),
			     ],
		  }),
	  ),
	  members => Set::Object->new
	  (
	   @people =
	   CD::Person->new({ name => "Jeremy Glenn" }),
	   CD::Person->new({ name => "Dylan Jones" }),
	  ),
	});

    # stick it in
    $oid = $storage->insert($band);
    $id = $storage->export_object($band);
    ok($oid, "Inserted a band and associated objects");

    # 2. print the object IDs
    if ( -t STDIN ) {  #unless running in the harness...
	diag($_) foreach
	    ("Band: ".$storage->export_object($band),
	     "People: ".join(",", $storage->export_object(@people)),
	     "CD storage ID: ".$storage->export_object($cd),
	     "Songs: ".join(",", $storage->export_object(@songs)));
    }

    # put in some extra data for fun
    require 'insert_extra_data.pl';
}

# objects should now be gone, as they have fallen out of scope
is($CD::c, 0, "no objects leaked");

{
    # two loading strategies - one is the `exported' object, where you
    # pass in a type and an ID - note that any superclass is OK (the
    # import is polymorphic)
    $band = $storage->import_object("CD::Artist", $id);
    isa_ok($band, "CD::Band", "Band loaded by exported ID");

    # the second is to import by oid, which includes the class ID...
    my $band2 = $storage->load($oid);
    isa_ok($band2, "CD::Band", "Band loaded by OID");

    is($band, $band2, "Seperate loads returned same object");
}

is($CD::c, 1, "no objects leaked");

{
    # 4. fetch an artist record by name (exact match)
    $r_artist = $storage->remote("CD::Artist");

    my @artists = $storage->select
	( $r_artist,
	  $r_artist->{name} eq "The Upbeats" );

    is(@artists, 1, "got an object out");

    # extra demonstration - is it the same object as $band ?
    is($artists[0], $band, "selects return cached objects");
}

is($CD::c, 1, "no objects leaked");

{
    # 5. fetch an artist record with a search term (globbing / LIKE /
    #    etc)
    my (@artists) = $storage->select
	( $r_artist,
	  $r_artist->{name}->upper()->like(uc("%beat%")),
	);

    is(@artists, 2, "got two artists matching %beat%");
    ok(Set::Object->new(@artists)->includes($band),
       "select still returns cached objects");
    undef($band);
}

is($CD::c, 0, "no objects leaked");

{
    # 6. fetch CD records by matching on a partial *artist's* name,
    #    using a cursor if possible.
    $r_cd = $storage->remote("CD");

    $join = ($r_cd->{artist} == $r_artist);
    my $query = $r_artist->{name}->upper()->like(uc("%beat%"));
    my $filter = $join & $query;

    my $cursor = $storage->cursor ( $r_cd, $filter );

    my @cds;
    while ( my $cd = $cursor->current ) {
	push @cds, $cd;
	$cursor->next;
    }
    is(@cds, 3, "Found three CDs by artists matching %beat%");

    # if we just wanted the count:
    my ($count) = $storage->count($filter);
    is($count, 3, "Can do simple COUNT() queries");

    # maybe some other aggregation type queries:
    ($row) = $storage->select
	( undef, # no object
	  filter => $filter,
	  retrieve => [ $r_cd->{publishdate}->min(),
			$r_cd->{publishdate}->max(),
		      ],
	);

    # this could probably be considered a design caveat
    $_ = $storage->from_dbms("date", $_) foreach @$row;
}

is($CD::c, 0, "no objects leaked");

{

    is_deeply($row, [ '1999-10-26T00:00:00', '2004-04-01T00:00:00' ],
	      "aggregation type queries");

    # 7. fetch unique CD records by matching on a partial artist's
    #    *or* partial CD name, using a cursor if possible.
    my $query =
	( $r_artist->{name}->upper()->like(uc("%beat%"))
	  | $r_cd->{title}->upper()->like(uc("%beat%")) );

    my $filter = $join & $query;
    my $cursor = $storage->cursor ( $r_cd, $filter );

    my @cds=();
    while ( my $cd = $cursor->current ) {
	diag ("found cd = " .$cd->title.", artist = ".$cd->artist->name);
	push @cds, $cd;
	$cursor->next;
    }
    is(@cds, 4, "Found four CDs by CD or artist name matching %beat%");

}

is($CD::c, 0, "no objects leaked");

{
    #use YAML;
    #local($Tangram::TRACE) = \*STDERR;
    #local($Tangram::DEBUG_LEVEL) = 3;
    # 8. update a record or two
    my ($pfloyd) = $storage->select
	( $r_artist,
	  $r_artist->{name} eq "Pink Floyd" );

    my $cd;
    $pfloyd->cds->insert
	($cd=
	 CD->new({ title => "The Dark Side of The Moon",
		   publishdate => iso("2004-04-06"),
		   songs => [ map { CD::Song->new({ name => $_ }) }
			      "Speak To Me/Breathe", "On The Run",
			    "Time", "The Great Gig in the Sky",
			      "Money", "Us And Them",
			      "Any Colour You Like", "Brain Damage",
			    "Eclipse",
			  ],
		 })
	);
    $pfloyd->popularity("legendary");
    $storage->update($pfloyd);

    ok($storage->id($cd), "Automatically added a new Set member");
}

is($CD::c, 0, "no objects leaked");

{
    my ($pfloyd) = $storage->select
	( $r_artist,
	  $r_artist->{name} eq "Pink Floyd" );
    is($pfloyd->popularity, "legendary", "saved an object property");
}

is($CD::c, 0, "no objects leaked");

{
    # 9. delete some records
    my (@gonners) = $storage->select
	($r_artist,
	 $r_artist->{popularity} eq "one hit wonder");

    $storage->erase(@gonners);

    ok(!$storage->id($gonners[0]), "No longer part of storage");
}

is($CD::c, 0, "no objects leaked");


our %formats;

BEGIN {
%formats =
    ( 4 => "%Y",
      10 => "%Y-%m-%d",
      19 => "%Y-%m-%dT%H:%M:%S",
    );
}

sub iso {
    my $str = shift;
    Time::Piece->strptime($str, $formats{length($str)});
}