xref: /aosp_15_r20/system/core/debuggerd/libdebuggerd/test/dump_memory_test.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
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  *      http://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 
17 #include <stdlib.h>
18 
19 #include <memory>
20 #include <string>
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <gtest/gtest.h>
26 #include <unwindstack/Memory.h>
27 
28 #include "libdebuggerd/utility.h"
29 
30 #include "log_fake.h"
31 
GetMemoryString(uintptr_t addr,const std::vector<uint64_t> & data)32 std::string GetMemoryString(uintptr_t addr, const std::vector<uint64_t>& data) {
33   // Must be even number of data values.
34   CHECK((data.size() & 1) == 0);
35 
36   std::string str;
37   for (size_t i = 0; i < data.size(); i += 2) {
38     str += "    ";
39     std::string ascii_str = "";
40     for (size_t j = 0; j < 2; j++) {
41       for (size_t k = 0; k < 8; k++) {
42         uint8_t c = (data[i + j] >> (k * 8)) & 0xff;
43         if (c >= 0x20 && c < 0x7f) {
44           ascii_str += c;
45         } else {
46           ascii_str += '.';
47         }
48       }
49     }
50 #if defined(__LP64__)
51     str += android::base::StringPrintf("%016zx %016zx %016zx  ", addr, data[i], data[i + 1]);
52 #else
53     str += android::base::StringPrintf(
54         "%08zx %08zx %08zx %08zx %08zx  ", addr, static_cast<uintptr_t>(data[i] & 0xffffffff),
55         static_cast<uintptr_t>(data[i] >> 32), static_cast<uintptr_t>(data[i + 1] & 0xffffffff),
56         static_cast<uintptr_t>(data[i + 1] >> 32));
57 #endif
58     str += ascii_str + "\n";
59     addr += 0x10;
60   }
61   return str;
62 }
63 
GetDefaultData()64 const std::vector<uint64_t>& GetDefaultData() {
65   static std::vector<uint64_t> data(
66       {0x0706050403020100UL, 0x0f0e0d0c0b0a0908UL, 0x1716151413121110UL, 0x1f1e1d1c1b1a1918UL,
67        0x2726252423222120UL, 0x2f2e2d2c2b2a2928UL, 0x3736353433323130UL, 0x3f3e3d3c3b3a3938UL,
68        0x4746454443424140UL, 0x4f4e4d4c4b4a4948UL, 0x5756555453525150UL, 0x5f5e5d5c5b5a5958UL,
69        0x6766656463626160UL, 0x6f6e6d6c6b6a6968UL, 0x7776757473727170UL, 0x7f7e7d7c7b7a7978UL,
70        0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
71        0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
72        0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
73        0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
74   return data;
75 }
76 
GetFullDumpString()77 std::string GetFullDumpString() {
78   std::string str = "\nmemory near r1:\n";
79   str += GetMemoryString(0x12345650U, GetDefaultData());
80   return str;
81 }
82 
GetPartialDumpString()83 std::string GetPartialDumpString() {
84   std::string str = "\nmemory near pc:\n";
85   std::vector<uint64_t> data = GetDefaultData();
86   data.resize(12);
87   str += GetMemoryString(0x123455e0U, data);
88   return str;
89 }
90 
91 class MemoryMock : public unwindstack::Memory {
92  public:
93   virtual ~MemoryMock() = default;
94 
Read(uint64_t addr,void * buffer,size_t bytes)95   virtual size_t Read(uint64_t addr, void* buffer, size_t bytes) override {
96     size_t offset = 0;
97     if (last_read_addr_ > 0) {
98       offset = addr - last_read_addr_;
99     }
100     size_t bytes_available = 0;
101     if (offset < buffer_.size()) {
102       bytes_available = buffer_.size() - offset;
103     }
104 
105     if (partial_read_) {
106       bytes = std::min(bytes, bytes_partial_read_);
107       bytes_partial_read_ -= bytes;
108       partial_read_ = bytes_partial_read_;
109     } else if (bytes > bytes_available) {
110       bytes = bytes_available;
111     }
112 
113     if (bytes > 0) {
114       memcpy(buffer, buffer_.data() + offset, bytes);
115     }
116 
117     last_read_addr_ = addr;
118     return bytes;
119   }
120 
SetReadData(uint8_t * buffer,size_t bytes)121   void SetReadData(uint8_t* buffer, size_t bytes) {
122     buffer_.resize(bytes);
123     memcpy(buffer_.data(), buffer, bytes);
124     bytes_partial_read_ = 0;
125     last_read_addr_ = 0;
126   }
127 
SetPartialReadAmount(size_t bytes)128   void SetPartialReadAmount(size_t bytes) {
129     if (bytes > buffer_.size()) {
130       abort();
131     }
132     partial_read_ = true;
133     bytes_partial_read_ = bytes;
134   }
135 
136  private:
137   std::vector<uint8_t> buffer_;
138   bool partial_read_ = false;
139   size_t bytes_partial_read_ = 0;
140   uintptr_t last_read_addr_ = 0;
141 };
142 
143 class DumpMemoryTest : public ::testing::Test {
144  protected:
SetUp()145   virtual void SetUp() {
146     memory_mock_ = std::make_unique<MemoryMock>();
147 
148     char tmp_file[256];
149     const char data_template[] = "/data/local/tmp/debuggerd_memory_testXXXXXX";
150     memcpy(tmp_file, data_template, sizeof(data_template));
151     int tombstone_fd = mkstemp(tmp_file);
152     if (tombstone_fd == -1) {
153       const char tmp_template[] = "/tmp/debuggerd_memory_testXXXXXX";
154       memcpy(tmp_file, tmp_template, sizeof(tmp_template));
155       tombstone_fd = mkstemp(tmp_file);
156       if (tombstone_fd == -1) {
157         abort();
158       }
159     }
160     if (unlink(tmp_file) == -1) {
161       abort();
162     }
163 
164     log_.tfd = tombstone_fd;
165     log_.amfd_data = nullptr;
166     log_.crashed_tid = 12;
167     log_.current_tid = 12;
168     log_.should_retrieve_logcat = false;
169 
170     resetLogs();
171   }
172 
TearDown()173   virtual void TearDown() {
174     if (log_.tfd >= 0) {
175       close(log_.tfd);
176     }
177     memory_mock_.reset();
178   }
179 
180   std::unique_ptr<MemoryMock> memory_mock_;
181 
182   log_t log_;
183 };
184 
TEST_F(DumpMemoryTest,aligned_addr)185 TEST_F(DumpMemoryTest, aligned_addr) {
186   uint8_t buffer[256];
187   for (size_t i = 0; i < sizeof(buffer); i++) {
188     buffer[i] = i;
189   }
190   memory_mock_->SetReadData(buffer, sizeof(buffer));
191 
192   dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near r1");
193 
194   std::string tombstone_contents;
195   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
196   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
197   ASSERT_EQ(GetFullDumpString(), tombstone_contents);
198 
199   // Verify that the log buf is empty, and no error messages.
200   ASSERT_STREQ("", getFakeLogBuf().c_str());
201   ASSERT_STREQ("", getFakeLogPrint().c_str());
202 }
203 
TEST_F(DumpMemoryTest,partial_read)204 TEST_F(DumpMemoryTest, partial_read) {
205   uint8_t buffer[256];
206   for (size_t i = 0; i < sizeof(buffer); i++) {
207     buffer[i] = i;
208   }
209   memory_mock_->SetReadData(buffer, sizeof(buffer));
210   memory_mock_->SetPartialReadAmount(96);
211 
212   dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
213 
214   std::string tombstone_contents;
215   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
216   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
217   ASSERT_EQ(GetFullDumpString(), tombstone_contents);
218 
219   // Verify that the log buf is empty, and no error messages.
220   ASSERT_STREQ("", getFakeLogBuf().c_str());
221   ASSERT_STREQ("", getFakeLogPrint().c_str());
222 }
223 
TEST_F(DumpMemoryTest,unaligned_addr)224 TEST_F(DumpMemoryTest, unaligned_addr) {
225   uint8_t buffer[256];
226   for (size_t i = 0; i < sizeof(buffer); i++) {
227     buffer[i] = i;
228   }
229   memory_mock_->SetReadData(buffer, sizeof(buffer));
230 
231   dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
232 
233   std::string tombstone_contents;
234   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
235   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
236   ASSERT_EQ(GetFullDumpString(), tombstone_contents);
237 
238   // Verify that the log buf is empty, and no error messages.
239   ASSERT_STREQ("", getFakeLogBuf().c_str());
240   ASSERT_STREQ("", getFakeLogPrint().c_str());
241 }
242 
TEST_F(DumpMemoryTest,memory_unreadable)243 TEST_F(DumpMemoryTest, memory_unreadable) {
244   dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc");
245 
246   std::string tombstone_contents;
247   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
248   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
249   ASSERT_STREQ("", tombstone_contents.c_str());
250 
251   // Verify that the log buf is empty, and no error messages.
252   ASSERT_STREQ("", getFakeLogBuf().c_str());
253   ASSERT_STREQ("", getFakeLogPrint().c_str());
254 }
255 
TEST_F(DumpMemoryTest,memory_partially_unreadable)256 TEST_F(DumpMemoryTest, memory_partially_unreadable) {
257   uint8_t buffer[104];
258   for (size_t i = 0; i < sizeof(buffer); i++) {
259     buffer[i] = i;
260   }
261   memory_mock_->SetReadData(buffer, sizeof(buffer));
262 
263   dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
264 
265   std::string tombstone_contents;
266   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
267   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
268   ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
269 
270   // Verify that the log buf is empty, and no error messages.
271   ASSERT_STREQ("", getFakeLogBuf().c_str());
272   ASSERT_STREQ("", getFakeLogPrint().c_str());
273 }
274 
TEST_F(DumpMemoryTest,memory_partially_unreadable_unaligned_return)275 TEST_F(DumpMemoryTest, memory_partially_unreadable_unaligned_return) {
276   uint8_t buffer[104];
277   for (size_t i = 0; i < sizeof(buffer); i++) {
278     buffer[i] = i;
279   }
280   memory_mock_->SetReadData(buffer, sizeof(buffer));
281   memory_mock_->SetPartialReadAmount(102);
282 
283   dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
284 
285   std::string tombstone_contents;
286   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
287   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
288   ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
289 
290 #if defined(__LP64__)
291   ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 8\n", getFakeLogPrint().c_str());
292 #else
293   ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 4\n", getFakeLogPrint().c_str());
294 #endif
295 
296   // Verify that the log buf is empty, and no error messages.
297   ASSERT_STREQ("", getFakeLogBuf().c_str());
298 }
299 
TEST_F(DumpMemoryTest,memory_partially_unreadable_two_unaligned_reads)300 TEST_F(DumpMemoryTest, memory_partially_unreadable_two_unaligned_reads) {
301   uint8_t buffer[106];
302   for (size_t i = 0; i < sizeof(buffer); i++) {
303     buffer[i] = i;
304   }
305   memory_mock_->SetReadData(buffer, sizeof(buffer));
306   memory_mock_->SetPartialReadAmount(45);
307 
308   dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
309 
310   std::string tombstone_contents;
311   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
312   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
313   ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
314 
315 #if defined(__LP64__)
316   ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 8\n"
317                "6 DEBUG Bytes after second read 106, is not a multiple of 8\n",
318                getFakeLogPrint().c_str());
319 #else
320   ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 4\n"
321                "6 DEBUG Bytes after second read 106, is not a multiple of 4\n",
322                getFakeLogPrint().c_str());
323 #endif
324 
325   // Verify that the log buf is empty, and no error messages.
326   ASSERT_STREQ("", getFakeLogBuf().c_str());
327 }
328 
TEST_F(DumpMemoryTest,address_low_fence)329 TEST_F(DumpMemoryTest, address_low_fence) {
330   uint8_t buffer[256];
331   memset(buffer, 0, sizeof(buffer));
332   memory_mock_->SetReadData(buffer, sizeof(buffer));
333 
334   dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near r1");
335 
336   std::string tombstone_contents;
337   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
338   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
339   std::string expected_dump = "\nmemory near r1:\n";
340   expected_dump += GetMemoryString(0x1000, std::vector<uint64_t>(32, 0UL));
341   ASSERT_EQ(expected_dump, tombstone_contents);
342 
343   // Verify that the log buf is empty, and no error messages.
344   ASSERT_STREQ("", getFakeLogBuf().c_str());
345   ASSERT_STREQ("", getFakeLogPrint().c_str());
346 }
347 
TEST_F(DumpMemoryTest,memory_address_too_high)348 TEST_F(DumpMemoryTest, memory_address_too_high) {
349   uint8_t buffer[256];
350   memset(buffer, 0, sizeof(buffer));
351   memory_mock_->SetReadData(buffer, sizeof(buffer));
352 
353 #if defined(__LP64__)
354   dump_memory(&log_, memory_mock_.get(), -32, "memory near r1");
355   dump_memory(&log_, memory_mock_.get(), -208, "memory near r1");
356 #else
357   dump_memory(&log_, memory_mock_.get(), 0x100000000 - 32, "memory near r1");
358   dump_memory(&log_, memory_mock_.get(), 0x100000000 - 208, "memory near r1");
359 #endif
360 
361   std::string tombstone_contents;
362   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
363   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
364   ASSERT_STREQ("", tombstone_contents.c_str());
365 
366   // Verify that the log buf is empty, and no error messages.
367   ASSERT_STREQ("", getFakeLogBuf().c_str());
368   ASSERT_STREQ("", getFakeLogPrint().c_str());
369 }
370 
TEST_F(DumpMemoryTest,memory_address_nearly_too_high)371 TEST_F(DumpMemoryTest, memory_address_nearly_too_high) {
372   uint8_t buffer[256];
373   for (size_t i = 0; i < sizeof(buffer); i++) {
374     buffer[i] = i;
375   }
376   memory_mock_->SetReadData(buffer, sizeof(buffer));
377 
378 #if defined(__LP64__)
379   dump_memory(&log_, memory_mock_.get(), -224, "memory near r4");
380 #else
381   dump_memory(&log_, memory_mock_.get(), 0x100000000 - 224, "memory near r4");
382 #endif
383 
384   std::string tombstone_contents;
385   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
386   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
387   std::string expected_dump = "\nmemory near r4:\n";
388   uintptr_t addr;
389 #if defined(__aarch64__)
390   addr = 0x00ffffffffffff00UL;
391 #elif defined(__LP64__)
392   addr = 0xffffffffffffff00UL;
393 #else
394   addr = 0xffffff00UL;
395 #endif
396   expected_dump += GetMemoryString(addr, GetDefaultData());
397   ASSERT_EQ(expected_dump, tombstone_contents);
398 
399   // Verify that the log buf is empty, and no error messages.
400   ASSERT_STREQ("", getFakeLogBuf().c_str());
401   ASSERT_STREQ("", getFakeLogPrint().c_str());
402 }
403 
TEST_F(DumpMemoryTest,first_read_empty)404 TEST_F(DumpMemoryTest, first_read_empty) {
405   uint8_t buffer[256];
406   for (size_t i = 0; i < sizeof(buffer); i++) {
407     buffer[i] = i;
408   }
409   memory_mock_->SetReadData(buffer, sizeof(buffer));
410   memory_mock_->SetPartialReadAmount(0);
411 
412   size_t page_size = sysconf(_SC_PAGE_SIZE);
413   uintptr_t addr = 0x10000020 + page_size - 120;
414   dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
415 
416   std::string tombstone_contents;
417   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
418   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
419   std::string expected_dump = "\nmemory near r4:\n";
420   expected_dump += GetMemoryString(
421       0x10000000 + page_size,
422       std::vector<uint64_t>{
423           0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
424           0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
425           0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
426           0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
427   ASSERT_EQ(expected_dump, tombstone_contents);
428 
429   // Verify that the log buf is empty, and no error messages.
430   ASSERT_STREQ("", getFakeLogBuf().c_str());
431   ASSERT_STREQ("", getFakeLogPrint().c_str());
432 }
433 
TEST_F(DumpMemoryTest,first_read_empty_second_read_stops)434 TEST_F(DumpMemoryTest, first_read_empty_second_read_stops) {
435   uint8_t buffer[224];
436   for (size_t i = 0; i < sizeof(buffer); i++) {
437     buffer[i] = i;
438   }
439   memory_mock_->SetReadData(buffer, sizeof(buffer));
440   memory_mock_->SetPartialReadAmount(0);
441 
442   size_t page_size = sysconf(_SC_PAGE_SIZE);
443   uintptr_t addr = 0x10000020 + page_size - 192;
444   dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
445 
446   std::string tombstone_contents;
447   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
448   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
449   std::string expected_dump = "\nmemory near r4:\n";
450   expected_dump += GetMemoryString(
451       0x10000000 + page_size, std::vector<uint64_t>{0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL,
452                                                     0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL});
453   ASSERT_EQ(expected_dump, tombstone_contents);
454 
455   // Verify that the log buf is empty, and no error messages.
456   ASSERT_STREQ("", getFakeLogBuf().c_str());
457   ASSERT_STREQ("", getFakeLogPrint().c_str());
458 }
459 
TEST_F(DumpMemoryTest,first_read_empty_next_page_out_of_range)460 TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range) {
461   uint8_t buffer[256];
462   for (size_t i = 0; i < sizeof(buffer); i++) {
463     buffer[i] = i;
464   }
465   memory_mock_->SetReadData(buffer, sizeof(buffer));
466   memory_mock_->SetPartialReadAmount(0);
467 
468   uintptr_t addr = 0x10000020;
469   dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
470 
471   std::string tombstone_contents;
472   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
473   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
474   ASSERT_STREQ("", tombstone_contents.c_str());
475 
476   // Verify that the log buf is empty, and no error messages.
477   ASSERT_STREQ("", getFakeLogBuf().c_str());
478   ASSERT_STREQ("", getFakeLogPrint().c_str());
479 }
480 
TEST_F(DumpMemoryTest,first_read_empty_next_page_out_of_range_fence_post)481 TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range_fence_post) {
482   uint8_t buffer[256];
483   for (size_t i = 0; i < sizeof(buffer); i++) {
484     buffer[i] = i;
485   }
486   memory_mock_->SetReadData(buffer, sizeof(buffer));
487   memory_mock_->SetPartialReadAmount(0);
488 
489   size_t page_size = sysconf(_SC_PAGE_SIZE);
490   uintptr_t addr = 0x10000020 + page_size - 256;
491 
492   dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
493 
494   std::string tombstone_contents;
495   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
496   ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
497   ASSERT_STREQ("", tombstone_contents.c_str());
498 
499   // Verify that the log buf is empty, and no error messages.
500   ASSERT_STREQ("", getFakeLogBuf().c_str());
501   ASSERT_STREQ("", getFakeLogPrint().c_str());
502 }
503