1 /* 2 * Copyright 2020 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 #pragma once 18 19 #include <unordered_map> 20 21 #include <unistd.h> 22 23 #include "base/logging.h" // LOG() stdout and android log 24 #include "include/hardware/bluetooth.h" 25 #include "test/headless/get_options.h" 26 27 extern bt_interface_t bluetoothInterface; 28 29 namespace bluetooth { 30 namespace test { 31 namespace headless { 32 33 namespace { 34 35 template <typename T> 36 using ExecutionUnit = std::function<T()>; 37 38 constexpr char kHeadlessInitialSentinel[] = 39 " INITIAL HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " 40 "HEADLESS"; 41 constexpr char kHeadlessStartSentinel[] = 42 " START HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " 43 "HEADLESS"; 44 constexpr char kHeadlessStopSentinel[] = 45 " STOP HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " 46 "HEADLESS"; 47 constexpr char kHeadlessFinalSentinel[] = 48 " FINAL HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS HEADLESS " 49 "HEADLESS"; 50 51 } // namespace 52 53 class HeadlessStack { 54 protected: HeadlessStack(const char ** stack_init_flags)55 HeadlessStack(const char** stack_init_flags) 56 : stack_init_flags_(stack_init_flags) {} 57 virtual ~HeadlessStack() = default; 58 59 void SetUp(); 60 void TearDown(); StackInitFlags()61 const char** StackInitFlags() const { return stack_init_flags_; } 62 63 private: 64 const char** stack_init_flags_; 65 }; 66 67 class HeadlessRun : public HeadlessStack { 68 protected: 69 const bluetooth::test::headless::GetOpt& options_; 70 unsigned long loop_{0}; 71 HeadlessRun(const bluetooth::test::headless::GetOpt & options)72 HeadlessRun(const bluetooth::test::headless::GetOpt& options) 73 : HeadlessStack(options.StackInitFlags()), options_(options) {} 74 75 template <typename T> RunOnHeadlessStack(ExecutionUnit<T> func)76 T RunOnHeadlessStack(ExecutionUnit<T> func) { 77 LOG(INFO) << kHeadlessInitialSentinel; 78 SetUp(); 79 LOG(INFO) << kHeadlessStartSentinel; 80 81 T rc; 82 for (loop_ = 0; loop_ < options_.loop_; loop_++) { 83 rc = func(); 84 if (options_.msec_ != 0) { 85 usleep(options_.msec_ * 1000); 86 } 87 if (rc) { 88 break; 89 } 90 } 91 if (rc) { 92 LOG(ERROR) << "FAIL:" << rc << " loop/loops:" << loop_ << "/" 93 << options_.loop_; 94 } else { 95 LOG(INFO) << "PASS:" << rc << " loop/loops:" << loop_ << "/" 96 << options_.loop_; 97 } 98 99 LOG(INFO) << kHeadlessStopSentinel; 100 TearDown(); 101 LOG(INFO) << kHeadlessFinalSentinel; 102 return rc; 103 } 104 virtual ~HeadlessRun() = default; 105 }; 106 107 template <typename T> 108 class HeadlessTest : public HeadlessRun { 109 public: Run()110 virtual T Run() { 111 if (options_.non_options_.size() == 0) { 112 fprintf(stdout, "Must supply at least one subtest name\n"); 113 return -1; 114 } 115 116 std::string subtest = options_.GetNextSubTest(); 117 if (test_nodes_.find(subtest) == test_nodes_.end()) { 118 fprintf(stdout, "Unknown subtest module:%s\n", subtest.c_str()); 119 return -1; 120 } 121 return test_nodes_.at(subtest)->Run(); 122 } 123 124 virtual ~HeadlessTest() = default; 125 126 protected: HeadlessTest(const bluetooth::test::headless::GetOpt & options)127 HeadlessTest(const bluetooth::test::headless::GetOpt& options) 128 : HeadlessRun(options) {} 129 130 std::unordered_map<std::string, std::unique_ptr<HeadlessTest<T>>> test_nodes_; 131 }; 132 133 } // namespace headless 134 } // namespace test 135 } // namespace bluetooth 136