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