• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "annotator/grammar/dates/utils/date-match.h"
18 
19 #include <stdint.h>
20 
21 #include <string>
22 
23 #include "annotator/grammar/dates/dates_generated.h"
24 #include "annotator/grammar/dates/timezone-code_generated.h"
25 #include "annotator/grammar/dates/utils/date-utils.h"
26 #include "utils/strings/append.h"
27 #include "gtest/gtest.h"
28 
29 namespace libtextclassifier3 {
30 namespace dates {
31 namespace {
32 
33 class DateMatchTest : public ::testing::Test {
34  protected:
35   enum {
36     X = NO_VAL,
37   };
38 
DOW_X()39   static DayOfWeek DOW_X() { return DayOfWeek_DOW_NONE; }
SUN()40   static DayOfWeek SUN() { return DayOfWeek_SUNDAY; }
41 
BCAD_X()42   static BCAD BCAD_X() { return BCAD_BCAD_NONE; }
BC()43   static BCAD BC() { return BCAD_BC; }
44 
SetDate(DateMatch * date,int year,int8 month,int8 day,DayOfWeek day_of_week=DOW_X (),BCAD bc_ad=BCAD_X ())45   DateMatch& SetDate(DateMatch* date, int year, int8 month, int8 day,
46                      DayOfWeek day_of_week = DOW_X(), BCAD bc_ad = BCAD_X()) {
47     date->year = year;
48     date->month = month;
49     date->day = day;
50     date->day_of_week = day_of_week;
51     date->bc_ad = bc_ad;
52     return *date;
53   }
54 
SetTimeValue(DateMatch * date,int8 hour,int8 minute=X,int8 second=X,double fraction_second=X)55   DateMatch& SetTimeValue(DateMatch* date, int8 hour, int8 minute = X,
56                           int8 second = X, double fraction_second = X) {
57     date->hour = hour;
58     date->minute = minute;
59     date->second = second;
60     date->fraction_second = fraction_second;
61     return *date;
62   }
63 
SetTimeSpan(DateMatch * date,TimespanCode time_span_code)64   DateMatch& SetTimeSpan(DateMatch* date, TimespanCode time_span_code) {
65     date->time_span_code = time_span_code;
66     return *date;
67   }
68 
SetTimeZone(DateMatch * date,TimezoneCode time_zone_code,int16 time_zone_offset=INT16_MIN)69   DateMatch& SetTimeZone(DateMatch* date, TimezoneCode time_zone_code,
70                          int16 time_zone_offset = INT16_MIN) {
71     date->time_zone_code = time_zone_code;
72     date->time_zone_offset = time_zone_offset;
73     return *date;
74   }
75 
SameDate(const DateMatch & a,const DateMatch & b)76   bool SameDate(const DateMatch& a, const DateMatch& b) {
77     return (a.day == b.day && a.month == b.month && a.year == b.year &&
78             a.day_of_week == b.day_of_week);
79   }
80 
SetDayOfWeek(DateMatch * date,DayOfWeek dow)81   DateMatch& SetDayOfWeek(DateMatch* date, DayOfWeek dow) {
82     date->day_of_week = dow;
83     return *date;
84   }
85 };
86 
TEST_F(DateMatchTest,BitFieldWidth)87 TEST_F(DateMatchTest, BitFieldWidth) {
88   // For DateMatch::day_of_week (:8).
89   EXPECT_GE(DayOfWeek_MIN, INT8_MIN);
90   EXPECT_LE(DayOfWeek_MAX, INT8_MAX);
91 
92   // For DateMatch::bc_ad (:8).
93   EXPECT_GE(BCAD_MIN, INT8_MIN);
94   EXPECT_LE(BCAD_MAX, INT8_MAX);
95 
96   // For DateMatch::time_span_code (:16).
97   EXPECT_GE(TimespanCode_MIN, INT16_MIN);
98   EXPECT_LE(TimespanCode_MAX, INT16_MAX);
99 }
100 
TEST_F(DateMatchTest,IsValid)101 TEST_F(DateMatchTest, IsValid) {
102   // Valid: dates.
103   {
104     DateMatch d;
105     SetDate(&d, 2014, 1, 26);
106     EXPECT_TRUE(d.IsValid()) << d.DebugString();
107   }
108   {
109     DateMatch d;
110     SetDate(&d, 2014, 1, X);
111     EXPECT_TRUE(d.IsValid()) << d.DebugString();
112   }
113   {
114     DateMatch d;
115     SetDate(&d, 2014, X, X);
116     EXPECT_TRUE(d.IsValid()) << d.DebugString();
117   }
118   {
119     DateMatch d;
120     SetDate(&d, X, 1, 26);
121     EXPECT_TRUE(d.IsValid()) << d.DebugString();
122   }
123   {
124     DateMatch d;
125     SetDate(&d, X, 1, X);
126     EXPECT_TRUE(d.IsValid()) << d.DebugString();
127   }
128   {
129     DateMatch d;
130     SetDate(&d, X, X, 26);
131     EXPECT_TRUE(d.IsValid()) << d.DebugString();
132   }
133   {
134     DateMatch d;
135     SetDate(&d, 2014, 1, 26, SUN());
136     EXPECT_TRUE(d.IsValid()) << d.DebugString();
137   }
138   {
139     DateMatch d;
140     SetDate(&d, X, 1, 26, SUN());
141     EXPECT_TRUE(d.IsValid()) << d.DebugString();
142   }
143   {
144     DateMatch d;
145     SetDate(&d, X, X, 26, SUN());
146     EXPECT_TRUE(d.IsValid()) << d.DebugString();
147   }
148   {
149     DateMatch d;
150     SetDate(&d, 2014, 1, 26, DOW_X(), BC());
151     EXPECT_TRUE(d.IsValid()) << d.DebugString();
152   }
153   // Valid: times.
154   {
155     DateMatch d;
156     SetTimeValue(&d, 12, 30, 59, 0.99);
157     EXPECT_TRUE(d.IsValid()) << d.DebugString();
158   }
159   {
160     DateMatch d;
161     SetTimeValue(&d, 12, 30, 59);
162     EXPECT_TRUE(d.IsValid()) << d.DebugString();
163   }
164   {
165     DateMatch d;
166     SetTimeValue(&d, 12, 30);
167     EXPECT_TRUE(d.IsValid()) << d.DebugString();
168   }
169   {
170     DateMatch d;
171     SetTimeValue(&d, 12);
172     EXPECT_TRUE(d.IsValid()) << d.DebugString();
173   }
174   // Valid: mixed.
175   {
176     DateMatch d;
177     SetDate(&d, 2014, 1, 26);
178     SetTimeValue(&d, 12, 30, 59, 0.99);
179     EXPECT_TRUE(d.IsValid()) << d.DebugString();
180   }
181   {
182     DateMatch d;
183     SetDate(&d, X, 1, 26);
184     SetTimeValue(&d, 12, 30, 59);
185     EXPECT_TRUE(d.IsValid()) << d.DebugString();
186   }
187   {
188     DateMatch d;
189     SetDate(&d, X, X, X, SUN());
190     SetTimeValue(&d, 12, 30);
191     EXPECT_TRUE(d.IsValid()) << d.DebugString();
192   }
193   // Invalid: dates.
194   {
195     DateMatch d;
196     SetDate(&d, X, 1, 26, DOW_X(), BC());
197     EXPECT_FALSE(d.IsValid()) << d.DebugString();
198   }
199   {
200     DateMatch d;
201     SetDate(&d, 2014, X, 26);
202     EXPECT_FALSE(d.IsValid()) << d.DebugString();
203   }
204   {
205     DateMatch d;
206     SetDate(&d, 2014, X, X, SUN());
207     EXPECT_FALSE(d.IsValid()) << d.DebugString();
208   }
209   {
210     DateMatch d;
211     SetDate(&d, X, 1, X, SUN());
212     EXPECT_FALSE(d.IsValid()) << d.DebugString();
213   }
214   // Invalid: times.
215   {
216     DateMatch d;
217     SetTimeValue(&d, 12, X, 59);
218     EXPECT_FALSE(d.IsValid()) << d.DebugString();
219   }
220   {
221     DateMatch d;
222     SetTimeValue(&d, 12, X, X, 0.99);
223     EXPECT_FALSE(d.IsValid()) << d.DebugString();
224   }
225   {
226     DateMatch d;
227     SetTimeValue(&d, 12, 30, X, 0.99);
228     EXPECT_FALSE(d.IsValid()) << d.DebugString();
229   }
230   {
231     DateMatch d;
232     SetTimeValue(&d, X, 30);
233     EXPECT_FALSE(d.IsValid()) << d.DebugString();
234   }
235   // Invalid: mixed.
236   {
237     DateMatch d;
238     SetDate(&d, 2014, 1, X);
239     SetTimeValue(&d, 12);
240     EXPECT_FALSE(d.IsValid()) << d.DebugString();
241   }
242   // Invalid: empty.
243   {
244     DateMatch d;
245     EXPECT_FALSE(d.IsValid()) << d.DebugString();
246   }
247 }
248 
DebugStrings(const std::vector<DateMatch> & instances)249 std::string DebugStrings(const std::vector<DateMatch>& instances) {
250   std::string res;
251   for (int i = 0; i < instances.size(); ++i) {
252     ::libtextclassifier3::strings::SStringAppendF(
253         &res, 0, "[%d] == %s\n", i, instances[i].DebugString().c_str());
254   }
255   return res;
256 }
257 
TEST_F(DateMatchTest,IsRefinement)258 TEST_F(DateMatchTest, IsRefinement) {
259   {
260     DateMatch a;
261     SetDate(&a, 2014, 2, X);
262     DateMatch b;
263     SetDate(&b, 2014, X, X);
264     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
265   }
266   {
267     DateMatch a;
268     SetDate(&a, 2014, 2, 24);
269     DateMatch b;
270     SetDate(&b, 2014, 2, X);
271     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
272   }
273   {
274     DateMatch a;
275     SetDate(&a, 2014, 2, 24);
276     DateMatch b;
277     SetDate(&b, X, 2, 24);
278     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
279   }
280   {
281     DateMatch a;
282     SetDate(&a, 2014, 2, 24);
283     SetTimeValue(&a, 9, X, X);
284     DateMatch b;
285     SetDate(&b, 2014, 2, 24);
286     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
287   }
288   {
289     DateMatch a;
290     SetDate(&a, 2014, 2, 24);
291     SetTimeValue(&a, 9, 0, X);
292     DateMatch b;
293     SetDate(&b, 2014, 2, 24);
294     SetTimeValue(&b, 9, X, X);
295     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
296   }
297   {
298     DateMatch a;
299     SetDate(&a, 2014, 2, 24);
300     SetTimeValue(&a, 9, 0, 0);
301     DateMatch b;
302     SetDate(&b, 2014, 2, 24);
303     SetTimeValue(&b, 9, 0, X);
304     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
305   }
306   {
307     DateMatch a;
308     SetDate(&a, 2014, 2, 24);
309     SetTimeValue(&a, 9, X, X);
310     SetTimeSpan(&a, TimespanCode_AM);
311     DateMatch b;
312     SetDate(&b, 2014, 2, 24);
313     SetTimeValue(&b, 9, X, X);
314     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
315   }
316   {
317     DateMatch a;
318     SetDate(&a, 2014, 2, 24);
319     SetTimeValue(&a, 9, X, X);
320     SetTimeZone(&a, TimezoneCode_PST8PDT);
321     DateMatch b;
322     SetDate(&b, 2014, 2, 24);
323     SetTimeValue(&b, 9, X, X);
324     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
325   }
326   {
327     DateMatch a;
328     SetDate(&a, 2014, 2, 24);
329     SetTimeValue(&a, 9, X, X);
330     a.priority += 10;
331     DateMatch b;
332     SetDate(&b, 2014, 2, 24);
333     SetTimeValue(&b, 9, X, X);
334     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
335   }
336   {
337     DateMatch a;
338     SetDate(&a, 2014, 2, 24);
339     SetTimeValue(&a, 9, X, X);
340     DateMatch b;
341     SetDate(&b, 2014, 2, 24);
342     SetTimeValue(&b, 9, X, X);
343     EXPECT_TRUE(IsRefinement(a, b)) << DebugStrings({a, b});
344   }
345   {
346     DateMatch a;
347     SetDate(&a, 2014, 2, 24);
348     SetTimeValue(&a, 9, X, X);
349     DateMatch b;
350     SetDate(&b, X, 2, 24);
351     SetTimeValue(&b, 9, 0, X);
352     EXPECT_FALSE(IsRefinement(a, b)) << DebugStrings({a, b});
353   }
354   {
355     DateMatch a;
356     SetDate(&a, X, 2, 24);
357     SetTimeValue(&a, 9, X, X);
358     DateMatch b;
359     SetDate(&b, 2014, 2, 24);
360     EXPECT_FALSE(IsRefinement(a, b)) << DebugStrings({a, b});
361   }
362   {
363     DateMatch a;
364     SetTimeValue(&a, 9, 0, 0);
365     DateMatch b;
366     SetTimeValue(&b, 9, X, X);
367     SetTimeSpan(&b, TimespanCode_AM);
368     EXPECT_FALSE(IsRefinement(a, b)) << DebugStrings({a, b});
369   }
370 }
371 
TEST_F(DateMatchTest,FillDateInstance_AnnotatorPriorityScore)372 TEST_F(DateMatchTest, FillDateInstance_AnnotatorPriorityScore) {
373   DateMatch date_match;
374   SetDate(&date_match, 2014, 2, X);
375   date_match.annotator_priority_score = 0.5;
376   DatetimeParseResultSpan datetime_parse_result_span;
377   FillDateInstance(date_match, &datetime_parse_result_span);
378   EXPECT_FLOAT_EQ(datetime_parse_result_span.priority_score, 0.5)
379       << DebugStrings({date_match});
380 }
381 
TEST_F(DateMatchTest,MergeDateMatch_AnnotatorPriorityScore)382 TEST_F(DateMatchTest, MergeDateMatch_AnnotatorPriorityScore) {
383   DateMatch a;
384   SetDate(&a, 2014, 2, 4);
385   a.annotator_priority_score = 0.5;
386 
387   DateMatch b;
388   SetTimeValue(&b, 10, 45, 23);
389   b.annotator_priority_score = 1.0;
390 
391   MergeDateMatch(b, &a, false);
392   EXPECT_FLOAT_EQ(a.annotator_priority_score, 1.0);
393 }
394 
395 }  // namespace
396 }  // namespace dates
397 }  // namespace libtextclassifier3
398