blob: 3b771a919815d9b533661c1124cf2e9f6669f6b0 [file] [log] [blame]
Wei Wang90fc4d42018-01-25 14:45:33 -08001/*
2 * Copyright (C) 2018 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 specic language governing permissions and
14 * limitations under the License.
15 */
16
17#include <thread>
18
19#include <getopt.h>
20#include <unistd.h>
21
22#include <android-base/file.h>
23#include <android-base/logging.h>
24#include <sys/types.h>
25
26#include "perfmgr/HintManager.h"
27
28namespace android {
29namespace perfmgr {
30
31class NodeVerifier : public HintManager {
32 public:
33 static bool VerifyNodes(const std::string& config_path) {
34 std::string json_doc;
35
36 if (!android::base::ReadFileToString(config_path, &json_doc)) {
37 LOG(ERROR) << "Failed to read JSON config from " << config_path;
38 return false;
39 }
40
41 std::vector<std::unique_ptr<Node>> nodes = ParseNodes(json_doc);
42 if (nodes.empty()) {
43 LOG(ERROR) << "Failed to parse Nodes section from " << config_path;
44 return false;
45 }
46
47 for (const auto& node : nodes) {
48 std::vector<std::string> values = node->GetValues();
49 std::string default_value = values[node->GetDefaultIndex()];
50 // Always set to default first
51 values.insert(values.begin(), default_value);
52 // And reset to default after test
53 values.push_back(default_value);
54 for (const auto& value : values) {
55 if (!android::base::WriteStringToFile(value, node->GetPath())) {
56 LOG(ERROR) << "Failed to write to node: " << node->GetPath()
57 << " with value: " << value;
58 return false;
59 }
60 LOG(VERBOSE) << "Wrote to node: " << node->GetPath()
61 << " with value: " << value;
62 }
63 }
64 return true;
65 }
66
67 private:
68 NodeVerifier(sp<NodeLooperThread> nm,
69 const std::map<std::string, std::vector<NodeAction>>& actions)
70 : HintManager(nm, actions) {}
71};
72
73} // namespace perfmgr
74} // namespace android
75
76static void printUsage(const char* exec_name) {
77 std::string usage = exec_name;
78 usage =
79 usage +
80 " is a command-line tool to verify Nodes in Json config are writable.\n"
81 "Usages:\n"
Wei Wang55b9d6d2018-04-16 20:30:36 -070082 " [su system] " +
Wei Wang90fc4d42018-01-25 14:45:33 -080083 exec_name +
84 " [options]\n"
85 "\n"
86 "Options:\n"
87 " --config [PATH], -c\n"
88 " path to Json config file\n\n"
89 " --exec_hint, -e\n"
90 " do hints in Json config\n\n"
91 " --help, -h\n"
92 " print this message\n\n"
93 " --verbose, -v\n"
94 " print verbose log during execution\n\n";
95
96 LOG(INFO) << usage;
97}
98
99static void execConfig(const std::string& json_file) {
100 std::unique_ptr<android::perfmgr::HintManager> hm =
101 android::perfmgr::HintManager::GetFromJSON(json_file);
102 if (!hm.get() || !hm->IsRunning()) {
103 LOG(ERROR) << "Failed to Parse JSON config";
104 }
105 std::vector<std::string> hints = hm->GetHints();
106 for (const auto& hint : hints) {
107 LOG(INFO) << "Do hint: " << hint;
108 hm->DoHint(hint);
109 std::this_thread::yield();
110 std::this_thread::sleep_for(std::chrono::milliseconds(50));
111 LOG(INFO) << "End hint: " << hint;
112 hm->EndHint(hint);
113 std::this_thread::yield();
114 std::this_thread::sleep_for(std::chrono::milliseconds(50));
115 }
116}
117
118int main(int argc, char* argv[]) {
119 android::base::InitLogging(argv, android::base::StderrLogger);
120
121 if (getuid() == 0) {
122 LOG(WARNING) << "Running as root might mask node permission";
123 }
124
125 std::string config_path;
126 bool exec_hint = false;
127 while (true) {
128 static struct option opts[] = {
129 {"config", required_argument, nullptr, 'c'},
130 {"exec_hint", no_argument, nullptr, 'e'},
131 {"help", no_argument, nullptr, 'h'},
132 {"verbose", no_argument, nullptr, 'v'},
133 {0, 0, 0, 0} // termination of the option list
134 };
135
136 int option_index = 0;
137 int c = getopt_long(argc, argv, "c:ehv", opts, &option_index);
138 if (c == -1) {
139 break;
140 }
141
142 switch (c) {
143 case 'c':
144 config_path = optarg;
145 break;
146 case 'e':
147 exec_hint = true;
148 break;
149 case 'v':
150 android::base::SetMinimumLogSeverity(android::base::VERBOSE);
151 break;
152 case 'h':
153 printUsage(argv[0]);
154 return 0;
155 default:
156 // getopt already prints "invalid option -- %c" for us.
157 return 1;
158 }
159 }
160
161 if (config_path.empty()) {
162 LOG(ERROR) << "Need specify JSON config";
163 printUsage(argv[0]);
164 return 1;
165 }
166
167 if (exec_hint) {
168 execConfig(config_path);
169 return 0;
170 }
171
172 if (android::perfmgr::NodeVerifier::VerifyNodes(config_path)) {
173 LOG(INFO) << "Verified writing to JSON config";
174 return 0;
175 } else {
176 LOG(ERROR) << "Failed to verify nodes in JSON config";
177 return 1;
178 }
179}