1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef ANDROID_C2_COMPONENT_INTERFACE_TEST_H 6 #define ANDROID_C2_COMPONENT_INTERFACE_TEST_H 7 8 #include <C2Config.h> 9 #include <C2PlatformSupport.h> 10 #include <util/C2InterfaceHelper.h> 11 12 #include <gtest/gtest.h> 13 14 #include <inttypes.h> 15 #include <limits> 16 #include <memory> 17 18 namespace android { 19 20 class C2CompIntfTest : public ::testing::Test { 21 public: 22 void dumpParamDescriptions(); 23 24 // The following codes are template implicit instantiations. These codes should not be separated 25 // into an individual cpp file from explicit specializations. Otherwise the compiler will fail 26 // to instantiate templates when the explicit specialization is present. 27 28 template <typename T> testReadOnlyParam(const T * expected,T * invalid)29 void testReadOnlyParam(const T* expected, T* invalid) { 30 testReadOnlyParamOnStack(expected, invalid); 31 testReadOnlyParamOnHeap(expected, invalid); 32 } 33 34 template <typename T> checkReadOnlyFailureOnConfig(T * param)35 void checkReadOnlyFailureOnConfig(T* param) { 36 std::vector<C2Param*> params{param}; 37 std::vector<std::unique_ptr<C2SettingResult>> failures; 38 39 // TODO: do not assert on checking return value since it is not consistent for 40 // C2InterfaceHelper now. (b/79720928) 41 // 1) if config same value, it returns C2_OK 42 // 2) if config different value, it returns C2_CORRUPTED. But when you config again, it 43 // returns C2_OK 44 //ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures)); 45 mIntf->config_vb(params, C2_DONT_BLOCK, &failures); 46 47 // TODO: failure is not yet supported for C2InterfaceHelper 48 //ASSERT_EQ(1u, failures.size()); 49 //EXPECT_EQ(C2SettingResult::READ_ONLY, failures[0]->failure); 50 } 51 52 // Note: this is not suitable for testing flex-type parameters. 53 template <typename T> testReadOnlyParamOnStack(const T * expected,T * invalid)54 void testReadOnlyParamOnStack(const T* expected, T* invalid) { 55 T param; 56 std::vector<C2Param*> stackParams{¶m}; 57 ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr)); 58 EXPECT_EQ(*expected, param); 59 60 checkReadOnlyFailureOnConfig(¶m); 61 checkReadOnlyFailureOnConfig(invalid); 62 63 // The param must not change after failed config. 64 ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr)); 65 EXPECT_EQ(*expected, param); 66 } 67 68 template <typename T> testReadOnlyParamOnHeap(const T * expected,T * invalid)69 void testReadOnlyParamOnHeap(const T* expected, T* invalid) { 70 std::vector<std::unique_ptr<C2Param>> heapParams; 71 72 uint32_t index = expected->index(); 73 74 ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams)); 75 ASSERT_EQ(1u, heapParams.size()); 76 EXPECT_EQ(*expected, *heapParams[0]); 77 78 checkReadOnlyFailureOnConfig(heapParams[0].get()); 79 checkReadOnlyFailureOnConfig(invalid); 80 81 // The param must not change after failed config. 82 heapParams.clear(); 83 ASSERT_EQ(C2_OK, mIntf->query_vb({}, {index}, C2_DONT_BLOCK, &heapParams)); 84 ASSERT_EQ(1u, heapParams.size()); 85 EXPECT_EQ(*expected, *heapParams[0]); 86 } 87 88 template <typename T> testWritableParam(T * newParam)89 void testWritableParam(T* newParam) { 90 std::vector<C2Param*> params{newParam}; 91 std::vector<std::unique_ptr<C2SettingResult>> failures; 92 ASSERT_EQ(C2_OK, mIntf->config_vb(params, C2_DONT_BLOCK, &failures)); 93 EXPECT_EQ(0u, failures.size()); 94 95 // The param must change to newParam 96 // Check like param on stack 97 T param; 98 std::vector<C2Param*> stackParams{¶m}; 99 ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr)); 100 EXPECT_EQ(*newParam, param); 101 102 // Check also like param on heap 103 std::vector<std::unique_ptr<C2Param>> heapParams; 104 ASSERT_EQ(C2_OK, mIntf->query_vb({}, {newParam->index()}, C2_DONT_BLOCK, &heapParams)); 105 ASSERT_EQ(1u, heapParams.size()); 106 EXPECT_EQ(*newParam, *heapParams[0]); 107 } 108 109 template <typename T> testInvalidWritableParam(T * invalidParam)110 void testInvalidWritableParam(T* invalidParam) { 111 // Get the current parameter info 112 T preParam; 113 std::vector<C2Param*> stackParams{&preParam}; 114 ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr)); 115 116 // Config invalid value. The failure is expected 117 std::vector<C2Param*> params{invalidParam}; 118 std::vector<std::unique_ptr<C2SettingResult>> failures; 119 ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures)); 120 EXPECT_EQ(1u, failures.size()); 121 122 // The param must not change after config failed 123 T param; 124 std::vector<C2Param*> stackParams2{¶m}; 125 ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams2, {}, C2_DONT_BLOCK, nullptr)); 126 EXPECT_EQ(preParam, param); 127 128 // Check also like param on heap 129 std::vector<std::unique_ptr<C2Param>> heapParams; 130 ASSERT_EQ(C2_OK, mIntf->query_vb({}, {invalidParam->index()}, C2_DONT_BLOCK, &heapParams)); 131 ASSERT_EQ(1u, heapParams.size()); 132 EXPECT_EQ(preParam, *heapParams[0]); 133 } 134 isUnderflowSubstract(int32_t a,int32_t b)135 bool isUnderflowSubstract(int32_t a, int32_t b) { 136 return a < 0 && b > a - std::numeric_limits<int32_t>::min(); 137 } 138 isOverflowAdd(int32_t a,int32_t b)139 bool isOverflowAdd(int32_t a, int32_t b) { 140 return a > 0 && b > std::numeric_limits<int32_t>::max() - a; 141 } 142 143 template <typename T> testWritableVideoSizeParam(int32_t widthMin,int32_t widthMax,int32_t widthStep,int32_t heightMin,int32_t heightMax,int32_t heightStep)144 void testWritableVideoSizeParam(int32_t widthMin, int32_t widthMax, int32_t widthStep, 145 int32_t heightMin, int32_t heightMax, int32_t heightStep) { 146 // Test supported values of video size 147 T valid; 148 for (int32_t h = heightMin; h <= heightMax; h += heightStep) { 149 for (int32_t w = widthMin; w <= widthMax; w += widthStep) { 150 valid.width = w; 151 valid.height = h; 152 { 153 SCOPED_TRACE("testWritableParam"); 154 testWritableParam(&valid); 155 if (HasFailure()) { 156 printf("Failed while config width = %d, height = %d\n", valid.width, 157 valid.height); 158 } 159 if (HasFatalFailure()) return; 160 } 161 } 162 } 163 164 // TODO: validate possible values in C2InterfaceHelper is not implemented yet. 165 //// Test invalid values video size 166 //T invalid; 167 //// Width or height is smaller than min values 168 //if (!isUnderflowSubstract(widthMin, widthStep)) { 169 // invalid.width = widthMin - widthStep; 170 // invalid.height = heightMin; 171 // testInvalidWritableParam(&invalid); 172 //} 173 //if (!isUnderflowSubstract(heightMin, heightStep)) { 174 // invalid.width = widthMin; 175 // invalid.height = heightMin - heightStep; 176 // testInvalidWritableParam(&invalid); 177 //} 178 179 //// Width or height is bigger than max values 180 //if (!isOverflowAdd(widthMax, widthStep)) { 181 // invalid.width = widthMax + widthStep; 182 // invalid.height = heightMax; 183 // testInvalidWritableParam(&invalid); 184 //} 185 //if (!isOverflowAdd(heightMax, heightStep)) { 186 // invalid.width = widthMax; 187 // invalid.height = heightMax + heightStep; 188 // testInvalidWritableParam(&invalid); 189 //} 190 191 //// Invalid width/height within the range 192 //if (widthStep != 1) { 193 // invalid.width = widthMin + 1; 194 // invalid.height = heightMin; 195 // testInvalidWritableParam(&invalid); 196 //} 197 //if (heightStep != 1) { 198 // invalid.width = widthMin; 199 // invalid.height = heightMin + 1; 200 // testInvalidWritableParam(&invalid); 201 //} 202 } 203 204 template <typename T> testWritableProfileLevelParam()205 void testWritableProfileLevelParam() { 206 T info; 207 208 std::vector<C2FieldSupportedValuesQuery> profileC2FSV = { 209 {C2ParamField(&info, &C2StreamProfileLevelInfo::profile), 210 C2FieldSupportedValuesQuery::CURRENT}, 211 }; 212 ASSERT_EQ(C2_OK, mIntf->querySupportedValues_vb(profileC2FSV, C2_DONT_BLOCK)); 213 ASSERT_EQ(1u, profileC2FSV.size()); 214 ASSERT_EQ(C2_OK, profileC2FSV[0].status); 215 ASSERT_EQ(C2FieldSupportedValues::VALUES, profileC2FSV[0].values.type); 216 auto& profileFSVValues = profileC2FSV[0].values.values; 217 218 std::vector<C2FieldSupportedValuesQuery> levelC2FSV = { 219 {C2ParamField(&info, &C2StreamProfileLevelInfo::level), 220 C2FieldSupportedValuesQuery::CURRENT}, 221 }; 222 ASSERT_EQ(C2_OK, mIntf->querySupportedValues_vb(levelC2FSV, C2_DONT_BLOCK)); 223 ASSERT_EQ(1u, levelC2FSV.size()); 224 ASSERT_EQ(C2_OK, levelC2FSV[0].status); 225 ASSERT_EQ(C2FieldSupportedValues::VALUES, levelC2FSV[0].values.type); 226 auto& levelFSVValues = levelC2FSV[0].values.values; 227 228 for (const auto& profile : profileFSVValues) { 229 for (const auto& level : levelFSVValues) { 230 info.profile = static_cast<C2Config::profile_t>(profile.u32); 231 info.level = static_cast<C2Config::level_t>(level.u32); 232 { 233 SCOPED_TRACE("testWritableParam"); 234 testWritableParam(&info); 235 if (HasFailure()) { 236 printf("Failed while config profile = 0x%x, level = 0x%x\n", info.profile, 237 info.level); 238 } 239 if (HasFatalFailure()) return; 240 } 241 } 242 } 243 // TODO: Add invalid value test after validate possible values in C2InterfaceHelper is 244 // implemented. 245 } 246 247 protected: 248 std::shared_ptr<C2ComponentInterface> mIntf; 249 std::shared_ptr<C2ReflectorHelper> mReflector; 250 }; 251 252 } // namespace android 253 254 #endif // ANDROID_C2_COMPONENT_INTERFACE_TEST_H 255