Bug 9988: Remove further references to dontmerge
[koha.git] / t / db_dependent / UsageStats.t
1 # Copyright 2015 BibLibre
2 #
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, see <http://www.gnu.org/licenses>.
16
17 use Modern::Perl;
18 use Test::More tests => 57;
19 use t::lib::Mocks qw(mock_preference);
20 use POSIX qw(strftime);
21 use Data::Dumper;
22 use Koha::Biblios;
23
24 use Koha::Libraries;
25
26 BEGIN {
27     use_ok('C4::UsageStats');
28     use_ok('C4::Context');
29     use_ok('C4::Biblio');
30     use_ok( 'C4::AuthoritiesMarc', qw(AddAuthority) );
31     use_ok('C4::Reserves');
32     use_ok('MARC::Record');
33     use_ok('Koha::Acquisition::Order');
34 }
35
36 can_ok(
37     'C4::UsageStats', qw(
38       NeedUpdate
39       BuildReport
40       ReportToCommunity
41       _count )
42 );
43
44 my $dbh = C4::Context->dbh;
45 $dbh->{AutoCommit} = 0;
46 $dbh->{RaiseError} = 1;
47
48 $dbh->do('DELETE FROM issues');
49 $dbh->do('DELETE FROM biblio');
50 $dbh->do('DELETE FROM items');
51 $dbh->do('DELETE FROM auth_header');
52 $dbh->do('DELETE FROM old_issues');
53 $dbh->do('DELETE FROM old_reserves');
54 $dbh->do('DELETE FROM borrowers');
55 $dbh->do('DELETE FROM aqorders');
56 $dbh->do('DELETE FROM subscription');
57
58 #################################################
59 #             Testing Subs
60 #################################################
61
62 # ---------- Testing NeedUpdate -----------------
63
64 #Mocking C4::Context->preference("UsageStatsLastUpdateTime") to 0
65 my $now = strftime( "%s", localtime );
66 t::lib::Mocks::mock_preference( "UsageStatsLastUpdateTime", 0 );
67
68 my $update = C4::UsageStats->NeedUpdate;
69 is( $update, 1, "There is no last update, update needed" );
70
71 #Mocking C4::Context->preference("UsageStatsLastUpdateTime") to now
72 $now = strftime( "%s", localtime );
73 t::lib::Mocks::mock_preference( "UsageStatsLastUpdateTime", $now );
74
75 $update = C4::UsageStats->NeedUpdate;
76 is( $update, 0, "Last update just be done, no update needed " );
77
78 my $nb_of_libraries = Koha::Libraries->count;
79
80 # ---------- Testing BuildReport ----------------
81
82 #Test report->library -----------------
83 #mock to 0
84 t::lib::Mocks::mock_preference( "UsageStatsID",          0 );
85 t::lib::Mocks::mock_preference( "UsageStatsLibraryName", 0 );
86 t::lib::Mocks::mock_preference( "UsageStatsLibrariesInfo",  0 );
87 t::lib::Mocks::mock_preference( "UsageStatsLibraryType", 0 );
88 t::lib::Mocks::mock_preference( "UsageStatsCountry",     0 );
89 t::lib::Mocks::mock_preference( "UsageStatsLibraryUrl",  0 );
90
91 my $report = C4::UsageStats->BuildReport();
92
93 isa_ok( $report,              'HASH',  '$report is a HASH' );
94 isa_ok( $report->{libraries}, 'ARRAY', '$report->{libraries} is an ARRAY' );
95 is( scalar( @{ $report->{libraries} } ), 0, "There are 0 fields in libraries, libraries info are not shared" );
96 is( $report->{installation}->{koha_id}, 0,  "UsageStatsID          is good" );
97 is( $report->{installation}->{name},    '', "UsageStatsLibraryName is good" );
98 is( $report->{installation}->{url},     '', "UsageStatsLibraryUrl  is good" );
99 is( $report->{installation}->{type},    '', "UsageStatsLibraryType is good" );
100 is( $report->{installation}->{country}, '', "UsageStatsCountry     is good" );
101
102
103 #mock with values
104 t::lib::Mocks::mock_preference( "UsageStatsID",          1 );
105 t::lib::Mocks::mock_preference( "UsageStatsLibraryName", 'NAME' );
106 t::lib::Mocks::mock_preference( "UsageStatsLibraryUrl",  'URL' );
107 t::lib::Mocks::mock_preference( "UsageStatsLibraryType", 'TYPE' );
108 t::lib::Mocks::mock_preference( "UsageStatsCountry",     'COUNTRY' );
109 t::lib::Mocks::mock_preference( "UsageStatsLibrariesInfo", 1 );
110 t::lib::Mocks::mock_preference( "UsageStatsGeolocation", 1 );
111
112
113 $report = C4::UsageStats->BuildReport();
114
115 isa_ok( $report,              'HASH',  '$report is a HASH' );
116 isa_ok( $report->{libraries}, 'ARRAY', '$report->{libraries} is an ARRAY' );
117 is( scalar( @{ $report->{libraries} } ), $nb_of_libraries, "There are 6 fields in $report->{libraries}" );
118 is( $report->{installation}->{koha_id}, 1,     "UsageStatsID          is good" );
119 is( $report->{installation}->{name},   'NAME', "UsageStatsLibraryName is good" );
120 is( $report->{installation}->{url},     'URL', "UsageStatsLibraryUrl  is good" );
121 is( $report->{installation}->{type},   'TYPE', "UsageStatsLibraryType is good" );
122 is( $report->{installation}->{country}, 'COUNTRY', "UsageStatsCountry is good" );
123
124 #Test report->volumetry ---------------
125 #with original values
126 $report = C4::UsageStats->BuildReport();
127
128 isa_ok( $report,              'HASH', '$report is a HASH' );
129 isa_ok( $report->{volumetry}, 'HASH', '$report->{volumetry} is a HASH' );
130 is( scalar( keys %{$report->{volumetry}} ), 8, "There are 8 fields in $report->{volumetry}" );
131 is( $report->{volumetry}->{biblio},         0, "There is no biblio" );
132 is( $report->{volumetry}->{items},          0, "There is no items" );
133 is( $report->{volumetry}->{auth_header},    0, "There is no auth_header" );
134 is( $report->{volumetry}->{old_issues},     0, "There is no old_issues" );
135 is( $report->{volumetry}->{old_reserves},   0, "There is no old_reserves" );
136 is( $report->{volumetry}->{borrowers},      0, "There is no borrowers" );
137 is( $report->{volumetry}->{aqorders},       0, "There is no aqorders" );
138 is( $report->{volumetry}->{subscription},   0, "There is no subscription" );
139
140 #after adding objects
141 construct_objects_needed();
142
143 $report = C4::UsageStats->BuildReport();
144
145 isa_ok( $report,              'HASH', '$report is a HASH' );
146 isa_ok( $report->{volumetry}, 'HASH', '$report->{volumetry} is a HASH' );
147 is( scalar( keys %{$report->{volumetry}} ), 8, "There are 8 fields in $report->{volumetry}" );
148 is( $report->{volumetry}->{biblio},         3, "There are 3 biblio" );
149 is( $report->{volumetry}->{items},          3, "There are 3 items" );
150 is( $report->{volumetry}->{auth_header},    2, "There are 2 auth_header" );
151 is( $report->{volumetry}->{old_issues},     1, "There is  1 old_issues" );
152 is( $report->{volumetry}->{old_reserves},   1, "There is  1 old_reserves" );
153 is( $report->{volumetry}->{borrowers},      3, "There are 3 borrowers" );
154 is( $report->{volumetry}->{aqorders},       1, "There is  1 aqorders" );
155 is( $report->{volumetry}->{subscription},   1, "There is  1 subscription" );
156
157 #Test report->systempreferences -------
158 #mock to 0
159 mocking_systempreferences_to_a_set_value(0);
160
161 $report = C4::UsageStats->BuildReport();
162 isa_ok( $report,                      'HASH', '$report is a HASH' );
163 isa_ok( $report->{systempreferences}, 'HASH', '$report->{systempreferences} is a HASH' );
164 verif_systempreferences_values( $report, 0 );
165
166 #mock with values
167 mocking_systempreferences_to_a_set_value(1);
168
169 $report = C4::UsageStats->BuildReport();
170 isa_ok( $report,                      'HASH', '$report is a HASH' );
171 isa_ok( $report->{systempreferences}, 'HASH', '$report->{systempreferences} is a HASH' );
172 verif_systempreferences_values( $report, 1 );
173
174 #Test if unwanted syspref are not sent
175 is( $report->{systempreferences}->{useDischarge}, undef, 'useDischarge should not be shared');
176 is( $report->{systempreferences}->{OpacUserJS},   undef, 'OpacUserJS   should not be shared');
177
178 # ---------- Testing ReportToCommunity ----------
179
180 # ---------- Testing _count ---------------------
181 my $query = '
182   SELECT count(*)
183   FROM   borrowers
184   ';
185 my $count = $dbh->selectrow_array($query);
186
187 my $nb_fields = C4::UsageStats::_count('borrowers');
188 is( $nb_fields, $count, "_count return the good number of fields" );
189
190 #################################################
191 #             Subs
192 #################################################
193
194 # Adding :
195 # 3 borrowers
196 # 4 biblio
197 # 3 biblio items
198 # 3 items
199 # 2 auth_header
200 # 1 old_issues
201 # 1 old_reserves
202 # 1 subscription
203 # 1 aqorders
204 sub construct_objects_needed {
205
206     # ---------- 3 borrowers  ---------------------
207     my $surname1     = 'Borrower 1';
208     my $surname2     = 'Borrower 2';
209     my $surname3     = 'Borrower 3';
210     my $firstname1   = 'firstname 1';
211     my $firstname2   = 'firstname 2';
212     my $firstname3   = 'firstname 3';
213     my $cardnumber1  = 'test_card1';
214     my $cardnumber2  = 'test_card2';
215     my $cardnumber3  = 'test_card3';
216     my $categorycode = Koha::Database->new()->schema()->resultset('Category')->first()->categorycode();
217     my $branchcode   = Koha::Database->new()->schema()->resultset('Branch')->first()->branchcode();
218
219     my $query = '
220     INSERT INTO borrowers
221       (surname, firstname, cardnumber, branchcode, categorycode)
222     VALUES (?,?,?,?,?)';
223     my $insert_sth = $dbh->prepare($query);
224     $insert_sth->execute( $surname1, $firstname1, $cardnumber1, $branchcode, $categorycode );
225     my $borrowernumber1 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
226     $insert_sth->execute( $surname2, $firstname2, $cardnumber2, $branchcode, $categorycode );
227     my $borrowernumber2 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
228     $insert_sth->execute( $surname3, $firstname3, $cardnumber3, $branchcode, $categorycode );
229     my $borrowernumber3 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
230
231     # ---------- 3 biblios -----------------------
232     my $title1  = 'Title 1';
233     my $title2  = 'Title 2';
234     my $title3  = 'Title 3';
235     my $author1 = 'Author 1';
236     my $author2 = 'Author 2';
237     my $author3 = 'Author 3';
238
239     $query = '
240     INSERT INTO biblio
241       (title, author)
242     VALUES (?,?)';
243     $insert_sth = $dbh->prepare($query);
244     $insert_sth->execute( $title1, $author1 );
245     my $biblionumber1 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
246     $insert_sth->execute( $title2, undef );
247     my $biblionumber2 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
248     $insert_sth->execute( $title3, $author3 );
249     my $biblionumber3 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
250
251     # ---------- 3 biblio items  -------------------------
252     $query = '
253     INSERT INTO biblioitems
254       (biblionumber, itemtype)
255     VALUES (?,?)';
256     $insert_sth = $dbh->prepare($query);
257     $insert_sth->execute( $biblionumber1, 'Book' );
258     my $biblioitemnumber1 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
259     $insert_sth->execute( $biblionumber2, 'Music' );
260     my $biblioitemnumber2 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
261     $insert_sth->execute( $biblionumber3, 'Book' );
262     my $biblioitemnumber3 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
263
264     # ---------- 3 items  -------------------------
265     my $barcode1 = '111111';
266     my $barcode2 = '222222';
267     my $barcode3 = '333333';
268
269     $query = '
270     INSERT INTO items
271       (biblionumber, biblioitemnumber, barcode, itype)
272     VALUES (?,?,?,?)';
273     $insert_sth = $dbh->prepare($query);
274     $insert_sth->execute( $biblionumber1, $biblioitemnumber1, $barcode1, 'Book' );
275     my $item_number1 = $dbh->last_insert_id( undef, undef, 'items', undef );
276     $insert_sth->execute( $biblionumber2, $biblioitemnumber2, $barcode2, 'Music' );
277     my $item_number2 = $dbh->last_insert_id( undef, undef, 'items', undef );
278     $insert_sth->execute( $biblionumber3, $biblioitemnumber3, $barcode3, 'Book' );
279     my $item_number3 = $dbh->last_insert_id( undef, undef, 'items', undef );
280
281     # ---------- Add 2 auth_header
282     $query = '
283     INSERT INTO auth_header
284       (authtypecode)
285     VALUES (?)';
286     $insert_sth = $dbh->prepare($query);
287     $insert_sth->execute('authtypecode1');
288     my $authid1 = $dbh->last_insert_id( undef, undef, 'auth_header', undef );
289     $insert_sth->execute('authtypecode2');
290     my $authid2 = $dbh->last_insert_id( undef, undef, 'auth_header', undef );
291
292     # ---------- Add 1 old_issues
293     $query = '
294     INSERT INTO old_issues
295       (borrowernumber, branchcode, itemnumber)
296     VALUES (?,?,?)';
297     $insert_sth = $dbh->prepare($query);
298     $insert_sth->execute( $borrowernumber1, $branchcode, $item_number1 );
299     my $issue_id1 = $dbh->last_insert_id( undef, undef, 'old_issues', undef );
300
301     # ---------- Add 1 old_reserves
302     AddReserve( $branchcode, $borrowernumber1, $biblionumber1, '', 1, undef, undef, '', 'Title', undef, undef );
303     my $biblio = Koha::Biblios->find( $biblionumber1 );
304     my $holds = $biblio->holds;
305     CancelReserve( { reserve_id => $holds->next->reserve_id } );
306
307     # ---------- Add 1 aqbudgets
308     $query = '
309     INSERT INTO aqbudgets
310       (budget_amount)
311     VALUES (?)';
312     $insert_sth = $dbh->prepare($query);
313     $insert_sth->execute("20.0");
314     my $aqbudgets1 = $dbh->last_insert_id( undef, undef, 'aqbudgets', undef );
315
316     # ---------- Add 1 aqorders
317     $query = '
318     INSERT INTO aqorders
319       (budget_id, basketno, biblionumber, invoiceid, subscriptionid)
320     VALUES (?,?,?,?,?)';
321     $insert_sth = $dbh->prepare($query);
322     $insert_sth->execute( $aqbudgets1, undef, undef, undef, undef );
323     my $aqorders1 = $dbh->last_insert_id( undef, undef, 'aqorders', undef );
324
325     # --------- Add 1 subscription
326     $query = '
327     INSERT INTO subscription
328       (biblionumber)
329     VALUES (?)';
330     $insert_sth = $dbh->prepare($query);
331     $insert_sth->execute($biblionumber1);
332     my $subscription1 = $dbh->last_insert_id( undef, undef, 'subscription', undef );
333
334 }
335
336 #Change systempreferences values to $set_value
337 sub mocking_systempreferences_to_a_set_value {
338     my $set_value = shift;
339
340     foreach (
341         qw/
342         AcqCreateItem
343         AcqWarnOnDuplicateInvoice
344         AcqViewBaskets
345         BasketConfirmations
346         OrderPdfFormat
347         casAuthentication
348         casLogout
349         AllowPKIAuth
350         DebugLevel
351         delimiter
352         noItemTypeImages
353         virtualshelves
354         AutoLocation
355         IndependentBranches
356         SessionStorage
357         Persona
358         AuthDisplayHierarchy
359         AutoCreateAuthorities
360         BiblioAddsAuthorities
361         AuthorityMergeLimit
362         AuthorityMergeMode
363         UseAuthoritiesForTracings
364         CatalogModuleRelink
365         hide_marc
366         IntranetBiblioDefaultView
367         LabelMARCView
368         OpacSuppression
369         SeparateHoldings
370         UseControlNumber
371         advancedMARCeditor
372         DefaultClassificationSource
373         EasyAnalyticalRecords
374         autoBarcode
375         item-level_itypes
376         marcflavour
377         PrefillItem
378         z3950NormalizeAuthor
379         SpineLabelAutoPrint
380         SpineLabelShowPrintOnBibDetails
381         BlockReturnOfWithdrawnItems
382         CalculateFinesOnReturn
383         AgeRestrictionOverride
384         AllFinesNeedOverride
385         AllowFineOverride
386         AllowItemsOnHoldCheckout
387         AllowItemsOnHoldCheckoutSCO
388         AllowNotForLoanOverride
389         AllowRenewalLimitOverride
390         AllowReturnToBranch
391         AllowTooManyOverride
392         AutomaticItemReturn
393         AutoRemoveOverduesRestrictions
394         CircControl
395         HomeOrHoldingBranch
396         HomeOrHoldingBranchReturn
397         InProcessingToShelvingCart
398         IssueLostItem
399         IssuingInProcess
400         ManInvInNoissuesCharge
401         OverduesBlockCirc
402         RenewalPeriodBase
403         RenewalSendNotice
404         RentalsInNoissuesCharge
405         ReturnBeforeExpiry
406         ReturnToShelvingCart
407         TransfersMaxDaysWarning
408         UseBranchTransferLimits
409         useDaysMode
410         UseTransportCostMatrix
411         UseCourseReserves
412         finesCalendar
413         FinesIncludeGracePeriod
414         finesMode
415         RefundLostOnReturnControl
416         WhenLostChargeReplacementFee
417         WhenLostForgiveFine
418         AllowHoldDateInFuture
419         AllowHoldPolicyOverride
420         AllowHoldsOnDamagedItems
421         AllowHoldsOnPatronsPossessions
422         AutoResumeSuspendedHolds
423         canreservefromotherbranches
424         decreaseLoanHighHolds
425         DisplayMultiPlaceHold
426         emailLibrarianWhenHoldIsPlaced
427         ExpireReservesMaxPickUpDelay
428         OPACAllowHoldDateInFuture
429         OPACAllowUserToChooseBranch
430         ReservesControlBranch
431         ReservesNeedReturns
432         SuspendHoldsIntranet
433         SuspendHoldsOpac
434         TransferWhenCancelAllWaitingHolds
435         AllowAllMessageDeletion
436         AllowOfflineCirculation
437         CircAutocompl
438         CircAutoPrintQuickSlip
439         DisplayClearScreenButton
440         FilterBeforeOverdueReport
441         FineNotifyAtCheckin
442         itemBarcodeFallbackSearch
443         itemBarcodeInputFilter
444         previousIssuesDefaultSortOrder
445         RecordLocalUseOnReturn
446         soundon
447         SpecifyDueDate
448         todaysIssuesDefaultSortOrder
449         UpdateTotalIssuesOnCirc
450         UseTablesortForCirc
451         WaitingNotifyAtCheckin
452         AllowSelfCheckReturns
453         AutoSelfCheckAllowed
454         FRBRizeEditions
455         OPACFRBRizeEditions
456         AmazonCoverImages
457         OPACAmazonCoverImages
458         Babeltheque
459         BakerTaylorEnabled
460         GoogleJackets
461         HTML5MediaEnabled
462         IDreamBooksReadometer
463         IDreamBooksResults
464         IDreamBooksReviews
465         LibraryThingForLibrariesEnabled
466         LocalCoverImages
467         OPACLocalCoverImages
468         NovelistSelectEnabled
469         XISBN
470         OpenLibraryCovers
471         OpenLibrarySearch
472         UseKohaPlugins
473         SyndeticsEnabled
474         TagsEnabled
475         CalendarFirstDayOfWeek
476         opaclanguagesdisplay
477         AuthoritiesLog
478         BorrowersLog
479         CataloguingLog
480         FinesLog
481         IssueLog
482         LetterLog
483         ReturnLog
484         SubscriptionLog
485         BiblioDefaultView
486         COinSinOPACResults
487         DisplayOPACiconsXSLT
488         hidelostitems
489         HighlightOwnItemsOnOPAC
490         OpacAddMastheadLibraryPulldown
491         OPACDisplay856uAsImage
492         OpacHighlightedWords
493         OpacKohaUrl
494         OpacMaintenance
495         OpacPublic
496         OpacSeparateHoldings
497         OPACShowBarcode
498         OPACShowCheckoutName
499         OpacShowFiltersPulldownMobile
500         OPACShowHoldQueueDetails
501         OpacShowLibrariesPulldownMobile
502         OpacShowRecentComments
503         OPACShowUnusedAuthorities
504         OpacStarRatings
505         opacthemes
506         OPACURLOpenInNewWindow
507         OpacAuthorities
508         opacbookbag
509         OpacBrowser
510         OpacBrowseResults
511         OpacCloud
512         OPACFinesTab
513         OpacHoldNotes
514         OpacItemLocation
515         OpacPasswordChange
516         OPACPatronDetails
517         OPACpatronimages
518         OPACPopupAuthorsSearch
519         OpacTopissue
520         opacuserlogin
521         QuoteOfTheDay
522         RequestOnOpac
523         reviewson
524         ShowReviewer
525         ShowReviewerPhoto
526         SocialNetworks
527         suggestion
528         AllowPurchaseSuggestionBranchChoice
529         OpacAllowPublicListCreation
530         OpacAllowSharingPrivateLists
531         OpacRenewalAllowed
532         OpacRenewalBranch
533         OPACViewOthersSuggestions
534         SearchMyLibraryFirst
535         singleBranchMode
536         AnonSuggestions
537         EnableOpacSearchHistory
538         OPACPrivacy
539         opacreadinghistory
540         TrackClicks
541         PatronSelfRegistration
542         OPACShelfBrowser
543         AutoEmailOpacUser
544         AutoEmailPrimaryAddress
545         autoMemberNum
546         BorrowerRenewalPeriodBase
547         checkdigit
548         EnableBorrowerFiles
549         EnhancedMessagingPreferences
550         ExtendedPatronAttributes
551         intranetreadinghistory
552         memberofinstitution
553         patronimages
554         TalkingTechItivaPhoneNotification
555         uppercasesurnames
556         IncludeSeeFromInSearches
557         OpacGroupResults
558         QueryAutoTruncate
559         QueryFuzzy
560         QueryStemming
561         QueryWeightFields
562         TraceCompleteSubfields
563         TraceSubjectSubdivisions
564         UseICU
565         UseQueryParser
566         defaultSortField
567         displayFacetCount
568         OPACdefaultSortField
569         OPACItemsResultsDisplay
570         expandedSearchOption
571         IntranetNumbersPreferPhrase
572         OPACNumbersPreferPhrase
573         opacSerialDefaultTab
574         RenewSerialAddsSuggestion
575         RoutingListAddReserves
576         RoutingSerials
577         SubscriptionHistory
578         Display856uAsImage
579         DisplayIconsXSLT
580         template
581         yuipath
582         HidePatronName
583         intranetbookbag
584         StaffDetailItemSelection
585         viewISBD
586         viewLabeledMARC
587         viewMARC
588         ILS-DI
589         OAI-PMH
590         version
591         AudioAlerts
592         /
593       ) {
594         t::lib::Mocks::mock_preference( $_, $set_value );
595     }
596 }
597
598 #Test if all systempreferences are at $value_to_test
599 sub verif_systempreferences_values {
600     my ( $report, $value_to_test ) = @_;
601
602     my @missings;
603     foreach my $key ( keys %{$report->{systempreferences}} ) {
604         if ( $report->{systempreferences}->{$key} ne $value_to_test ) {
605             warn $key;
606             push @missings, $key;
607         }
608     }
609     unless ( @missings ) {
610         ok(1, 'All prefs are present');
611     } else {
612         ok(0, 'Some prefs are missing: ' . Dumper(\@missings));
613     }
614 }
615
616 $dbh->rollback;