Loading system/test/headless/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,13 @@ cc_test { srcs: [ "get_options.cc", "headless.cc", "sdp/main.cc", "main.cc", "pairing/pairing.cc", "sdp/sdp.cc", "sdp/sdp_db.cc", "nop/nop.cc", "read/read.cc", "read/name.cc", ], include_dirs: [ "packages/modules/Bluetooth/system", Loading system/test/headless/get_options.cc +30 −18 Original line number Diff line number Diff line Loading @@ -24,19 +24,34 @@ #include <string> namespace { constexpr struct option long_options[] = {{"device", required_argument, 0, 0}, {"loop", required_argument, 0, 0}, {"uuid", required_argument, 0, 0}, {0, 0, 0, 0}}; constexpr struct option long_options[] = { {"device", required_argument, 0, 0}, {"loop", required_argument, 0, 0}, {"uuid", required_argument, 0, 0}, {"msleep", required_argument, 0, 0}, {"stderr", no_argument, 0, 0}, {0, 0, 0, 0}}; enum OptionType { kOptionDevice = 0, kOptionLoop = 1, kOptionUuid = 2, kOptionMsleep = 3, kOptionStdErr = 4, }; } // namespace void bluetooth::test::headless::GetOpt::Usage() const { fprintf(stdout, "%s: Usage:\n", name_); fprintf(stdout, "%s --device=<device,> Comma separated list of remote devices\n", name_); fprintf(stdout, "%s --uuid=<uuid,> Comma separated list of uuids\n", name_); fprintf(stdout, "%s --loop=<loop> Number of loops\n", name_); fprintf(stdout, "%s --msleep=<msecs> Sleep msec between loops\n", name_); fprintf(stdout, "%s --stderr Dump stderr to stdout\n", name_); fflush(nullptr); } void bluetooth::test::headless::GetOpt::ParseValue( char* optarg, std::list<std::string>& string_list) { CHECK(optarg != nullptr); Loading @@ -58,9 +73,9 @@ void bluetooth::test::headless::GetOpt::ProcessOption(int option_index, std::list<std::string> string_list; OptionType option_type = static_cast<OptionType>(option_index); if (!optarg) return; switch (option_type) { case kOptionDevice: if (!optarg) return; ParseValue(optarg, string_list); for (auto& entry : string_list) { if (RawAddress::IsValidAddress(entry)) { Loading @@ -74,12 +89,20 @@ void bluetooth::test::headless::GetOpt::ProcessOption(int option_index, loop_ = std::stoul(optarg, nullptr, 0); break; case kOptionUuid: if (!optarg) return; ParseValue(optarg, string_list); for (auto& entry : string_list) { uuid_.push_back( bluetooth::Uuid::From16Bit(std::stoul(entry.c_str(), nullptr, 0))); } break; case kOptionMsleep: if (!optarg) return; msec_ = std::stoul(optarg, nullptr, 0); break; case kOptionStdErr: close_stderr_ = false; break; default: fflush(nullptr); valid_ = false; Loading Loading @@ -108,20 +131,9 @@ bluetooth::test::headless::GetOpt::GetOpt(int argc, char** argv) } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); valid_ = false; while (optind < argc) { non_options_.push_back(argv[optind++]); } fflush(nullptr); } void bluetooth::test::headless::GetOpt::Usage() const { printf("%s: Usage:\n", name_); printf("%s --device=<device,> Comma separated list of remote devices\n", name_); printf("%s --uuid=<uuid,> Comma separated list of uuids\n", name_); printf("%s --loop=<loop> Number of loops\n", name_); fflush(nullptr); } system/test/headless/get_options.h +12 −1 Original line number Diff line number Diff line Loading @@ -33,9 +33,20 @@ class GetOpt { virtual void Usage() const; virtual bool IsValid() const { return valid_; }; std::string GetNextSubTest() const { std::string test = non_options_.front(); non_options_.pop_front(); return test; } std::list<RawAddress> device_; std::list<bluetooth::Uuid> uuid_; int loop_; unsigned long loop_{1}; unsigned long msec_{0}; bool close_stderr_{true}; mutable std::list<std::string> non_options_; private: void ParseValue(char* optarg, std::list<std::string>& my_list); Loading system/test/headless/headless.cc +6 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "base/logging.h" // LOG() stdout and android log #include "include/hardware/bluetooth.h" #include "osi/include/log.h" // android log only #include "test/headless/get_options.h" #include "test/headless/headless.h" extern bt_interface_t bluetoothInterface; Loading Loading @@ -137,7 +138,7 @@ bt_os_callouts_t bt_os_callouts{ }; } // namespace void Headless::SetUp() { void HeadlessStack::SetUp() { LOG(INFO) << __func__ << " Entry"; int status = bluetoothInterface.init(&bt_callbacks, false, false); Loading @@ -151,14 +152,14 @@ void Headless::SetUp() { : LOG(ERROR) << "Failed to set up Bluetooth OS callouts"; bluetoothInterface.enable(); LOG_INFO(LOG_TAG, "%s Headless stack has enabled", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack has enabled", __func__); std::unique_lock<std::mutex> lck(adapter_state_mutex_); while (bt_state_ != BT_STATE_ON) adapter_state_cv_.wait(lck); LOG_INFO(LOG_TAG, "%s Headless stack is operational", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack is operational", __func__); } void Headless::TearDown() { void HeadlessStack::TearDown() { LOG_INFO(LOG_TAG, "Stack has disabled"); int status = bluetoothInterface.disable(); Loading @@ -169,5 +170,5 @@ void Headless::TearDown() { std::unique_lock<std::mutex> lck(adapter_state_mutex_); while (bt_state_ != BT_STATE_OFF) adapter_state_cv_.wait(lck); LOG_INFO(LOG_TAG, "%s Headless stack has exited", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack has exited", __func__); } system/test/headless/headless.h +82 −10 Original line number Diff line number Diff line Loading @@ -14,32 +14,104 @@ * limitations under the License. */ #pragma once #include <unordered_map> #include <unistd.h> #include "base/logging.h" // LOG() stdout and android log #include "test/headless/get_options.h" namespace bluetooth { namespace test { namespace headless { namespace { template <typename T> using ExecutionUnit = std::function<T()>; class Headless { public: Headless() = default; virtual ~Headless() = default; constexpr char kHeadlessStartSentinel[] = " START HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " "HEADLESS"; constexpr char kHeadlessStopSentinel[] = " STOP HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " "HEADLESS"; } // namespace class HeadlessStack { protected: virtual void SetUp(); virtual void TearDown(); HeadlessStack() = default; virtual ~HeadlessStack() = default; void SetUp(); void TearDown(); }; class Test : public Headless { public: class HeadlessRun : public HeadlessStack { protected: const bluetooth::test::headless::GetOpt& options_; unsigned long loop_{0}; HeadlessRun(const bluetooth::test::headless::GetOpt& options) : options_(options) {} template <typename T> T Run(ExecutionUnit<T> func) { T RunOnHeadlessStack(ExecutionUnit<T> func) { SetUp(); T rc = func(); LOG(INFO) << kHeadlessStartSentinel; T rc; for (loop_ = 0; loop_ < options_.loop_; loop_++) { rc = func(); if (options_.msec_ != 0) { usleep(options_.msec_ * 1000); } if (rc) { break; } } if (rc) { LOG(ERROR) << "FAIL:" << rc << " loop/loops:" << loop_ << "/" << options_.loop_; } else { LOG(INFO) << "PASS:" << rc << " loop/loops:" << loop_ << "/" << options_.loop_; } LOG(INFO) << kHeadlessStopSentinel; TearDown(); return rc; } virtual ~HeadlessRun() = default; }; template <typename T> class HeadlessTest : public HeadlessRun { public: virtual T Run() { if (options_.non_options_.size() == 0) { fprintf(stdout, "Must supply at least one subtest name\n"); return -1; } std::string subtest = options_.GetNextSubTest(); if (test_nodes_.find(subtest) == test_nodes_.end()) { fprintf(stdout, "Unknown subtest module:%s\n", subtest.c_str()); return -1; } return test_nodes_.at(subtest)->Run(); } virtual ~HeadlessTest() = default; protected: HeadlessTest(const bluetooth::test::headless::GetOpt& options) : HeadlessRun(options) {} std::unordered_map<std::string, std::unique_ptr<HeadlessTest<T>>> test_nodes_; }; } // namespace headless Loading Loading
system/test/headless/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,13 @@ cc_test { srcs: [ "get_options.cc", "headless.cc", "sdp/main.cc", "main.cc", "pairing/pairing.cc", "sdp/sdp.cc", "sdp/sdp_db.cc", "nop/nop.cc", "read/read.cc", "read/name.cc", ], include_dirs: [ "packages/modules/Bluetooth/system", Loading
system/test/headless/get_options.cc +30 −18 Original line number Diff line number Diff line Loading @@ -24,19 +24,34 @@ #include <string> namespace { constexpr struct option long_options[] = {{"device", required_argument, 0, 0}, {"loop", required_argument, 0, 0}, {"uuid", required_argument, 0, 0}, {0, 0, 0, 0}}; constexpr struct option long_options[] = { {"device", required_argument, 0, 0}, {"loop", required_argument, 0, 0}, {"uuid", required_argument, 0, 0}, {"msleep", required_argument, 0, 0}, {"stderr", no_argument, 0, 0}, {0, 0, 0, 0}}; enum OptionType { kOptionDevice = 0, kOptionLoop = 1, kOptionUuid = 2, kOptionMsleep = 3, kOptionStdErr = 4, }; } // namespace void bluetooth::test::headless::GetOpt::Usage() const { fprintf(stdout, "%s: Usage:\n", name_); fprintf(stdout, "%s --device=<device,> Comma separated list of remote devices\n", name_); fprintf(stdout, "%s --uuid=<uuid,> Comma separated list of uuids\n", name_); fprintf(stdout, "%s --loop=<loop> Number of loops\n", name_); fprintf(stdout, "%s --msleep=<msecs> Sleep msec between loops\n", name_); fprintf(stdout, "%s --stderr Dump stderr to stdout\n", name_); fflush(nullptr); } void bluetooth::test::headless::GetOpt::ParseValue( char* optarg, std::list<std::string>& string_list) { CHECK(optarg != nullptr); Loading @@ -58,9 +73,9 @@ void bluetooth::test::headless::GetOpt::ProcessOption(int option_index, std::list<std::string> string_list; OptionType option_type = static_cast<OptionType>(option_index); if (!optarg) return; switch (option_type) { case kOptionDevice: if (!optarg) return; ParseValue(optarg, string_list); for (auto& entry : string_list) { if (RawAddress::IsValidAddress(entry)) { Loading @@ -74,12 +89,20 @@ void bluetooth::test::headless::GetOpt::ProcessOption(int option_index, loop_ = std::stoul(optarg, nullptr, 0); break; case kOptionUuid: if (!optarg) return; ParseValue(optarg, string_list); for (auto& entry : string_list) { uuid_.push_back( bluetooth::Uuid::From16Bit(std::stoul(entry.c_str(), nullptr, 0))); } break; case kOptionMsleep: if (!optarg) return; msec_ = std::stoul(optarg, nullptr, 0); break; case kOptionStdErr: close_stderr_ = false; break; default: fflush(nullptr); valid_ = false; Loading Loading @@ -108,20 +131,9 @@ bluetooth::test::headless::GetOpt::GetOpt(int argc, char** argv) } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); valid_ = false; while (optind < argc) { non_options_.push_back(argv[optind++]); } fflush(nullptr); } void bluetooth::test::headless::GetOpt::Usage() const { printf("%s: Usage:\n", name_); printf("%s --device=<device,> Comma separated list of remote devices\n", name_); printf("%s --uuid=<uuid,> Comma separated list of uuids\n", name_); printf("%s --loop=<loop> Number of loops\n", name_); fflush(nullptr); }
system/test/headless/get_options.h +12 −1 Original line number Diff line number Diff line Loading @@ -33,9 +33,20 @@ class GetOpt { virtual void Usage() const; virtual bool IsValid() const { return valid_; }; std::string GetNextSubTest() const { std::string test = non_options_.front(); non_options_.pop_front(); return test; } std::list<RawAddress> device_; std::list<bluetooth::Uuid> uuid_; int loop_; unsigned long loop_{1}; unsigned long msec_{0}; bool close_stderr_{true}; mutable std::list<std::string> non_options_; private: void ParseValue(char* optarg, std::list<std::string>& my_list); Loading
system/test/headless/headless.cc +6 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "base/logging.h" // LOG() stdout and android log #include "include/hardware/bluetooth.h" #include "osi/include/log.h" // android log only #include "test/headless/get_options.h" #include "test/headless/headless.h" extern bt_interface_t bluetoothInterface; Loading Loading @@ -137,7 +138,7 @@ bt_os_callouts_t bt_os_callouts{ }; } // namespace void Headless::SetUp() { void HeadlessStack::SetUp() { LOG(INFO) << __func__ << " Entry"; int status = bluetoothInterface.init(&bt_callbacks, false, false); Loading @@ -151,14 +152,14 @@ void Headless::SetUp() { : LOG(ERROR) << "Failed to set up Bluetooth OS callouts"; bluetoothInterface.enable(); LOG_INFO(LOG_TAG, "%s Headless stack has enabled", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack has enabled", __func__); std::unique_lock<std::mutex> lck(adapter_state_mutex_); while (bt_state_ != BT_STATE_ON) adapter_state_cv_.wait(lck); LOG_INFO(LOG_TAG, "%s Headless stack is operational", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack is operational", __func__); } void Headless::TearDown() { void HeadlessStack::TearDown() { LOG_INFO(LOG_TAG, "Stack has disabled"); int status = bluetoothInterface.disable(); Loading @@ -169,5 +170,5 @@ void Headless::TearDown() { std::unique_lock<std::mutex> lck(adapter_state_mutex_); while (bt_state_ != BT_STATE_OFF) adapter_state_cv_.wait(lck); LOG_INFO(LOG_TAG, "%s Headless stack has exited", __func__); LOG_INFO(LOG_TAG, "%s HeadlessStack stack has exited", __func__); }
system/test/headless/headless.h +82 −10 Original line number Diff line number Diff line Loading @@ -14,32 +14,104 @@ * limitations under the License. */ #pragma once #include <unordered_map> #include <unistd.h> #include "base/logging.h" // LOG() stdout and android log #include "test/headless/get_options.h" namespace bluetooth { namespace test { namespace headless { namespace { template <typename T> using ExecutionUnit = std::function<T()>; class Headless { public: Headless() = default; virtual ~Headless() = default; constexpr char kHeadlessStartSentinel[] = " START HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " "HEADLESS"; constexpr char kHeadlessStopSentinel[] = " STOP HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " "HEADLESS"; } // namespace class HeadlessStack { protected: virtual void SetUp(); virtual void TearDown(); HeadlessStack() = default; virtual ~HeadlessStack() = default; void SetUp(); void TearDown(); }; class Test : public Headless { public: class HeadlessRun : public HeadlessStack { protected: const bluetooth::test::headless::GetOpt& options_; unsigned long loop_{0}; HeadlessRun(const bluetooth::test::headless::GetOpt& options) : options_(options) {} template <typename T> T Run(ExecutionUnit<T> func) { T RunOnHeadlessStack(ExecutionUnit<T> func) { SetUp(); T rc = func(); LOG(INFO) << kHeadlessStartSentinel; T rc; for (loop_ = 0; loop_ < options_.loop_; loop_++) { rc = func(); if (options_.msec_ != 0) { usleep(options_.msec_ * 1000); } if (rc) { break; } } if (rc) { LOG(ERROR) << "FAIL:" << rc << " loop/loops:" << loop_ << "/" << options_.loop_; } else { LOG(INFO) << "PASS:" << rc << " loop/loops:" << loop_ << "/" << options_.loop_; } LOG(INFO) << kHeadlessStopSentinel; TearDown(); return rc; } virtual ~HeadlessRun() = default; }; template <typename T> class HeadlessTest : public HeadlessRun { public: virtual T Run() { if (options_.non_options_.size() == 0) { fprintf(stdout, "Must supply at least one subtest name\n"); return -1; } std::string subtest = options_.GetNextSubTest(); if (test_nodes_.find(subtest) == test_nodes_.end()) { fprintf(stdout, "Unknown subtest module:%s\n", subtest.c_str()); return -1; } return test_nodes_.at(subtest)->Run(); } virtual ~HeadlessTest() = default; protected: HeadlessTest(const bluetooth::test::headless::GetOpt& options) : HeadlessRun(options) {} std::unordered_map<std::string, std::unique_ptr<HeadlessTest<T>>> test_nodes_; }; } // namespace headless Loading