1# -*- cperl -*-
2use strict;
3use warnings;
4use utf8;
5no warnings 'utf8';
6
7use Test::More tests => 33;
8use Test::Differences;
9unified_diff;
10
11use Biber;
12use Biber::Output::bbl;
13use Biber::Utils;
14use Log::Log4perl;
15chdir("t/tdata");
16
17# Set up Biber object
18my $biber = Biber->new(noconf => 1);
19my $LEVEL = 'ERROR';
20my $l4pconf = qq|
21    log4perl.category.main                             = $LEVEL, Screen
22    log4perl.category.screen                           = $LEVEL, Screen
23    log4perl.appender.Screen                           = Log::Log4perl::Appender::Screen
24    log4perl.appender.Screen.utf8                      = 1
25    log4perl.appender.Screen.Threshold                 = $LEVEL
26    log4perl.appender.Screen.stderr                    = 0
27    log4perl.appender.Screen.layout                    = Log::Log4perl::Layout::SimpleLayout
28|;
29Log::Log4perl->init(\$l4pconf);
30
31$biber->parse_ctrlfile('dm-dateformats.bcf');
32$biber->set_output_obj(Biber::Output::bbl->new());
33
34# Options - we could set these in the control file but it's nice to see what we're
35# relying on here for tests
36
37# Biber options
38Biber::Config->setoption('fastsort', 1);
39Biber::Config->setoption('sortlocale', 'C');
40Biber::Config->setoption('validate_datamodel', 1);
41
42# Biblatex options
43Biber::Config->setblxoption('labeldatespec', [ {content => 'date', type => 'field'} ]);
44
45# Now generate the information
46$biber->prepare;
47my $out = $biber->get_output_obj;
48my $section = $biber->sections->get_section(0);
49my $main = $biber->sortlists->get_list(0, 'nty', 'entry', 'nty');
50my $bibentries = $section->bibentries;
51my $l1 = [ "Datamodel: Entry 'L1' (dm-dateformats.bib): Invalid format '1985-1030' of date field 'origdate' - ignoring",
52           "Datamodel: Entry 'L1' (dm-dateformats.bib): Invalid format '1.5.1998' of date field 'urldate' - ignoring",
53           "Datamodel: Entry 'L1' (dm-dateformats.bib): Invalid date value 'YYYY/14/DD' - ignoring its components" ];
54my $l2 = [ "Datamodel: Entry 'L2' (dm-dateformats.bib): Invalid format '1995-1230' of date field 'origdate' - ignoring" ];
55my $l3 = [ "Datamodel: Entry 'L3' (dm-dateformats.bib): Invalid format '1.5.1988' of date field 'urldate' - ignoring" ];
56my $l4 = [ "Datamodel: Entry 'L4' (dm-dateformats.bib): Invalid format '1995-1-04' of date field 'date' - ignoring",
57           "Datamodel: Entry 'L4' (dm-dateformats.bib): Missing mandatory field - one of 'date, year' must be defined" ];
58my $l5 = [ "Datamodel: Entry 'L5' (dm-dateformats.bib): Invalid format '1995-10-4' of date field 'date' - ignoring",
59           "Datamodel: Entry 'L5' (dm-dateformats.bib): Missing mandatory field - one of 'date, year' must be defined" ];
60my $l6 = [ "Datamodel: Entry 'L6' (dm-dateformats.bib): Invalid date value '1996/13/03' - ignoring its components" ];
61my $l7 = [ "Datamodel: Entry 'L7' (dm-dateformats.bib): Invalid date value '1996/10/35' - ignoring its components" ];
62my $l11 = [ "Overwriting field 'year' with year value from field 'date' for entry 'L11'"];
63my $l12 = [ "Overwriting field 'month' with month value from field 'date' for entry 'L12'" ];
64
65my $l13c = q|    \entry{L13}{book}{}
66      \name{author}{2}{}{%
67        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
68        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
69      }
70      \list{publisher}{1}{%
71        {Oxford}%
72      }
73      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
74      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
75      \field{sortinit}{D}
76      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
77      \field{labelyear}{1996\bibdatedash }
78      \field{labelmonth}{01}
79      \field{labelday}{01}
80      \field{datelabelsource}{}
81      \field{labelnamesource}{author}
82      \field{labeltitlesource}{title}
83      \field{day}{01}
84      \field{endyear}{}
85      \field{month}{01}
86      \field{title}{Title 2}
87      \field{year}{1996}
88    \endentry
89|;
90
91my $l14 = q|    \entry{L14}{book}{}
92      \name{author}{2}{}{%
93        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
94        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
95      }
96      \list{publisher}{1}{%
97        {Oxford}%
98      }
99      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
100      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
101      \field{sortinit}{D}
102      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
103      \field{extrayear}{3}
104      \field{labelyear}{1996}
105      \field{labelmonth}{12}
106      \field{labelday}{10\bibdatedash 12}
107      \field{datelabelsource}{}
108      \field{labelnamesource}{author}
109      \field{labeltitlesource}{title}
110      \field{day}{10}
111      \field{endday}{12}
112      \field{endmonth}{12}
113      \field{endyear}{1996}
114      \field{month}{12}
115      \field{title}{Title 2}
116      \field{year}{1996}
117    \endentry
118|;
119
120my $l15 = q|    \entry{L15}{book}{}
121      \name{author}{2}{}{%
122        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
123        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
124      }
125      \list{publisher}{1}{%
126        {Oxford}%
127      }
128      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
129      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
130      \field{sortinit}{D}
131      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
132      \field{extrayear}{4}
133      \field{labelnamesource}{author}
134      \field{labeltitlesource}{title}
135      \field{title}{Title 2}
136      \warn{\item Datamodel: Entry 'L15' (dm-dateformats.bib): Missing mandatory field - one of 'date, year' must be defined}
137    \endentry
138|;
139
140my $l16 = q|    \entry{L16}{proceedings}{}
141      \name{editor}{2}{}{%
142        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
143        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
144      }
145      \list{publisher}{1}{%
146        {Oxford}%
147      }
148      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
149      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
150      \field{sortinit}{D}
151      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
152      \field{extrayear}{5}
153      \field{labelyear}{1996}
154      \field{labelmonth}{01}
155      \field{labelday}{01}
156      \field{datelabelsource}{event}
157      \field{labelnamesource}{editor}
158      \field{labeltitlesource}{title}
159      \field{eventday}{01}
160      \field{eventmonth}{01}
161      \field{eventyear}{1996}
162      \field{title}{Title 2}
163      \warn{\item Datamodel: Entry 'L16' (dm-dateformats.bib): Missing mandatory field - one of 'date, year' must be defined}
164    \endentry
165|;
166
167my $l17 = q|    \entry{L17}{proceedings}{}
168      \name{editor}{2}{}{%
169        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
170        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
171      }
172      \list{publisher}{1}{%
173        {Oxford}%
174      }
175      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
176      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
177      \field{sortinit}{D}
178      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
179      \field{extrayear}{4}
180      \field{labelyear}{1996}
181      \field{labelmonth}{12}
182      \field{labelday}{10\bibdatedash 12}
183      \field{datelabelsource}{}
184      \field{labelnamesource}{editor}
185      \field{labeltitlesource}{title}
186      \field{day}{10}
187      \field{endday}{12}
188      \field{endmonth}{12}
189      \field{endyear}{1996}
190      \field{eventday}{10}
191      \field{eventendday}{12}
192      \field{eventendmonth}{12}
193      \field{eventendyear}{2004}
194      \field{eventmonth}{12}
195      \field{eventyear}{1998}
196      \field{month}{12}
197      \field{origday}{10}
198      \field{origendday}{12}
199      \field{origendmonth}{12}
200      \field{origendyear}{1998}
201      \field{origmonth}{12}
202      \field{origyear}{1998}
203      \field{pubstate}{inpress}
204      \field{title}{Title 2}
205      \field{year}{1996}
206    \endentry
207|;
208
209my $l17c = q|    \entry{L17}{proceedings}{}
210      \name{editor}{2}{}{%
211        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
212        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
213      }
214      \list{publisher}{1}{%
215        {Oxford}%
216      }
217      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
218      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
219      \field{sortinit}{D}
220      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
221      \field{labelyear}{1998}
222      \field{labelmonth}{12}
223      \field{labelday}{10\bibdatedash 12}
224      \field{datelabelsource}{orig}
225      \field{labelnamesource}{editor}
226      \field{labeltitlesource}{title}
227      \field{day}{10}
228      \field{endday}{12}
229      \field{endmonth}{12}
230      \field{endyear}{1996}
231      \field{eventday}{10}
232      \field{eventendday}{12}
233      \field{eventendmonth}{12}
234      \field{eventendyear}{2004}
235      \field{eventmonth}{12}
236      \field{eventyear}{1998}
237      \field{month}{12}
238      \field{origday}{10}
239      \field{origendday}{12}
240      \field{origendmonth}{12}
241      \field{origendyear}{1998}
242      \field{origmonth}{12}
243      \field{origyear}{1998}
244      \field{pubstate}{inpress}
245      \field{title}{Title 2}
246      \field{year}{1996}
247    \endentry
248|;
249
250my $l17e = q|    \entry{L17}{proceedings}{}
251      \name{editor}{2}{}{%
252        {{hash=bd051a2f7a5f377e3a62581b0e0f8577}{Doe}{D\bibinitperiod}{John}{J\bibinitperiod}{}{}{}{}}%
253        {{hash=df9bf04cd41245e6d23ad7543e7fd90d}{Abrahams}{A\bibinitperiod}{Albert}{A\bibinitperiod}{}{}{}{}}%
254      }
255      \list{publisher}{1}{%
256        {Oxford}%
257      }
258      \strng{namehash}{8c77336299b25bdada7bf8038f46722f}
259      \strng{fullhash}{8c77336299b25bdada7bf8038f46722f}
260      \field{sortinit}{D}
261      \field{sortinithash}{78f7c4753a2004675f316a80bdb31742}
262      \field{labelyear}{1998\bibdatedash 2004}
263      \field{labelmonth}{12}
264      \field{labelday}{10\bibdatedash 12}
265      \field{datelabelsource}{event}
266      \field{labelnamesource}{editor}
267      \field{labeltitlesource}{title}
268      \field{day}{10}
269      \field{endday}{12}
270      \field{endmonth}{12}
271      \field{endyear}{1996}
272      \field{eventday}{10}
273      \field{eventendday}{12}
274      \field{eventendmonth}{12}
275      \field{eventendyear}{2004}
276      \field{eventmonth}{12}
277      \field{eventyear}{1998}
278      \field{month}{12}
279      \field{origday}{10}
280      \field{origendday}{12}
281      \field{origendmonth}{12}
282      \field{origendyear}{1998}
283      \field{origmonth}{12}
284      \field{origyear}{1998}
285      \field{pubstate}{inpress}
286      \field{title}{Title 2}
287      \field{year}{1996}
288    \endentry
289|;
290
291is_deeply($bibentries->entry('L1')->get_field('warnings'), $l1, 'Date values test 1' ) ;
292ok(is_undef($bibentries->entry('L1')->get_field('origyear')), 'Date values test 1a - ORIGYEAR undef since ORIGDATE is bad' ) ;
293ok(is_undef($bibentries->entry('L1')->get_field('urlyear')), 'Date values test 1b - URLYEAR undef since URLDATE is bad' ) ;
294ok(is_undef($bibentries->entry('L1')->get_field('month')), 'Date values test 1c - MONTH undef since not integer' ) ;
295is_deeply($bibentries->entry('L2')->get_field('warnings'), $l2, 'Date values test 2' ) ;
296is_deeply($bibentries->entry('L3')->get_field('warnings'), $l3, 'Date values test 3' ) ;
297is_deeply($bibentries->entry('L4')->get_field('warnings'), $l4, 'Date values test 4' ) ;
298is_deeply($bibentries->entry('L5')->get_field('warnings'), $l5, 'Date values test 5' ) ;
299is_deeply($bibentries->entry('L6')->get_field('warnings'), $l6, 'Date values test 6' ) ;
300is_deeply($bibentries->entry('L7')->get_field('warnings'), $l7, 'Date values test 7' ) ;
301eq_or_diff($bibentries->entry('L8')->get_field('month'), '01', 'Date values test 8b - MONTH hacked to integer' ) ;
302ok(is_undef($bibentries->entry('L9')->get_field('warnings')), 'Date values test 9' ) ;
303ok(is_undef($bibentries->entry('L10')->get_field('warnings')), 'Date values test 10' ) ;
304is_deeply($bibentries->entry('L11')->get_field('warnings'), $l11, 'Date values test 11' );
305eq_or_diff($bibentries->entry('L11')->get_field('year'), '1996', 'Date values test 11a - DATE overrides YEAR' ) ;
306is_deeply($bibentries->entry('L12')->get_field('warnings'), $l12, 'Date values test 12' );
307eq_or_diff($bibentries->entry('L12')->get_field('month'), '01', 'Date values test 12a - DATE overrides MONTH' ) ;
308# it means something if endyear is defined but null ("1935-")
309ok(is_def_and_null($bibentries->entry('L13')->get_field('endyear')), 'Date values test 13 - range with no end' ) ;
310ok(is_undef($bibentries->entry('L13')->get_field('endmonth')), 'Date values test 13a - ENDMONTH undef for open-ended range' ) ;
311ok(is_undef($bibentries->entry('L13')->get_field('endday')), 'Date values test 13b - ENDDAY undef for open-ended range' ) ;
312eq_or_diff( $out->get_output_entry('L13', $main), $l13c, 'Date values test 13c - labelyear open-ended range' ) ;
313eq_or_diff( $out->get_output_entry('L14', $main), $l14, 'Date values test 14 - labelyear same as YEAR when ENDYEAR == YEAR') ;
314eq_or_diff( $out->get_output_entry('L15', $main), $l15, 'Date values test 15 - labelyear should be undef, no DATE or YEAR') ;
315
316# reset options and regenerate information
317Biber::Config->setblxoption('labeldatespec', [ {content => 'date', type => 'field'},
318                                               {content => 'eventdate', type => 'field'},
319                                               {content => 'origdate', type => 'field'} ]);
320$bibentries->del_entry('L17');
321$bibentries->del_entry('L16');
322$biber->prepare;
323$out = $biber->get_output_obj;
324
325eq_or_diff($bibentries->entry('L16')->get_labeldate_info->{field}{year}, 'eventyear', 'Date values test 16 - labelyear = EVENTYEAR when YEAR is (mistakenly) missing' ) ;
326eq_or_diff($out->get_output_entry('L16', $main), $l16, 'Date values test 16a - labelyear = EVENTYEAR value when YEAR is (mistakenly) missing' );
327eq_or_diff($bibentries->entry('L17')->get_labeldate_info->{field}{year}, 'year', 'Date values test 17 - labelyear = YEAR' ) ;
328eq_or_diff($out->get_output_entry('L17', $main), $l17, 'Date values test 17a - labelyear = YEAR value when ENDYEAR is the same and ORIGYEAR is also present' ) ;
329
330# reset options and regenerate information
331Biber::Config->setblxoption('labeldatespec', [ {content => 'origdate', type => 'field'},
332                                               {content => 'date', type => 'field'},
333                                               {content => 'eventdate', type => 'field'} ]);
334$bibentries->del_entry('L17');
335$biber->prepare;
336$out = $biber->get_output_obj;
337
338eq_or_diff($bibentries->entry('L17')->get_labeldate_info->{field}{year}, 'origyear', 'Date values test 17b - labelyear = ORIGYEAR' ) ;
339eq_or_diff($out->get_output_entry('L17', $main), $l17c, 'Date values test 17c - labelyear = ORIGYEAR value when ENDORIGYEAR is the same and YEAR is also present' ) ;
340
341# reset options and regenerate information
342Biber::Config->setblxoption('labeldatespec', [ {content => 'eventdate', type => 'field'},
343                                               {content => 'date', type => 'field'},
344                                               {content => 'origdate', type => 'field'} ], 'PER_TYPE', 'proceedings');
345$bibentries->del_entry('L17');
346$biber->prepare;
347$out = $biber->get_output_obj;
348
349eq_or_diff($bibentries->entry('L17')->get_labeldate_info->{field}{year}, 'eventyear', 'Date values test 17d - labelyear = EVENTYEAR' ) ;
350eq_or_diff($bibentries->entry('L17')->get_labeldate_info->{field}{source}, 'event', 'Date values test 17d - source = event' ) ;
351eq_or_diff($out->get_output_entry('L17', $main), $l17e, 'Date values test 17e - labelyear = ORIGYEAR-ORIGENDYEAR' ) ;
352
353# reset options and regenerate information
354Biber::Config->setblxoption('labeldatespec', [ {content => 'pubstate', type => 'field'} ], 'PER_TYPE', 'proceedings');
355
356$bibentries->del_entry('L17');
357$biber->prepare;
358$out = $biber->get_output_obj;
359eq_or_diff($bibentries->entry('L17')->get_labeldate_info->{field}{source}, 'pubstate', 'Source is non-date field' );
360