1 /*
2 * Copyright 2017 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 #define LOG_TAG "C2ComponentInterface_test"
18
19 #include <dlfcn.h>
20 #include <stdio.h>
21
22 #include <gtest/gtest.h>
23 #include <utils/Log.h>
24
25 #include <C2Component.h>
26 #include <C2Config.h>
27 #include <util/C2InterfaceHelper.h>
28 #include <C2Param.h>
29
30 #if !defined(UNUSED)
31 #define UNUSED(expr) \
32 do { \
33 (void)(expr); \
34 } while (0)
35
36 #endif //!defined(UNUSED)
37
38 namespace android {
39
alloc_unique_cstr(const char * cstr)40 template <class T> std::unique_ptr<T> alloc_unique_cstr(const char *cstr) {
41 size_t len = strlen(cstr);
42 std::unique_ptr<T> ptr = T::AllocUnique(len);
43 memcpy(ptr->m.value, cstr, len);
44 return ptr;
45 }
46
47 class C2CompIntfTest : public ::testing::Test {
48 protected:
C2CompIntfTest()49 C2CompIntfTest() {}
~C2CompIntfTest()50 ~C2CompIntfTest() override {}
51
setComponent(std::shared_ptr<C2ComponentInterface> intf)52 void setComponent(std::shared_ptr<C2ComponentInterface> intf) {
53 mIntf = intf;
54 }
55
resetResults()56 void resetResults() {
57 mIntf = nullptr;
58 mParamResults.clear();
59 }
60
61 template <typename T> void testUnsupportedParam();
62
63 template <typename T> void testSupportedParam();
64
65 // testReadOnlyParam() and testWritableParam() are the main functions for testing a parameter.
66 // A caller should find out if a tested parameter is read-only or writable before calling them
67 // and it must call one of the corresponded them.
68
69 // If a parameter is read-only this is called.
70 // Test read-only parameter |preParam|. The test expects failure while config() with |newParam|,
71 // and make sure |preParam| stay unchanged.
72 template <typename T>
73 void testReadOnlyParam(const T &preParam, const T &newParam);
74
75 // If a parameter is writable this is called.
76 // Test one filed |writableField| for given writable parameter |param|.
77 // |validValues| contains all values obtained from querySupportedValues() for |writableField|.
78 // The test checks validity for config() with each value, and make sure values are config-ed
79 // by query() them out. |invalidValues| contains some values which are not in |validValues|.
80 // The test expects C2_BAD_VALUE while config() with these values,
81 // and |param| should stay unchanged.
82 template <typename TParam, typename TRealField, typename TField>
83 void testWritableParam(TParam *const param, TRealField *const writableField,
84 const std::vector<TField> &validValues,
85 const std::vector<TField> &invalidValues);
86
87 // Test all the defined parameters in C2Param.h.
88 void testMain(std::shared_ptr<C2ComponentInterface> intf,
89 const std::string &componentName);
90
91 // Check permission of parameter type |T| for testing interface.
92 // This should be called first of the testing per parameter type,
93 // therefore different testing process is applied according to the permission type.
94 template <typename T>
95 void checkParamPermission(
96 int *const writable,
97 const std::vector<std::shared_ptr<C2ParamDescriptor>> &supportedParams);
98
99 private:
100 enum ParamPermission : int {
101 WRITABLE,
102 READONLY,
103 UNSUPPORTED,
104 };
105
106 struct paramTestInfo {
107 std::string name;
108 int result;
paramTestInfoandroid::C2CompIntfTest::paramTestInfo109 paramTestInfo(const char *name_, int result_)
110 : name(name_), result(result_) {}
111 };
112
113 // queryOnStack() and queryonHeap() both call an interface's query_vb() and
114 // check if a component has a parameter whose type is |T|.
115 // If a component has, the value should be copied into an argument, that is
116 // |p| in queryOnStack() and |heapParams| in queryOnHeap().
117 // The return value is c2_status_t (e.g. C2_OK).
118 template <typename T> c2_status_t queryOnStack(T *const p);
119
120 template <typename T>
121 c2_status_t queryOnHeap(const T &p,
122 std::vector<std::unique_ptr<C2Param>> *const heapParams);
123
124 // Get a value whose type is |T| in a component. The value is copied to |param|.
125 // This should be called only if a component has the parameter.
126 template <typename T> void getValue(T *const param);
127
128 // Check if the parameter's value in component is equal to |expected| and
129 // queryOnStack() and queryOnHeap() are succeeded. When this function called,
130 // it should be guaranteed a component has the parameter.
131 template <typename T> void queryParamAsExpected(const T &expected);
132
133 // Test if query functions works correctly for supported parameters.
134 // "Support" means here a component has the parameter.
135 template <typename T> void querySupportedParam();
136
137 // Test query functions works correctly for unsupported parameters.
138 // "Unsupport" means here a component doesn't have the parameter.
139 template <typename T> void queryUnsupportedParam();
140
141 // Execute an interface's config_vb(). |T| is a single parameter type, not std::vector.
142 // config() creates std::vector<C2Param *> {p} and passes it to config_vb().
143 template <typename T>
144 c2_status_t
145 config(T *const p,
146 std::vector<std::unique_ptr<C2SettingResult>> *const failures);
147
148 // Test if config works correctly for read-only parameters.
149 // Because the failure of config() is assumed, |newParam| doesn't matter.
150 template <typename T> void configReadOnlyParam(const T &newParam);
151
152 // Test if config works correctly for writable parameters.
153 // This changes the parameter's value to |newParam|.
154 // |stConfig| is a return value of config().
155 template <typename T> void configWritableParamValidValue(const T &newParam, c2_status_t *stConfig);
156
157 // Test if config works correctly in the case an invalid value |newParam| is tried to write
158 // to an writable parameter.
159 template <typename T> void configWritableParamInvalidValue(const T &newParam);
160
161 // Create values for testing from |validValueInfos|. The values are returned as arguments.
162 // |validValues| : valid values, which can be written for the parameter.
163 // |InvalidValues| : invalid values, which cannot be written for the parameter.
164 // config() should be failed if these values are used as new values.
165 // This function should be called only for writable and supported parameters.
166 template <typename TField>
167 void getTestValues(const C2FieldSupportedValues &validValueInfos,
168 std::vector<TField> *const validValues,
169 std::vector<TField> *const invalidValues);
170
171 // Output the summary of test results. Categorizes parameters with their configuration.
172 void outputResults(const std::string &name);
173
174 std::shared_ptr<C2ComponentInterface> mIntf;
175 std::vector<paramTestInfo> mParamResults;
176 std::string mCurrentParamName;
177 };
178
179 // factory function
180 // TODO(hiroh): Add factory functions for other types.
makeParam()181 template <typename T> std::unique_ptr<T> makeParam() {
182 return std::make_unique<T>();
183 }
184
makeParam()185 template <> std::unique_ptr<C2PortMimeConfig::input> makeParam() {
186 // TODO(hiroh): Set more precise length.
187 return C2PortMimeConfig::input::AllocUnique(100);
188 }
189
190 #define TRACED_FAILURE(func) \
191 do { \
192 SCOPED_TRACE(mCurrentParamName); \
193 func; \
194 if (::testing::Test::HasFatalFailure()) { \
195 return; \
196 } \
197 } while (false)
198
queryOnStack(T * const p)199 template <typename T> c2_status_t C2CompIntfTest::queryOnStack(T *const p) {
200 std::vector<C2Param*> stackParams{p};
201 return mIntf->query_vb(stackParams, {}, C2_DONT_BLOCK, nullptr);
202 }
203
204 template <typename T>
queryOnHeap(const T & p,std::vector<std::unique_ptr<C2Param>> * const heapParams)205 c2_status_t C2CompIntfTest::queryOnHeap(
206 const T &p, std::vector<std::unique_ptr<C2Param>> *const heapParams) {
207 uint32_t index = p.index() & ~0x03FE0000;
208 if (p.forStream()) {
209 index |= ((p.stream() << 17) & 0x01FE0000) | 0x02000000;
210 }
211 return mIntf->query_vb({}, {index}, C2_DONT_BLOCK, heapParams);
212 }
213
getValue(T * const param)214 template <typename T> void C2CompIntfTest::getValue(T *const param) {
215 // When getValue() is called, a component has to have the parameter.
216 ASSERT_EQ(C2_OK, queryOnStack(param));
217 }
218
219 template <typename T>
queryParamAsExpected(const T & expected)220 void C2CompIntfTest::queryParamAsExpected(const T &expected) {
221 // TODO(hiroh): Don't create param on stack and call queryOnStack for flex params.
222 // Note that all the current supported parameters are non-flex params.
223 T stack;
224 std::unique_ptr<T> pHeap = makeParam<T>();
225 std::vector<std::unique_ptr<C2Param>> heapParams;
226
227 ASSERT_EQ(C2_OK, queryOnStack(&stack));
228
229 // |stack| is a parameter value. The parameter size shouldn't be 0.
230 EXPECT_NE(0u, stack.size());
231 EXPECT_EQ(stack, expected);
232
233 ASSERT_EQ(C2_OK, queryOnHeap(*pHeap, &heapParams));
234
235 // |*heapParams[0]| is a parameter value. The size of |heapParams| has to be one.
236 ASSERT_EQ(1u, heapParams.size());
237 EXPECT_TRUE(heapParams[0]);
238 EXPECT_EQ(*heapParams[0], expected);
239 }
240
querySupportedParam()241 template <typename T> void C2CompIntfTest::querySupportedParam() {
242 std::unique_ptr<T> param = makeParam<T>();
243 // The current parameter's value is acquired by getValue(), which should be succeeded.
244 getValue(param.get());
245 queryParamAsExpected(*param);
246 }
247
queryUnsupportedParam()248 template <typename T> void C2CompIntfTest::queryUnsupportedParam() {
249 // TODO(hiroh): Don't create param on stack and call queryOnStack for flex params.
250 // Note that all the current supported parameters are non-flex params.
251 T stack;
252 std::unique_ptr<T> pHeap = makeParam<T>();
253 std::vector<std::unique_ptr<C2Param>> heapParams;
254 // If a component doesn't have the parameter, queryOnStack() and queryOnHeap()
255 // should return C2_BAD_INDEX.
256 ASSERT_EQ(C2_BAD_INDEX, queryOnStack(&stack));
257 EXPECT_FALSE(stack);
258 ASSERT_EQ(C2_BAD_INDEX, queryOnHeap(*pHeap, &heapParams));
259 EXPECT_EQ(0u, heapParams.size());
260 }
261
262 template <typename T>
config(T * const p,std::vector<std::unique_ptr<C2SettingResult>> * const failures)263 c2_status_t C2CompIntfTest::config(
264 T *const p, std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
265 std::vector<C2Param*> params{p};
266 return mIntf->config_vb(params, C2_DONT_BLOCK, failures);
267 }
268
269 // Create a new parameter copied from |p|.
makeParamFrom(const T & p)270 template <typename T> std::unique_ptr<T> makeParamFrom(const T &p) {
271 std::unique_ptr<T> retP = makeParam<T>();
272 EXPECT_TRUE(retP->updateFrom(p));
273 EXPECT_TRUE(memcmp(retP.get(), &p, sizeof(T)) == 0);
274 return retP;
275 }
276
277 template <typename T>
configReadOnlyParam(const T & newParam)278 void C2CompIntfTest::configReadOnlyParam(const T &newParam) {
279 std::unique_ptr<T> p = makeParamFrom(newParam);
280
281 std::vector<C2Param*> params{p.get()};
282 std::vector<std::unique_ptr<C2SettingResult>> failures;
283
284 // config_vb should be failed because a parameter is read-only.
285 ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
286 ASSERT_EQ(1u, failures.size());
287 EXPECT_EQ(C2SettingResult::READ_ONLY, failures[0]->failure);
288 }
289
290 template <typename T>
configWritableParamValidValue(const T & newParam,c2_status_t * configResult)291 void C2CompIntfTest::configWritableParamValidValue(const T &newParam, c2_status_t *configResult) {
292 std::unique_ptr<T> p = makeParamFrom(newParam);
293
294 std::vector<C2Param*> params{p.get()};
295 std::vector<std::unique_ptr<C2SettingResult>> failures;
296 // In most cases, config_vb return C2_OK and the parameter's value should be changed
297 // to |newParam|, which is confirmed in a caller of configWritableParamValueValue().
298 // However, this can return ~~~~ and the parameter's values is not changed,
299 // because there may be dependent limitations between fields or between parameters.
300 // TODO(hiroh): I have to fill the return value. Comments in C2Component.h doesn't mention
301 // about the return value when conflict happens. I set C2_BAD_VALUE to it temporarily now.
302 c2_status_t stConfig = mIntf->config_vb(params, C2_DONT_BLOCK, &failures);
303 if (stConfig == C2_OK) {
304 EXPECT_EQ(0u, failures.size());
305 } else {
306 ASSERT_EQ(C2_BAD_VALUE, stConfig);
307 EXPECT_EQ(1u, failures.size());
308 EXPECT_EQ(C2SettingResult::CONFLICT, failures[0]->failure);
309 }
310 *configResult = stConfig;
311 }
312
313 template <typename T>
configWritableParamInvalidValue(const T & newParam)314 void C2CompIntfTest::configWritableParamInvalidValue(const T &newParam) {
315 std::unique_ptr<T> p = makeParamFrom(newParam);
316
317 std::vector<C2Param*> params{p.get()};
318 std::vector<std::unique_ptr<C2SettingResult>> failures;
319 // Although a parameter is writable, config_vb should be failed,
320 // because a new value is invalid.
321 ASSERT_EQ(C2_BAD_VALUE, mIntf->config_vb(params, C2_DONT_BLOCK, &failures));
322 ASSERT_EQ(1u, failures.size());
323 EXPECT_EQ(C2SettingResult::BAD_VALUE, failures[0]->failure);
324 }
325
326 // There is only used enum type for the field type, that is C2DomainKind.
327 // If another field type is added, it is necessary to add function for that.
328 template <>
getTestValues(const C2FieldSupportedValues & validValueInfos,std::vector<C2DomainKind> * const validValues,std::vector<C2DomainKind> * const invalidValues)329 void C2CompIntfTest::getTestValues(
330 const C2FieldSupportedValues &validValueInfos,
331 std::vector<C2DomainKind> *const validValues,
332 std::vector<C2DomainKind> *const invalidValues) {
333 UNUSED(validValueInfos);
334 validValues->emplace_back(C2DomainVideo);
335 validValues->emplace_back(C2DomainAudio);
336 validValues->emplace_back(C2DomainOther);
337
338 // There is no invalid value.
339 UNUSED(invalidValues);
340 }
341
342 template <typename TField>
getTestValues(const C2FieldSupportedValues & validValueInfos,std::vector<TField> * const validValues,std::vector<TField> * const invalidValues)343 void C2CompIntfTest::getTestValues(
344 const C2FieldSupportedValues &validValueInfos,
345 std::vector<TField> *const validValues,
346 std::vector<TField> *const invalidValues) {
347 using TStorage = typename _c2_reduce_enum_to_underlying_type<TField>::type;
348
349 // The supported values are represented by C2Values. C2Value::Primitive needs to
350 // be transformed to a primitive value. This function is one to do that.
351 auto prim2Value = [](const C2Value::Primitive &prim) -> TField {
352 return (TField)prim.ref<TStorage>();
353 static_assert(std::is_same<TStorage, int32_t>::value ||
354 std::is_same<TStorage, uint32_t>::value ||
355 std::is_same<TStorage, int64_t>::value ||
356 std::is_same<TStorage, uint64_t>::value ||
357 std::is_same<TStorage, float>::value, "Invalid TField type.");
358 };
359
360 // The size of validValueInfos is one.
361 const auto &c2FSV = validValueInfos;
362
363 switch (c2FSV.type) {
364 case C2FieldSupportedValues::type_t::EMPTY: {
365 invalidValues->emplace_back(TField(0));
366 // TODO(hiroh) : Should other invalid values be tested?
367 break;
368 }
369 case C2FieldSupportedValues::type_t::RANGE: {
370 const auto &range = c2FSV.range;
371 auto rmin = prim2Value(range.min);
372 auto rmax = prim2Value(range.max);
373 auto rstep = prim2Value(range.step);
374
375 ASSERT_LE(rmin, rmax);
376
377 if (rstep != 0) {
378 // Increase linear
379 for (auto v = rmin; v <= rmax; v = TField(v + rstep)) {
380 validValues->emplace_back(v);
381 }
382 if (rmin > std::numeric_limits<TField>::min()) {
383 invalidValues->emplace_back(TField(rmin - 1));
384 }
385 if (rmax < std::numeric_limits<TField>::max()) {
386 invalidValues->emplace_back(TField(rmax + 1));
387 }
388 const unsigned int N = validValues->size();
389 if (N >= 2) {
390 if (std::is_same<TField, float>::value) {
391 invalidValues->emplace_back(TField((validValues->at(0) + validValues->at(1)) / 2));
392 invalidValues->emplace_back(TField((validValues->at(N - 2) + validValues->at(N - 1)) / 2));
393 } else {
394 if (rstep > 1) {
395 invalidValues->emplace_back(TField(validValues->at(0) + 1));
396 invalidValues->emplace_back(TField(validValues->at(N - 1) - 1));
397 }
398 }
399 }
400 } else {
401 // There should be two cases, except linear case.
402 // 1. integer geometric case
403 // 2. float geometric case
404
405 auto num = prim2Value(range.num);
406 auto denom = prim2Value(range.denom);
407
408 // If both range.num and range.denom are 1 and step is 0, we should use
409 // VALUES, shouldn't we?
410 ASSERT_FALSE(num == 1 && denom == 1);
411
412 // (num / denom) is not less than 1.
413 ASSERT_FALSE(denom == 0);
414 ASSERT_LE(denom, num);
415 for (auto v = rmin; v <= rmax; v = TField(v * num / denom)) {
416 validValues->emplace_back(v);
417 }
418
419 if (rmin > std::numeric_limits<TField>::min()) {
420 invalidValues->emplace_back(TField(rmin - 1));
421 }
422 if (rmax < std::numeric_limits<TField>::max()) {
423 invalidValues->emplace_back(TField(rmax + 1));
424 }
425
426 const unsigned int N = validValues->size();
427 if (N >= 2) {
428 if (std::is_same<TField, float>::value) {
429 invalidValues->emplace_back(TField((validValues->at(0) + validValues->at(1)) / 2));
430 invalidValues->emplace_back(TField((validValues->at(N - 2) + validValues->at(N - 1)) / 2));
431 } else {
432 if (validValues->at(1) - validValues->at(0) > 1) {
433 invalidValues->emplace_back(TField(validValues->at(0) + 1));
434 }
435 if (validValues->at(N - 1) - validValues->at(N - 2) > 1) {
436 invalidValues->emplace_back(TField(validValues->at(N - 1) - 1));
437 }
438 }
439 }
440 }
441 break;
442 }
443 case C2FieldSupportedValues::type_t::VALUES: {
444 for (const C2Value::Primitive &prim : c2FSV.values) {
445 validValues->emplace_back(prim2Value(prim));
446 }
447 auto minv = *std::min_element(validValues->begin(), validValues->end());
448 auto maxv = *std::max_element(validValues->begin(), validValues->end());
449 if (minv - 1 > std::numeric_limits<TField>::min()) {
450 invalidValues->emplace_back(TField(minv - 1));
451 }
452 if (maxv + 1 < std::numeric_limits<TField>::max()) {
453 invalidValues->emplace_back(TField(maxv + 1));
454 }
455 break;
456 }
457 case C2FieldSupportedValues::type_t::FLAGS: {
458 // TODO(hiroh) : Implement the case that param.type is FLAGS.
459 break;
460 }
461 }
462 }
463
464 template <typename T>
testReadOnlyParam(const T & preParam,const T & newParam)465 void C2CompIntfTest::testReadOnlyParam(const T &preParam, const T &newParam) {
466 TRACED_FAILURE(configReadOnlyParam(newParam));
467 // Parameter value must not be changed
468 TRACED_FAILURE(queryParamAsExpected(preParam));
469 }
470
471 template <typename TParam, typename TRealField, typename TField>
testWritableParam(TParam * const param,TRealField * const writableField,const std::vector<TField> & validValues,const std::vector<TField> & invalidValues)472 void C2CompIntfTest::testWritableParam(
473 TParam *const param, TRealField *const writableField,
474 const std::vector<TField> &validValues,
475 const std::vector<TField> &invalidValues) {
476 c2_status_t stConfig;
477
478 // Get the parameter's value in the beginning in order to reset the value at the end.
479 TRACED_FAILURE(getValue(param));
480 std::unique_ptr<TParam> defaultParam = makeParamFrom(*param);
481
482 // Test valid values
483 for (const auto &val : validValues) {
484 std::unique_ptr<TParam> preParam = makeParamFrom(*param);
485
486 // Param is try to be changed
487 *writableField = val;
488 TRACED_FAILURE(configWritableParamValidValue(*param, &stConfig));
489 if (stConfig == C2_OK) {
490 TRACED_FAILURE(queryParamAsExpected(*param));
491 } else {
492 // Param is unchanged because a field value conflicts with other field or parameter.
493 TRACED_FAILURE(queryParamAsExpected(*preParam));
494 }
495 }
496
497 // Store the current parameter in order to test |param| is unchanged
498 // after trying to write an invalid value.
499 std::unique_ptr<TParam> lastValidParam = makeParamFrom(*param);
500
501 // Test invalid values
502 for (const auto &val : invalidValues) {
503 // Param is changed
504 *writableField = val;
505 TRACED_FAILURE(configWritableParamInvalidValue(*param));
506 TRACED_FAILURE(queryParamAsExpected(*lastValidParam));
507 }
508 // Reset the parameter by config().
509 TRACED_FAILURE(configWritableParamValidValue(*defaultParam, &stConfig));
510 }
511
testUnsupportedParam()512 template <typename T> void C2CompIntfTest::testUnsupportedParam() {
513 TRACED_FAILURE(queryUnsupportedParam<T>());
514 }
515
testSupportedParam()516 template <typename T> void C2CompIntfTest::testSupportedParam() {
517 TRACED_FAILURE(querySupportedParam<T>());
518 }
519
isSupportedParam(const C2Param & param,const std::vector<std::shared_ptr<C2ParamDescriptor>> & sParams)520 bool isSupportedParam(
521 const C2Param ¶m,
522 const std::vector<std::shared_ptr<C2ParamDescriptor>> &sParams) {
523 for (const auto &pd : sParams) {
524 if (param.type() == pd->index().type()) {
525 return true;
526 }
527 }
528 return false;
529 }
530
531 template <typename T>
checkParamPermission(int * const result,const std::vector<std::shared_ptr<C2ParamDescriptor>> & supportedParams)532 void C2CompIntfTest::checkParamPermission(
533 int *const result,
534 const std::vector<std::shared_ptr<C2ParamDescriptor>> &supportedParams) {
535 std::unique_ptr<T> param = makeParam<T>();
536
537 if (!isSupportedParam(*param, supportedParams)) {
538 // If a parameter isn't supported, it just finish after calling testUnsupportedParam().
539 testUnsupportedParam<T>();
540 *result = ParamPermission::UNSUPPORTED;
541 return;
542 }
543
544 testSupportedParam<T>();
545
546 TRACED_FAILURE(getValue(param.get()));
547 std::vector<std::unique_ptr<C2SettingResult>> failures;
548 // Config does not change the parameter, because param is the present param.
549 // This config is executed to find out if a parameter is read-only or writable.
550 c2_status_t stStack = config(param.get(), &failures);
551 if (stStack == C2_BAD_VALUE) {
552 // Read-only
553 std::unique_ptr<T> newParam = makeParam<T>();
554 testReadOnlyParam(*param, *newParam);
555 *result = ParamPermission::READONLY;
556 } else {
557 // Writable
558 EXPECT_EQ(stStack, C2_OK);
559 *result = ParamPermission::WRITABLE;
560 }
561 }
562
outputResults(const std::string & name)563 void C2CompIntfTest::outputResults(const std::string &name) {
564 std::vector<std::string> params[3];
565 for (const auto &testInfo : mParamResults) {
566 int result = testInfo.result;
567 ASSERT_TRUE(0 <= result && result <= 2);
568 params[result].emplace_back(testInfo.name);
569 }
570 const char *resultString[] = {"Writable", "Read-Only", "Unsupported"};
571 printf("\n----TEST RESULTS (%s)----\n\n", name.c_str());
572 for (int i = 0; i < 3; i++) {
573 printf("[ %s ]\n", resultString[i]);
574 for (const auto &t : params[i]) {
575 printf("%s\n", t.c_str());
576 }
577 printf("\n");
578 }
579 }
580
581 #define TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, field_name_) \
582 do { \
583 std::unique_ptr<TParam_> param = makeParam<TParam_>(); \
584 std::vector<C2FieldSupportedValuesQuery> validValueInfos = { \
585 C2FieldSupportedValuesQuery::Current( \
586 C2ParamField(param.get(), &field_type_name_::field_name_)) \
587 }; \
588 ASSERT_EQ(C2_OK, \
589 mIntf->querySupportedValues_vb(validValueInfos, C2_DONT_BLOCK)); \
590 ASSERT_EQ(1u, validValueInfos.size()); \
591 std::vector<decltype(param->field_name_)> validValues; \
592 std::vector<decltype(param->field_name_)> invalidValues; \
593 getTestValues(validValueInfos[0].values, &validValues, &invalidValues); \
594 testWritableParam(param.get(), ¶m->field_name_, validValues,\
595 invalidValues); \
596 } while (0)
597
598 #define TEST_VSSTRUCT_WRITABLE_FIELD(TParam_, field_type_name_) \
599 do { \
600 TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, width); \
601 TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, height); \
602 } while (0)
603
604 #define TEST_U32_WRITABLE_FIELD(TParam_, field_type_name_) \
605 TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, value)
606
607 #define TEST_ENUM_WRITABLE_FIELD(TParam_, field_type_name_) \
608 TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, value)
609
610 // TODO(hiroh): Support parameters based on char[] and uint32_t[].
611 //#define TEST_STRING_WRITABLE_FIELD(TParam_, field_type_name_)
612 // TEST_GENERAL_WRITABLE_FIELD(TParam_, field_type_name_, m.value)
613 //#define TEST_U32ARRAY_WRITABLE_FIELD(Tparam_, field_type_name_)
614 // TEST_GENERAL_WRITABLE_FIELD(Tparam_, uint32_t[], field_type_name_, values)
615
616 #define EACH_TEST(TParam_, field_type_name_, test_name) \
617 do { \
618 int result = 0; \
619 this->mCurrentParamName = #TParam_; \
620 checkParamPermission<TParam_>(&result, supportedParams); \
621 if (result == ParamPermission::WRITABLE) { \
622 test_name(TParam_, field_type_name_); \
623 } \
624 mParamResults.emplace_back(#TParam_, result); \
625 } while (0)
626
627 #define EACH_TEST_SELF(type_, test_name) EACH_TEST(type_, type_, test_name)
628 #define EACH_TEST_INPUT(type_, test_name) EACH_TEST(type_::input, type_, test_name)
629 #define EACH_TEST_OUTPUT(type_, test_name) EACH_TEST(type_::output, type_, test_name)
testMain(std::shared_ptr<C2ComponentInterface> intf,const std::string & componentName)630 void C2CompIntfTest::testMain(std::shared_ptr<C2ComponentInterface> intf,
631 const std::string &componentName) {
632 setComponent(intf);
633
634 std::vector<std::shared_ptr<C2ParamDescriptor>> supportedParams;
635 ASSERT_EQ(C2_OK, mIntf->querySupportedParams_nb(&supportedParams));
636
637 EACH_TEST_SELF(C2ComponentLatencyInfo, TEST_U32_WRITABLE_FIELD);
638 EACH_TEST_SELF(C2ComponentTemporalInfo, TEST_U32_WRITABLE_FIELD);
639 EACH_TEST_INPUT(C2PortLatencyInfo, TEST_U32_WRITABLE_FIELD);
640 EACH_TEST_OUTPUT(C2PortLatencyInfo, TEST_U32_WRITABLE_FIELD);
641 EACH_TEST_INPUT(C2StreamFormatConfig, TEST_U32_WRITABLE_FIELD);
642 EACH_TEST_OUTPUT(C2StreamFormatConfig, TEST_U32_WRITABLE_FIELD);
643 EACH_TEST_INPUT(C2PortStreamCountConfig, TEST_U32_WRITABLE_FIELD);
644 EACH_TEST_OUTPUT(C2PortStreamCountConfig, TEST_U32_WRITABLE_FIELD);
645
646 EACH_TEST_SELF(C2ComponentDomainInfo, TEST_ENUM_WRITABLE_FIELD);
647
648 // TODO(hiroh): Support parameters based on uint32_t[] and char[].
649 // EACH_TEST_INPUT(C2PortMimeConfig, TEST_STRING_WRITABLE_FIELD);
650 // EACH_TEST_OUTPUT(C2PortMimeConfig, TEST_STRING_WRITABLE_FIELD);
651 // EACH_TEST_INPUT(C2StreamMimeConfig, TEST_STRING_WRITABLE_FIELD);
652 // EACH_TEST_OUTPUT(C2StreamMimeConfig, TEST_STRING_WRITABLE_FIELD);
653
654 // EACH_TEST_SELF(C2SupportedParamsInfo, TEST_U32ARRAY_WRITABLE_FIELD);
655 // EACH_TEST_SELF(C2RequiredParamsInfo, TEST_U32ARRAY_WRITABLE_FIELD);
656 // EACH_TEST_SELF(C2ReadOnlyParamsInfo, TEST_U32ARRAY_WRITABLE_FIELD);
657 // EACH_TEST_SELF(C2RequestedInfosInfo, TEST_U32ARRAY_WRITABLE_FIELD);
658
659 EACH_TEST_INPUT(C2VideoSizeStreamInfo, TEST_VSSTRUCT_WRITABLE_FIELD);
660 EACH_TEST_OUTPUT(C2VideoSizeStreamInfo, TEST_VSSTRUCT_WRITABLE_FIELD);
661 EACH_TEST_INPUT(C2VideoSizeStreamTuning, TEST_VSSTRUCT_WRITABLE_FIELD);
662 EACH_TEST_OUTPUT(C2VideoSizeStreamTuning, TEST_VSSTRUCT_WRITABLE_FIELD);
663 EACH_TEST_INPUT(C2MaxVideoSizeHintPortSetting, TEST_VSSTRUCT_WRITABLE_FIELD);
664 EACH_TEST_OUTPUT(C2MaxVideoSizeHintPortSetting, TEST_VSSTRUCT_WRITABLE_FIELD);
665
666 outputResults(componentName);
667 resetResults();
668 }
669
TEST_F(C2CompIntfTest,C2V4L2CodecIntf)670 TEST_F(C2CompIntfTest, C2V4L2CodecIntf) {
671
672 // Read a shared object library.
673 void* compLib = dlopen("system/lib/libv4l2_codec2.so", RTLD_NOW);
674
675 if (!compLib) {
676 printf("Cannot open library: %s.\n", dlerror());
677 FAIL();
678 return;
679 }
680
681 typedef C2ComponentStore* create_t();
682 create_t* create_store= (create_t*) dlsym(compLib, "create_store");
683 const char* dlsym_error = dlerror();
684 if (dlsym_error) {
685 printf("Cannot load symbol create: %s.\n", dlsym_error);
686 FAIL();
687 return;
688 }
689
690 typedef void destroy_t(C2ComponentStore*);
691 destroy_t* destroy_store = (destroy_t*) dlsym(compLib, "destroy_store");
692 dlsym_error = dlerror();
693 if (dlsym_error) {
694 printf("Cannot load symbol destroy: %s.\n", dlsym_error);
695 FAIL();
696 return;
697 }
698
699 std::shared_ptr<C2ComponentStore> componentStore(create_store(), destroy_store);
700 std::shared_ptr<C2ComponentInterface> componentIntf;
701 componentStore->createInterface("v4l2.decoder", &componentIntf);
702 auto componentName = "C2V4L2Codec";
703 testMain(componentIntf, componentName);
704 }
705
706 } // namespace android
707