diff options
Diffstat (limited to 'src/mongo/db/timeseries/timeseries_options_test.cpp')
| -rw-r--r-- | src/mongo/db/timeseries/timeseries_options_test.cpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/mongo/db/timeseries/timeseries_options_test.cpp b/src/mongo/db/timeseries/timeseries_options_test.cpp index e3106407cea..db3d8e4a46b 100644 --- a/src/mongo/db/timeseries/timeseries_options_test.cpp +++ b/src/mongo/db/timeseries/timeseries_options_test.cpp @@ -29,6 +29,11 @@ #include "mongo/platform/basic.h" +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/date_time/posix_time/time_parsers.hpp> +#include <boost/move/utility_core.hpp> + +#include "mongo/base/string_data.h" #include "mongo/db/timeseries/timeseries_options.h" #include "mongo/unittest/unittest.h" #include "mongo/util/time_support.h" @@ -36,6 +41,21 @@ namespace mongo { +int roundingSecondsFromGranularity(BucketGranularityEnum granularity) { + switch (granularity) { + case BucketGranularityEnum::Seconds: + // Round down to nearest minute. + return 60; + case BucketGranularityEnum::Minutes: + // Round down to nearest hour. + return 60 * 60; + case BucketGranularityEnum::Hours: + // Round down to nearest day. + return 60 * 60 * 24; + } + MONGO_UNREACHABLE; +} + TEST(TimeseriesOptionsTest, RoundTimestampToGranularity) { std::vector<std::tuple<BucketGranularityEnum, std::string, std::string>> testCases{ {BucketGranularityEnum::Seconds, "2021-01-01T00:00:15.555Z", "2021-01-01T00:00:00.000Z"}, @@ -60,4 +80,123 @@ TEST(TimeseriesOptionsTest, RoundTimestampToGranularity) { } } +TEST(TimeseriesOptionsTest, RoundTimestampBySeconds) { + std::vector<std::tuple<BucketGranularityEnum, std::string, std::string>> testCases{ + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:00.001Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:15.555Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:30.555Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:45.555Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T00:00:59.999Z", "2024-08-08T00:00:00.000Z"}, + + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:00.000Z", "2024-08-08T05:04:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:00.001Z", "2024-08-08T05:04:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:15.555Z", "2024-08-08T05:04:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:30.555Z", "2024-08-08T05:04:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:45.555Z", "2024-08-08T05:04:00.000Z"}, + {BucketGranularityEnum::Seconds, "2024-08-08T05:04:59.999Z", "2024-08-08T05:04:00.000Z"}, + + {BucketGranularityEnum::Minutes, "2024-08-08T00:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Minutes, "2024-08-08T00:00:00.001Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Minutes, "2024-08-08T00:15:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Minutes, "2024-08-08T00:30:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Minutes, "2024-08-08T00:45:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Minutes, "2024-08-08T00:59:59.999Z", "2024-08-08T00:00:00.000Z"}, + + {BucketGranularityEnum::Hours, "2024-08-08T00:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Hours, "2024-08-08T00:00:00.001Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Hours, "2024-08-08T06:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Hours, "2024-08-08T12:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Hours, "2024-08-08T18:00:00.000Z", "2024-08-08T00:00:00.000Z"}, + {BucketGranularityEnum::Hours, "2024-08-08T23:59:59.999Z", "2024-08-08T00:00:00.000Z"}, + }; + + for (const auto& [roundingGranularity, input, expectedOutput] : testCases) { + auto inputDate = dateFromISOString(input); + ASSERT_OK(inputDate); + auto roundedDate = + timeseries::roundTimestampToGranularity(inputDate.getValue(), roundingGranularity); + ASSERT_EQ(dateToISOStringUTC(roundedDate), expectedOutput); + } +} + +TEST(TimeseriesOptionsTest, ExtendedRangeRoundTimestamp) { + std::vector<std::tuple<BucketGranularityEnum, std::string, std::string>> testCases{ + {BucketGranularityEnum::Seconds, "1901-01-01T00:00:12.345", "1901-01-01T00:00:00"}, + {BucketGranularityEnum::Seconds, "1901-01-01T00:04:12.345", "1901-01-01T00:04:00"}, + {BucketGranularityEnum::Seconds, "1901-01-01T02:04:12.345", "1901-01-01T02:04:00"}, + + {BucketGranularityEnum::Seconds, "1969-01-01T00:00:12.345", "1969-01-01T00:00:00"}, + {BucketGranularityEnum::Seconds, "1969-01-01T00:04:12.345", "1969-01-01T00:04:00"}, + {BucketGranularityEnum::Seconds, "1969-01-01T02:04:12.345", "1969-01-01T02:04:00"}, + + {BucketGranularityEnum::Seconds, "2040-01-01T00:00:12.345", "2040-01-01T00:00:00"}, + {BucketGranularityEnum::Seconds, "2040-01-01T00:04:12.345", "2040-01-01T00:04:00"}, + {BucketGranularityEnum::Seconds, "2040-01-01T02:04:12.345", "2040-01-01T02:04:00"}, + + {BucketGranularityEnum::Seconds, "2108-01-01T00:00:12.345", "2108-01-01T00:00:00"}, + {BucketGranularityEnum::Seconds, "2108-01-01T00:04:12.345", "2108-01-01T00:04:00"}, + {BucketGranularityEnum::Seconds, "2108-01-01T02:04:12.345", "2108-01-01T02:04:00"}, + + {BucketGranularityEnum::Minutes, "1901-01-01T00:00:12.345", "1901-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "1901-01-01T00:04:12.345", "1901-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "1901-01-01T02:04:12.345", "1901-01-01T02:00:00"}, + + {BucketGranularityEnum::Minutes, "1969-01-01T00:00:12.345", "1969-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "1969-01-01T00:04:12.345", "1969-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "1969-01-01T02:04:12.345", "1969-01-01T02:00:00"}, + + {BucketGranularityEnum::Minutes, "2040-01-01T00:00:12.345", "2040-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "2040-01-01T00:04:12.345", "2040-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "2040-01-01T02:04:12.345", "2040-01-01T02:00:00"}, + + {BucketGranularityEnum::Minutes, "2108-01-01T00:00:12.345", "2108-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "2108-01-01T00:04:12.345", "2108-01-01T00:00:00"}, + {BucketGranularityEnum::Minutes, "2108-01-01T02:04:12.345", "2108-01-01T02:00:00"}, + + {BucketGranularityEnum::Hours, "1901-01-01T00:00:12.345", "1901-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "1901-01-01T00:04:12.345", "1901-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "1901-01-01T02:04:12.345", "1901-01-01T00:00:00"}, + + {BucketGranularityEnum::Hours, "1969-01-01T00:00:12.345", "1969-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "1969-01-01T00:04:12.345", "1969-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "1969-01-01T02:04:12.345", "1969-01-01T00:00:00"}, + + {BucketGranularityEnum::Hours, "2040-01-01T00:00:12.345", "2040-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "2040-01-01T00:04:12.345", "2040-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "2040-01-01T02:04:12.345", "2040-01-01T00:00:00"}, + + {BucketGranularityEnum::Hours, "2108-01-01T00:00:12.345", "2108-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "2108-01-01T00:04:12.345", "2108-01-01T00:00:00"}, + {BucketGranularityEnum::Hours, "2108-01-01T02:04:12.345", "2108-01-01T00:00:00"}, + }; + + // TODO SERVER-94228: Support ISO 8601 date parsing and formatting of dates prior to 1970. + static constexpr auto epoch = boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); + auto parse = [](const std::string& input) { + auto ptime = boost::posix_time::from_iso_extended_string(input); + return Date_t::fromMillisSinceEpoch((ptime - epoch).total_milliseconds()); + }; + auto format = [](Date_t date) { + boost::posix_time::milliseconds ms(date.toMillisSinceEpoch()); + return boost::posix_time::to_iso_extended_string(epoch + ms); + }; + + for (const auto& [roundingGranularity, input, expectedOutput] : testCases) { + Date_t inputDate = parse(input); + auto roundedDate = timeseries::roundTimestampToGranularity(inputDate, roundingGranularity); + // We should always round down + ASSERT_LTE(roundedDate, inputDate); + // The rounding amount should be less than the rounding seconds + ASSERT_LT((inputDate - roundedDate).count(), + roundingSecondsFromGranularity(roundingGranularity) * 1000); + // Ensure that we've rounded to an even number according to our rounding seconds + ASSERT_EQ(durationCount<Seconds>(roundedDate.toDurationSinceEpoch()) % + roundingSecondsFromGranularity(roundingGranularity), + 0); + // Validate the expected output + ASSERT_EQ(format(roundedDate), expectedOutput); + } +} + } // namespace mongo |
