Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "base/test/launcher/test_results_tracker.h" | 5 #include "base/test/launcher/test_results_tracker.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 "had unknown result"); | 294 "had unknown result"); |
| 295 | 295 |
| 296 fprintf(stdout, "End of the summary.\n"); | 296 fprintf(stdout, "End of the summary.\n"); |
| 297 fflush(stdout); | 297 fflush(stdout); |
| 298 } | 298 } |
| 299 | 299 |
| 300 void TestResultsTracker::AddGlobalTag(const std::string& tag) { | 300 void TestResultsTracker::AddGlobalTag(const std::string& tag) { |
| 301 global_tags_.insert(tag); | 301 global_tags_.insert(tag); |
| 302 } | 302 } |
| 303 | 303 |
| 304 // Sets output_snippet-related fields in test_result_value. | |
| 305 // Does not take ownership of test_result_value. | |
| 306 // Returns the number of bytes of snippet data that were added to | |
| 307 // test_result_value. | |
| 308 int SetSnippets(StringPiece output_snippet, | |
| 309 DictionaryValue* test_result_value) { | |
| 310 int num_bytes = 0; | |
| 311 // Always include the raw version (base64-encoded so that it can be safely | |
| 312 // JSON-serialized - there are no guarantees about character encoding of the | |
| 313 // snippet). This can be very useful piece of information when debugging a | |
| 314 // test failure related to character encoding. | |
| 315 std::string base64; | |
| 316 Base64Encode(output_snippet, &base64); | |
| 317 test_result_value->SetString("output_snippet_base64", base64); | |
| 318 num_bytes += base64.size(); | |
| 319 | |
| 320 bool lossless_snippet = false; | |
| 321 if (IsStringUTF8(output_snippet)) { | |
| 322 lossless_snippet = true; | |
| 323 } else { | |
| 324 output_snippet = "<non-UTF-8 snippet, see output_snippet_base64>"; | |
| 325 } | |
| 326 | |
| 327 test_result_value->SetString("output_snippet", output_snippet); | |
| 328 num_bytes += output_snippet.size(); | |
| 329 | |
| 330 // TODO(phajdan.jr): Fix typo in JSON key (losless -> lossless) | |
| 331 // making sure not to break any consumers of this data. | |
| 332 test_result_value->SetBoolean("losless_snippet", lossless_snippet); | |
| 333 | |
| 334 return num_bytes; | |
| 335 } | |
| 336 | |
| 337 // This is the maximum output.json which can be handled by | |
| 338 // build/scripts/slave/recipe_modules/swarming/resources/collect_gtest_task.py | |
| 339 // SaveSummaryAsJSON does not strictly ensure that its output is below this | |
| 340 // threshold, but it will attempt to avoid exceeding this maximum by dropping | |
| 341 // output_snippets as the total output approaches this threshold. | |
| 342 const int kMaxSummaryJSON = 100 * 1024 * 1024; | |
| 343 | |
| 304 bool TestResultsTracker::SaveSummaryAsJSON( | 344 bool TestResultsTracker::SaveSummaryAsJSON( |
| 305 const FilePath& path, | 345 const FilePath& path, |
| 306 const std::vector<std::string>& additional_tags) const { | 346 const std::vector<std::string>& additional_tags) const { |
| 307 std::unique_ptr<DictionaryValue> summary_root(new DictionaryValue); | 347 std::unique_ptr<DictionaryValue> summary_root(new DictionaryValue); |
| 308 | 348 |
| 309 std::unique_ptr<ListValue> global_tags(new ListValue); | 349 std::unique_ptr<ListValue> global_tags(new ListValue); |
| 310 for (const auto& global_tag : global_tags_) { | 350 for (const auto& global_tag : global_tags_) { |
| 311 global_tags->AppendString(global_tag); | 351 global_tags->AppendString(global_tag); |
| 312 } | 352 } |
| 313 for (const auto& tag : additional_tags) { | 353 for (const auto& tag : additional_tags) { |
| 314 global_tags->AppendString(tag); | 354 global_tags->AppendString(tag); |
| 315 } | 355 } |
| 316 summary_root->Set("global_tags", std::move(global_tags)); | 356 summary_root->Set("global_tags", std::move(global_tags)); |
| 317 | 357 |
| 318 std::unique_ptr<ListValue> all_tests(new ListValue); | 358 std::unique_ptr<ListValue> all_tests(new ListValue); |
| 319 for (const auto& test : all_tests_) { | 359 for (const auto& test : all_tests_) { |
| 320 all_tests->AppendString(test); | 360 all_tests->AppendString(test); |
| 321 } | 361 } |
| 322 summary_root->Set("all_tests", std::move(all_tests)); | 362 summary_root->Set("all_tests", std::move(all_tests)); |
| 323 | 363 |
| 324 std::unique_ptr<ListValue> disabled_tests(new ListValue); | 364 std::unique_ptr<ListValue> disabled_tests(new ListValue); |
| 325 for (const auto& disabled_test : disabled_tests_) { | 365 for (const auto& disabled_test : disabled_tests_) { |
| 326 disabled_tests->AppendString(disabled_test); | 366 disabled_tests->AppendString(disabled_test); |
| 327 } | 367 } |
| 328 summary_root->Set("disabled_tests", std::move(disabled_tests)); | 368 summary_root->Set("disabled_tests", std::move(disabled_tests)); |
| 329 | 369 |
| 330 std::unique_ptr<ListValue> per_iteration_data(new ListValue); | 370 std::unique_ptr<ListValue> per_iteration_data(new ListValue); |
| 331 | 371 |
| 372 // Keep track of the number of bytes used by the contents of output snippets. | |
| 373 // Once we use up half of the maxium output size, we will start dropping | |
| 374 // snippets. | |
| 375 int snippet_bytes = 0; | |
| 376 int snippet_byte_threshold = kMaxSummaryJSON / 2; | |
| 377 | |
| 332 for (int i = 0; i <= iteration_; i++) { | 378 for (int i = 0; i <= iteration_; i++) { |
| 333 std::unique_ptr<DictionaryValue> current_iteration_data( | 379 std::unique_ptr<DictionaryValue> current_iteration_data( |
| 334 new DictionaryValue); | 380 new DictionaryValue); |
| 335 | 381 |
| 336 for (PerIterationData::ResultsMap::const_iterator j = | 382 for (PerIterationData::ResultsMap::const_iterator j = |
| 337 per_iteration_data_[i].results.begin(); | 383 per_iteration_data_[i].results.begin(); |
| 338 j != per_iteration_data_[i].results.end(); | 384 j != per_iteration_data_[i].results.end(); |
| 339 ++j) { | 385 ++j) { |
| 340 std::unique_ptr<ListValue> test_results(new ListValue); | 386 std::unique_ptr<ListValue> test_results(new ListValue); |
| 341 | 387 |
| 342 for (size_t k = 0; k < j->second.test_results.size(); k++) { | 388 for (size_t k = 0; k < j->second.test_results.size(); k++) { |
| 343 const TestResult& test_result = j->second.test_results[k]; | 389 const TestResult& test_result = j->second.test_results[k]; |
| 344 | 390 |
| 345 std::unique_ptr<DictionaryValue> test_result_value(new DictionaryValue); | 391 std::unique_ptr<DictionaryValue> test_result_value(new DictionaryValue); |
| 346 | 392 |
| 347 test_result_value->SetString("status", test_result.StatusAsString()); | 393 test_result_value->SetString("status", test_result.StatusAsString()); |
| 348 test_result_value->SetInteger( | 394 test_result_value->SetInteger( |
| 349 "elapsed_time_ms", | 395 "elapsed_time_ms", |
| 350 static_cast<int>(test_result.elapsed_time.InMilliseconds())); | 396 static_cast<int>(test_result.elapsed_time.InMilliseconds())); |
| 351 | 397 |
| 352 bool lossless_snippet = false; | 398 StringPiece snippet = snippet_bytes > snippet_byte_threshold |
| 353 if (IsStringUTF8(test_result.output_snippet)) { | 399 ? "lengthy output elided" |
|
Paweł Hajdan Jr.
2016/12/22 14:18:39
I'm concerned this seems to result in a silent fai
| |
| 354 test_result_value->SetString( | 400 : test_result.output_snippet; |
| 355 "output_snippet", test_result.output_snippet); | 401 snippet_bytes += SetSnippets(snippet, test_result_value.get()); |
| 356 lossless_snippet = true; | |
| 357 } else { | |
| 358 test_result_value->SetString( | |
| 359 "output_snippet", | |
| 360 "<non-UTF-8 snippet, see output_snippet_base64>"); | |
| 361 } | |
| 362 | 402 |
| 363 // TODO(phajdan.jr): Fix typo in JSON key (losless -> lossless) | |
| 364 // making sure not to break any consumers of this data. | |
| 365 test_result_value->SetBoolean("losless_snippet", lossless_snippet); | |
| 366 | |
| 367 // Also include the raw version (base64-encoded so that it can be safely | |
| 368 // JSON-serialized - there are no guarantees about character encoding | |
| 369 // of the snippet). This can be very useful piece of information when | |
| 370 // debugging a test failure related to character encoding. | |
| 371 std::string base64_output_snippet; | |
| 372 Base64Encode(test_result.output_snippet, &base64_output_snippet); | |
| 373 test_result_value->SetString("output_snippet_base64", | |
| 374 base64_output_snippet); | |
| 375 test_results->Append(std::move(test_result_value)); | 403 test_results->Append(std::move(test_result_value)); |
| 376 } | 404 } |
| 377 | 405 |
| 378 current_iteration_data->SetWithoutPathExpansion(j->first, | 406 current_iteration_data->SetWithoutPathExpansion(j->first, |
| 379 std::move(test_results)); | 407 std::move(test_results)); |
| 380 } | 408 } |
| 381 per_iteration_data->Append(std::move(current_iteration_data)); | 409 per_iteration_data->Append(std::move(current_iteration_data)); |
| 382 } | 410 } |
| 383 summary_root->Set("per_iteration_data", std::move(per_iteration_data)); | 411 summary_root->Set("per_iteration_data", std::move(per_iteration_data)); |
| 384 | 412 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 TestResultsTracker::PerIterationData::PerIterationData() { | 491 TestResultsTracker::PerIterationData::PerIterationData() { |
| 464 } | 492 } |
| 465 | 493 |
| 466 TestResultsTracker::PerIterationData::PerIterationData( | 494 TestResultsTracker::PerIterationData::PerIterationData( |
| 467 const PerIterationData& other) = default; | 495 const PerIterationData& other) = default; |
| 468 | 496 |
| 469 TestResultsTracker::PerIterationData::~PerIterationData() { | 497 TestResultsTracker::PerIterationData::~PerIterationData() { |
| 470 } | 498 } |
| 471 | 499 |
| 472 } // namespace base | 500 } // namespace base |
| OLD | NEW |