1 /*
2 * Copyright (C) 2021 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 "odr_metrics_record.h"
18
19 #include <string.h>
20
21 #include <fstream>
22
23 #include "android-base/result-gmock.h"
24 #include "android-base/stringprintf.h"
25 #include "base/common_art_test.h"
26
27 namespace art {
28 namespace odrefresh {
29
30 class OdrMetricsRecordTest : public CommonArtTest {
31 protected:
WriteFile()32 void WriteFile() {
33 std::ofstream ofs(file_path_);
34
35 ofs << "<odrefresh_metrics>";
36 ofs << metrics_version_;
37 ofs << "<art_apex_version>81966764218039518</art_apex_version>";
38 ofs << "<trigger>16909060</trigger>";
39 ofs << "<stage_reached>286397204</stage_reached>";
40 ofs << status_;
41 ofs << "<cache_space_free_start_mib>1633837924</cache_space_free_start_mib>";
42 ofs << "<cache_space_free_end_mib>1903326068</cache_space_free_end_mib>";
43 ofs << "<primary_bcp_compilation_millis>825373492</primary_bcp_compilation_millis>";
44 ofs << "<secondary_bcp_compilation_millis>1094861636</secondary_bcp_compilation_millis>";
45 ofs << "<system_server_compilation_millis>1364349780</system_server_compilation_millis>";
46 ofs << primary_bcp_dex2oat_result_;
47 ofs << secondary_bcp_dex2oat_result_;
48 ofs << system_server_dex2oat_result_;
49 ofs << "</odrefresh_metrics>";
50
51 ofs.close();
52 }
53
SetUp()54 void SetUp() override {
55 CommonArtTest::SetUp();
56 scratch_dir_ = std::make_unique<ScratchDir>(/*keep_files=*/false);
57 file_path_ = scratch_dir_->GetPath() + "/metrics-record.xml";
58 }
59
TearDown()60 void TearDown() override { scratch_dir_.reset(); }
61
62 std::unique_ptr<ScratchDir> scratch_dir_;
63 std::string file_path_;
64 std::string metrics_version_ = android::base::StringPrintf(
65 "<odrefresh_metrics_version>%d</odrefresh_metrics_version>", kOdrefreshMetricsVersion);
66 std::string status_ = "<status>30</status>";
67 std::string primary_bcp_dex2oat_result_ =
68 R"(<primary_bcp_dex2oat_result status="1" exit-code="-1" signal="0" />)";
69 std::string secondary_bcp_dex2oat_result_ =
70 R"(<secondary_bcp_dex2oat_result status="2" exit-code="15" signal="0" />)";
71 std::string system_server_dex2oat_result_ =
72 R"(<system_server_dex2oat_result status="3" exit-code="-1" signal="9" />)";
73 };
74
75 using android::base::testing::HasError;
76 using android::base::testing::Ok;
77 using android::base::testing::WithMessage;
78
TEST_F(OdrMetricsRecordTest,HappyPath)79 TEST_F(OdrMetricsRecordTest, HappyPath) {
80 OdrMetricsRecord expected{};
81 expected.odrefresh_metrics_version = art::odrefresh::kOdrefreshMetricsVersion;
82 expected.art_apex_version = 0x01233456'789abcde;
83 expected.trigger = 0x01020304;
84 expected.stage_reached = 0x11121314;
85 expected.status = 0x21222324;
86 expected.cache_space_free_start_mib = 0x61626364;
87 expected.cache_space_free_end_mib = 0x71727374;
88 expected.primary_bcp_compilation_millis = 0x31323334;
89 expected.secondary_bcp_compilation_millis = 0x41424344;
90 expected.system_server_compilation_millis = 0x51525354;
91 expected.primary_bcp_dex2oat_result = OdrMetricsRecord::Dex2OatExecResult(1, -1, 0);
92 expected.secondary_bcp_dex2oat_result = OdrMetricsRecord::Dex2OatExecResult(2, 15, 0);
93 expected.system_server_dex2oat_result = OdrMetricsRecord::Dex2OatExecResult(3, -1, 9);
94 expected.primary_bcp_compilation_type = 0x82837192;
95 expected.secondary_bcp_compilation_type = 0x91827312;
96
97 ASSERT_THAT(expected.WriteToFile(file_path_), Ok());
98
99 OdrMetricsRecord actual{};
100 ASSERT_THAT(actual.ReadFromFile(file_path_), Ok());
101
102 ASSERT_EQ(expected.odrefresh_metrics_version, actual.odrefresh_metrics_version);
103 ASSERT_EQ(expected.art_apex_version, actual.art_apex_version);
104 ASSERT_EQ(expected.trigger, actual.trigger);
105 ASSERT_EQ(expected.stage_reached, actual.stage_reached);
106 ASSERT_EQ(expected.status, actual.status);
107 ASSERT_EQ(expected.cache_space_free_start_mib, actual.cache_space_free_start_mib);
108 ASSERT_EQ(expected.cache_space_free_end_mib, actual.cache_space_free_end_mib);
109 ASSERT_EQ(expected.primary_bcp_compilation_millis, actual.primary_bcp_compilation_millis);
110 ASSERT_EQ(expected.secondary_bcp_compilation_millis, actual.secondary_bcp_compilation_millis);
111 ASSERT_EQ(expected.system_server_compilation_millis, actual.system_server_compilation_millis);
112 ASSERT_EQ(expected.primary_bcp_dex2oat_result.status, actual.primary_bcp_dex2oat_result.status);
113 ASSERT_EQ(expected.primary_bcp_dex2oat_result.exit_code,
114 actual.primary_bcp_dex2oat_result.exit_code);
115 ASSERT_EQ(expected.primary_bcp_dex2oat_result.signal, actual.primary_bcp_dex2oat_result.signal);
116 ASSERT_EQ(expected.secondary_bcp_dex2oat_result.status,
117 actual.secondary_bcp_dex2oat_result.status);
118 ASSERT_EQ(expected.secondary_bcp_dex2oat_result.exit_code,
119 actual.secondary_bcp_dex2oat_result.exit_code);
120 ASSERT_EQ(expected.secondary_bcp_dex2oat_result.signal,
121 actual.secondary_bcp_dex2oat_result.signal);
122 ASSERT_EQ(expected.system_server_dex2oat_result.status,
123 actual.system_server_dex2oat_result.status);
124 ASSERT_EQ(expected.system_server_dex2oat_result.exit_code,
125 actual.system_server_dex2oat_result.exit_code);
126 ASSERT_EQ(expected.system_server_dex2oat_result.signal,
127 actual.system_server_dex2oat_result.signal);
128 ASSERT_EQ(expected.primary_bcp_compilation_type, actual.primary_bcp_compilation_type);
129 ASSERT_EQ(expected.secondary_bcp_compilation_type, actual.secondary_bcp_compilation_type);
130 ASSERT_EQ(0, memcmp(&expected, &actual, sizeof(expected)));
131 }
132
TEST_F(OdrMetricsRecordTest,EmptyInput)133 TEST_F(OdrMetricsRecordTest, EmptyInput) {
134 OdrMetricsRecord record{};
135 ASSERT_THAT(record.ReadFromFile(file_path_), testing::Not(Ok()));
136 }
137
TEST_F(OdrMetricsRecordTest,UnexpectedInput)138 TEST_F(OdrMetricsRecordTest, UnexpectedInput) {
139 std::ofstream ofs(file_path_);
140 ofs << "<not_odrefresh_metrics></not_odrefresh_metrics>";
141 ofs.close();
142
143 OdrMetricsRecord record{};
144 ASSERT_THAT(record.ReadFromFile(file_path_),
145 HasError(WithMessage("odrefresh_metrics element not found in " + file_path_)));
146 }
147
TEST_F(OdrMetricsRecordTest,ExpectedElementNotFound)148 TEST_F(OdrMetricsRecordTest, ExpectedElementNotFound) {
149 metrics_version_ = "<not_valid_metric>25</not_valid_metric>";
150 WriteFile();
151
152 OdrMetricsRecord record{};
153 ASSERT_THAT(
154 record.ReadFromFile(file_path_),
155 HasError(WithMessage("Expected Odrefresh metric odrefresh_metrics_version not found")));
156 }
157
TEST_F(OdrMetricsRecordTest,ExpectedAttributeNotFound)158 TEST_F(OdrMetricsRecordTest, ExpectedAttributeNotFound) {
159 // Missing "status".
160 primary_bcp_dex2oat_result_ = R"(<primary_bcp_dex2oat_result exit-code="17" signal="18" />)";
161 WriteFile();
162
163 OdrMetricsRecord record{};
164 ASSERT_THAT(record.ReadFromFile(file_path_),
165 HasError(WithMessage(
166 "Expected Odrefresh metric primary_bcp_dex2oat_result.status is not an int32")));
167 }
168
TEST_F(OdrMetricsRecordTest,UnexpectedOdrefreshMetricsVersion)169 TEST_F(OdrMetricsRecordTest, UnexpectedOdrefreshMetricsVersion) {
170 metrics_version_ = "<odrefresh_metrics_version>0</odrefresh_metrics_version>";
171 WriteFile();
172
173 OdrMetricsRecord record{};
174 std::string expected_error = android::base::StringPrintf(
175 "odrefresh_metrics_version 0 is different than expected (%d)", kOdrefreshMetricsVersion);
176 ASSERT_THAT(record.ReadFromFile(file_path_), HasError(WithMessage(expected_error)));
177 }
178
TEST_F(OdrMetricsRecordTest,UnexpectedType)179 TEST_F(OdrMetricsRecordTest, UnexpectedType) {
180 status_ = "<status>abcd</status>"; // It should be an int32.
181 WriteFile();
182
183 OdrMetricsRecord record{};
184 ASSERT_THAT(record.ReadFromFile(file_path_),
185 HasError(WithMessage("Odrefresh metric status is not an int32")));
186 }
187
TEST_F(OdrMetricsRecordTest,ResultStatusOutsideOfRange)188 TEST_F(OdrMetricsRecordTest, ResultStatusOutsideOfRange) {
189 // Status is valid between 0 and 5 (5 being NOT_RUN)
190 primary_bcp_dex2oat_result_ =
191 R"(<primary_bcp_dex2oat_result status="-1" exit-code="-1" signal="0" />)";
192 WriteFile();
193
194 OdrMetricsRecord record{};
195 ASSERT_THAT(
196 record.ReadFromFile(file_path_),
197 HasError(WithMessage("Odrefresh metric primary_bcp_dex2oat_result.status has a value (-1) "
198 "outside of the expected range ([0, 5])")));
199
200 primary_bcp_dex2oat_result_ =
201 R"(<primary_bcp_dex2oat_result status="9" exit-code="-1" signal="0" />)";
202 WriteFile();
203
204 ASSERT_THAT(
205 record.ReadFromFile(file_path_),
206 HasError(WithMessage("Odrefresh metric primary_bcp_dex2oat_result.status has a value (9) "
207 "outside of the expected range ([0, 5])")));
208 }
209
TEST_F(OdrMetricsRecordTest,ResultExitCodeOutsideOfRange)210 TEST_F(OdrMetricsRecordTest, ResultExitCodeOutsideOfRange) {
211 // Exit Code is valid between -1 and 255
212 secondary_bcp_dex2oat_result_ =
213 R"(<secondary_bcp_dex2oat_result status="2" exit-code="-2" signal="0" />)";
214 WriteFile();
215
216 OdrMetricsRecord record{};
217 ASSERT_THAT(record.ReadFromFile(file_path_),
218 HasError(WithMessage(
219 "Odrefresh metric secondary_bcp_dex2oat_result.exit-code has a value (-2) "
220 "outside of the expected range ([-1, 255])")));
221
222 secondary_bcp_dex2oat_result_ =
223 R"(<secondary_bcp_dex2oat_result status="2" exit-code="258" signal="0" />)";
224 WriteFile();
225
226 ASSERT_THAT(record.ReadFromFile(file_path_),
227 HasError(WithMessage(
228 "Odrefresh metric secondary_bcp_dex2oat_result.exit-code has a value (258) "
229 "outside of the expected range ([-1, 255])")));
230 }
231
TEST_F(OdrMetricsRecordTest,ResultSignalOutsideOfRange)232 TEST_F(OdrMetricsRecordTest, ResultSignalOutsideOfRange) {
233 // Signal is valid between 0 and SIGRTMAX
234 system_server_dex2oat_result_ =
235 R"(<system_server_dex2oat_result status="3" exit-code="0" signal="-6" />)";
236 WriteFile();
237
238 OdrMetricsRecord record{};
239 ASSERT_THAT(record.ReadFromFile(file_path_),
240 HasError(WithMessage(android::base::StringPrintf(
241 "Odrefresh metric system_server_dex2oat_result.signal has a value (-6) "
242 "outside of the expected range ([0, %d])",
243 SIGRTMAX))));
244
245 system_server_dex2oat_result_ =
246 R"(<system_server_dex2oat_result status="3" exit-code="0" signal="65" />)";
247 WriteFile();
248
249 ASSERT_THAT(record.ReadFromFile(file_path_),
250 HasError(WithMessage(android::base::StringPrintf(
251 "Odrefresh metric system_server_dex2oat_result.signal has a value (65) "
252 "outside of the expected range ([0, %d])",
253 SIGRTMAX))));
254 }
255
256 } // namespace odrefresh
257 } // namespace art
258