You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
12 KiB
293 lines
12 KiB
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "annotator/datetime/datetime-grounder.h"
|
|
|
|
#include "annotator/datetime/datetime_generated.h"
|
|
#include "utils/flatbuffers/flatbuffers.h"
|
|
#include "utils/jvm-test-utils.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using ::libtextclassifier3::grammar::datetime::AbsoluteDateTimeT;
|
|
using ::libtextclassifier3::grammar::datetime::ComponentType;
|
|
using ::libtextclassifier3::grammar::datetime::Meridiem;
|
|
using ::libtextclassifier3::grammar::datetime::RelativeDatetimeComponentT;
|
|
using ::libtextclassifier3::grammar::datetime::RelativeDateTimeT;
|
|
using ::libtextclassifier3::grammar::datetime::TimeZoneT;
|
|
using ::libtextclassifier3::grammar::datetime::UngroundedDatetime;
|
|
using ::libtextclassifier3::grammar::datetime::UngroundedDatetimeT;
|
|
using ::libtextclassifier3::grammar::datetime::RelativeDatetimeComponent_::
|
|
Modifier;
|
|
using ::testing::SizeIs;
|
|
|
|
namespace libtextclassifier3 {
|
|
|
|
class DatetimeGrounderTest : public testing::Test {
|
|
public:
|
|
void SetUp() override {
|
|
calendarlib_ = CreateCalendarLibForTesting();
|
|
datetime_grounder_.reset(new DatetimeGrounder(calendarlib_.get()));
|
|
}
|
|
|
|
protected:
|
|
OwnedFlatbuffer<UngroundedDatetime, std::string> BuildAbsoluteDatetime(
|
|
const int year, const int month, const int day, const int hour,
|
|
const int minute, const int second, const Meridiem meridiem) {
|
|
grammar::datetime::UngroundedDatetimeT ungrounded_datetime;
|
|
ungrounded_datetime.absolute_datetime.reset(new AbsoluteDateTimeT);
|
|
|
|
// Set absolute datetime value.
|
|
ungrounded_datetime.absolute_datetime->year = year;
|
|
ungrounded_datetime.absolute_datetime->month = month;
|
|
ungrounded_datetime.absolute_datetime->day = day;
|
|
ungrounded_datetime.absolute_datetime->hour = hour;
|
|
ungrounded_datetime.absolute_datetime->minute = minute;
|
|
ungrounded_datetime.absolute_datetime->second = second;
|
|
ungrounded_datetime.absolute_datetime->meridiem = meridiem;
|
|
|
|
return OwnedFlatbuffer<UngroundedDatetime, std::string>(
|
|
PackFlatbuffer<UngroundedDatetime>(&ungrounded_datetime));
|
|
}
|
|
|
|
OwnedFlatbuffer<UngroundedDatetime, std::string> BuildRelativeDatetime(
|
|
const ComponentType component_type, const Modifier modifier,
|
|
const int relative_count) {
|
|
UngroundedDatetimeT ungrounded_datetime;
|
|
ungrounded_datetime.relative_datetime.reset(new RelativeDateTimeT);
|
|
ungrounded_datetime.relative_datetime->relative_datetime_component
|
|
.emplace_back(new RelativeDatetimeComponentT);
|
|
ungrounded_datetime.relative_datetime->relative_datetime_component.back()
|
|
->modifier = modifier;
|
|
ungrounded_datetime.relative_datetime->relative_datetime_component.back()
|
|
->component_type = component_type;
|
|
ungrounded_datetime.relative_datetime->relative_datetime_component.back()
|
|
->value = relative_count;
|
|
ungrounded_datetime.relative_datetime->base.reset(new AbsoluteDateTimeT);
|
|
ungrounded_datetime.relative_datetime->base->year = 2020;
|
|
ungrounded_datetime.relative_datetime->base->month = 6;
|
|
ungrounded_datetime.relative_datetime->base->day = 30;
|
|
|
|
return OwnedFlatbuffer<UngroundedDatetime, std::string>(
|
|
PackFlatbuffer<UngroundedDatetime>(&ungrounded_datetime));
|
|
}
|
|
|
|
void VerifyValidUngroundedDatetime(
|
|
const UngroundedDatetime* ungrounded_datetime) {
|
|
EXPECT_TRUE(
|
|
datetime_grounder_->IsValidUngroundedDatetime(ungrounded_datetime));
|
|
}
|
|
|
|
void VerifyInValidUngroundedDatetime(
|
|
const UngroundedDatetime* ungrounded_datetime) {
|
|
EXPECT_FALSE(
|
|
datetime_grounder_->IsValidUngroundedDatetime(ungrounded_datetime));
|
|
}
|
|
|
|
std::unique_ptr<DatetimeGrounder> datetime_grounder_;
|
|
std::unique_ptr<CalendarLib> calendarlib_;
|
|
};
|
|
|
|
TEST_F(DatetimeGrounderTest, AbsoluteDatetimeTest) {
|
|
const OwnedFlatbuffer<UngroundedDatetime, std::string> datetime =
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/03, /*day=*/30,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM);
|
|
const std::vector<DatetimeParseResult> data =
|
|
datetime_grounder_
|
|
->Ground(
|
|
/*reference_time_ms_utc=*/0, "Europe/Zurich", "en-US",
|
|
datetime.get())
|
|
.ValueOrDie();
|
|
|
|
EXPECT_THAT(data, SizeIs(1));
|
|
EXPECT_EQ(data[0].granularity, DatetimeGranularity::GRANULARITY_SECOND);
|
|
|
|
// Meridiem
|
|
EXPECT_EQ(data[0].datetime_components[0].component_type,
|
|
DatetimeComponent::ComponentType::MERIDIEM);
|
|
EXPECT_EQ(data[0].datetime_components[0].value, 0);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[1].component_type,
|
|
DatetimeComponent::ComponentType::SECOND);
|
|
EXPECT_EQ(data[0].datetime_components[1].component_type,
|
|
DatetimeComponent::ComponentType::SECOND);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[2].component_type,
|
|
DatetimeComponent::ComponentType::MINUTE);
|
|
EXPECT_EQ(data[0].datetime_components[2].value, 59);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[3].component_type,
|
|
DatetimeComponent::ComponentType::HOUR);
|
|
EXPECT_EQ(data[0].datetime_components[3].value, 11);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[4].component_type,
|
|
DatetimeComponent::ComponentType::DAY_OF_MONTH);
|
|
EXPECT_EQ(data[0].datetime_components[4].value, 30);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[5].component_type,
|
|
DatetimeComponent::ComponentType::MONTH);
|
|
EXPECT_EQ(data[0].datetime_components[5].value, 3);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[6].component_type,
|
|
DatetimeComponent::ComponentType::YEAR);
|
|
EXPECT_EQ(data[0].datetime_components[6].value, 2000);
|
|
}
|
|
|
|
TEST_F(DatetimeGrounderTest, InterpretDatetimeTest) {
|
|
const OwnedFlatbuffer<UngroundedDatetime, std::string> datetime =
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/03, /*day=*/30,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_UNKNOWN);
|
|
const std::vector<DatetimeParseResult> data =
|
|
datetime_grounder_
|
|
->Ground(
|
|
/*reference_time_ms_utc=*/0, "Europe/Zurich", "en-US",
|
|
datetime.get())
|
|
.ValueOrDie();
|
|
|
|
EXPECT_THAT(data, SizeIs(2));
|
|
EXPECT_EQ(data[0].granularity, DatetimeGranularity::GRANULARITY_SECOND);
|
|
EXPECT_EQ(data[1].granularity, DatetimeGranularity::GRANULARITY_SECOND);
|
|
|
|
// Check Meridiem's values
|
|
EXPECT_EQ(data[0].datetime_components[0].component_type,
|
|
DatetimeComponent::ComponentType::MERIDIEM);
|
|
EXPECT_EQ(data[0].datetime_components[0].value, 0);
|
|
EXPECT_EQ(data[1].datetime_components[0].component_type,
|
|
DatetimeComponent::ComponentType::MERIDIEM);
|
|
EXPECT_EQ(data[1].datetime_components[0].value, 1);
|
|
}
|
|
|
|
TEST_F(DatetimeGrounderTest, RelativeDatetimeTest) {
|
|
const OwnedFlatbuffer<UngroundedDatetime, std::string> datetime =
|
|
BuildRelativeDatetime(ComponentType::ComponentType_DAY_OF_MONTH,
|
|
Modifier::Modifier_NEXT, 1);
|
|
const std::vector<DatetimeParseResult> data =
|
|
datetime_grounder_
|
|
->Ground(
|
|
/*reference_time_ms_utc=*/0, "Europe/Zurich", "en-US",
|
|
datetime.get())
|
|
.ValueOrDie();
|
|
|
|
EXPECT_THAT(data, SizeIs(1));
|
|
EXPECT_EQ(data[0].granularity, DatetimeGranularity::GRANULARITY_DAY);
|
|
|
|
EXPECT_EQ(data[0].datetime_components[0].component_type,
|
|
DatetimeComponent::ComponentType::DAY_OF_MONTH);
|
|
EXPECT_EQ(data[0].datetime_components[0].relative_qualifier,
|
|
DatetimeComponent::RelativeQualifier::NEXT);
|
|
EXPECT_EQ(data[0].datetime_components[0].relative_count, 1);
|
|
EXPECT_EQ(data[0].datetime_components[1].component_type,
|
|
DatetimeComponent::ComponentType::MONTH);
|
|
EXPECT_EQ(data[0].datetime_components[2].component_type,
|
|
DatetimeComponent::ComponentType::YEAR);
|
|
}
|
|
|
|
TEST_F(DatetimeGrounderTest, TimeZoneTest) {
|
|
grammar::datetime::UngroundedDatetimeT ungrounded_datetime;
|
|
ungrounded_datetime.absolute_datetime.reset(new AbsoluteDateTimeT);
|
|
ungrounded_datetime.absolute_datetime->time_zone.reset(new TimeZoneT);
|
|
ungrounded_datetime.absolute_datetime->time_zone->utc_offset_mins = 120;
|
|
const OwnedFlatbuffer<UngroundedDatetime, std::string> timezone(
|
|
PackFlatbuffer<UngroundedDatetime>(&ungrounded_datetime));
|
|
|
|
const std::vector<DatetimeParseResult> data =
|
|
datetime_grounder_
|
|
->Ground(
|
|
/*reference_time_ms_utc=*/0, "Europe/Zurich", "en-US",
|
|
timezone.get())
|
|
.ValueOrDie();
|
|
|
|
EXPECT_THAT(data, SizeIs(1));
|
|
EXPECT_EQ(data[0].granularity, DatetimeGranularity::GRANULARITY_UNKNOWN);
|
|
EXPECT_EQ(data[0].datetime_components[0].component_type,
|
|
DatetimeComponent::ComponentType::ZONE_OFFSET);
|
|
EXPECT_EQ(data[0].datetime_components[0].value, 120);
|
|
}
|
|
|
|
TEST_F(DatetimeGrounderTest, InValidUngroundedDatetime) {
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/23, /*day=*/30,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/03, /*day=*/33,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/02, /*day=*/30,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/07, /*day=*/31,
|
|
/*hour=*/24, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/02, /*day=*/28,
|
|
/*hour=*/24, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/02, /*day=*/28,
|
|
/*hour=*/11, /*minute=*/69, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/02, /*day=*/28,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/99,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyInValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/00, /*day=*/28,
|
|
/*hour=*/11, /*minute=*/59, /*second=*/99,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
}
|
|
|
|
TEST_F(DatetimeGrounderTest, ValidUngroundedDatetime) {
|
|
VerifyValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/2, /*day=*/29,
|
|
/*hour=*/23, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/7, /*day=*/31,
|
|
/*hour=*/23, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
|
|
VerifyValidUngroundedDatetime(
|
|
BuildAbsoluteDatetime(/*year=*/2000, /*month=*/10, /*day=*/31,
|
|
/*hour=*/23, /*minute=*/59, /*second=*/59,
|
|
grammar::datetime::Meridiem_AM)
|
|
.get());
|
|
}
|
|
|
|
} // namespace libtextclassifier3
|