summaryrefslogtreecommitdiff
path: root/src/mongo/db/timeseries/timeseries_options_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/timeseries/timeseries_options_test.cpp')
-rw-r--r--src/mongo/db/timeseries/timeseries_options_test.cpp139
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