• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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{&param};
57         ASSERT_EQ(C2_OK, mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr));
58         EXPECT_EQ(*expected, param);
59 
60         checkReadOnlyFailureOnConfig(&param);
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{&param};
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{&param};
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