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.h"
18
19 #include <unistd.h>
20
21 #include <chrono>
22 #include <cstdint>
23 #include <fstream>
24 #include <memory>
25 #include <string>
26 #include <thread>
27
28 #include "base/casts.h"
29 #include "base/common_art_test.h"
30 #include "odr_metrics_record.h"
31
32 namespace art {
33 namespace odrefresh {
34
35 using std::chrono_literals::operator""ms; // NOLINT
36
37 class OdrMetricsTest : public CommonArtTest {
38 public:
SetUp()39 void SetUp() override {
40 CommonArtTest::SetUp();
41
42 scratch_dir_ = std::make_unique<ScratchDir>();
43 metrics_file_path_ = scratch_dir_->GetPath() + "/metrics.xml";
44 cache_directory_ = scratch_dir_->GetPath() + "/dir";
45 mkdir(cache_directory_.c_str(), S_IRWXU);
46 }
47
TearDown()48 void TearDown() override {
49 scratch_dir_.reset();
50 }
51
MetricsFileExists() const52 bool MetricsFileExists() const {
53 const char* path = metrics_file_path_.c_str();
54 return OS::FileExists(path);
55 }
56
GetCacheDirectory() const57 const std::string GetCacheDirectory() const { return cache_directory_; }
GetMetricsFilePath() const58 const std::string GetMetricsFilePath() const { return metrics_file_path_; }
59
60 protected:
61 std::unique_ptr<ScratchDir> scratch_dir_;
62 std::string metrics_file_path_;
63 std::string cache_directory_;
64 };
65
TEST_F(OdrMetricsTest,MetricsFileIsNotCreatedIfNotEnabled)66 TEST_F(OdrMetricsTest, MetricsFileIsNotCreatedIfNotEnabled) {
67 // Metrics file is (potentially) written in OdrMetrics destructor.
68 {
69 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
70 metrics.SetArtApexVersion(99);
71 metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
72 metrics.SetStage(OdrMetrics::Stage::kCheck);
73 metrics.SetStatus(OdrMetrics::Status::kNoSpace);
74 }
75 EXPECT_FALSE(MetricsFileExists());
76 }
77
TEST_F(OdrMetricsTest,MetricsFileIsCreatedIfEnabled)78 TEST_F(OdrMetricsTest, MetricsFileIsCreatedIfEnabled) {
79 // Metrics file is (potentially) written in OdrMetrics destructor.
80 {
81 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
82 metrics.SetEnabled(true);
83 metrics.SetArtApexVersion(101);
84 metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
85 metrics.SetStage(OdrMetrics::Stage::kCheck);
86 metrics.SetStatus(OdrMetrics::Status::kNoSpace);
87 }
88 EXPECT_TRUE(MetricsFileExists());
89 }
90
TEST_F(OdrMetricsTest,CacheSpaceValuesAreUpdated)91 TEST_F(OdrMetricsTest, CacheSpaceValuesAreUpdated) {
92 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
93 metrics.CaptureSpaceFreeEnd();
94 OdrMetricsRecord record = metrics.ToRecord();
95 EXPECT_GT(record.cache_space_free_start_mib, 0);
96 EXPECT_GT(record.cache_space_free_end_mib, 0);
97 }
98
TEST_F(OdrMetricsTest,PrimaryBcpResultWithValue)99 TEST_F(OdrMetricsTest, PrimaryBcpResultWithValue) {
100 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
101 metrics.SetDex2OatResult(
102 OdrMetrics::Stage::kPrimaryBootClasspath,
103 100,
104 ExecResult{.status = ExecResult::Status::kExited, .exit_code = 0, .signal = 0});
105 metrics.SetBcpCompilationType(OdrMetrics::Stage::kPrimaryBootClasspath,
106 OdrMetrics::BcpCompilationType::kMainline);
107 OdrMetricsRecord record = metrics.ToRecord();
108
109 EXPECT_EQ(record.primary_bcp_compilation_millis, 100);
110 EXPECT_EQ(record.primary_bcp_dex2oat_result.status, ExecResult::Status::kExited);
111 EXPECT_EQ(record.primary_bcp_dex2oat_result.exit_code, 0);
112 EXPECT_EQ(record.primary_bcp_dex2oat_result.signal, 0);
113 EXPECT_EQ(record.primary_bcp_compilation_type,
114 static_cast<int32_t>(OdrMetrics::BcpCompilationType::kMainline));
115
116 EXPECT_EQ(record.secondary_bcp_compilation_millis, 0);
117 EXPECT_EQ(record.secondary_bcp_dex2oat_result.status, kExecResultNotRun);
118 EXPECT_EQ(record.secondary_bcp_compilation_type,
119 static_cast<int32_t>(OdrMetrics::BcpCompilationType::kUnknown));
120
121 EXPECT_EQ(record.system_server_compilation_millis, 0);
122 EXPECT_EQ(record.system_server_dex2oat_result.status, kExecResultNotRun);
123 }
124
TEST_F(OdrMetricsTest,PrimaryBcpResultWithoutValue)125 TEST_F(OdrMetricsTest, PrimaryBcpResultWithoutValue) {
126 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
127
128 OdrMetricsRecord record = metrics.ToRecord();
129 EXPECT_EQ(record.primary_bcp_dex2oat_result.status, kExecResultNotRun);
130 EXPECT_EQ(record.primary_bcp_dex2oat_result.exit_code, -1);
131 EXPECT_EQ(record.primary_bcp_dex2oat_result.signal, 0);
132 }
133
TEST_F(OdrMetricsTest,SecondaryBcpResultWithValue)134 TEST_F(OdrMetricsTest, SecondaryBcpResultWithValue) {
135 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
136 metrics.SetDex2OatResult(
137 OdrMetrics::Stage::kPrimaryBootClasspath,
138 100,
139 ExecResult{.status = ExecResult::Status::kExited, .exit_code = 0, .signal = 0});
140 metrics.SetBcpCompilationType(OdrMetrics::Stage::kPrimaryBootClasspath,
141 OdrMetrics::BcpCompilationType::kMainline);
142 metrics.SetDex2OatResult(
143 OdrMetrics::Stage::kSecondaryBootClasspath,
144 200,
145 ExecResult{.status = ExecResult::Status::kTimedOut, .exit_code = 3, .signal = 0});
146 metrics.SetBcpCompilationType(OdrMetrics::Stage::kSecondaryBootClasspath,
147 OdrMetrics::BcpCompilationType::kPrimaryAndMainline);
148 OdrMetricsRecord record = metrics.ToRecord();
149
150 EXPECT_EQ(record.primary_bcp_compilation_millis, 100);
151 EXPECT_EQ(record.primary_bcp_dex2oat_result.status, ExecResult::Status::kExited);
152 EXPECT_EQ(record.primary_bcp_dex2oat_result.exit_code, 0);
153 EXPECT_EQ(record.primary_bcp_dex2oat_result.signal, 0);
154 EXPECT_EQ(record.primary_bcp_compilation_type,
155 static_cast<int32_t>(OdrMetrics::BcpCompilationType::kMainline));
156
157 EXPECT_EQ(record.secondary_bcp_compilation_millis, 200);
158 EXPECT_EQ(record.secondary_bcp_dex2oat_result.status, ExecResult::Status::kTimedOut);
159 EXPECT_EQ(record.secondary_bcp_dex2oat_result.exit_code, 3);
160 EXPECT_EQ(record.secondary_bcp_dex2oat_result.signal, 0);
161 EXPECT_EQ(record.secondary_bcp_compilation_type,
162 static_cast<int32_t>(OdrMetrics::BcpCompilationType::kPrimaryAndMainline));
163
164 EXPECT_EQ(record.system_server_compilation_millis, 0);
165 EXPECT_EQ(record.system_server_dex2oat_result.status, kExecResultNotRun);
166 }
167
TEST_F(OdrMetricsTest,SystemServerResultWithValue)168 TEST_F(OdrMetricsTest, SystemServerResultWithValue) {
169 OdrMetrics metrics(GetCacheDirectory(), GetMetricsFilePath());
170 metrics.SetDex2OatResult(
171 OdrMetrics::Stage::kPrimaryBootClasspath,
172 100,
173 ExecResult{.status = ExecResult::Status::kExited, .exit_code = 0, .signal = 0});
174 metrics.SetDex2OatResult(
175 OdrMetrics::Stage::kSecondaryBootClasspath,
176 200,
177 ExecResult{.status = ExecResult::Status::kTimedOut, .exit_code = 3, .signal = 0});
178 metrics.SetDex2OatResult(
179 OdrMetrics::Stage::kSystemServerClasspath,
180 300,
181 ExecResult{.status = ExecResult::Status::kSignaled, .exit_code = 2, .signal = 9});
182 OdrMetricsRecord record = metrics.ToRecord();
183
184 EXPECT_EQ(record.primary_bcp_compilation_millis, 100);
185 EXPECT_EQ(record.primary_bcp_dex2oat_result.status, ExecResult::Status::kExited);
186 EXPECT_EQ(record.primary_bcp_dex2oat_result.exit_code, 0);
187 EXPECT_EQ(record.primary_bcp_dex2oat_result.signal, 0);
188
189 EXPECT_EQ(record.secondary_bcp_compilation_millis, 200);
190 EXPECT_EQ(record.secondary_bcp_dex2oat_result.status, ExecResult::Status::kTimedOut);
191 EXPECT_EQ(record.secondary_bcp_dex2oat_result.exit_code, 3);
192 EXPECT_EQ(record.secondary_bcp_dex2oat_result.signal, 0);
193
194 EXPECT_EQ(record.system_server_compilation_millis, 300);
195 EXPECT_EQ(record.system_server_dex2oat_result.status, ExecResult::Status::kSignaled);
196 EXPECT_EQ(record.system_server_dex2oat_result.exit_code, 2);
197 EXPECT_EQ(record.system_server_dex2oat_result.signal, 9);
198 }
199
200 } // namespace odrefresh
201 } // namespace art
202