353 lines
15 KiB
C++
353 lines
15 KiB
C++
/*
|
|
* Copyright 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define __C2_GENERATE_GLOBAL_VARS__
|
|
|
|
#include <set>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <C2ParamDef.h>
|
|
|
|
#include <media/stagefright/foundation/ABuffer.h>
|
|
#include <media/stagefright/foundation/hexdump.h>
|
|
#include <ReflectedParamUpdater.h>
|
|
|
|
namespace android {
|
|
|
|
namespace {
|
|
|
|
enum {
|
|
kParamIndexTestStart = 0x1000,
|
|
kParamIndexInt,
|
|
kParamIndexString,
|
|
kParamIndexComposite,
|
|
kParamIndexFlexString,
|
|
|
|
kParamIndexLong = C2Param::TYPE_INDEX_VENDOR_START,
|
|
};
|
|
|
|
typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexInt> C2IntInfo;
|
|
typedef C2GlobalParam<C2Info, C2Int64Value, kParamIndexLong> C2LongInfo;
|
|
|
|
struct C2FixedSizeStringStruct {
|
|
char value[12];
|
|
|
|
DEFINE_AND_DESCRIBE_BASE_C2STRUCT(FixedSizeString)
|
|
C2FIELD(value, "value")
|
|
};
|
|
typedef C2GlobalParam<C2Info, C2FixedSizeStringStruct, kParamIndexString> C2StringInfo;
|
|
|
|
struct C2CompositeStruct {
|
|
int32_t i32;
|
|
uint64_t u64;
|
|
char str[12];
|
|
uint8_t blob[8];
|
|
uint8_t flexBlob[];
|
|
|
|
C2CompositeStruct() = default;
|
|
|
|
DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(Composite, flexBlob)
|
|
C2FIELD(i32, "i32")
|
|
C2FIELD(u64, "u64")
|
|
C2FIELD(str, "str")
|
|
C2FIELD(blob, "blob")
|
|
C2FIELD(flexBlob, "flex-blob")
|
|
};
|
|
static_assert(C2CompositeStruct::FLEX_SIZE == 1, "");
|
|
static_assert(_C2FlexHelper<C2CompositeStruct>::FLEX_SIZE == 1, "");
|
|
typedef C2GlobalParam<C2Info, C2CompositeStruct, kParamIndexComposite> C2CompositeInfo;
|
|
|
|
typedef C2GlobalParam<C2Info, C2StringValue, kParamIndexFlexString> C2FlexStringInfo;
|
|
|
|
#define SUPPORTED_TYPES \
|
|
C2IntInfo, \
|
|
C2LongInfo, \
|
|
C2StringInfo, \
|
|
C2CompositeInfo, \
|
|
C2FlexStringInfo
|
|
|
|
template<typename... TYPES> struct describe_impl;
|
|
template<typename T, typename... TYPES> struct describe_impl<T, TYPES...> {
|
|
static std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex index) {
|
|
if (index == T::CORE_INDEX) {
|
|
return std::make_unique<C2StructDescriptor>(T::CORE_INDEX, T::FieldList());
|
|
} else {
|
|
return describe_impl<TYPES...>::describe(index);
|
|
}
|
|
}
|
|
};
|
|
|
|
template<> struct describe_impl<> {
|
|
static std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex) {
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
template<typename T> const char *GetName() { return nullptr; }
|
|
template<> const char *GetName<C2IntInfo>() { return "int"; }
|
|
template<> const char *GetName<C2LongInfo>() { return "long"; }
|
|
template<> const char *GetName<C2StringInfo>() { return "string"; }
|
|
template<> const char *GetName<C2CompositeInfo>() { return "composite"; }
|
|
template<> const char *GetName<C2FlexStringInfo>() { return "flex-string"; }
|
|
|
|
template<typename... TYPES> struct fill_descriptors_impl;
|
|
template<typename T, typename... TYPES> struct fill_descriptors_impl<T, TYPES...> {
|
|
static void fill(std::vector<std::shared_ptr<C2ParamDescriptor>> *vec) {
|
|
fill_descriptors_impl<TYPES...>::fill(vec);
|
|
vec->push_back(std::make_shared<C2ParamDescriptor>(
|
|
T::PARAM_TYPE, C2ParamDescriptor::IS_PERSISTENT, GetName<T>()));
|
|
}
|
|
};
|
|
|
|
template<> struct fill_descriptors_impl<> {
|
|
static void fill(std::vector<std::shared_ptr<C2ParamDescriptor>> *) {}
|
|
};
|
|
|
|
template<typename T> T *CastParam(const std::unique_ptr<C2Param> ¶m) {
|
|
return (T *)param.get();
|
|
}
|
|
|
|
class ParamReflector : public C2ParamReflector {
|
|
public:
|
|
ParamReflector() = default;
|
|
~ParamReflector() override = default;
|
|
|
|
std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex paramIndex) const override {
|
|
return describe_impl<SUPPORTED_TYPES>::describe(paramIndex);
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
class ReflectedParamUpdaterTest : public ::testing::Test {
|
|
public:
|
|
ReflectedParamUpdaterTest() : mReflector(new ParamReflector) {
|
|
fill_descriptors_impl<SUPPORTED_TYPES>::fill(&mDescriptors);
|
|
}
|
|
|
|
std::shared_ptr<C2ParamReflector> mReflector;
|
|
std::vector<std::shared_ptr<C2ParamDescriptor>> mDescriptors;
|
|
};
|
|
|
|
TEST_F(ReflectedParamUpdaterTest, SingleValueTest) {
|
|
ReflectedParamUpdater updater;
|
|
|
|
ReflectedParamUpdater::Dict msg;
|
|
msg.emplace("int.value", int32_t(12));
|
|
msg.emplace("vendor.long.value", int64_t(34));
|
|
|
|
updater.addParamDesc(mReflector, mDescriptors);
|
|
|
|
std::vector<C2Param::Index> indices;
|
|
updater.getParamIndicesFromMessage(msg, &indices);
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2FlexStringInfo::PARAM_TYPE; }));
|
|
|
|
std::vector<std::unique_ptr<C2Param>> params;
|
|
params.emplace_back(new C2IntInfo);
|
|
params.emplace_back(new C2LongInfo);
|
|
EXPECT_EQ(0, CastParam<C2IntInfo>(params[0])->value);
|
|
EXPECT_EQ(0, CastParam<C2LongInfo>(params[1])->value);
|
|
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_EQ(12, CastParam<C2IntInfo>(params[0])->value);
|
|
EXPECT_EQ(34, CastParam<C2LongInfo>(params[1])->value);
|
|
|
|
C2Value c2Value;
|
|
int32_t int32Value = 0;
|
|
int64_t int64Value = 0;
|
|
msg = updater.getParams(params);
|
|
ASSERT_EQ(1u, msg.count("int.value"));
|
|
EXPECT_EQ(true, msg["int.value"].find(&c2Value));
|
|
EXPECT_EQ(true, c2Value.get(&int32Value));
|
|
EXPECT_EQ(12, int32Value);
|
|
|
|
ASSERT_EQ(1u, msg.count("vendor.long.value"));
|
|
EXPECT_EQ(true, msg["vendor.long.value"].find(&c2Value));
|
|
EXPECT_EQ(true, c2Value.get(&int64Value));
|
|
EXPECT_EQ(34, int64Value);
|
|
}
|
|
|
|
TEST_F(ReflectedParamUpdaterTest, StringTest) {
|
|
ReflectedParamUpdater updater;
|
|
|
|
ReflectedParamUpdater::Dict msg;
|
|
msg.emplace("string.value", AString("56"));
|
|
msg.emplace("flex-string.value", AString("Some string"));
|
|
updater.addParamDesc(mReflector, mDescriptors);
|
|
|
|
std::vector<C2Param::Index> indices;
|
|
updater.getParamIndicesFromMessage(msg, &indices);
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2FlexStringInfo::PARAM_TYPE; }));
|
|
|
|
std::vector<std::unique_ptr<C2Param>> params;
|
|
params.emplace_back(new C2StringInfo);
|
|
EXPECT_EQ(0, CastParam<C2StringInfo>(params[0])->value[0]);
|
|
params.emplace_back(C2FlexStringInfo::AllocUnique(0));
|
|
EXPECT_EQ(0u, CastParam<C2FlexStringInfo>(params[1])->flexCount());
|
|
char *flexStringData = &CastParam<C2FlexStringInfo>(params[1])->m.value[0];
|
|
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_STREQ("56", CastParam<C2StringInfo>(params[0])->value);
|
|
EXPECT_EQ(12u, CastParam<C2FlexStringInfo>(params[0])->flexCount());
|
|
EXPECT_STREQ("Some string", CastParam<C2FlexStringInfo>(params[1])->m.value);
|
|
EXPECT_NE(flexStringData, &CastParam<C2FlexStringInfo>(params[1])->m.value[0]);
|
|
flexStringData = &CastParam<C2FlexStringInfo>(params[1])->m.value[0];
|
|
|
|
// verify truncation and in-place update
|
|
msg["string.value"] = ReflectedParamUpdater::Value(AString("1234567890ABCDE"));
|
|
msg["flex-string.value"] = ReflectedParamUpdater::Value(AString("abc"));
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_STREQ("1234567890A", CastParam<C2StringInfo>(params[0])->value);
|
|
EXPECT_EQ(4u, CastParam<C2FlexStringInfo>(params[1])->flexCount());
|
|
EXPECT_STREQ("abc", CastParam<C2FlexStringInfo>(params[1])->m.value);
|
|
EXPECT_EQ(flexStringData, &CastParam<C2FlexStringInfo>(params[1])->m.value[0]);
|
|
|
|
AString strValue;
|
|
msg = updater.getParams(params);
|
|
ASSERT_EQ(1u, msg.count("string.value"));
|
|
EXPECT_EQ(true, msg["string.value"].find(&strValue));
|
|
EXPECT_STREQ("1234567890A", strValue.c_str());
|
|
|
|
ASSERT_EQ(1u, msg.count("flex-string.value"));
|
|
EXPECT_EQ(true, msg["flex-string.value"].find(&strValue));
|
|
EXPECT_STREQ("abc", strValue.c_str());
|
|
}
|
|
|
|
TEST_F(ReflectedParamUpdaterTest, CompositeTest) {
|
|
ReflectedParamUpdater updater;
|
|
|
|
ReflectedParamUpdater::Dict msg;
|
|
msg.emplace("composite.i32", int32_t(78));
|
|
msg.emplace("composite.u64", int64_t(910));
|
|
msg.emplace("composite.str", AString("1112"));
|
|
msg.emplace("composite.blob", ABuffer::CreateAsCopy("buffer08", 8));
|
|
msg.emplace("composite.flex-blob", ABuffer::CreateAsCopy("flex-buffer-14", 14));
|
|
|
|
updater.addParamDesc(mReflector, mDescriptors);
|
|
|
|
std::vector<C2Param::Index> indices;
|
|
updater.getParamIndicesFromMessage(msg, &indices);
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; }));
|
|
|
|
std::vector<std::unique_ptr<C2Param>> params;
|
|
params.emplace_back(C2CompositeInfo::AllocUnique(0));
|
|
EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.i32);
|
|
EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64);
|
|
EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.str[0]);
|
|
EXPECT_EQ(0, memcmp("\0\0\0\0\0\0\0\0", CastParam<C2CompositeInfo>(params[0])->m.blob, 8));
|
|
EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->flexCount());
|
|
uint8_t *flexBlobData = &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0];
|
|
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_EQ(78, CastParam<C2CompositeInfo>(params[0])->m.i32);
|
|
EXPECT_EQ(910u, CastParam<C2CompositeInfo>(params[0])->m.u64);
|
|
EXPECT_STREQ("1112", CastParam<C2CompositeInfo>(params[0])->m.str);
|
|
EXPECT_EQ(0, memcmp("buffer08", CastParam<C2CompositeInfo>(params[0])->m.blob, 8));
|
|
AString hex;
|
|
hexdump(CastParam<C2CompositeInfo>(params[0])->m.blob, 8, 0, &hex);
|
|
printf("%s\n", hex.c_str());
|
|
ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount());
|
|
EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14));
|
|
EXPECT_NE(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]);
|
|
flexBlobData = &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0];
|
|
|
|
// test setting and zero extending shorter blob than allowed
|
|
msg.clear();
|
|
msg.emplace("composite.blob", ABuffer::CreateAsCopy("buf05", 5));
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_EQ(0, memcmp("buf05\0\0\0", CastParam<C2CompositeInfo>(params[0])->m.blob, 8));
|
|
ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount());
|
|
EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14));
|
|
EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]);
|
|
|
|
// test setting and trimming larger blob than allowed
|
|
msg.clear();
|
|
msg.emplace("composite.blob", ABuffer::CreateAsCopy("ReallyLongBuffer", 16));
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_EQ(0, memcmp("ReallyLo", CastParam<C2CompositeInfo>(params[0])->m.blob, 8));
|
|
ASSERT_EQ(14u, CastParam<C2CompositeInfo>(params[0])->flexCount());
|
|
EXPECT_EQ(0, memcmp("flex-buffer-14", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 14));
|
|
EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]);
|
|
|
|
// test trimming flex blob in-place
|
|
msg.clear();
|
|
msg.emplace("composite.flex-blob", ABuffer::CreateAsCopy("buf05", 5));
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
ASSERT_EQ(5u, CastParam<C2CompositeInfo>(params[0])->flexCount());
|
|
EXPECT_EQ(0, memcmp("buf05", CastParam<C2CompositeInfo>(params[0])->m.flexBlob, 5));
|
|
EXPECT_EQ(flexBlobData, &CastParam<C2CompositeInfo>(params[0])->m.flexBlob[0]);
|
|
}
|
|
|
|
TEST_F(ReflectedParamUpdaterTest, CompositePartialTest) {
|
|
ReflectedParamUpdater updater;
|
|
|
|
ReflectedParamUpdater::Dict msg;
|
|
msg.emplace("composite.i32", C2Value(1314));
|
|
msg.emplace("composite.str", AString("1516"));
|
|
|
|
updater.addParamDesc(mReflector, mDescriptors);
|
|
|
|
std::vector<C2Param::Index> indices;
|
|
updater.getParamIndicesFromMessage(msg, &indices);
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2IntInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2LongInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(0, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2StringInfo::PARAM_TYPE; }));
|
|
EXPECT_EQ(1, std::count_if(indices.begin(), indices.end(),
|
|
[](const auto &value) { return (uint32_t)value == C2CompositeInfo::PARAM_TYPE; }));
|
|
|
|
std::vector<std::unique_ptr<C2Param>> params;
|
|
params.emplace_back(C2CompositeInfo::AllocUnique(12u));
|
|
EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.i32);
|
|
EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64);
|
|
EXPECT_EQ(0, CastParam<C2CompositeInfo>(params[0])->m.str[0]);
|
|
|
|
updater.updateParamsFromMessage(msg, ¶ms);
|
|
EXPECT_EQ(1314, CastParam<C2CompositeInfo>(params[0])->m.i32);
|
|
EXPECT_EQ(0u, CastParam<C2CompositeInfo>(params[0])->m.u64);
|
|
EXPECT_STREQ("1516", CastParam<C2CompositeInfo>(params[0])->m.str);
|
|
}
|
|
|
|
} // namespace android
|