log_entry_test.cc (22243B)
1 // 2 // Copyright 2022 The Abseil Authors. 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 // https://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 #include "absl/log/log_entry.h" 17 18 #include <stddef.h> 19 #include <stdint.h> 20 21 #include <cstring> 22 #include <limits> 23 #include <string> 24 #include <type_traits> 25 #include <utility> 26 #include <vector> 27 28 #include "gmock/gmock.h" 29 #include "gtest/gtest.h" 30 #include "absl/base/attributes.h" 31 #include "absl/base/config.h" 32 #include "absl/base/log_severity.h" 33 #include "absl/log/internal/append_truncated.h" 34 #include "absl/log/internal/log_format.h" 35 #include "absl/log/internal/test_helpers.h" 36 #include "absl/strings/numbers.h" 37 #include "absl/strings/str_split.h" 38 #include "absl/strings/string_view.h" 39 #include "absl/time/civil_time.h" 40 #include "absl/time/time.h" 41 #include "absl/types/span.h" 42 43 namespace { 44 using ::absl::log_internal::LogEntryTestPeer; 45 using ::testing::Eq; 46 using ::testing::IsTrue; 47 using ::testing::StartsWith; 48 using ::testing::StrEq; 49 50 auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment( 51 new absl::log_internal::LogTestEnvironment); 52 } // namespace 53 54 namespace absl { 55 ABSL_NAMESPACE_BEGIN 56 namespace log_internal { 57 58 class LogEntryTestPeer { 59 public: 60 LogEntryTestPeer(absl::string_view base_filename, int line, bool prefix, 61 absl::LogSeverity severity, absl::string_view timestamp, 62 absl::LogEntry::tid_t tid, PrefixFormat format, 63 absl::string_view text_message) 64 : format_{format}, buf_(15000, '\0') { 65 entry_.base_filename_ = base_filename; 66 entry_.line_ = line; 67 entry_.prefix_ = prefix; 68 entry_.severity_ = severity; 69 std::string time_err; 70 EXPECT_THAT( 71 absl::ParseTime("%Y-%m-%d%ET%H:%M:%E*S", timestamp, 72 absl::LocalTimeZone(), &entry_.timestamp_, &time_err), 73 IsTrue()) 74 << "Failed to parse time " << timestamp << ": " << time_err; 75 entry_.tid_ = tid; 76 std::pair<absl::string_view, std::string> timestamp_bits = 77 absl::StrSplit(timestamp, absl::ByChar('.')); 78 EXPECT_THAT(absl::ParseCivilTime(timestamp_bits.first, &ci_.cs), IsTrue()) 79 << "Failed to parse time " << timestamp_bits.first; 80 timestamp_bits.second.resize(9, '0'); 81 int64_t nanos = 0; 82 EXPECT_THAT(absl::SimpleAtoi(timestamp_bits.second, &nanos), IsTrue()) 83 << "Failed to parse time " << timestamp_bits.first; 84 ci_.subsecond = absl::Nanoseconds(nanos); 85 86 absl::Span<char> view = absl::MakeSpan(buf_); 87 view.remove_suffix(2); 88 entry_.prefix_len_ = 89 entry_.prefix_ 90 ? log_internal::FormatLogPrefix( 91 entry_.log_severity(), entry_.timestamp(), entry_.tid(), 92 entry_.source_basename(), entry_.source_line(), format_, view) 93 : 0; 94 95 EXPECT_THAT(entry_.prefix_len_, 96 Eq(static_cast<size_t>(view.data() - buf_.data()))); 97 log_internal::AppendTruncated(text_message, view); 98 view = absl::Span<char>(view.data(), view.size() + 2); 99 view[0] = '\n'; 100 view[1] = '\0'; 101 view.remove_prefix(2); 102 buf_.resize(static_cast<size_t>(view.data() - buf_.data())); 103 entry_.text_message_with_prefix_and_newline_and_nul_ = absl::MakeSpan(buf_); 104 } 105 LogEntryTestPeer(const LogEntryTestPeer&) = delete; 106 LogEntryTestPeer& operator=(const LogEntryTestPeer&) = delete; 107 108 std::string FormatLogMessage() const { 109 return log_internal::FormatLogMessage( 110 entry_.log_severity(), ci_.cs, ci_.subsecond, entry_.tid(), 111 entry_.source_basename(), entry_.source_line(), format_, 112 entry_.text_message()); 113 } 114 std::string FormatPrefixIntoSizedBuffer(size_t sz) { 115 std::string str(sz, '\0'); 116 absl::Span<char> buf(&str[0], str.size()); 117 const size_t prefix_size = log_internal::FormatLogPrefix( 118 entry_.log_severity(), entry_.timestamp(), entry_.tid(), 119 entry_.source_basename(), entry_.source_line(), format_, buf); 120 EXPECT_THAT(prefix_size, Eq(static_cast<size_t>(buf.data() - str.data()))); 121 str.resize(prefix_size); 122 return str; 123 } 124 const absl::LogEntry& entry() const { return entry_; } 125 126 private: 127 absl::LogEntry entry_; 128 PrefixFormat format_; 129 absl::TimeZone::CivilInfo ci_; 130 std::vector<char> buf_; 131 }; 132 133 } // namespace log_internal 134 ABSL_NAMESPACE_END 135 } // namespace absl 136 137 namespace { 138 constexpr bool kUsePrefix = true, kNoPrefix = false; 139 140 TEST(LogEntryTest, Baseline) { 141 LogEntryTestPeer entry("foo.cc", 1234, kUsePrefix, absl::LogSeverity::kInfo, 142 "2020-01-02T03:04:05.6789", 451, 143 absl::log_internal::PrefixFormat::kNotRaw, 144 "hello world"); 145 EXPECT_THAT(entry.FormatLogMessage(), 146 Eq("I0102 03:04:05.678900 451 foo.cc:1234] hello world")); 147 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 148 Eq("I0102 03:04:05.678900 451 foo.cc:1234] ")); 149 for (size_t sz = strlen("I0102 03:04:05.678900 451 foo.cc:1234] ") + 20; 150 sz != std::numeric_limits<size_t>::max(); sz--) 151 EXPECT_THAT("I0102 03:04:05.678900 451 foo.cc:1234] ", 152 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 153 154 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(), 155 Eq("I0102 03:04:05.678900 451 foo.cc:1234] hello world\n")); 156 EXPECT_THAT( 157 entry.entry().text_message_with_prefix_and_newline_c_str(), 158 StrEq("I0102 03:04:05.678900 451 foo.cc:1234] hello world\n")); 159 EXPECT_THAT(entry.entry().text_message_with_prefix(), 160 Eq("I0102 03:04:05.678900 451 foo.cc:1234] hello world")); 161 EXPECT_THAT(entry.entry().text_message(), Eq("hello world")); 162 } 163 164 TEST(LogEntryTest, NoPrefix) { 165 LogEntryTestPeer entry("foo.cc", 1234, kNoPrefix, absl::LogSeverity::kInfo, 166 "2020-01-02T03:04:05.6789", 451, 167 absl::log_internal::PrefixFormat::kNotRaw, 168 "hello world"); 169 EXPECT_THAT(entry.FormatLogMessage(), 170 Eq("I0102 03:04:05.678900 451 foo.cc:1234] hello world")); 171 // These methods are not responsible for honoring `prefix()`. 172 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 173 Eq("I0102 03:04:05.678900 451 foo.cc:1234] ")); 174 for (size_t sz = strlen("I0102 03:04:05.678900 451 foo.cc:1234] ") + 20; 175 sz != std::numeric_limits<size_t>::max(); sz--) 176 EXPECT_THAT("I0102 03:04:05.678900 451 foo.cc:1234] ", 177 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 178 179 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(), 180 Eq("hello world\n")); 181 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(), 182 StrEq("hello world\n")); 183 EXPECT_THAT(entry.entry().text_message_with_prefix(), Eq("hello world")); 184 EXPECT_THAT(entry.entry().text_message(), Eq("hello world")); 185 } 186 187 TEST(LogEntryTest, EmptyFields) { 188 LogEntryTestPeer entry("", 0, kUsePrefix, absl::LogSeverity::kInfo, 189 "2020-01-02T03:04:05", 0, 190 absl::log_internal::PrefixFormat::kNotRaw, ""); 191 const std::string format_message = entry.FormatLogMessage(); 192 EXPECT_THAT(format_message, Eq("I0102 03:04:05.000000 0 :0] ")); 193 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), Eq(format_message)); 194 for (size_t sz = format_message.size() + 20; 195 sz != std::numeric_limits<size_t>::max(); sz--) 196 EXPECT_THAT(format_message, 197 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 198 199 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(), 200 Eq("I0102 03:04:05.000000 0 :0] \n")); 201 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline_c_str(), 202 StrEq("I0102 03:04:05.000000 0 :0] \n")); 203 EXPECT_THAT(entry.entry().text_message_with_prefix(), 204 Eq("I0102 03:04:05.000000 0 :0] ")); 205 EXPECT_THAT(entry.entry().text_message(), Eq("")); 206 } 207 208 TEST(LogEntryTest, NegativeFields) { 209 // When Abseil's minimum C++ version is C++17, this conditional can be 210 // converted to a constexpr if and the static_cast below removed. 211 if (std::is_signed<absl::LogEntry::tid_t>::value) { 212 LogEntryTestPeer entry( 213 "foo.cc", -1234, kUsePrefix, absl::LogSeverity::kInfo, 214 "2020-01-02T03:04:05.6789", static_cast<absl::LogEntry::tid_t>(-451), 215 absl::log_internal::PrefixFormat::kNotRaw, "hello world"); 216 EXPECT_THAT(entry.FormatLogMessage(), 217 Eq("I0102 03:04:05.678900 -451 foo.cc:-1234] hello world")); 218 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 219 Eq("I0102 03:04:05.678900 -451 foo.cc:-1234] ")); 220 for (size_t sz = 221 strlen("I0102 03:04:05.678900 -451 foo.cc:-1234] ") + 20; 222 sz != std::numeric_limits<size_t>::max(); sz--) 223 EXPECT_THAT("I0102 03:04:05.678900 -451 foo.cc:-1234] ", 224 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 225 226 EXPECT_THAT( 227 entry.entry().text_message_with_prefix_and_newline(), 228 Eq("I0102 03:04:05.678900 -451 foo.cc:-1234] hello world\n")); 229 EXPECT_THAT( 230 entry.entry().text_message_with_prefix_and_newline_c_str(), 231 StrEq("I0102 03:04:05.678900 -451 foo.cc:-1234] hello world\n")); 232 EXPECT_THAT(entry.entry().text_message_with_prefix(), 233 Eq("I0102 03:04:05.678900 -451 foo.cc:-1234] hello world")); 234 EXPECT_THAT(entry.entry().text_message(), Eq("hello world")); 235 } else { 236 LogEntryTestPeer entry("foo.cc", -1234, kUsePrefix, 237 absl::LogSeverity::kInfo, "2020-01-02T03:04:05.6789", 238 451, absl::log_internal::PrefixFormat::kNotRaw, 239 "hello world"); 240 EXPECT_THAT(entry.FormatLogMessage(), 241 Eq("I0102 03:04:05.678900 451 foo.cc:-1234] hello world")); 242 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 243 Eq("I0102 03:04:05.678900 451 foo.cc:-1234] ")); 244 for (size_t sz = 245 strlen("I0102 03:04:05.678900 451 foo.cc:-1234] ") + 20; 246 sz != std::numeric_limits<size_t>::max(); sz--) 247 EXPECT_THAT("I0102 03:04:05.678900 451 foo.cc:-1234] ", 248 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 249 250 EXPECT_THAT( 251 entry.entry().text_message_with_prefix_and_newline(), 252 Eq("I0102 03:04:05.678900 451 foo.cc:-1234] hello world\n")); 253 EXPECT_THAT( 254 entry.entry().text_message_with_prefix_and_newline_c_str(), 255 StrEq("I0102 03:04:05.678900 451 foo.cc:-1234] hello world\n")); 256 EXPECT_THAT(entry.entry().text_message_with_prefix(), 257 Eq("I0102 03:04:05.678900 451 foo.cc:-1234] hello world")); 258 EXPECT_THAT(entry.entry().text_message(), Eq("hello world")); 259 } 260 } 261 262 TEST(LogEntryTest, LongFields) { 263 LogEntryTestPeer entry( 264 "I am the very model of a modern Major-General / " 265 "I've information vegetable, animal, and mineral.", 266 2147483647, kUsePrefix, absl::LogSeverity::kInfo, 267 "2020-01-02T03:04:05.678967896789", 2147483647, 268 absl::log_internal::PrefixFormat::kNotRaw, 269 "I know the kings of England, and I quote the fights historical / " 270 "From Marathon to Waterloo, in order categorical."); 271 EXPECT_THAT(entry.FormatLogMessage(), 272 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 273 "modern Major-General / I've information vegetable, animal, " 274 "and mineral.:2147483647] I know the kings of England, and I " 275 "quote the fights historical / From Marathon to Waterloo, in " 276 "order categorical.")); 277 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 278 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 279 "modern Major-General / I've information vegetable, animal, " 280 "and mineral.:2147483647] ")); 281 for (size_t sz = 282 strlen("I0102 03:04:05.678967 2147483647 I am the very model of a " 283 "modern Major-General / I've information vegetable, animal, " 284 "and mineral.:2147483647] ") + 285 20; 286 sz != std::numeric_limits<size_t>::max(); sz--) 287 EXPECT_THAT( 288 "I0102 03:04:05.678967 2147483647 I am the very model of a " 289 "modern Major-General / I've information vegetable, animal, " 290 "and mineral.:2147483647] ", 291 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 292 293 EXPECT_THAT(entry.entry().text_message_with_prefix_and_newline(), 294 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 295 "modern Major-General / I've information vegetable, animal, " 296 "and mineral.:2147483647] I know the kings of England, and I " 297 "quote the fights historical / From Marathon to Waterloo, in " 298 "order categorical.\n")); 299 EXPECT_THAT( 300 entry.entry().text_message_with_prefix_and_newline_c_str(), 301 StrEq("I0102 03:04:05.678967 2147483647 I am the very model of a " 302 "modern Major-General / I've information vegetable, animal, " 303 "and mineral.:2147483647] I know the kings of England, and I " 304 "quote the fights historical / From Marathon to Waterloo, in " 305 "order categorical.\n")); 306 EXPECT_THAT(entry.entry().text_message_with_prefix(), 307 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 308 "modern Major-General / I've information vegetable, animal, " 309 "and mineral.:2147483647] I know the kings of England, and I " 310 "quote the fights historical / From Marathon to Waterloo, in " 311 "order categorical.")); 312 EXPECT_THAT( 313 entry.entry().text_message(), 314 Eq("I know the kings of England, and I quote the fights historical / " 315 "From Marathon to Waterloo, in order categorical.")); 316 } 317 318 TEST(LogEntryTest, LongNegativeFields) { 319 // When Abseil's minimum C++ version is C++17, this conditional can be 320 // converted to a constexpr if and the static_cast below removed. 321 if (std::is_signed<absl::LogEntry::tid_t>::value) { 322 LogEntryTestPeer entry( 323 "I am the very model of a modern Major-General / " 324 "I've information vegetable, animal, and mineral.", 325 -2147483647, kUsePrefix, absl::LogSeverity::kInfo, 326 "2020-01-02T03:04:05.678967896789", 327 static_cast<absl::LogEntry::tid_t>(-2147483647), 328 absl::log_internal::PrefixFormat::kNotRaw, 329 "I know the kings of England, and I quote the fights historical / " 330 "From Marathon to Waterloo, in order categorical."); 331 EXPECT_THAT( 332 entry.FormatLogMessage(), 333 Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a " 334 "modern Major-General / I've information vegetable, animal, " 335 "and mineral.:-2147483647] I know the kings of England, and I " 336 "quote the fights historical / From Marathon to Waterloo, in " 337 "order categorical.")); 338 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 339 Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a " 340 "modern Major-General / I've information vegetable, animal, " 341 "and mineral.:-2147483647] ")); 342 for (size_t sz = 343 strlen( 344 "I0102 03:04:05.678967 -2147483647 I am the very model of a " 345 "modern Major-General / I've information vegetable, animal, " 346 "and mineral.:-2147483647] ") + 347 20; 348 sz != std::numeric_limits<size_t>::max(); sz--) 349 EXPECT_THAT( 350 "I0102 03:04:05.678967 -2147483647 I am the very model of a " 351 "modern Major-General / I've information vegetable, animal, " 352 "and mineral.:-2147483647] ", 353 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 354 355 EXPECT_THAT( 356 entry.entry().text_message_with_prefix_and_newline(), 357 Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a " 358 "modern Major-General / I've information vegetable, animal, " 359 "and mineral.:-2147483647] I know the kings of England, and I " 360 "quote the fights historical / From Marathon to Waterloo, in " 361 "order categorical.\n")); 362 EXPECT_THAT( 363 entry.entry().text_message_with_prefix_and_newline_c_str(), 364 StrEq("I0102 03:04:05.678967 -2147483647 I am the very model of a " 365 "modern Major-General / I've information vegetable, animal, " 366 "and mineral.:-2147483647] I know the kings of England, and I " 367 "quote the fights historical / From Marathon to Waterloo, in " 368 "order categorical.\n")); 369 EXPECT_THAT( 370 entry.entry().text_message_with_prefix(), 371 Eq("I0102 03:04:05.678967 -2147483647 I am the very model of a " 372 "modern Major-General / I've information vegetable, animal, " 373 "and mineral.:-2147483647] I know the kings of England, and I " 374 "quote the fights historical / From Marathon to Waterloo, in " 375 "order categorical.")); 376 EXPECT_THAT( 377 entry.entry().text_message(), 378 Eq("I know the kings of England, and I quote the fights historical / " 379 "From Marathon to Waterloo, in order categorical.")); 380 } else { 381 LogEntryTestPeer entry( 382 "I am the very model of a modern Major-General / " 383 "I've information vegetable, animal, and mineral.", 384 -2147483647, kUsePrefix, absl::LogSeverity::kInfo, 385 "2020-01-02T03:04:05.678967896789", 2147483647, 386 absl::log_internal::PrefixFormat::kNotRaw, 387 "I know the kings of England, and I quote the fights historical / " 388 "From Marathon to Waterloo, in order categorical."); 389 EXPECT_THAT( 390 entry.FormatLogMessage(), 391 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 392 "modern Major-General / I've information vegetable, animal, " 393 "and mineral.:-2147483647] I know the kings of England, and I " 394 "quote the fights historical / From Marathon to Waterloo, in " 395 "order categorical.")); 396 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 397 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 398 "modern Major-General / I've information vegetable, animal, " 399 "and mineral.:-2147483647] ")); 400 for (size_t sz = 401 strlen( 402 "I0102 03:04:05.678967 2147483647 I am the very model of a " 403 "modern Major-General / I've information vegetable, animal, " 404 "and mineral.:-2147483647] ") + 405 20; 406 sz != std::numeric_limits<size_t>::max(); sz--) 407 EXPECT_THAT( 408 "I0102 03:04:05.678967 2147483647 I am the very model of a " 409 "modern Major-General / I've information vegetable, animal, " 410 "and mineral.:-2147483647] ", 411 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 412 413 EXPECT_THAT( 414 entry.entry().text_message_with_prefix_and_newline(), 415 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 416 "modern Major-General / I've information vegetable, animal, " 417 "and mineral.:-2147483647] I know the kings of England, and I " 418 "quote the fights historical / From Marathon to Waterloo, in " 419 "order categorical.\n")); 420 EXPECT_THAT( 421 entry.entry().text_message_with_prefix_and_newline_c_str(), 422 StrEq("I0102 03:04:05.678967 2147483647 I am the very model of a " 423 "modern Major-General / I've information vegetable, animal, " 424 "and mineral.:-2147483647] I know the kings of England, and I " 425 "quote the fights historical / From Marathon to Waterloo, in " 426 "order categorical.\n")); 427 EXPECT_THAT( 428 entry.entry().text_message_with_prefix(), 429 Eq("I0102 03:04:05.678967 2147483647 I am the very model of a " 430 "modern Major-General / I've information vegetable, animal, " 431 "and mineral.:-2147483647] I know the kings of England, and I " 432 "quote the fights historical / From Marathon to Waterloo, in " 433 "order categorical.")); 434 EXPECT_THAT( 435 entry.entry().text_message(), 436 Eq("I know the kings of England, and I quote the fights historical / " 437 "From Marathon to Waterloo, in order categorical.")); 438 } 439 } 440 441 TEST(LogEntryTest, Raw) { 442 LogEntryTestPeer entry("foo.cc", 1234, kUsePrefix, absl::LogSeverity::kInfo, 443 "2020-01-02T03:04:05.6789", 451, 444 absl::log_internal::PrefixFormat::kRaw, "hello world"); 445 EXPECT_THAT( 446 entry.FormatLogMessage(), 447 Eq("I0102 03:04:05.678900 451 foo.cc:1234] RAW: hello world")); 448 EXPECT_THAT(entry.FormatPrefixIntoSizedBuffer(1000), 449 Eq("I0102 03:04:05.678900 451 foo.cc:1234] RAW: ")); 450 for (size_t sz = 451 strlen("I0102 03:04:05.678900 451 foo.cc:1234] RAW: ") + 20; 452 sz != std::numeric_limits<size_t>::max(); sz--) 453 EXPECT_THAT("I0102 03:04:05.678900 451 foo.cc:1234] RAW: ", 454 StartsWith(entry.FormatPrefixIntoSizedBuffer(sz))); 455 456 EXPECT_THAT( 457 entry.entry().text_message_with_prefix_and_newline(), 458 Eq("I0102 03:04:05.678900 451 foo.cc:1234] RAW: hello world\n")); 459 EXPECT_THAT( 460 entry.entry().text_message_with_prefix_and_newline_c_str(), 461 StrEq("I0102 03:04:05.678900 451 foo.cc:1234] RAW: hello world\n")); 462 EXPECT_THAT( 463 entry.entry().text_message_with_prefix(), 464 Eq("I0102 03:04:05.678900 451 foo.cc:1234] RAW: hello world")); 465 EXPECT_THAT(entry.entry().text_message(), Eq("hello world")); 466 } 467 468 } // namespace