luci_test_result_unittest.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "testing/perf/luci_test_result.h"
  5. #include "base/files/file_path.h"
  6. #include "base/files/file_util.h"
  7. #include "base/files/scoped_temp_dir.h"
  8. #include "base/json/json_reader.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "base/time/time.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. namespace perf_test {
  14. class LuciTestResultTest : public testing::Test {
  15. public:
  16. LuciTestResultTest() = default;
  17. LuciTestResultTest(const LuciTestResultTest&) = delete;
  18. LuciTestResultTest& operator=(const LuciTestResultTest&) = delete;
  19. ~LuciTestResultTest() override = default;
  20. // testing::Test:
  21. void SetUp() override {
  22. testing::Test::SetUp();
  23. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  24. }
  25. base::FilePath GetResultFilePath() const {
  26. return temp_dir_.GetPath().AppendASCII("luci_test_results.json");
  27. }
  28. // Validates that |result| is written to file that contains an equivalent JSON
  29. // as |expected_json|.
  30. void ValidateResult(const LuciTestResult& result,
  31. const std::string& expected_json) {
  32. const base::FilePath result_file = GetResultFilePath();
  33. result.WriteToFile(result_file);
  34. std::string json;
  35. ASSERT_TRUE(ReadFileToString(GetResultFilePath(), &json));
  36. absl::optional<base::Value> value = base::JSONReader::Read(json);
  37. ASSERT_TRUE(value.has_value());
  38. absl::optional<base::Value> expected_value =
  39. base::JSONReader::Read(expected_json);
  40. ASSERT_TRUE(expected_value.has_value());
  41. EXPECT_EQ(expected_value, value) << "Expected:\n====\n"
  42. << expected_json << "\nActual:\n====\n"
  43. << json;
  44. }
  45. private:
  46. base::ScopedTempDir temp_dir_;
  47. };
  48. TEST_F(LuciTestResultTest, Basic) {
  49. LuciTestResult result;
  50. result.set_test_path("FakeTestSuite.FakeTest");
  51. result.set_status(LuciTestResult::Status::kPass);
  52. result.set_is_expected(true);
  53. result.AddVariant("variantKey", "variantValue");
  54. result.AddVariant("param/instantiation", "FooType");
  55. result.AddVariant("param/index", "0");
  56. // 2019/9/11 12:30 UTC
  57. base::Time start_time;
  58. ASSERT_TRUE(
  59. base::Time::FromUTCExploded({2019, 9, 3, 11, 12, 30, 0}, &start_time));
  60. result.set_start_time(start_time);
  61. result.set_duration(base::Milliseconds(1500));
  62. result.AddOutputArtifactContents("plain", "plain data", "text/plain");
  63. result.AddOutputArtifactContents("new_line", "first\nsecond", "text/plain");
  64. result.AddOutputArtifactFile(
  65. "file.json", base::FilePath(FILE_PATH_LITERAL("/tmp/file.json")),
  66. "application/json");
  67. result.AddTag("tbmv2", "umaMetric");
  68. const std::string expected_json =
  69. R"({
  70. "testResult":{
  71. "outputArtifacts":{
  72. "file.json":{
  73. "contentType":"application/json",
  74. "filePath":"/tmp/file.json"
  75. },
  76. "new_line":{
  77. "contentType":"text/plain",
  78. "contents":"first\nsecond"
  79. },
  80. "plain":{
  81. "contentType":"text/plain",
  82. "contents":"plain data"
  83. }
  84. },
  85. "expected":true,
  86. "runDuration":"1.50s",
  87. "startTime":"2019-09-11T12:30:00.000Z",
  88. "status":"PASS",
  89. "tags":[
  90. {"key":"tbmv2","value":"umaMetric"}
  91. ],
  92. "variant":{
  93. "variantKey": "variantValue",
  94. "param/instantiation": "FooType",
  95. "param/index": "0"
  96. },
  97. "testPath":"FakeTestSuite.FakeTest"
  98. }
  99. })";
  100. ValidateResult(result, expected_json);
  101. }
  102. TEST_F(LuciTestResultTest, Status) {
  103. using Status = LuciTestResult::Status;
  104. LuciTestResult result;
  105. result.set_test_path("FakeTestSuite.Status");
  106. const std::string json_template =
  107. R"({
  108. "testResult":{
  109. "expected":false,
  110. "status":"%s",
  111. "testPath":"FakeTestSuite.Status"
  112. }
  113. })";
  114. const struct {
  115. Status status;
  116. const char* status_text;
  117. } kTestCases[] = {
  118. {Status::kUnspecified, "UNSPECIFIED"},
  119. {Status::kPass, "PASS"},
  120. {Status::kFail, "FAIL"},
  121. {Status::kCrash, "CRASH"},
  122. {Status::kAbort, "ABORT"},
  123. {Status::kSkip, "SKIP"},
  124. };
  125. for (const auto& test_case : kTestCases) {
  126. result.set_status(test_case.status);
  127. const std::string expected_json =
  128. base::StringPrintf(json_template.c_str(), test_case.status_text);
  129. ValidateResult(result, expected_json);
  130. }
  131. }
  132. ///////////////////////////////////////////////////////////////////////////////
  133. class LuciTestResultParameterizedTest
  134. : public LuciTestResultTest,
  135. public testing::WithParamInterface<int> {
  136. public:
  137. LuciTestResultParameterizedTest() = default;
  138. ~LuciTestResultParameterizedTest() override = default;
  139. };
  140. TEST_P(LuciTestResultParameterizedTest, Variant) {
  141. LuciTestResult result = LuciTestResult::CreateForGTest();
  142. // 2019/9/11 12:30 UTC
  143. base::Time start_time;
  144. ASSERT_TRUE(
  145. base::Time::FromUTCExploded({2019, 9, 3, 11, 12, 30, 0}, &start_time));
  146. result.set_start_time(start_time);
  147. result.set_duration(base::Milliseconds(1500));
  148. const std::string json_template =
  149. R"({
  150. "testResult":{
  151. "expected":true,
  152. "runDuration":"1.50s",
  153. "startTime":"2019-09-11T12:30:00.000Z",
  154. "status":"PASS",
  155. "testPath":
  156. "ZeroToFiveSequence/LuciTestResultParameterizedTest.Variant",
  157. "variant":{"param/index":"%d"}
  158. }
  159. })";
  160. const std::string expected_json =
  161. base::StringPrintf(json_template.c_str(), GetParam());
  162. ValidateResult(result, expected_json);
  163. }
  164. INSTANTIATE_TEST_SUITE_P(ZeroToFiveSequence,
  165. LuciTestResultParameterizedTest,
  166. testing::Range(0, 5));
  167. ///////////////////////////////////////////////////////////////////////////////
  168. template <typename T>
  169. class LuciTestResultTypedTest : public LuciTestResultTest {
  170. public:
  171. LuciTestResultTypedTest() = default;
  172. ~LuciTestResultTypedTest() override = default;
  173. };
  174. TYPED_TEST_SUITE_P(LuciTestResultTypedTest);
  175. TYPED_TEST_P(LuciTestResultTypedTest, Variant) {
  176. LuciTestResult result = LuciTestResult::CreateForGTest();
  177. // 2019/9/11 12:30 UTC
  178. base::Time start_time;
  179. ASSERT_TRUE(
  180. base::Time::FromUTCExploded({2019, 9, 3, 11, 12, 30, 0}, &start_time));
  181. result.set_start_time(start_time);
  182. result.set_duration(base::Milliseconds(1500));
  183. std::string test_suite_name =
  184. testing::UnitTest::GetInstance()->current_test_info()->test_suite_name();
  185. auto pos = test_suite_name.rfind('/');
  186. ASSERT_NE(pos, std::string::npos);
  187. std::string type_param_name = test_suite_name.substr(pos + 1);
  188. const std::string json_template =
  189. R"({
  190. "testResult":{
  191. "expected":true,
  192. "runDuration":"1.50s",
  193. "startTime":"2019-09-11T12:30:00.000Z",
  194. "status":"PASS",
  195. "testPath":"SomeTypes/LuciTestResultTypedTest/%s.Variant",
  196. "variant":{"param/instantiation":"%s"}
  197. }
  198. })";
  199. // Note that chromium has RTTI disabled. As a result, type_param() and
  200. // GetTypeName<> always returns a generic "<type>".
  201. const std::string expected_json =
  202. base::StringPrintf(json_template.c_str(), type_param_name.c_str(),
  203. testing::internal::GetTypeName<TypeParam>().c_str());
  204. this->ValidateResult(result, expected_json);
  205. }
  206. REGISTER_TYPED_TEST_SUITE_P(LuciTestResultTypedTest, Variant);
  207. using SomeTypes = testing::Types<int, double>;
  208. INSTANTIATE_TYPED_TEST_SUITE_P(SomeTypes, LuciTestResultTypedTest, SomeTypes);
  209. } // namespace perf_test