blob: 961b38fd2e0d778c0af7ac7a76e713fb26c4dc0f [file] [log] [blame]
/*
* Copyright (C) 2015, 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 <string>
#include <gtest/gtest.h>
#include "aidl.h"
#include "aidl_language.h"
#include "ast_cpp.h"
#include "code_writer.h"
#include "generate_cpp.h"
#include "tests/fake_io_delegate.h"
#include "tests/test_util.h"
#include "type_cpp.h"
using android::aidl::test::FakeIoDelegate;
using std::string;
using std::unique_ptr;
namespace android {
namespace aidl {
namespace cpp {
namespace {
const string kComplexTypeInterfaceAIDL =
R"(package android.os;
import foo.IFooType;
interface IComplexTypeInterface {
int[] Send(in int[] goes_in, inout double[] goes_in_and_out, out boolean[] goes_out);
oneway void Piff(int times);
IFooType TakesABinder(IFooType f);
List<String> StringListMethod(in java.util.List<String> input, out List<String> output);
List<IBinder> BinderListMethod(in java.util.List<IBinder> input, out List<IBinder> output);
})";
const char kExpectedComplexTypeClientHeaderOutput[] =
R"(#ifndef AIDL_GENERATED_ANDROID_OS_BP_COMPLEX_TYPE_INTERFACE_H_
#define AIDL_GENERATED_ANDROID_OS_BP_COMPLEX_TYPE_INTERFACE_H_
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <utils/Errors.h>
#include <android/os/IComplexTypeInterface.h>
namespace android {
namespace os {
class BpComplexTypeInterface : public android::BpInterface<IComplexTypeInterface> {
public:
explicit BpComplexTypeInterface(const android::sp<android::IBinder>& impl);
virtual ~BpComplexTypeInterface() = default;
android::status_t Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) override;
android::status_t Piff(int32_t times) override;
android::status_t TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) override;
android::status_t StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) override;
android::status_t BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) override;
}; // class BpComplexTypeInterface
} // namespace os
} // namespace android
#endif // AIDL_GENERATED_ANDROID_OS_BP_COMPLEX_TYPE_INTERFACE_H_)";
const char kExpectedComplexTypeClientSourceOutput[] =
R"(#include <android/os/BpComplexTypeInterface.h>
#include <binder/Parcel.h>
namespace android {
namespace os {
BpComplexTypeInterface::BpComplexTypeInterface(const android::sp<android::IBinder>& impl)
: BpInterface<IComplexTypeInterface>(impl){
}
android::status_t BpComplexTypeInterface::Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) {
android::Parcel data;
android::Parcel reply;
android::status_t status;
status = data.writeInterfaceToken(getInterfaceDescriptor());
if (((status) != (android::OK))) {
return status;
}
status = data.writeInt32Vector(goes_in);
if (((status) != (android::OK))) {
return status;
}
status = data.writeDoubleVector(*goes_in_and_out);
if (((status) != (android::OK))) {
return status;
}
status = remote()->transact(IComplexTypeInterface::SEND, data, &reply);
if (((status) != (android::OK))) {
return status;
}
if (reply.readExceptionCode()) {
status = android::FAILED_TRANSACTION;
return status;
}
status = reply.readInt32Vector(_aidl_return);
if (((status) != (android::OK))) {
return status;
}
status = reply.readDoubleVector(goes_in_and_out);
if (((status) != (android::OK))) {
return status;
}
status = reply.readBoolVector(goes_out);
if (((status) != (android::OK))) {
return status;
}
return status;
}
android::status_t BpComplexTypeInterface::Piff(int32_t times) {
android::Parcel data;
android::Parcel reply;
android::status_t status;
status = data.writeInterfaceToken(getInterfaceDescriptor());
if (((status) != (android::OK))) {
return status;
}
status = data.writeInt32(times);
if (((status) != (android::OK))) {
return status;
}
status = remote()->transact(IComplexTypeInterface::PIFF, data, &reply, android::IBinder::FLAG_ONEWAY);
if (((status) != (android::OK))) {
return status;
}
return status;
}
android::status_t BpComplexTypeInterface::TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) {
android::Parcel data;
android::Parcel reply;
android::status_t status;
status = data.writeInterfaceToken(getInterfaceDescriptor());
if (((status) != (android::OK))) {
return status;
}
status = data.writeStrongBinder(IFooType::asBinder(f));
if (((status) != (android::OK))) {
return status;
}
status = remote()->transact(IComplexTypeInterface::TAKESABINDER, data, &reply);
if (((status) != (android::OK))) {
return status;
}
if (reply.readExceptionCode()) {
status = android::FAILED_TRANSACTION;
return status;
}
status = reply.readStrongBinder(_aidl_return);
if (((status) != (android::OK))) {
return status;
}
return status;
}
android::status_t BpComplexTypeInterface::StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) {
android::Parcel data;
android::Parcel reply;
android::status_t status;
status = data.writeInterfaceToken(getInterfaceDescriptor());
if (((status) != (android::OK))) {
return status;
}
status = data.writeString16Vector(input);
if (((status) != (android::OK))) {
return status;
}
status = remote()->transact(IComplexTypeInterface::STRINGLISTMETHOD, data, &reply);
if (((status) != (android::OK))) {
return status;
}
if (reply.readExceptionCode()) {
status = android::FAILED_TRANSACTION;
return status;
}
status = reply.readString16Vector(_aidl_return);
if (((status) != (android::OK))) {
return status;
}
status = reply.readString16Vector(output);
if (((status) != (android::OK))) {
return status;
}
return status;
}
android::status_t BpComplexTypeInterface::BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) {
android::Parcel data;
android::Parcel reply;
android::status_t status;
status = data.writeInterfaceToken(getInterfaceDescriptor());
if (((status) != (android::OK))) {
return status;
}
status = data.writeStrongBinderVector(input);
if (((status) != (android::OK))) {
return status;
}
status = remote()->transact(IComplexTypeInterface::BINDERLISTMETHOD, data, &reply);
if (((status) != (android::OK))) {
return status;
}
if (reply.readExceptionCode()) {
status = android::FAILED_TRANSACTION;
return status;
}
status = reply.readStrongBinderVector(_aidl_return);
if (((status) != (android::OK))) {
return status;
}
status = reply.readStrongBinderVector(output);
if (((status) != (android::OK))) {
return status;
}
return status;
}
} // namespace os
} // namespace android
)";
const char kExpectedComplexTypeServerHeaderOutput[] =
R"(#ifndef AIDL_GENERATED_ANDROID_OS_BN_COMPLEX_TYPE_INTERFACE_H_
#define AIDL_GENERATED_ANDROID_OS_BN_COMPLEX_TYPE_INTERFACE_H_
#include <binder/IInterface.h>
#include <android/os/IComplexTypeInterface.h>
namespace android {
namespace os {
class BnComplexTypeInterface : public android::BnInterface<IComplexTypeInterface> {
public:
android::status_t onTransact(uint32_t code, const android::Parcel& data, android::Parcel* reply, uint32_t flags = 0) override;
}; // class BnComplexTypeInterface
} // namespace os
} // namespace android
#endif // AIDL_GENERATED_ANDROID_OS_BN_COMPLEX_TYPE_INTERFACE_H_)";
const char kExpectedComplexTypeServerSourceOutput[] =
R"(#include <android/os/BnComplexTypeInterface.h>
#include <binder/Parcel.h>
namespace android {
namespace os {
android::status_t BnComplexTypeInterface::onTransact(uint32_t code, const android::Parcel& data, android::Parcel* reply, uint32_t flags) {
android::status_t status;
switch (code) {
case Call::SEND:
{
std::vector<int32_t> in_goes_in;
std::vector<double> in_goes_in_and_out;
std::vector<bool> out_goes_out;
std::vector<int32_t> _aidl_return;
if ((!data.checkInterface(this))) {
status = android::BAD_TYPE;
break;
}
status = data.readInt32Vector(&in_goes_in);
if (((status) != (android::OK))) {
break;
}
status = data.readDoubleVector(&in_goes_in_and_out);
if (((status) != (android::OK))) {
break;
}
status = Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeNoException();
if (((status) != (android::OK))) {
break;
}
status = reply->writeInt32Vector(_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeDoubleVector(in_goes_in_and_out);
if (((status) != (android::OK))) {
break;
}
status = reply->writeBoolVector(out_goes_out);
if (((status) != (android::OK))) {
break;
}
}
break;
case Call::PIFF:
{
int32_t in_times;
if ((!data.checkInterface(this))) {
status = android::BAD_TYPE;
break;
}
status = data.readInt32(&in_times);
if (((status) != (android::OK))) {
break;
}
status = Piff(in_times);
if (((status) != (android::OK))) {
break;
}
status = reply->writeNoException();
if (((status) != (android::OK))) {
break;
}
}
break;
case Call::TAKESABINDER:
{
android::sp<::foo::IFooType> in_f;
android::sp<::foo::IFooType> _aidl_return;
if ((!data.checkInterface(this))) {
status = android::BAD_TYPE;
break;
}
status = data.readStrongBinder(&in_f);
if (((status) != (android::OK))) {
break;
}
status = TakesABinder(in_f, &_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeNoException();
if (((status) != (android::OK))) {
break;
}
status = reply->writeStrongBinder(IFooType::asBinder(_aidl_return));
if (((status) != (android::OK))) {
break;
}
}
break;
case Call::STRINGLISTMETHOD:
{
std::vector<android::String16> in_input;
std::vector<android::String16> out_output;
std::vector<android::String16> _aidl_return;
if ((!data.checkInterface(this))) {
status = android::BAD_TYPE;
break;
}
status = data.readString16Vector(&in_input);
if (((status) != (android::OK))) {
break;
}
status = StringListMethod(in_input, &out_output, &_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeNoException();
if (((status) != (android::OK))) {
break;
}
status = reply->writeString16Vector(_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeString16Vector(out_output);
if (((status) != (android::OK))) {
break;
}
}
break;
case Call::BINDERLISTMETHOD:
{
std::vector<android::sp<::android::IBinder>> in_input;
std::vector<android::sp<::android::IBinder>> out_output;
std::vector<android::sp<::android::IBinder>> _aidl_return;
if ((!data.checkInterface(this))) {
status = android::BAD_TYPE;
break;
}
status = data.readStrongBinderVector(&in_input);
if (((status) != (android::OK))) {
break;
}
status = BinderListMethod(in_input, &out_output, &_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeNoException();
if (((status) != (android::OK))) {
break;
}
status = reply->writeStrongBinderVector(_aidl_return);
if (((status) != (android::OK))) {
break;
}
status = reply->writeStrongBinderVector(out_output);
if (((status) != (android::OK))) {
break;
}
}
break;
default:
{
status = android::BBinder::onTransact(code, data, reply, flags);
}
break;
}
return status;
}
} // namespace os
} // namespace android
)";
const char kExpectedComplexTypeInterfaceHeaderOutput[] =
R"(#ifndef AIDL_GENERATED_ANDROID_OS_I_COMPLEX_TYPE_INTERFACE_H_
#define AIDL_GENERATED_ANDROID_OS_I_COMPLEX_TYPE_INTERFACE_H_
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <cstdint>
#include <foo/IFooType.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
#include <vector>
namespace android {
namespace os {
class IComplexTypeInterface : public android::IInterface {
public:
DECLARE_META_INTERFACE(ComplexTypeInterface);
virtual android::status_t Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) = 0;
virtual android::status_t Piff(int32_t times) = 0;
virtual android::status_t TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) = 0;
virtual android::status_t StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) = 0;
virtual android::status_t BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) = 0;
enum Call {
SEND = android::IBinder::FIRST_CALL_TRANSACTION + 0,
PIFF = android::IBinder::FIRST_CALL_TRANSACTION + 1,
TAKESABINDER = android::IBinder::FIRST_CALL_TRANSACTION + 2,
STRINGLISTMETHOD = android::IBinder::FIRST_CALL_TRANSACTION + 3,
BINDERLISTMETHOD = android::IBinder::FIRST_CALL_TRANSACTION + 4,
};
}; // class IComplexTypeInterface
} // namespace os
} // namespace android
#endif // AIDL_GENERATED_ANDROID_OS_I_COMPLEX_TYPE_INTERFACE_H_)";
const char kExpectedComplexTypeInterfaceSourceOutput[] =
R"(#include <android/os/IComplexTypeInterface.h>
#include <android/os/BpComplexTypeInterface.h>
namespace android {
namespace os {
IMPLEMENT_META_INTERFACE(ComplexTypeInterface, "android.os.IComplexTypeInterface");
} // namespace os
} // namespace android
)";
} // namespace
class ASTTest : public ::testing::Test {
protected:
ASTTest(string file_path, string file_contents)
: file_path_(file_path),
file_contents_(file_contents) {
types_.Init();
}
unique_ptr<AidlInterface> Parse() {
io_delegate_.SetFileContents(file_path_, file_contents_);
unique_ptr<AidlInterface> ret;
std::vector<std::unique_ptr<AidlImport>> imports;
int err = ::android::aidl::internals::load_and_validate_aidl(
{}, // no preprocessed files
{"."},
file_path_,
io_delegate_,
&types_,
&ret,
&imports);
if (err)
return nullptr;
return ret;
}
void Compare(Document* doc, const char* expected) {
string output;
unique_ptr<CodeWriter> cw = GetStringWriter(&output);
doc->Write(cw.get());
if (expected == output) {
return; // Success
}
test::PrintDiff(expected, output);
FAIL() << "Document contents did not match expected contents";
}
const string file_path_;
const string file_contents_;
FakeIoDelegate io_delegate_;
TypeNamespace types_;
};
class ComplexTypeInterfaceASTTest : public ASTTest {
public:
ComplexTypeInterfaceASTTest()
: ASTTest("android/os/IComplexTypeInterface.aidl",
kComplexTypeInterfaceAIDL) {
io_delegate_.SetFileContents("foo/IFooType.aidl",
"package foo; interface IFooType {}");
}
};
TEST_F(ComplexTypeInterfaceASTTest, GeneratesClientHeader) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildClientHeader(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeClientHeaderOutput);
}
TEST_F(ComplexTypeInterfaceASTTest, GeneratesClientSource) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildClientSource(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeClientSourceOutput);
}
TEST_F(ComplexTypeInterfaceASTTest, GeneratesServerHeader) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildServerHeader(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeServerHeaderOutput);
}
TEST_F(ComplexTypeInterfaceASTTest, GeneratesServerSource) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildServerSource(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeServerSourceOutput);
}
TEST_F(ComplexTypeInterfaceASTTest, GeneratesInterfaceHeader) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildInterfaceHeader(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeInterfaceHeaderOutput);
}
TEST_F(ComplexTypeInterfaceASTTest, GeneratesInterfaceSource) {
unique_ptr<AidlInterface> interface = Parse();
ASSERT_NE(interface, nullptr);
unique_ptr<Document> doc = internals::BuildInterfaceSource(types_, *interface);
Compare(doc.get(), kExpectedComplexTypeInterfaceSourceOutput);
}
} // namespace cpp
} // namespace aidl
} // namespace android