1 /*
2 * Copyright (C) 2019 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 "common/debug.h"
18 #include "maintenance/controller.h"
19
20 #include "db/file_models.h"
21 #include "db/models.h"
22
23 #include <cstdio>
24 #include <filesystem>
25 #include <fstream>
26 #include <string>
27 #include <vector>
28
29 #include <android-base/file.h>
30 #include <gtest/gtest.h>
31 #include <gmock/gmock.h>
32
33 using ::testing::Return;
34 using ::testing::_;
35 using ::testing::SaveArg;
36 using ::testing::SaveArgPointee;
37
38 namespace iorap::maintenance {
39
GetTestDataPath(const std::string & fn)40 static std::string GetTestDataPath(const std::string& fn) {
41 static std::string exec_dir = android::base::GetExecutableDirectory();
42 return exec_dir + "/tests/src/maintenance/testdata/" + fn;
43 }
44
45 class MockExec : public IExec {
46 public:
47 MOCK_METHOD(int,
48 Execve,
49 (const std::string& pathname, std::vector<std::string>& argv_vec, char *const envp[]),
50 (override));
51
52 MOCK_METHOD(pid_t, Fork, (), (override));
53 };
54
55 class ControllerTest: public ::testing::Test {
56 protected:
SetUp()57 void SetUp() override {
58 // The db is a fake db with the following tables:
59 //
60 // packages:
61 // id, name, version
62 // 1, com.android.settings, 1
63 // 2, com.yawanng, 1
64 //
65 // activities:
66 // id, name
67 // 1, Setting
68 // 2, yawanng
69 //
70 // app_launch_histories:
71 // id, activity_id, temperature, trace_enabled, readahead_enabled, intent_start_ns, total_time_ns, report_fully_drawn_ns
72 // 1, 1, 1, 1, 1, 1, 2, NULL
73 // 2, 1, 1, 1, 1, NULL, 4, 5
74 // 3, 1, 1, 1, 1, 3, NULL, NULL
75 // 4, 1, 1, 1, 1, 3, 7, 8
76 // 5, 1, 1, 0, 1, 4, 9, 10
77 // 6, 1, 2, 1, 1, 5, 11, 12
78 // 7, 2, 1, 1, 1, 6, 21, 22
79 // 8, 2, 1, 1, 1, 7, 22, 23
80 //
81 // raw_traces:
82 // id, history_id, file_path
83 // 1, 1, 1.txt
84 // 2, 3, 3.txt
85 // 3, 4, 4.txt
86 // 4, 5, 5.txt
87 // 5, 6, 6.txt
88 // 6, 7, 7.txt
89 // 7, 8, 8.txt
90 db_path = GetTestDataPath("test_sqlite.db");
91 }
92
93 std::string db_path;
94 TemporaryDir root_path;
95 };
96
97 MATCHER_P(AreArgsExpected, compiled_trace_path, "") {
98 std::vector<std::string> expect =
99 { "1.txt",
100 "3.txt",
101 "4.txt",
102 "--timestamp_limit_ns", "2",
103 "--timestamp_limit_ns", "18446744073709551615",
104 "--timestamp_limit_ns", "8",
105 "--output-text",
106 "--output-proto", compiled_trace_path,
107 "--verbose" };
108 return arg == expect;
109 }
110
TEST_F(ControllerTest,CompilationController)111 TEST_F(ControllerTest, CompilationController) {
112 auto mock_exec = std::make_shared<MockExec>();
113 iorap::db::SchemaModel db_schema = db::SchemaModel::GetOrCreate(db_path);
114 db::DbHandle db{db_schema.db()};
115
116 setenv("IORAPD_ROOT_DIR", root_path.path ,1);
117 std::string compiled_trace_path = std::string(root_path.path) +
118 "/com.android.settings/1/Setting/compiled_traces/compiled_trace.pb";
119
120 // No recompile
121 ControllerParameters params{
122 /*output_text=*/true,
123 /*inode_textcache=*/std::nullopt,
124 /*verbose=*/true,
125 /*recompile=*/false,
126 /*min_traces=*/3,
127 mock_exec};
128
129 ON_CALL(*mock_exec, Fork())
130 .WillByDefault(Return(-2));
131
132 EXPECT_CALL(*mock_exec,
133 Execve("/system/bin/iorap.cmd.compiler",
134 AreArgsExpected(compiled_trace_path),
135 nullptr))
136 .Times(2);
137
138 CompileAppsOnDevice(db, params);
139
140 // Recompile
141 ControllerParameters params2{
142 /*output_text=*/true,
143 /*inode_textcache=*/std::nullopt,
144 /*verbose=*/true,
145 /*recompile=*/true,
146 /*min_traces=*/3,
147 mock_exec};
148
149 // Create a fake compiled trace file to test recompile.
150 std::ofstream tmp_file;
151 tmp_file.open(compiled_trace_path);
152 tmp_file.close();
153
154 CompileAppsOnDevice(db, params2);
155 }
156
157 } // namespace iorap::maintenance
158