1 /* 2 * Copyright (C) 2023 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.0dd 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 <utility> 20 #include <sstream> 21 #include <string> 22 #include <vector> 23 24 #include <flag_checker.h> 25 #include <gtest/gtest.h> 26 27 #define _FLAG_GTEST_CLASS_NAME(test_fixture, test_name) \ 28 test_fixture##_##test_name##_FLAG_GTest 29 30 #define _FLAG_STRINGFY(...) #__VA_ARGS__ 31 32 #define _FLAG_NAME(namespace, flag) namespace::flag 33 34 // Defines a class inherit from the original test fixture. 35 // 36 // The class is defined for each test case. The class constructor calls 37 // SkipIfFlagRequirementsNotMet to decide whether the test should be 38 // skipped. 39 40 #define _FLAG_GTEST_CLASS(test_fixture, test_name, parent_class, flags...) \ 41 class _FLAG_GTEST_CLASS_NAME(test_fixture, test_name) \ 42 : public parent_class { \ 43 public: \ 44 void SkipTest( \ 45 std::vector<std::pair<bool, std::string>> unsatisfied_flags) { \ 46 std::ostringstream skip_message; \ 47 for (const std::pair<bool, std::string> flag : unsatisfied_flags) { \ 48 skip_message << " flag(" \ 49 << flag.second << ")=" \ 50 << (flag.first ? "true":"false"); \ 51 } \ 52 GTEST_SKIP() << "Skipping test: not meet feature flag conditions:" \ 53 << skip_message.str(); \ 54 } \ 55 \ 56 _FLAG_GTEST_CLASS_NAME(test_fixture, test_name)() { \ 57 std::vector<std::pair<bool, std::string>> unsatisfied_flags = \ 58 android::test::flag::GetFlagsNotMetRequirements({flags}); \ 59 if (unsatisfied_flags.size() != 0) { \ 60 SkipTest(unsatisfied_flags); \ 61 } \ 62 } \ 63 }; 64 65 // Defines an aconfig feature flag. 66 // 67 // The first parameter is the package (with cpp namespace format) of the 68 // feature flag. The second parameter is the name of the feature flag. 69 // 70 // For example: ACONFIG_FLAG(android::cts::test, flag_rw) 71 72 #if !TEST_WITH_FLAGS_DONT_DEFINE 73 #define ACONFIG_FLAG(package, flag) \ 74 std::make_pair<std::function<bool()>, std::string>( \ 75 static_cast<bool (*)()>(_FLAG_NAME(package, flag)), \ 76 _FLAG_STRINGFY(package, flag)) 77 #endif 78 79 // Defines a legacy feature flag. 80 // 81 // The first parameter is the namespace of the feature flag. The second 82 // parameter (with cpp namespace format) is the package of the feature 83 // flag. The third parameter is the name of the feature flag. 84 // 85 // For example: LEGACY_FLAG(cts, android::cts::test, flag_rw) 86 87 #if !TEST_WITH_FLAGS_DONT_DEFINE 88 #define LEGACY_FLAG(namespace, package, flag) \ 89 std::make_pair<std::function<bool()>, std::string>( \ 90 nullptr, _FLAG_STRINGFY(namespace, package, flag)) 91 #endif 92 93 // Defines a set of feature flags that must meet "enabled" condition. 94 // 95 // The input parameters of REQUIRES_FLAGS_ENABLED is a set of flags 96 // warpped by ACONFIG_FLAG or LEGACY_FLAG macros, indicating that the 97 // expected values of these flags are true. 98 // 99 // For example: 100 // REQUIRES_FLAGS_ENABLED(LEGACY_FLAG(...), ACONFIG_FLAG(...)) 101 102 #if !TEST_WITH_FLAGS_DONT_DEFINE 103 #define REQUIRES_FLAGS_ENABLED(flags...) \ 104 std::make_pair<bool, std::vector< \ 105 std::pair<std::function<bool()>, std::string>>>(true, {flags}) 106 #endif 107 108 // Defines a set of feature flags that must meet "disabled" condition. 109 // 110 // The input parameters of REQUIRES_FLAGS_DISABLED is a set of flags 111 // warpped by ACONFIG_FLAG or LEGACY_FLAG macros, indicating that the 112 // expected values of these flags are false. 113 // 114 // For example: 115 // REQUIRES_FLAGS_DISABLED(LEGACY_FLAG(...), ACONFIG_FLAG(...)) 116 117 #if !TEST_WITH_FLAGS_DONT_DEFINE 118 #define REQUIRES_FLAGS_DISABLED(flags...) \ 119 std::make_pair<bool, std::vector< \ 120 std::pair<std::function<bool()>, std::string>>>(false, {flags}) 121 #endif 122 123 // TEST_F_WITH_FLAGS is an extension to the TEST_F macro in the GoogleTest 124 // framework. It supports adding feature flag conditions wrapped by 125 // REQUIRES_FLAGS_ENABLED or REQUIRES_FLAGS_DISABLED macros at the end of 126 // input parameters. 127 // 128 // For example: 129 // 130 // TEST_F_WITH_FLAGS( 131 // MyTestFixture, 132 // myTest, 133 // REQUIRES_FLAGS_ENABLED(...), 134 // REQUIRES_FLAGS_DISABLED(...)) {...} 135 // 136 // If any feature flag condition cannot be satisfied, the test will be 137 // skipped. 138 139 #if !TEST_WITH_FLAGS_DONT_DEFINE 140 #define TEST_F_WITH_FLAGS(test_fixture, test_name, flags...) \ 141 _FLAG_GTEST_CLASS(test_fixture, test_name, test_fixture, flags) \ 142 GTEST_TEST_(test_fixture, test_name, \ 143 _FLAG_GTEST_CLASS_NAME(test_fixture, test_name), \ 144 ::testing::internal::GetTypeId<test_fixture>()) 145 #endif 146 147 // TEST_WITH_FLAGS is an extension to the TEST macro in the GoogleTest 148 // framework. It supports adding feature flag conditions wrapped by 149 // REQUIRES_FLAGS_ENABLED or REQUIRES_FLAGS_DISABLED macros at the end of 150 // input parameters. 151 // 152 // For example: 153 // 154 // TEST_WITH_FLAGS( 155 // MyTestFixture, 156 // myTest, 157 // REQUIRES_FLAGS_ENABLED(...), 158 // REQUIRES_FLAGS_DISABLED(...)) {...} 159 // 160 // If any feature flag condition cannot be satisfied, the test will be 161 // skipped. 162 163 #if !TEST_WITH_FLAGS_DONT_DEFINE 164 #define TEST_WITH_FLAGS(test_fixture, test_name, flags...) \ 165 _FLAG_GTEST_CLASS(test_fixture, test_name, ::testing::Test, flags) \ 166 GTEST_TEST_(test_fixture, test_name, \ 167 _FLAG_GTEST_CLASS_NAME(test_fixture, test_name), \ 168 ::testing::internal::GetTestTypeId()) 169 #endif