222 lines
7.2 KiB
C++
222 lines
7.2 KiB
C++
/*
|
|
* Copyright (C) 2021 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.
|
|
*/
|
|
|
|
#include <aidl/android/aidl/loggable/ILoggableInterface.h>
|
|
|
|
#include <functional>
|
|
|
|
#include <android/binder_auto_utils.h>
|
|
#include <android/binder_manager.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h>
|
|
#include <aidl/android/aidl/tests/ITestService.h>
|
|
#include <aidl/android/aidl/tests/RecursiveList.h>
|
|
#include <aidl/android/aidl/tests/Union.h>
|
|
|
|
using aidl::android::aidl::fixedsizearray::FixedSizeArrayExample;
|
|
using BnRepeatFixedSizeArray =
|
|
aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnRepeatFixedSizeArray;
|
|
using BpRepeatFixedSizeArray =
|
|
aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BpRepeatFixedSizeArray;
|
|
using IntParcelable = aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable;
|
|
using IRepeatFixedSizeArray =
|
|
aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IRepeatFixedSizeArray;
|
|
using BnEmptyInterface =
|
|
aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnEmptyInterface;
|
|
using aidl::android::aidl::tests::BackendType;
|
|
using aidl::android::aidl::tests::ITestService;
|
|
using aidl::android::aidl::tests::RecursiveList;
|
|
using aidl::android::aidl::tests::Union;
|
|
using android::OK;
|
|
using ndk::AParcel_readData;
|
|
using ndk::AParcel_writeData;
|
|
using ndk::ScopedAStatus;
|
|
using ndk::SharedRefBase;
|
|
using ndk::SpAIBinder;
|
|
|
|
struct AidlTest : testing::Test {
|
|
template <typename T>
|
|
std::shared_ptr<T> getService() {
|
|
ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
|
|
return T::fromBinder(binder);
|
|
}
|
|
};
|
|
|
|
// TODO(b/196454897): copy more tests from aidl_test_client
|
|
|
|
TEST_F(AidlTest, ReverseRecursiveList) {
|
|
std::unique_ptr<RecursiveList> head;
|
|
for (int i = 0; i < 10; i++) {
|
|
auto node = std::make_unique<RecursiveList>();
|
|
node->value = i;
|
|
node->next = std::move(head);
|
|
head = std::move(node);
|
|
}
|
|
// head: [9, 8, ... 0]
|
|
|
|
RecursiveList reversed;
|
|
auto status = getService<ITestService>()->ReverseList(*head, &reversed);
|
|
ASSERT_TRUE(status.isOk());
|
|
|
|
// reversed should be [0, 1, .. 9]
|
|
RecursiveList* cur = &reversed;
|
|
for (int i = 0; i < 10; i++) {
|
|
EXPECT_EQ(i, cur->value);
|
|
cur = cur->next.get();
|
|
}
|
|
EXPECT_EQ(nullptr, cur);
|
|
}
|
|
|
|
TEST_F(AidlTest, GetUnionTags) {
|
|
std::vector<Union> unions;
|
|
std::vector<Union::Tag> tags;
|
|
// test empty
|
|
auto status = getService<ITestService>()->GetUnionTags(unions, &tags);
|
|
ASSERT_TRUE(status.isOk());
|
|
EXPECT_EQ(tags, (std::vector<Union::Tag>{}));
|
|
// test non-empty
|
|
unions.push_back(Union::make<Union::n>());
|
|
unions.push_back(Union::make<Union::ns>());
|
|
status = getService<ITestService>()->GetUnionTags(unions, &tags);
|
|
ASSERT_TRUE(status.isOk());
|
|
EXPECT_EQ(tags, (std::vector<Union::Tag>{Union::n, Union::ns}));
|
|
}
|
|
|
|
TEST_F(AidlTest, FixedSizeArray) {
|
|
auto parcel = AParcel_create();
|
|
|
|
FixedSizeArrayExample p;
|
|
p.byteMatrix[0][0] = 0;
|
|
p.byteMatrix[0][1] = 1;
|
|
p.byteMatrix[1][0] = 2;
|
|
p.byteMatrix[1][1] = 3;
|
|
p.floatMatrix[0][0] = 0.f;
|
|
p.floatMatrix[0][1] = 1.f;
|
|
p.floatMatrix[1][0] = 2.f;
|
|
p.floatMatrix[1][1] = 3.f;
|
|
EXPECT_EQ(OK, p.writeToParcel(parcel));
|
|
|
|
AParcel_setDataPosition(parcel, 0);
|
|
|
|
FixedSizeArrayExample q;
|
|
EXPECT_EQ(OK, q.readFromParcel(parcel));
|
|
EXPECT_EQ(p, q);
|
|
|
|
AParcel_delete(parcel);
|
|
}
|
|
|
|
TEST_F(AidlTest, FixedSizeArrayWithValuesAtNullableFields) {
|
|
auto parcel = AParcel_create();
|
|
|
|
FixedSizeArrayExample p;
|
|
p.boolNullableArray = std::array<bool, 2>{true, false};
|
|
p.byteNullableArray = std::array<uint8_t, 2>{42, 0};
|
|
p.stringNullableArray = std::array<std::optional<std::string>, 2>{"hello", "world"};
|
|
|
|
p.boolNullableMatrix.emplace();
|
|
p.boolNullableMatrix->at(0) = std::array<bool, 2>{true, false};
|
|
p.byteNullableMatrix.emplace();
|
|
p.byteNullableMatrix->at(0) = std::array<uint8_t, 2>{42, 0};
|
|
p.stringNullableMatrix.emplace();
|
|
p.stringNullableMatrix->at(0) = std::array<std::optional<std::string>, 2>{"hello", "world"};
|
|
|
|
EXPECT_EQ(OK, p.writeToParcel(parcel));
|
|
|
|
AParcel_setDataPosition(parcel, 0);
|
|
|
|
FixedSizeArrayExample q;
|
|
EXPECT_EQ(OK, q.readFromParcel(parcel));
|
|
EXPECT_EQ(p, q);
|
|
|
|
AParcel_delete(parcel);
|
|
}
|
|
|
|
TEST_F(AidlTest, FixedSizeArrayOfBytesShouldBePacked) {
|
|
auto parcel = AParcel_create();
|
|
|
|
std::array<std::array<uint8_t, 3>, 2> byte_array;
|
|
byte_array[0] = {1, 2, 3};
|
|
byte_array[1] = {4, 5, 6};
|
|
EXPECT_EQ(OK, AParcel_writeData(parcel, byte_array));
|
|
|
|
AParcel_setDataPosition(parcel, 0);
|
|
|
|
int32_t len;
|
|
EXPECT_EQ(OK, AParcel_readData(parcel, &len));
|
|
EXPECT_EQ(2, len);
|
|
std::vector<uint8_t> byte_vector;
|
|
EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
|
|
EXPECT_EQ(byte_vector, (std::vector<uint8_t>{1, 2, 3}));
|
|
EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
|
|
EXPECT_EQ(byte_vector, (std::vector<uint8_t>{4, 5, 6}));
|
|
|
|
AParcel_delete(parcel);
|
|
}
|
|
|
|
template <typename Service, typename MemFn, typename Input>
|
|
void CheckRepeat(Service service, MemFn fn, Input input) {
|
|
Input out1, out2;
|
|
EXPECT_TRUE(std::invoke(fn, service, input, &out1, &out2).isOk());
|
|
EXPECT_EQ(input, out1);
|
|
EXPECT_EQ(input, out2);
|
|
}
|
|
|
|
template <typename T>
|
|
std::array<std::array<T, 3>, 2> Make2dArray(std::initializer_list<T> values) {
|
|
std::array<std::array<T, 3>, 2> arr = {};
|
|
auto it = std::begin(values);
|
|
for (auto& row : arr) {
|
|
for (auto& el : row) {
|
|
if (it == std::end(values)) break;
|
|
el = *it++;
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
TEST_F(AidlTest, FixedSizeArrayOverBinder) {
|
|
auto service = getService<IRepeatFixedSizeArray>();
|
|
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
|
|
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::RepeatInts, (std::array<int32_t, 3>{1, 2, 3}));
|
|
|
|
auto binder1 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
|
|
auto binder2 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
|
|
auto binder3 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBinders,
|
|
(std::array<SpAIBinder, 3>{binder1, binder2, binder3}));
|
|
|
|
IntParcelable p1, p2, p3;
|
|
p1.value = 1;
|
|
p2.value = 2;
|
|
p3.value = 3;
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::RepeatParcelables,
|
|
(std::array<IntParcelable, 3>{p1, p2, p3}));
|
|
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBytes, Make2dArray<uint8_t>({1, 2, 3}));
|
|
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dInts, Make2dArray<int32_t>({1, 2, 3}));
|
|
|
|
// Not-nullable
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBinders,
|
|
Make2dArray<SpAIBinder>({binder1, binder2, binder3, binder1, binder2, binder3}));
|
|
|
|
CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dParcelables,
|
|
Make2dArray<IntParcelable>({p1, p2, p3}));
|
|
}
|