1 /*
2 * Copyright 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 specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "test_command_handler.h"
18
19 #include <stdlib.h>
20
21 #include <fstream>
22 #include <memory>
23 #include <regex>
24
25 #include "device_boutique.h"
26 #include "log.h"
27 #include "phy.h"
28
29 using std::vector;
30
31 namespace rootcanal {
32
TestCommandHandler(TestModel & test_model)33 TestCommandHandler::TestCommandHandler(TestModel& test_model)
34 : model_(test_model) {
35 #define SET_HANDLER(command_name, method) \
36 active_commands_[command_name] = [this](const vector<std::string>& param) { \
37 method(param); \
38 };
39 SET_HANDLER("add", Add);
40 SET_HANDLER("add_remote", AddRemote);
41 SET_HANDLER("del", Del);
42 SET_HANDLER("add_phy", AddPhy);
43 SET_HANDLER("del_phy", DelPhy);
44 SET_HANDLER("add_device_to_phy", AddDeviceToPhy);
45 SET_HANDLER("del_device_from_phy", DelDeviceFromPhy);
46 SET_HANDLER("list", List);
47 SET_HANDLER("set_device_address", SetDeviceAddress);
48 SET_HANDLER("set_timer_period", SetTimerPeriod);
49 SET_HANDLER("start_timer", StartTimer);
50 SET_HANDLER("stop_timer", StopTimer);
51 SET_HANDLER("reset", Reset);
52 #undef SET_HANDLER
53 }
54
AddDefaults()55 void TestCommandHandler::AddDefaults() {
56 // Add a phy for LE and one for BR/EDR
57 AddPhy({"LOW_ENERGY"});
58 AddPhy({"BR_EDR"});
59
60 // Add the controller to the Phys
61 AddDeviceToPhy({"1", "1"});
62 AddDeviceToPhy({"1", "2"});
63
64 // Add default test devices and add the devices to the phys
65 //
66 // Add({"beacon", "be:ac:10:00:00:01", "1000"});
67 // AddDeviceToPhy({"2", "1"});
68 //
69 // Add({"sniffer", "ca:12:1c:17:00:01"});
70 // AddDeviceToPhy({"3", "2"});
71 //
72 // Add({"sniffer", "3c:5a:b4:04:05:06"});
73 // AddDeviceToPhy({"4", "2"});
74
75 List({});
76
77 SetTimerPeriod({"10"});
78 StartTimer({});
79 }
80
HandleCommand(const std::string & name,const vector<std::string> & args)81 void TestCommandHandler::HandleCommand(const std::string& name,
82 const vector<std::string>& args) {
83 if (active_commands_.count(name) == 0) {
84 response_string_ = "Unhandled command: " + name;
85 send_response_(response_string_);
86 return;
87 }
88 active_commands_[name](args);
89 }
90
FromFile(const std::string & file_name)91 void TestCommandHandler::FromFile(const std::string& file_name) {
92 if (file_name.size() == 0) {
93 return;
94 }
95
96 std::ifstream file(file_name.c_str());
97
98 const std::regex re("\\s+");
99
100 std::string line;
101 while (std::getline(file, line)) {
102 auto begin = std::sregex_token_iterator(line.begin(), line.end(), re, -1);
103 auto end = std::sregex_token_iterator();
104 auto params = std::vector<std::string>(std::next(begin), end);
105
106 HandleCommand(*begin, params);
107 }
108
109 if (file.fail()) {
110 LOG_ERROR("Error reading commands from file.");
111 return;
112 }
113 }
114
RegisterSendResponse(const std::function<void (const std::string &)> callback)115 void TestCommandHandler::RegisterSendResponse(
116 const std::function<void(const std::string&)> callback) {
117 send_response_ = callback;
118 send_response_("RegisterSendResponse called");
119 }
120
Add(const vector<std::string> & args)121 void TestCommandHandler::Add(const vector<std::string>& args) {
122 if (args.size() < 1) {
123 response_string_ = "TestCommandHandler 'add' takes an argument";
124 send_response_(response_string_);
125 return;
126 }
127 std::shared_ptr<Device> new_dev = DeviceBoutique::Create(args);
128
129 if (new_dev == NULL) {
130 response_string_ = "TestCommandHandler 'add' " + args[0] + " failed!";
131 send_response_(response_string_);
132 LOG_WARN("%s", response_string_.c_str());
133 return;
134 }
135
136 LOG_INFO("Add %s", new_dev->ToString().c_str());
137 size_t dev_index = model_.Add(new_dev);
138 response_string_ =
139 std::to_string(dev_index) + std::string(":") + new_dev->ToString();
140 send_response_(response_string_);
141 }
142
AddRemote(const vector<std::string> & args)143 void TestCommandHandler::AddRemote(const vector<std::string>& args) {
144 if (args.size() < 3) {
145 response_string_ =
146 "TestCommandHandler usage: add_remote host port phy_type";
147 send_response_(response_string_);
148 return;
149 }
150
151 size_t port = std::stoi(args[1]);
152 Phy::Type phy_type = Phy::Type::BR_EDR;
153 if ("LOW_ENERGY" == args[2]) {
154 phy_type = Phy::Type::LOW_ENERGY;
155 }
156 if (port == 0 || port > 0xffff || args[0].size() < 2) {
157 response_string_ = "TestCommandHandler bad arguments to 'add_remote': ";
158 response_string_ += args[0];
159 response_string_ += "@";
160 response_string_ += args[1];
161 send_response_(response_string_);
162 return;
163 }
164
165 model_.AddRemote(args[0], port, phy_type);
166
167 response_string_ = args[0] + std::string("@") + std::to_string(port);
168 send_response_(response_string_);
169 }
170
Del(const vector<std::string> & args)171 void TestCommandHandler::Del(const vector<std::string>& args) {
172 size_t dev_index = std::stoi(args[0]);
173
174 model_.Del(dev_index);
175 response_string_ = "TestCommandHandler 'del' called with device at index " +
176 std::to_string(dev_index);
177 send_response_(response_string_);
178 }
179
AddPhy(const vector<std::string> & args)180 void TestCommandHandler::AddPhy(const vector<std::string>& args) {
181 if (args.size() != 1) {
182 response_string_ = "TestCommandHandler 'add_phy' takes one argument";
183 } else if (args[0] == "LOW_ENERGY") {
184 model_.AddPhy(Phy::Type::LOW_ENERGY);
185 response_string_ = "TestCommandHandler 'add_phy' called with LOW_ENERGY";
186 } else if (args[0] == "BR_EDR") {
187 model_.AddPhy(Phy::Type::BR_EDR);
188 response_string_ = "TestCommandHandler 'add_phy' called with BR_EDR";
189 } else {
190 response_string_ =
191 "TestCommandHandler 'add_phy' with unrecognized type " + args[0];
192 }
193 send_response_(response_string_);
194 }
195
DelPhy(const vector<std::string> & args)196 void TestCommandHandler::DelPhy(const vector<std::string>& args) {
197 size_t phy_index = std::stoi(args[0]);
198
199 model_.DelPhy(phy_index);
200 response_string_ = "TestCommandHandler 'del_phy' called with phy at index " +
201 std::to_string(phy_index);
202 send_response_(response_string_);
203 }
204
AddDeviceToPhy(const vector<std::string> & args)205 void TestCommandHandler::AddDeviceToPhy(const vector<std::string>& args) {
206 if (args.size() != 2) {
207 response_string_ =
208 "TestCommandHandler 'add_device_to_phy' takes two arguments";
209 send_response_(response_string_);
210 return;
211 }
212 size_t dev_index = std::stoi(args[0]);
213 size_t phy_index = std::stoi(args[1]);
214 model_.AddDeviceToPhy(dev_index, phy_index);
215 response_string_ =
216 "TestCommandHandler 'add_device_to_phy' called with device " +
217 std::to_string(dev_index) + " and phy " + std::to_string(phy_index);
218 send_response_(response_string_);
219 return;
220 }
221
DelDeviceFromPhy(const vector<std::string> & args)222 void TestCommandHandler::DelDeviceFromPhy(const vector<std::string>& args) {
223 if (args.size() != 2) {
224 response_string_ =
225 "TestCommandHandler 'del_device_from_phy' takes two arguments";
226 send_response_(response_string_);
227 return;
228 }
229 size_t dev_index = std::stoi(args[0]);
230 size_t phy_index = std::stoi(args[1]);
231 model_.DelDeviceFromPhy(dev_index, phy_index);
232 response_string_ =
233 "TestCommandHandler 'del_device_from_phy' called with device " +
234 std::to_string(dev_index) + " and phy " + std::to_string(phy_index);
235 send_response_(response_string_);
236 return;
237 }
238
List(const vector<std::string> & args)239 void TestCommandHandler::List(const vector<std::string>& args) {
240 if (args.size() > 0) {
241 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
242 return;
243 }
244 send_response_(model_.List());
245 }
246
SetDeviceAddress(const vector<std::string> & args)247 void TestCommandHandler::SetDeviceAddress(const vector<std::string>& args) {
248 if (args.size() != 2) {
249 response_string_ =
250 "TestCommandHandler 'set_device_address' takes two arguments";
251 send_response_(response_string_);
252 return;
253 }
254 size_t device_id = std::stoi(args[0]);
255 Address device_address{};
256 Address::FromString(args[1], device_address);
257 model_.SetDeviceAddress(device_id, device_address);
258 response_string_ = "set_device_address " + args[0];
259 response_string_ += " ";
260 response_string_ += args[1];
261 send_response_(response_string_);
262 }
263
SetTimerPeriod(const vector<std::string> & args)264 void TestCommandHandler::SetTimerPeriod(const vector<std::string>& args) {
265 if (args.size() != 1) {
266 LOG_INFO("SetTimerPeriod takes 1 argument");
267 }
268 size_t period = std::stoi(args[0]);
269 if (period != 0) {
270 response_string_ = "set timer period to ";
271 response_string_ += args[0];
272 model_.SetTimerPeriod(std::chrono::milliseconds(period));
273 } else {
274 response_string_ = "invalid timer period ";
275 response_string_ += args[0];
276 }
277 send_response_(response_string_);
278 }
279
StartTimer(const vector<std::string> & args)280 void TestCommandHandler::StartTimer(const vector<std::string>& args) {
281 if (args.size() > 0) {
282 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
283 }
284 model_.StartTimer();
285 response_string_ = "timer started";
286 send_response_(response_string_);
287 }
288
StopTimer(const vector<std::string> & args)289 void TestCommandHandler::StopTimer(const vector<std::string>& args) {
290 if (args.size() > 0) {
291 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
292 }
293 model_.StopTimer();
294 response_string_ = "timer stopped";
295 send_response_(response_string_);
296 }
297
Reset(const std::vector<std::string> & args)298 void TestCommandHandler::Reset(const std::vector<std::string>& args) {
299 if (args.size() > 0) {
300 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
301 }
302 model_.Reset();
303 response_string_ = "model reset";
304 send_response_(response_string_);
305 }
306
307 } // namespace rootcanal
308