Bug 20144: [sql_modes] Set correct value for old_issues.issue_id in tests
[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 t::lib::TestBuilder;
21 use POSIX qw(strftime);
22 use Data::Dumper;
23 use Koha::Biblios;
24
25 use Koha::Libraries;
26
27 BEGIN {
28     use_ok('C4::UsageStats');
29     use_ok('C4::Context');
30     use_ok('C4::Biblio');
31     use_ok( 'C4::AuthoritiesMarc', qw(AddAuthority) );
32     use_ok('C4::Reserves');
33     use_ok('MARC::Record');
34     use_ok('Koha::Acquisition::Orders');
35 }
36
37 can_ok(
38     'C4::UsageStats', qw(
39       NeedUpdate
40       BuildReport
41       ReportToCommunity
42       _count )
43 );
44
45 my $schema  = Koha::Database->new->schema;
46 $schema->storage->txn_begin;
47 my $builder = t::lib::TestBuilder->new;
48 my $dbh = C4::Context->dbh;
49
50 $dbh->do('DELETE FROM issues');
51 $dbh->do('DELETE FROM biblio');
52 $dbh->do('DELETE FROM items');
53 $dbh->do('DELETE FROM auth_header');
54 $dbh->do('DELETE FROM old_issues');
55 $dbh->do('DELETE FROM old_reserves');
56 $dbh->do('DELETE FROM borrowers');
57 $dbh->do('DELETE FROM aqorders');
58 $dbh->do('DELETE FROM subscription');
59
60 #################################################
61 #             Testing Subs
62 #################################################
63
64 # ---------- Testing NeedUpdate -----------------
65
66 #Mocking C4::Context->preference("UsageStatsLastUpdateTime") to 0
67 my $now = strftime( "%s", localtime );
68 t::lib::Mocks::mock_preference( "UsageStatsLastUpdateTime", 0 );
69
70 my $update = C4::UsageStats->NeedUpdate;
71 is( $update, 1, "There is no last update, update needed" );
72
73 #Mocking C4::Context->preference("UsageStatsLastUpdateTime") to now
74 $now = strftime( "%s", localtime );
75 t::lib::Mocks::mock_preference( "UsageStatsLastUpdateTime", $now );
76
77 $update = C4::UsageStats->NeedUpdate;
78 is( $update, 0, "Last update just be done, no update needed " );
79
80 my $nb_of_libraries = Koha::Libraries->count;
81
82 # ---------- Testing BuildReport ----------------
83
84 #Test report->library -----------------
85 #mock to 0
86 t::lib::Mocks::mock_preference( "UsageStatsID",          0 );
87 t::lib::Mocks::mock_preference( "UsageStatsLibraryName", 0 );
88 t::lib::Mocks::mock_preference( "UsageStatsLibrariesInfo",  0 );
89 t::lib::Mocks::mock_preference( "UsageStatsLibraryType", 0 );
90 t::lib::Mocks::mock_preference( "UsageStatsCountry",     0 );
91 t::lib::Mocks::mock_preference( "UsageStatsLibraryUrl",  0 );
92
93 my $report = C4::UsageStats->BuildReport();
94
95 isa_ok( $report,              'HASH',  '$report is a HASH' );
96 isa_ok( $report->{libraries}, 'ARRAY', '$report->{libraries} is an ARRAY' );
97 is( scalar( @{ $report->{libraries} } ), 0, "There are 0 fields in libraries, libraries info are not shared" );
98 is( $report->{installation}->{koha_id}, 0,  "UsageStatsID          is good" );
99 is( $report->{installation}->{name},    '', "UsageStatsLibraryName is good" );
100 is( $report->{installation}->{url},     '', "UsageStatsLibraryUrl  is good" );
101 is( $report->{installation}->{type},    '', "UsageStatsLibraryType is good" );
102 is( $report->{installation}->{country}, '', "UsageStatsCountry     is good" );
103
104
105 #mock with values
106 t::lib::Mocks::mock_preference( "UsageStatsID",          1 );
107 t::lib::Mocks::mock_preference( "UsageStatsLibraryName", 'NAME' );
108 t::lib::Mocks::mock_preference( "UsageStatsLibraryUrl",  'URL' );
109 t::lib::Mocks::mock_preference( "UsageStatsLibraryType", 'TYPE' );
110 t::lib::Mocks::mock_preference( "UsageStatsCountry",     'COUNTRY' );
111 t::lib::Mocks::mock_preference( "UsageStatsLibrariesInfo", 1 );
112 t::lib::Mocks::mock_preference( "UsageStatsGeolocation", 1 );
113
114
115 $report = C4::UsageStats->BuildReport();
116
117 isa_ok( $report,              'HASH',  '$report is a HASH' );
118 isa_ok( $report->{libraries}, 'ARRAY', '$report->{libraries} is an ARRAY' );
119 is( scalar( @{ $report->{libraries} } ), $nb_of_libraries, "There are 6 fields in $report->{libraries}" );
120 is( $report->{installation}->{koha_id}, 1,     "UsageStatsID          is good" );
121 is( $report->{installation}->{name},   'NAME', "UsageStatsLibraryName is good" );
122 is( $report->{installation}->{url},     'URL', "UsageStatsLibraryUrl  is good" );
123 is( $report->{installation}->{type},   'TYPE', "UsageStatsLibraryType is good" );
124 is( $report->{installation}->{country}, 'COUNTRY', "UsageStatsCountry is good" );
125
126 #Test report->volumetry ---------------
127 #with original values
128 $report = C4::UsageStats->BuildReport();
129
130 isa_ok( $report,              'HASH', '$report is a HASH' );
131 isa_ok( $report->{volumetry}, 'HASH', '$report->{volumetry} is a HASH' );
132 is( scalar( keys %{$report->{volumetry}} ), 8, "There are 8 fields in $report->{volumetry}" );
133 is( $report->{volumetry}->{biblio},         0, "There is no biblio" );
134 is( $report->{volumetry}->{items},          0, "There is no items" );
135 is( $report->{volumetry}->{auth_header},    0, "There is no auth_header" );
136 is( $report->{volumetry}->{old_issues},     0, "There is no old_issues" );
137 is( $report->{volumetry}->{old_reserves},   0, "There is no old_reserves" );
138 is( $report->{volumetry}->{borrowers},      0, "There is no borrowers" );
139 is( $report->{volumetry}->{aqorders},       0, "There is no aqorders" );
140 is( $report->{volumetry}->{subscription},   0, "There is no subscription" );
141
142 #after adding objects
143 construct_objects_needed();
144
145 $report = C4::UsageStats->BuildReport();
146
147 isa_ok( $report,              'HASH', '$report is a HASH' );
148 isa_ok( $report->{volumetry}, 'HASH', '$report->{volumetry} is a HASH' );
149 is( scalar( keys %{$report->{volumetry}} ), 8, "There are 8 fields in $report->{volumetry}" );
150 is( $report->{volumetry}->{biblio},         3, "There are 3 biblio" );
151 is( $report->{volumetry}->{items},          3, "There are 3 items" );
152 is( $report->{volumetry}->{auth_header},    2, "There are 2 auth_header" );
153 is( $report->{volumetry}->{old_issues},     1, "There is  1 old_issues" );
154 is( $report->{volumetry}->{old_reserves},   1, "There is  1 old_reserves" );
155 is( $report->{volumetry}->{borrowers},      3, "There are 3 borrowers" );
156 is( $report->{volumetry}->{aqorders},       1, "There is  1 aqorders" );
157 is( $report->{volumetry}->{subscription},   1, "There is  1 subscription" );
158
159 #Test report->systempreferences -------
160 #mock to 0
161 mocking_systempreferences_to_a_set_value(0);
162
163 $report = C4::UsageStats->BuildReport();
164 isa_ok( $report,                      'HASH', '$report is a HASH' );
165 isa_ok( $report->{systempreferences}, 'HASH', '$report->{systempreferences} is a HASH' );
166 verif_systempreferences_values( $report, 0 );
167
168 #mock with values
169 mocking_systempreferences_to_a_set_value(1);
170
171 $report = C4::UsageStats->BuildReport();
172 isa_ok( $report,                      'HASH', '$report is a HASH' );
173 isa_ok( $report->{systempreferences}, 'HASH', '$report->{systempreferences} is a HASH' );
174 verif_systempreferences_values( $report, 1 );
175
176 #Test if unwanted syspref are not sent
177 is( $report->{systempreferences}->{useDischarge}, undef, 'useDischarge should not be shared');
178 is( $report->{systempreferences}->{OpacUserJS},   undef, 'OpacUserJS   should not be shared');
179
180 # ---------- Testing ReportToCommunity ----------
181
182 # ---------- Testing _count ---------------------
183 my $query = '
184   SELECT count(*)
185   FROM   borrowers
186   ';
187 my $count = $dbh->selectrow_array($query);
188
189 my $nb_fields = C4::UsageStats::_count('borrowers');
190 is( $nb_fields, $count, "_count return the good number of fields" );
191
192 #################################################
193 #             Subs
194 #################################################
195
196 # Adding :
197 # 3 borrowers
198 # 4 biblio
199 # 3 biblio items
200 # 3 items
201 # 2 auth_header
202 # 1 old_issues
203 # 1 old_reserves
204 # 1 subscription
205 # 1 aqorders
206 sub construct_objects_needed {
207
208     # ---------- 3 borrowers  ---------------------
209     my $surname1     = 'Borrower 1';
210     my $surname2     = 'Borrower 2';
211     my $surname3     = 'Borrower 3';
212     my $firstname1   = 'firstname 1';
213     my $firstname2   = 'firstname 2';
214     my $firstname3   = 'firstname 3';
215     my $cardnumber1  = 'test_card1';
216     my $cardnumber2  = 'test_card2';
217     my $cardnumber3  = 'test_card3';
218     my $categorycode = $builder->build({ source => 'Category' })->{categorycode};
219     my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
220
221     my $query = '
222     INSERT INTO borrowers
223       (surname, firstname, cardnumber, branchcode, categorycode)
224     VALUES (?,?,?,?,?)';
225     my $insert_sth = $dbh->prepare($query);
226     $insert_sth->execute( $surname1, $firstname1, $cardnumber1, $branchcode, $categorycode );
227     my $borrowernumber1 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
228     $insert_sth->execute( $surname2, $firstname2, $cardnumber2, $branchcode, $categorycode );
229     my $borrowernumber2 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
230     $insert_sth->execute( $surname3, $firstname3, $cardnumber3, $branchcode, $categorycode );
231     my $borrowernumber3 = $dbh->last_insert_id( undef, undef, 'borrowers', undef );
232
233     # ---------- 3 biblios -----------------------
234     my $title1  = 'Title 1';
235     my $title2  = 'Title 2';
236     my $title3  = 'Title 3';
237     my $author1 = 'Author 1';
238     my $author2 = 'Author 2';
239     my $author3 = 'Author 3';
240
241     $query = '
242     INSERT INTO biblio
243       (title, author, datecreated)
244     VALUES (?,?, NOW())';
245     $insert_sth = $dbh->prepare($query);
246     $insert_sth->execute( $title1, $author1 );
247     my $biblionumber1 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
248     $insert_sth->execute( $title2, undef );
249     my $biblionumber2 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
250     $insert_sth->execute( $title3, $author3 );
251     my $biblionumber3 = $dbh->last_insert_id( undef, undef, 'biblio', undef );
252
253     # ---------- 3 biblio items  -------------------------
254     $query = '
255     INSERT INTO biblioitems
256       (biblionumber, itemtype)
257     VALUES (?,?)';
258     $insert_sth = $dbh->prepare($query);
259     $insert_sth->execute( $biblionumber1, 'Book' );
260     my $biblioitemnumber1 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
261     $insert_sth->execute( $biblionumber2, 'Music' );
262     my $biblioitemnumber2 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
263     $insert_sth->execute( $biblionumber3, 'Book' );
264     my $biblioitemnumber3 = $dbh->last_insert_id( undef, undef, 'biblioitems', undef );
265
266     # ---------- 3 items  -------------------------
267     my $barcode1 = '111111';
268     my $barcode2 = '222222';
269     my $barcode3 = '333333';
270
271     $query = '
272     INSERT INTO items
273       (biblionumber, biblioitemnumber, barcode, itype)
274     VALUES (?,?,?,?)';
275     $insert_sth = $dbh->prepare($query);
276     $insert_sth->execute( $biblionumber1, $biblioitemnumber1, $barcode1, 'Book' );
277     my $item_number1 = $dbh->last_insert_id( undef, undef, 'items', undef );
278     $insert_sth->execute( $biblionumber2, $biblioitemnumber2, $barcode2, 'Music' );
279     my $item_number2 = $dbh->last_insert_id( undef, undef, 'items', undef );
280     $insert_sth->execute( $biblionumber3, $biblioitemnumber3, $barcode3, 'Book' );
281     my $item_number3 = $dbh->last_insert_id( undef, undef, 'items', undef );
282
283     # ---------- Add 2 auth_header
284     $query = '
285     INSERT INTO auth_header
286       (authtypecode, marcxml)
287     VALUES (?, "")';
288     $insert_sth = $dbh->prepare($query);
289     $insert_sth->execute('atc1');
290     my $authid1 = $dbh->last_insert_id( undef, undef, 'auth_header', undef );
291     $insert_sth->execute('atc2');
292     my $authid2 = $dbh->last_insert_id( undef, undef, 'auth_header', undef );
293
294     # ---------- Add 1 old_issues
295     $query = '
296     INSERT INTO old_issues
297       (issue_id, borrowernumber, branchcode, itemnumber)
298     VALUES ((select coalesce(max(issue_id), 0)+1 from issues),?,?,?)';
299     $insert_sth = $dbh->prepare($query);
300     $insert_sth->execute( $borrowernumber1, $branchcode, $item_number1 );
301     my $issue_id1 = $dbh->last_insert_id( undef, undef, 'old_issues', undef );
302
303     # ---------- Add 1 old_reserves
304     AddReserve( $branchcode, $borrowernumber1, $biblionumber1, '', 1, undef, undef, '', 'Title', undef, undef );
305     my $biblio = Koha::Biblios->find( $biblionumber1 );
306     my $holds = $biblio->holds;
307     $holds->next->cancel if $holds->count;
308
309     # ---------- Add 1 aqbudgets
310     $query = '
311     INSERT INTO aqbudgets
312       (budget_amount)
313     VALUES (?)';
314     $insert_sth = $dbh->prepare($query);
315     $insert_sth->execute("20.0");
316     my $aqbudgets1 = $dbh->last_insert_id( undef, undef, 'aqbudgets', undef );
317
318     # ---------- Add 1 aqorders
319     $query = '
320     INSERT INTO aqorders
321       (budget_id, basketno, biblionumber, invoiceid, subscriptionid)
322     VALUES (?,?,?,?,?)';
323     $insert_sth = $dbh->prepare($query);
324     $insert_sth->execute( $aqbudgets1, undef, undef, undef, undef );
325     my $aqorders1 = $dbh->last_insert_id( undef, undef, 'aqorders', undef );
326
327     # --------- Add 1 subscription
328     $query = '
329     INSERT INTO subscription
330       (biblionumber)
331     VALUES (?)';
332     $insert_sth = $dbh->prepare($query);
333     $insert_sth->execute($biblionumber1);
334     my $subscription1 = $dbh->last_insert_id( undef, undef, 'subscription', undef );
335
336 }
337
338 #Change systempreferences values to $set_value
339 sub mocking_systempreferences_to_a_set_value {
340     my $set_value = shift;
341
342     foreach (
343         qw/
344         AcqCreateItem
345         AcqWarnOnDuplicateInvoice
346         AcqViewBaskets
347         BasketConfirmations
348         OrderPdfFormat
349         casAuthentication
350         casLogout
351         AllowPKIAuth
352         DebugLevel
353         delimiter
354         noItemTypeImages
355         virtualshelves
356         AutoLocation
357         IndependentBranches
358         SessionStorage
359         Persona
360         AuthDisplayHierarchy
361         AutoCreateAuthorities
362         BiblioAddsAuthorities
363         AuthorityMergeLimit
364         AuthorityMergeMode
365         UseAuthoritiesForTracings
366         CatalogModuleRelink
367         hide_marc
368         IntranetBiblioDefaultView
369         LabelMARCView
370         OpacSuppression
371         SeparateHoldings
372         UseControlNumber
373         advancedMARCeditor
374         DefaultClassificationSource
375         EasyAnalyticalRecords
376         autoBarcode
377         item-level_itypes
378         marcflavour
379         PrefillItem
380         z3950NormalizeAuthor
381         SpineLabelAutoPrint
382         SpineLabelShowPrintOnBibDetails
383         BlockReturnOfLostItems
384         BlockReturnOfWithdrawnItems
385         CalculateFinesOnReturn
386         AgeRestrictionOverride
387         AllFinesNeedOverride
388         AllowFineOverride
389         AllowItemsOnHoldCheckout
390         AllowItemsOnHoldCheckoutSCO
391         AllowNotForLoanOverride
392         AllowRenewalLimitOverride
393         AllowReturnToBranch
394         AllowTooManyOverride
395         AutomaticItemReturn
396         AutoRemoveOverduesRestrictions
397         CircControl
398         HomeOrHoldingBranch
399         HomeOrHoldingBranchReturn
400         InProcessingToShelvingCart
401         IssueLostItem
402         IssuingInProcess
403         ManInvInNoissuesCharge
404         OverduesBlockCirc
405         RenewalPeriodBase
406         RenewalSendNotice
407         RentalsInNoissuesCharge
408         ReturnBeforeExpiry
409         ReturnToShelvingCart
410         TransfersMaxDaysWarning
411         UseBranchTransferLimits
412         useDaysMode
413         UseTransportCostMatrix
414         UseCourseReserves
415         finesCalendar
416         FinesIncludeGracePeriod
417         finesMode
418         RefundLostOnReturnControl
419         WhenLostChargeReplacementFee
420         WhenLostForgiveFine
421         AllowHoldDateInFuture
422         AllowHoldPolicyOverride
423         AllowHoldsOnDamagedItems
424         AllowHoldsOnPatronsPossessions
425         AutoResumeSuspendedHolds
426         canreservefromotherbranches
427         decreaseLoanHighHolds
428         DisplayMultiPlaceHold
429         emailLibrarianWhenHoldIsPlaced
430         ExpireReservesMaxPickUpDelay
431         OPACAllowHoldDateInFuture
432         OPACAllowUserToChooseBranch
433         ReservesControlBranch
434         ReservesNeedReturns
435         SuspendHoldsIntranet
436         SuspendHoldsOpac
437         TransferWhenCancelAllWaitingHolds
438         AllowAllMessageDeletion
439         AllowOfflineCirculation
440         CircAutocompl
441         CircAutoPrintQuickSlip
442         DisplayClearScreenButton
443         FilterBeforeOverdueReport
444         FineNotifyAtCheckin
445         itemBarcodeFallbackSearch
446         itemBarcodeInputFilter
447         previousIssuesDefaultSortOrder
448         RecordLocalUseOnReturn
449         soundon
450         SpecifyDueDate
451         todaysIssuesDefaultSortOrder
452         UpdateTotalIssuesOnCirc
453         UseTablesortForCirc
454         WaitingNotifyAtCheckin
455         AllowSelfCheckReturns
456         AutoSelfCheckAllowed
457         FRBRizeEditions
458         OPACFRBRizeEditions
459         AmazonCoverImages
460         OPACAmazonCoverImages
461         Babeltheque
462         BakerTaylorEnabled
463         GoogleJackets
464         HTML5MediaEnabled
465         IDreamBooksReadometer
466         IDreamBooksResults
467         IDreamBooksReviews
468         LibraryThingForLibrariesEnabled
469         LocalCoverImages
470         OPACLocalCoverImages
471         NovelistSelectEnabled
472         XISBN
473         OpenLibraryCovers
474         OpenLibrarySearch
475         UseKohaPlugins
476         SyndeticsEnabled
477         TagsEnabled
478         CalendarFirstDayOfWeek
479         opaclanguagesdisplay
480         AuthoritiesLog
481         BorrowersLog
482         CataloguingLog
483         FinesLog
484         IssueLog
485         LetterLog
486         ReturnLog
487         SubscriptionLog
488         BiblioDefaultView
489         COinSinOPACResults
490         DisplayOPACiconsXSLT
491         hidelostitems
492         HighlightOwnItemsOnOPAC
493         OpacAddMastheadLibraryPulldown
494         OPACDisplay856uAsImage
495         OpacHighlightedWords
496         OpacKohaUrl
497         OpacMaintenance
498         OpacPublic
499         OpacSeparateHoldings
500         OPACShowCheckoutName
501         OpacShowFiltersPulldownMobile
502         OPACShowHoldQueueDetails
503         OpacShowRecentComments
504         OPACShowUnusedAuthorities
505         OpacStarRatings
506         opacthemes
507         OPACURLOpenInNewWindow
508         OpacAuthorities
509         opacbookbag
510         OpacBrowser
511         OpacBrowseResults
512         OpacCloud
513         OPACFinesTab
514         OpacHoldNotes
515         OpacItemLocation
516         OpacPasswordChange
517         OPACPatronDetails
518         OPACpatronimages
519         OPACPopupAuthorsSearch
520         OpacTopissue
521         opacuserlogin
522         QuoteOfTheDay
523         RequestOnOpac
524         reviewson
525         ShowReviewer
526         ShowReviewerPhoto
527         SocialNetworks
528         suggestion
529         AllowPurchaseSuggestionBranchChoice
530         OpacAllowPublicListCreation
531         OpacAllowSharingPrivateLists
532         OpacRenewalAllowed
533         OpacRenewalBranch
534         OPACViewOthersSuggestions
535         SearchMyLibraryFirst
536         singleBranchMode
537         AnonSuggestions
538         EnableOpacSearchHistory
539         OPACPrivacy
540         opacreadinghistory
541         TrackClicks
542         PatronSelfRegistration
543         OPACShelfBrowser
544         AutoEmailOpacUser
545         AutoEmailPrimaryAddress
546         autoMemberNum
547         BorrowerRenewalPeriodBase
548         checkdigit
549         EnableBorrowerFiles
550         EnhancedMessagingPreferences
551         ExtendedPatronAttributes
552         intranetreadinghistory
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 $schema->storage->txn_rollback;