diff --git a/source/common/formatter/BUILD b/source/common/formatter/BUILD index 6f908bcdbdde9..dbe960c1ca024 100644 --- a/source/common/formatter/BUILD +++ b/source/common/formatter/BUILD @@ -109,7 +109,9 @@ envoy_cc_library( hdrs = ["stream_info_formatter.h"], rbe_pool = "6gig", deps = [ + ":substitution_format_utility_lib", "//envoy/api:api_interface", + "//envoy/common:exception_lib", "//envoy/formatter:substitution_formatter_interface", "//envoy/runtime:runtime_interface", "//envoy/stream_info:stream_info_interface", @@ -117,13 +119,13 @@ envoy_cc_library( "//source/common/common:assert_lib", "//source/common/common:random_generator_lib", "//source/common/common:utility_lib", - "//source/common/formatter:substitution_format_utility_lib", "//source/common/grpc:common_lib", "//source/common/http:utility_lib", "//source/common/json:json_loader_lib", "//source/common/json:json_utility_lib", "//source/common/protobuf:message_validator_lib", "//source/common/stream_info:utility_lib", + "@abseil-cpp//absl/status", "@abseil-cpp//absl/status:statusor", ], alwayslink = 1, # has factory registration diff --git a/source/common/formatter/stream_info_formatter.cc b/source/common/formatter/stream_info_formatter.cc index f2488a8e5c6b7..909850fe3cbe0 100644 --- a/source/common/formatter/stream_info_formatter.cc +++ b/source/common/formatter/stream_info_formatter.cc @@ -9,6 +9,7 @@ #include "source/common/runtime/runtime_features.h" #include "source/common/stream_info/utility.h" +#include "absl/status/statusor.h" #include "absl/strings/str_format.h" #include "absl/strings/str_replace.h" #include "re2/re2.h" @@ -601,15 +602,22 @@ UpstreamPeerCertVEndFormatter::UpstreamPeerCertVEndFormatter(absl::string_view f : absl::optional(); })) {} +absl::Status SystemTimeFormatter::checkConstructPreconditions(absl::string_view format) { + // Validate the input specifier here. The formatted string may be destined for a header, and + // should not contain invalid characters {NUL, LR, CF}. + if (RE2::PartialMatch(format, getSystemTimeFormatNewlinePattern())) { + return absl::InvalidArgumentError( + "Invalid header configuration. Format string contains newline."); + } + return absl::OkStatus(); +} + SystemTimeFormatter::SystemTimeFormatter(absl::string_view format, TimeFieldExtractorPtr f, bool local_time) : date_formatter_(format, local_time), time_field_extractor_(std::move(f)), local_time_(local_time) { - // Validate the input specifier here. The formatted string may be destined for a header, and - // should not contain invalid characters {NUL, LR, CF}. - if (re2::RE2::PartialMatch(format, getSystemTimeFormatNewlinePattern())) { - throw EnvoyException("Invalid header configuration. Format string contains newline."); - } + // Sanity checking that pre-constructor validation was not skipped. + ASSERT(checkConstructPreconditions(format).ok()); } absl::optional @@ -2414,7 +2422,7 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide {"START_TIME", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique( + return SystemTimeFormatter::make( format, std::make_unique( [](const StreamInfo::StreamInfo& stream_info) @@ -2425,7 +2433,7 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide {"START_TIME_LOCAL", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique( + return SystemTimeFormatter::make( format, std::make_unique( [](const StreamInfo::StreamInfo& stream_info) @@ -2437,7 +2445,7 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide {"EMIT_TIME", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique( + return SystemTimeFormatter::make( format, std::make_unique( [](const StreamInfo::StreamInfo& stream_info) @@ -2448,7 +2456,7 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide {"EMIT_TIME_LOCAL", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique( + return SystemTimeFormatter::make( format, std::make_unique( [](const StreamInfo::StreamInfo& stream_info) @@ -2507,22 +2515,23 @@ const StreamInfoFormatterProviderLookupTable& getKnownStreamInfoFormatterProvide {"DOWNSTREAM_PEER_CERT_V_START", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique(format); + return makeTimeFormatter( + format); }}}, {"DOWNSTREAM_PEER_CERT_V_END", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique(format); + return makeTimeFormatter(format); }}}, {"UPSTREAM_PEER_CERT_V_START", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique(format); + return makeTimeFormatter(format); }}}, {"UPSTREAM_PEER_CERT_V_END", {CommandSyntaxChecker::PARAMS_OPTIONAL, [](absl::string_view format, absl::optional) { - return std::make_unique(format); + return makeTimeFormatter(format); }}}, {"ENVIRONMENT", {CommandSyntaxChecker::PARAMS_REQUIRED | diff --git a/source/common/formatter/stream_info_formatter.h b/source/common/formatter/stream_info_formatter.h index 4b4d3f4a97495..0f0c37fd32544 100644 --- a/source/common/formatter/stream_info_formatter.h +++ b/source/common/formatter/stream_info_formatter.h @@ -6,8 +6,10 @@ #include #include #include +#include #include +#include "envoy/common/exception.h" #include "envoy/formatter/substitution_formatter.h" #include "envoy/stream_info/stream_info.h" @@ -15,6 +17,7 @@ #include "source/common/formatter/substitution_format_utility.h" #include "absl/container/flat_hash_map.h" +#include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/types/optional.h" @@ -220,7 +223,12 @@ class SystemTimeFormatter : public StreamInfoFormatterProvider { std::function(const StreamInfo::StreamInfo& stream_info)>; using TimeFieldExtractorPtr = std::unique_ptr; - SystemTimeFormatter(absl::string_view format, TimeFieldExtractorPtr f, bool local_time = false); + static absl::StatusOr> + make(absl::string_view format, TimeFieldExtractorPtr&& f, bool local_time = false) { + RETURN_IF_NOT_OK(checkConstructPreconditions(format)); + return std::unique_ptr( + new SystemTimeFormatter(format, std::move(f), local_time)); + } // StreamInfoFormatterProvider // Don't hide the other structure of format and formatValue. @@ -229,6 +237,10 @@ class SystemTimeFormatter : public StreamInfoFormatterProvider { absl::optional format(const StreamInfo::StreamInfo&) const override; Protobuf::Value formatValue(const StreamInfo::StreamInfo&) const override; +protected: + SystemTimeFormatter(absl::string_view format, TimeFieldExtractorPtr f, bool local_time = false); + static absl::Status checkConstructPreconditions(absl::string_view format); + private: const Envoy::DateFormatter date_formatter_; const TimeFieldExtractorPtr time_field_extractor_; @@ -240,8 +252,11 @@ class SystemTimeFormatter : public StreamInfoFormatterProvider { * SystemTimeFormatter (FormatterProvider) for request start time from StreamInfo. */ class StartTimeFormatter : public SystemTimeFormatter { -public: +protected: StartTimeFormatter(absl::string_view format); + + template + friend absl::StatusOr> makeTimeFormatter(absl::string_view format); }; /** @@ -249,8 +264,11 @@ class StartTimeFormatter : public SystemTimeFormatter { * ConnectionInfo. */ class DownstreamPeerCertVStartFormatter : public SystemTimeFormatter { -public: +protected: DownstreamPeerCertVStartFormatter(absl::string_view format); + + template + friend absl::StatusOr> makeTimeFormatter(absl::string_view format); }; /** @@ -258,8 +276,11 @@ class DownstreamPeerCertVStartFormatter : public SystemTimeFormatter { * ConnectionInfo. */ class DownstreamPeerCertVEndFormatter : public SystemTimeFormatter { -public: +protected: DownstreamPeerCertVEndFormatter(absl::string_view format); + + template + friend absl::StatusOr> makeTimeFormatter(absl::string_view format); }; /** @@ -267,8 +288,11 @@ class DownstreamPeerCertVEndFormatter : public SystemTimeFormatter { * upstreamInfo. */ class UpstreamPeerCertVStartFormatter : public SystemTimeFormatter { -public: +protected: UpstreamPeerCertVStartFormatter(absl::string_view format); + + template + friend absl::StatusOr> makeTimeFormatter(absl::string_view format); }; /** @@ -276,10 +300,27 @@ class UpstreamPeerCertVStartFormatter : public SystemTimeFormatter { * upstreamInfo. */ class UpstreamPeerCertVEndFormatter : public SystemTimeFormatter { -public: +protected: UpstreamPeerCertVEndFormatter(absl::string_view format); + + template + friend absl::StatusOr> makeTimeFormatter(absl::string_view format); }; +/** + * Factory method for creating an object of type derived from SystemTimeFormatter + * The method first checks constructor preconditions are satisfied. If not the method + * return an error. + * Otherwise it returns unique_ptr with an object. + */ +template +absl::StatusOr> makeTimeFormatter(absl::string_view format) { + static_assert(std::is_base_of::value, + "T must be derived from SystemTimeFormatter"); + RETURN_IF_NOT_OK(T::checkConstructPreconditions(format)); + return std::unique_ptr(new T(format)); +} + /** * FormatterProvider for environment. If no valid environment value then */ diff --git a/test/common/formatter/substitution_formatter_test.cc b/test/common/formatter/substitution_formatter_test.cc index be0aa78d13ecd..c64730147ea89 100644 --- a/test/common/formatter/substitution_formatter_test.cc +++ b/test/common/formatter/substitution_formatter_test.cc @@ -3897,41 +3897,46 @@ TEST(SubstitutionFormatterTest, DownstreamPeerCertVStartFormatter) { { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); - DownstreamPeerCertVStartFormatter cert_start_formart("DOWNSTREAM_PEER_CERT_V_START(%Y/%m/%d)"); - EXPECT_EQ(absl::nullopt, cert_start_formart.format(stream_info)); - EXPECT_THAT(cert_start_formart.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_start_formart = makeTimeFormatter( + "DOWNSTREAM_PEER_CERT_V_START(%Y/%m/%d)") + .value(); + EXPECT_EQ(absl::nullopt, cert_start_formart->format(stream_info)); + EXPECT_THAT(cert_start_formart->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No validFromPeerCertificate { NiceMock stream_info; - DownstreamPeerCertVStartFormatter cert_start_formart("DOWNSTREAM_PEER_CERT_V_START(%Y/%m/%d)"); + auto cert_start_formart = makeTimeFormatter( + "DOWNSTREAM_PEER_CERT_V_START(%Y/%m/%d)") + .value(); auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(absl::nullopt)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ(absl::nullopt, cert_start_formart.format(stream_info)); - EXPECT_THAT(cert_start_formart.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + EXPECT_EQ(absl::nullopt, cert_start_formart->format(stream_info)); + EXPECT_THAT(cert_start_formart->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // Default format string { NiceMock stream_info; - DownstreamPeerCertVStartFormatter cert_start_format(""); + auto cert_start_format = makeTimeFormatter("").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(time)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_start_format.format(stream_info)); + EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_start_format->format(stream_info)); } // Custom format string { NiceMock stream_info; - DownstreamPeerCertVStartFormatter cert_start_format("%b %e %H:%M:%S %Y %Z"); + auto cert_start_format = + makeTimeFormatter("%b %e %H:%M:%S %Y %Z").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(time)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_start_format.format(stream_info)); + EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_start_format->format(stream_info)); } } @@ -3940,42 +3945,43 @@ TEST(SubstitutionFormatterTest, DownstreamPeerCertVEndFormatter) { { NiceMock stream_info; stream_info.downstream_connection_info_provider_->setSslConnection(nullptr); - DownstreamPeerCertVEndFormatter cert_end_format("%Y/%m/%d"); - EXPECT_EQ(absl::nullopt, cert_end_format.format(stream_info)); - EXPECT_THAT(cert_end_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_end_format = makeTimeFormatter("%Y/%m/%d").value(); + EXPECT_EQ(absl::nullopt, cert_end_format->format(stream_info)); + EXPECT_THAT(cert_end_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No expirationPeerCertificate { NiceMock stream_info; - DownstreamPeerCertVEndFormatter cert_end_format("%Y/%m/%d"); + auto cert_end_format = makeTimeFormatter("%Y/%m/%d").value(); auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, expirationPeerCertificate()) .WillRepeatedly(Return(absl::nullopt)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ(absl::nullopt, cert_end_format.format(stream_info)); - EXPECT_THAT(cert_end_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + EXPECT_EQ(absl::nullopt, cert_end_format->format(stream_info)); + EXPECT_THAT(cert_end_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // Default format string { NiceMock stream_info; - DownstreamPeerCertVEndFormatter cert_end_format(""); + auto cert_end_format = makeTimeFormatter("").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, expirationPeerCertificate()).WillRepeatedly(Return(time)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_end_format.format(stream_info)); + EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_end_format->format(stream_info)); } // Custom format string { NiceMock stream_info; - DownstreamPeerCertVEndFormatter cert_end_format("%b %e %H:%M:%S %Y %Z"); + auto cert_end_format = + makeTimeFormatter("%b %e %H:%M:%S %Y %Z").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, expirationPeerCertificate()).WillRepeatedly(Return(time)); stream_info.downstream_connection_info_provider_->setSslConnection(connection_info); - EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_end_format.format(stream_info)); + EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_end_format->format(stream_info)); } } @@ -3984,49 +3990,54 @@ TEST(SubstitutionFormatterTest, UpstreamPeerCertVStartFormatter) { { NiceMock stream_info; EXPECT_CALL(stream_info, upstreamInfo()).WillRepeatedly(Return(nullptr)); - UpstreamPeerCertVStartFormatter cert_start_format("%Y/%m/%d"); - EXPECT_EQ(absl::nullopt, cert_start_format.format(stream_info)); - EXPECT_THAT(cert_start_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_start_format = makeTimeFormatter("%Y/%m/%d").value(); + EXPECT_EQ(absl::nullopt, cert_start_format->format(stream_info)); + EXPECT_THAT(cert_start_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No upstreamSslConnection { NiceMock stream_info; stream_info.upstreamInfo()->setUpstreamSslConnection(nullptr); - DownstreamPeerCertVStartFormatter cert_start_format("UPSTREAM_PEER_CERT_V_START(%Y/%m/%d)"); - EXPECT_EQ(absl::nullopt, cert_start_format.format(stream_info)); - EXPECT_THAT(cert_start_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_start_format = + makeTimeFormatter("UPSTREAM_PEER_CERT_V_START(%Y/%m/%d)") + .value(); + EXPECT_EQ(absl::nullopt, cert_start_format->format(stream_info)); + EXPECT_THAT(cert_start_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No validFromPeerCertificate { NiceMock stream_info; - DownstreamPeerCertVStartFormatter cert_start_format("UPSTREAM_PEER_CERT_V_START(%Y/%m/%d)"); + auto cert_start_format = + makeTimeFormatter("UPSTREAM_PEER_CERT_V_START(%Y/%m/%d)") + .value(); auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(absl::nullopt)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ(absl::nullopt, cert_start_format.format(stream_info)); - EXPECT_THAT(cert_start_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + EXPECT_EQ(absl::nullopt, cert_start_format->format(stream_info)); + EXPECT_THAT(cert_start_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // Default format string { NiceMock stream_info; - UpstreamPeerCertVStartFormatter cert_start_format(""); + auto cert_start_format = makeTimeFormatter("").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(time)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_start_format.format(stream_info)); + EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_start_format->format(stream_info)); } // Custom format string { NiceMock stream_info; - UpstreamPeerCertVStartFormatter cert_start_format("%b %e %H:%M:%S %Y %Z"); + auto cert_start_format = + makeTimeFormatter("%b %e %H:%M:%S %Y %Z").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, validFromPeerCertificate()).WillRepeatedly(Return(time)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_start_format.format(stream_info)); + EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_start_format->format(stream_info)); } } @@ -4035,50 +4046,51 @@ TEST(SubstitutionFormatterTest, UpstreamPeerCertVEndFormatter) { { NiceMock stream_info; EXPECT_CALL(stream_info, upstreamInfo()).WillRepeatedly(Return(nullptr)); - UpstreamPeerCertVEndFormatter cert_end_format("%Y/%m/%d"); - EXPECT_EQ(absl::nullopt, cert_end_format.format(stream_info)); - EXPECT_THAT(cert_end_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_end_format = makeTimeFormatter("%Y/%m/%d").value(); + EXPECT_EQ(absl::nullopt, cert_end_format->format(stream_info)); + EXPECT_THAT(cert_end_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No upstreamSslConnection { NiceMock stream_info; stream_info.upstreamInfo()->setUpstreamSslConnection(nullptr); - UpstreamPeerCertVEndFormatter cert_end_format("%Y/%m/%d"); - EXPECT_EQ(absl::nullopt, cert_end_format.format(stream_info)); - EXPECT_THAT(cert_end_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + auto cert_end_format = makeTimeFormatter("%Y/%m/%d").value(); + EXPECT_EQ(absl::nullopt, cert_end_format->format(stream_info)); + EXPECT_THAT(cert_end_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // No expirationPeerCertificate { NiceMock stream_info; - UpstreamPeerCertVEndFormatter cert_end_format("%Y/%m/%d"); + auto cert_end_format = makeTimeFormatter("%Y/%m/%d").value(); auto connection_info = std::make_shared(); EXPECT_CALL(*connection_info, expirationPeerCertificate()) .WillRepeatedly(Return(absl::nullopt)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ(absl::nullopt, cert_end_format.format(stream_info)); - EXPECT_THAT(cert_end_format.formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); + EXPECT_EQ(absl::nullopt, cert_end_format->format(stream_info)); + EXPECT_THAT(cert_end_format->formatValue(stream_info), ProtoEq(ValueUtil::nullValue())); } // Default format string { NiceMock stream_info; - UpstreamPeerCertVEndFormatter cert_end_format(""); + auto cert_end_format = makeTimeFormatter("").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, expirationPeerCertificate()).WillRepeatedly(Return(time)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_end_format.format(stream_info)); + EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), cert_end_format->format(stream_info)); } // Custom format string { NiceMock stream_info; - UpstreamPeerCertVEndFormatter cert_end_format("%b %e %H:%M:%S %Y %Z"); + auto cert_end_format = + makeTimeFormatter("%b %e %H:%M:%S %Y %Z").value(); auto connection_info = std::make_shared(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(*connection_info, expirationPeerCertificate()).WillRepeatedly(Return(time)); stream_info.upstreamInfo()->setUpstreamSslConnection(connection_info); - EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_end_format.format(stream_info)); + EXPECT_EQ("Mar 28 23:35:58 2018 UTC", cert_end_format->format(stream_info)); } } @@ -4090,21 +4102,21 @@ TEST(SubstitutionFormatterTest, StartTimeFormatter) { std::string body; { - StartTimeFormatter start_time_format("%Y/%m/%d"); + auto start_time_format = makeTimeFormatter("%Y/%m/%d").value(); time_t test_epoch = 1522280158; SystemTime time = std::chrono::system_clock::from_time_t(test_epoch); EXPECT_CALL(stream_info, startTime()).WillRepeatedly(Return(time)); - EXPECT_EQ("2018/03/28", start_time_format.format(stream_info)); - EXPECT_THAT(start_time_format.formatValue(stream_info), + EXPECT_EQ("2018/03/28", start_time_format->format(stream_info)); + EXPECT_THAT(start_time_format->formatValue(stream_info), ProtoEq(ValueUtil::stringValue("2018/03/28"))); } { - StartTimeFormatter start_time_format(""); + auto start_time_format = makeTimeFormatter("").value(); SystemTime time; EXPECT_CALL(stream_info, startTime()).WillRepeatedly(Return(time)); - EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), start_time_format.format(stream_info)); - EXPECT_THAT(start_time_format.formatValue(stream_info), + EXPECT_EQ(AccessLogDateTimeFormatter::fromTime(time), start_time_format->format(stream_info)); + EXPECT_THAT(start_time_format->formatValue(stream_info), ProtoEq(ValueUtil::stringValue(AccessLogDateTimeFormatter::fromTime(time)))); } }