• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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