Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Test of classes in the tracked_objects.h classes. | 5 // Test of classes in the tracked_objects.h classes. |
| 6 | 6 |
| 7 #include "base/tracked_objects.h" | 7 #include "base/tracked_objects.h" |
| 8 | 8 |
| 9 #include "base/json/json_writer.h" | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 10 #include "base/time.h" | 12 #include "base/time.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 14 |
| 13 namespace tracked_objects { | 15 namespace tracked_objects { |
| 14 | 16 |
| 15 class TrackedObjectsTest : public testing::Test { | 17 class TrackedObjectsTest : public testing::Test { |
| 16 public: | 18 public: |
| 17 MessageLoop message_loop_; | 19 |
|
ramant (doing other things)
2011/10/24 18:03:49
nit: lint was saying no extra space after public:
jar (doing other things)
2011/10/24 18:43:27
Removed references to message_loop (including head
| |
| 20 // MessageLoop message_loop_; | |
| 18 }; | 21 }; |
| 19 | 22 |
| 20 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { | 23 TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { |
| 21 // Minimal test doesn't even create any tasks. | 24 // Minimal test doesn't even create any tasks. |
| 22 if (!ThreadData::StartTracking(true)) | 25 if (!ThreadData::StartTracking(true)) |
| 23 return; | 26 return; |
| 24 | 27 |
| 25 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. | 28 EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. |
| 26 ThreadData* data = ThreadData::Get(); | 29 ThreadData* data = ThreadData::Get(); |
| 27 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 30 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 43 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. | 46 EXPECT_TRUE(ThreadData::first()); // Now class was constructed. |
| 44 EXPECT_TRUE(data); | 47 EXPECT_TRUE(data); |
| 45 EXPECT_TRUE(!data->next()); | 48 EXPECT_TRUE(!data->next()); |
| 46 EXPECT_EQ(data, ThreadData::Get()); | 49 EXPECT_EQ(data, ThreadData::Get()); |
| 47 birth_map.clear(); | 50 birth_map.clear(); |
| 48 data->SnapshotBirthMap(&birth_map); | 51 data->SnapshotBirthMap(&birth_map); |
| 49 EXPECT_EQ(0u, birth_map.size()); | 52 EXPECT_EQ(0u, birth_map.size()); |
| 50 death_map.clear(); | 53 death_map.clear(); |
| 51 data->SnapshotDeathMap(&death_map); | 54 data->SnapshotDeathMap(&death_map); |
| 52 EXPECT_EQ(0u, death_map.size()); | 55 EXPECT_EQ(0u, death_map.size()); |
| 56 | |
| 53 ThreadData::ShutdownSingleThreadedCleanup(); | 57 ThreadData::ShutdownSingleThreadedCleanup(); |
| 54 } | 58 } |
| 55 | 59 |
| 56 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { | 60 TEST_F(TrackedObjectsTest, TinyStartupShutdown) { |
| 57 if (!ThreadData::StartTracking(true)) | 61 if (!ThreadData::StartTracking(true)) |
| 58 return; | 62 return; |
| 59 | 63 |
| 60 // Instigate tracking on a single tracked object, or our thread. | 64 // Instigate tracking on a single tracked object, on our thread. |
| 61 const Location& location = FROM_HERE; | 65 const Location& location = FROM_HERE; |
| 62 ThreadData::TallyABirthIfActive(location); | 66 ThreadData::TallyABirthIfActive(location); |
| 63 | 67 |
| 64 const ThreadData* data = ThreadData::first(); | 68 const ThreadData* data = ThreadData::first(); |
| 65 ASSERT_TRUE(data); | 69 ASSERT_TRUE(data); |
| 66 EXPECT_TRUE(!data->next()); | 70 EXPECT_TRUE(!data->next()); |
| 67 EXPECT_EQ(data, ThreadData::Get()); | 71 EXPECT_EQ(data, ThreadData::Get()); |
| 68 ThreadData::BirthMap birth_map; | 72 ThreadData::BirthMap birth_map; |
| 69 data->SnapshotBirthMap(&birth_map); | 73 data->SnapshotBirthMap(&birth_map); |
| 70 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 74 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
| 71 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. | 75 EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. |
| 72 ThreadData::DeathMap death_map; | 76 ThreadData::DeathMap death_map; |
| 73 data->SnapshotDeathMap(&death_map); | 77 data->SnapshotDeathMap(&death_map); |
| 74 EXPECT_EQ(0u, death_map.size()); // No deaths. | 78 EXPECT_EQ(0u, death_map.size()); // No deaths. |
| 75 | 79 |
| 76 | 80 |
| 77 // Now instigate a birth, and a death. | 81 // Now instigate a birth, and a death. |
| 78 const Births* second_birth = ThreadData::TallyABirthIfActive(location); | 82 const Births* second_birth = ThreadData::TallyABirthIfActive(location); |
| 79 ThreadData::TallyADeathIfActive( | 83 ThreadData::TallyADeathIfActive( |
| 80 second_birth, | 84 second_birth, |
| 81 base::TimeTicks(), /* Bogus post_time. */ | 85 base::TimeTicks(), /* Bogus post_time. */ |
| 82 base::TimeTicks(), /* Bogus delayed_start_time. */ | 86 base::TimeTicks(), /* Bogus delayed_start_time. */ |
| 83 base::TimeTicks() /* Bogus start_run_time. */); | 87 base::TimeTicks(), /* Bogus start_run_time. */ |
| 88 base::TimeTicks() /* Bogus end_run_time */ ); | |
| 84 | 89 |
| 85 birth_map.clear(); | 90 birth_map.clear(); |
| 86 data->SnapshotBirthMap(&birth_map); | 91 data->SnapshotBirthMap(&birth_map); |
| 87 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. | 92 EXPECT_EQ(1u, birth_map.size()); // 1 birth location. |
| 88 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. | 93 EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. |
| 89 death_map.clear(); | 94 death_map.clear(); |
| 90 data->SnapshotDeathMap(&death_map); | 95 data->SnapshotDeathMap(&death_map); |
| 91 EXPECT_EQ(1u, death_map.size()); // 1 location. | 96 EXPECT_EQ(1u, death_map.size()); // 1 location. |
| 92 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. | 97 EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. |
| 93 | 98 |
| 94 // The births were at the same location as the one known death. | 99 // The births were at the same location as the one known death. |
| 95 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); | 100 EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); |
| 96 | 101 |
| 97 ThreadData::ShutdownSingleThreadedCleanup(); | 102 ThreadData::ShutdownSingleThreadedCleanup(); |
|
ramant (doing other things)
2011/10/24 18:03:49
nit: consider putting it in TearDown?
jar (doing other things)
2011/10/24 18:43:27
Done.
| |
| 98 } | 103 } |
| 99 | 104 |
| 105 TEST_F(TrackedObjectsTest, DeathDataTest) { | |
| 106 if (!ThreadData::StartTracking(true)) | |
| 107 return; | |
| 108 | |
| 109 scoped_ptr<DeathData> data(new DeathData()); | |
| 110 ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); | |
| 111 EXPECT_EQ(data->run_duration(), base::TimeDelta()); | |
| 112 EXPECT_EQ(data->queue_duration(), base::TimeDelta()); | |
| 113 EXPECT_EQ(data->AverageMsRunDuration(), 0); | |
| 114 EXPECT_EQ(data->AverageMsQueueDuration(), 0); | |
| 115 EXPECT_EQ(data->count(), 0); | |
| 116 | |
| 117 int run_ms = 42; | |
| 118 int queue_ms = 8; | |
| 119 | |
| 120 base::TimeDelta run_duration = base::TimeDelta().FromMilliseconds(run_ms); | |
| 121 base::TimeDelta queue_duration = base::TimeDelta().FromMilliseconds(queue_ms); | |
| 122 data->RecordDeath(queue_duration, run_duration); | |
| 123 EXPECT_EQ(data->run_duration(), run_duration); | |
| 124 EXPECT_EQ(data->queue_duration(), queue_duration); | |
| 125 EXPECT_EQ(data->AverageMsRunDuration(), run_ms); | |
| 126 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms); | |
| 127 EXPECT_EQ(data->count(), 1); | |
| 128 | |
| 129 data->RecordDeath(queue_duration, run_duration); | |
| 130 EXPECT_EQ(data->run_duration(), run_duration + run_duration); | |
| 131 EXPECT_EQ(data->queue_duration(), queue_duration + queue_duration); | |
| 132 EXPECT_EQ(data->AverageMsRunDuration(), run_ms); | |
| 133 EXPECT_EQ(data->AverageMsQueueDuration(), queue_ms); | |
| 134 EXPECT_EQ(data->count(), 2); | |
| 135 | |
| 136 scoped_ptr<base::DictionaryValue> dictionary(data->ToValue()); | |
| 137 int integer; | |
| 138 EXPECT_TRUE(dictionary->GetInteger("run_ms", &integer)); | |
| 139 EXPECT_EQ(integer, 2 * run_ms); | |
| 140 EXPECT_TRUE(dictionary->GetInteger("queue_ms", &integer)); | |
| 141 EXPECT_EQ(integer, 2* queue_ms); | |
| 142 EXPECT_TRUE(dictionary->GetInteger("count", &integer)); | |
| 143 EXPECT_EQ(integer, 2); | |
| 144 | |
| 145 std::string output; | |
| 146 data->WriteHTML(&output); | |
| 147 std::string results = "Lives:2, Run:84ms(42ms/life) Queue:16ms(8ms/life) "; | |
| 148 EXPECT_EQ(output, results); | |
| 149 | |
| 150 scoped_ptr<base::Value> value(data->ToValue()); | |
| 151 std::string json; | |
| 152 base::JSONWriter::Write(value.get(), false, &json); | |
| 153 std::string birth_only_result = "{\"count\":2,\"queue_ms\":16,\"run_ms\":84}"; | |
| 154 EXPECT_EQ(json, birth_only_result); | |
| 155 | |
| 156 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 157 } | |
| 158 | |
| 159 TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { | |
| 160 if (!ThreadData::StartTracking(true)) | |
| 161 return; | |
| 162 // We don't initialize system with a thread name, so we're viewed as a worker | |
| 163 // thread. | |
| 164 int fake_line_number = 173; | |
| 165 const char* kFile = "FixedFileName"; | |
| 166 const char* kFunction = "BirthOnlyToValueWorkerThread"; | |
| 167 Location location(kFunction, kFile, fake_line_number, NULL); | |
| 168 Births* birth = ThreadData::TallyABirthIfActive(location); | |
| 169 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
| 170 | |
| 171 int process_type = 3; | |
| 172 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
| 173 std::string json; | |
| 174 base::JSONWriter::Write(value.get(), false, &json); | |
| 175 std::string birth_only_result = "{" | |
| 176 "\"list\":[" | |
| 177 "{" | |
| 178 "\"birth_thread\":\"WorkerThread-1\"," | |
| 179 "\"death_data\":{" | |
| 180 "\"count\":1," | |
| 181 "\"queue_ms\":0," | |
| 182 "\"run_ms\":0" | |
| 183 "}," | |
| 184 "\"death_thread\":\"Still_Alive\"," | |
| 185 "\"location\":{" | |
| 186 "\"file_name\":\"FixedFileName\"," | |
| 187 "\"function_name\":\"BirthOnlyToValueWorkerThread\"," | |
| 188 "\"line_number\":173" | |
| 189 "}" | |
| 190 "}" | |
| 191 "]," | |
| 192 "\"process\":3" | |
| 193 "}"; | |
| 194 EXPECT_EQ(json, birth_only_result); | |
| 195 | |
| 196 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 197 } | |
| 198 | |
| 199 TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { | |
| 200 if (!ThreadData::StartTracking(true)) | |
| 201 return; | |
| 202 | |
| 203 // Use a well named thread. | |
| 204 ThreadData::InitializeThreadContext("SomeMainThreadName"); | |
| 205 int fake_line_number = 173; | |
| 206 const char* kFile = "FixedFileName"; | |
| 207 const char* kFunction = "BirthOnlyToValueMainThread"; | |
| 208 Location location(kFunction, kFile, fake_line_number, NULL); | |
| 209 // Do not delete birth. We don't own it. | |
| 210 Births* birth = ThreadData::TallyABirthIfActive(location); | |
| 211 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
| 212 | |
| 213 int process_type = 34; | |
| 214 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
| 215 std::string json; | |
| 216 base::JSONWriter::Write(value.get(), false, &json); | |
| 217 std::string birth_only_result = "{" | |
| 218 "\"list\":[" | |
| 219 "{" | |
| 220 "\"birth_thread\":\"SomeMainThreadName\"," | |
| 221 "\"death_data\":{" | |
| 222 "\"count\":1," | |
| 223 "\"queue_ms\":0," | |
| 224 "\"run_ms\":0" | |
| 225 "}," | |
| 226 "\"death_thread\":\"Still_Alive\"," | |
| 227 "\"location\":{" | |
| 228 "\"file_name\":\"FixedFileName\"," | |
| 229 "\"function_name\":\"BirthOnlyToValueMainThread\"," | |
| 230 "\"line_number\":173" | |
| 231 "}" | |
| 232 "}" | |
| 233 "]," | |
| 234 "\"process\":34" | |
| 235 "}"; | |
| 236 EXPECT_EQ(json, birth_only_result); | |
| 237 | |
| 238 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 239 } | |
| 240 | |
| 241 TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { | |
| 242 if (!ThreadData::StartTracking(true)) | |
| 243 return; | |
| 244 | |
| 245 // Use a well named thread. | |
| 246 ThreadData::InitializeThreadContext("SomeMainThreadName"); | |
| 247 int fake_line_number = 236; | |
| 248 const char* kFile = "FixedFileName"; | |
| 249 const char* kFunction = "LifeCycleToValueMainThread"; | |
| 250 Location location(kFunction, kFile, fake_line_number, NULL); | |
| 251 // Do not delete birth. We don't own it. | |
| 252 Births* birth = ThreadData::TallyABirthIfActive(location); | |
| 253 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
| 254 | |
| 255 // TimeTicks initializers ar ein microseconds. Durations are calculated in | |
| 256 // milliseconds, so we need to use 1000x. | |
| 257 const base::TimeTicks time_posted = base::TimeTicks() + | |
| 258 base::TimeDelta::FromMilliseconds(1); | |
| 259 const base::TimeTicks delayed_start_time = base::TimeTicks(); | |
| 260 const base::TimeTicks start_of_run = base::TimeTicks() + | |
| 261 base::TimeDelta::FromMilliseconds(5); | |
| 262 const base::TimeTicks end_of_run = base::TimeTicks() + | |
| 263 base::TimeDelta::FromMilliseconds(7); | |
| 264 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
| 265 start_of_run, end_of_run); | |
| 266 | |
| 267 int process_type = 7; | |
| 268 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
| 269 std::string json; | |
| 270 base::JSONWriter::Write(value.get(), false, &json); | |
| 271 std::string one_line_result = "{" | |
| 272 "\"list\":[" | |
| 273 "{" | |
| 274 "\"birth_thread\":\"SomeMainThreadName\"," | |
| 275 "\"death_data\":{" | |
| 276 "\"count\":1," | |
| 277 "\"queue_ms\":4," | |
| 278 "\"run_ms\":2" | |
| 279 "}," | |
| 280 "\"death_thread\":\"SomeMainThreadName\"," | |
| 281 "\"location\":{" | |
| 282 "\"file_name\":\"FixedFileName\"," | |
| 283 "\"function_name\":\"LifeCycleToValueMainThread\"," | |
| 284 "\"line_number\":236" | |
| 285 "}" | |
| 286 "}" | |
| 287 "]," | |
| 288 "\"process\":7" | |
| 289 "}"; | |
| 290 EXPECT_EQ(json, one_line_result); | |
| 291 | |
| 292 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 293 } | |
| 294 | |
| 295 TEST_F(TrackedObjectsTest, TwoLives) { | |
| 296 if (!ThreadData::StartTracking(true)) | |
| 297 return; | |
| 298 | |
| 299 // Use a well named thread. | |
| 300 ThreadData::InitializeThreadContext("SomeFileThreadName"); | |
| 301 int fake_line_number = 222; | |
| 302 const char* kFile = "AnotherFileName"; | |
| 303 const char* kFunction = "TwoLives"; | |
| 304 Location location(kFunction, kFile, fake_line_number, NULL); | |
| 305 // Do not delete birth. We don't own it. | |
| 306 Births* birth = ThreadData::TallyABirthIfActive(location); | |
| 307 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
| 308 | |
| 309 // TimeTicks initializers ar ein microseconds. Durations are calculated in | |
| 310 // milliseconds, so we need to use 1000x. | |
| 311 const base::TimeTicks time_posted = base::TimeTicks() + | |
| 312 base::TimeDelta::FromMilliseconds(1); | |
| 313 const base::TimeTicks delayed_start_time = base::TimeTicks(); | |
| 314 const base::TimeTicks start_of_run = base::TimeTicks() + | |
| 315 base::TimeDelta::FromMilliseconds(5); | |
| 316 const base::TimeTicks end_of_run = base::TimeTicks() + | |
| 317 base::TimeDelta::FromMilliseconds(7); | |
| 318 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
| 319 start_of_run, end_of_run); | |
| 320 | |
| 321 birth = ThreadData::TallyABirthIfActive(location); | |
| 322 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
| 323 start_of_run, end_of_run); | |
| 324 | |
| 325 int process_type = 7; | |
| 326 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
| 327 std::string json; | |
| 328 base::JSONWriter::Write(value.get(), false, &json); | |
| 329 std::string one_line_result = "{" | |
| 330 "\"list\":[" | |
| 331 "{" | |
| 332 "\"birth_thread\":\"SomeFileThreadName\"," | |
| 333 "\"death_data\":{" | |
| 334 "\"count\":2," | |
| 335 "\"queue_ms\":8," | |
| 336 "\"run_ms\":4" | |
| 337 "}," | |
| 338 "\"death_thread\":\"SomeFileThreadName\"," | |
| 339 "\"location\":{" | |
| 340 "\"file_name\":\"AnotherFileName\"," | |
| 341 "\"function_name\":\"TwoLives\"," | |
| 342 "\"line_number\":222" | |
| 343 "}" | |
| 344 "}" | |
| 345 "]," | |
| 346 "\"process\":7" | |
| 347 "}"; | |
| 348 EXPECT_EQ(json, one_line_result); | |
| 349 | |
| 350 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 351 } | |
| 352 | |
| 353 TEST_F(TrackedObjectsTest, DifferentLives) { | |
| 354 if (!ThreadData::StartTracking(true)) | |
| 355 return; | |
| 356 | |
| 357 // Use a well named thread. | |
| 358 ThreadData::InitializeThreadContext("SomeFileThreadName"); | |
| 359 int fake_line_number = 567; | |
| 360 const char* kFile = "AnotherFileName"; | |
| 361 const char* kFunction = "DifferentLives"; | |
| 362 Location location(kFunction, kFile, fake_line_number, NULL); | |
| 363 // Do not delete birth. We don't own it. | |
| 364 Births* birth = ThreadData::TallyABirthIfActive(location); | |
| 365 EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); | |
| 366 | |
| 367 // TimeTicks initializers ar ein microseconds. Durations are calculated in | |
| 368 // milliseconds, so we need to use 1000x. | |
| 369 const base::TimeTicks time_posted = base::TimeTicks() + | |
| 370 base::TimeDelta::FromMilliseconds(1); | |
| 371 const base::TimeTicks delayed_start_time = base::TimeTicks(); | |
| 372 const base::TimeTicks start_of_run = base::TimeTicks() + | |
| 373 base::TimeDelta::FromMilliseconds(5); | |
| 374 const base::TimeTicks end_of_run = base::TimeTicks() + | |
| 375 base::TimeDelta::FromMilliseconds(7); | |
| 376 ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, | |
| 377 start_of_run, end_of_run); | |
| 378 | |
| 379 int second_fake_line_number = 999; | |
| 380 Location second_location(kFunction, kFile, second_fake_line_number, NULL); | |
| 381 birth = ThreadData::TallyABirthIfActive(second_location); | |
| 382 | |
| 383 int process_type = 2; | |
| 384 scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); | |
| 385 std::string json; | |
| 386 base::JSONWriter::Write(value.get(), false, &json); | |
| 387 std::string one_line_result = "{" | |
| 388 "\"list\":[" | |
| 389 "{" | |
| 390 "\"birth_thread\":\"SomeFileThreadName\"," | |
| 391 "\"death_data\":{" | |
| 392 "\"count\":1," | |
| 393 "\"queue_ms\":4," | |
| 394 "\"run_ms\":2" | |
| 395 "}," | |
| 396 "\"death_thread\":\"SomeFileThreadName\"," | |
| 397 "\"location\":{" | |
| 398 "\"file_name\":\"AnotherFileName\"," | |
| 399 "\"function_name\":\"DifferentLives\"," | |
| 400 "\"line_number\":567" | |
| 401 "}" | |
| 402 "}," | |
| 403 "{" | |
| 404 "\"birth_thread\":\"SomeFileThreadName\"," | |
| 405 "\"death_data\":{" | |
| 406 "\"count\":1," | |
| 407 "\"queue_ms\":0," | |
| 408 "\"run_ms\":0" | |
| 409 "}," | |
| 410 "\"death_thread\":\"Still_Alive\"," | |
| 411 "\"location\":{" | |
| 412 "\"file_name\":\"AnotherFileName\"," | |
| 413 "\"function_name\":\"DifferentLives\"," | |
| 414 "\"line_number\":999" | |
| 415 "}" | |
| 416 "}" | |
| 417 "]," | |
| 418 "\"process\":2" | |
| 419 "}"; | |
| 420 EXPECT_EQ(json, one_line_result); | |
| 421 | |
| 422 ThreadData::ShutdownSingleThreadedCleanup(); | |
| 423 } | |
| 424 | |
| 100 } // namespace tracked_objects | 425 } // namespace tracked_objects |
| OLD | NEW |