blob: 36c9a2614ab7a6fc0f8d30be4f2dbafe517b6368 [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 "hasher.h"
#include <iostream>
#include <android-base/logging.h>
#include <hwbinder/IServiceManager.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
#include "ITypes.h"
#include "ISmallTest.h"
#include "BnSmallTest.h"
using std::string;
// libutils:
using android::OK;
using android::sp;
using android::status_t;
using android::String16;
// libbinder:
using android::hardware::getService;
using android::hardware::hidl_version;
using android::hardware::make_hidl_version;
using android::hardware::gen_ref;
using android::hardware::from_ref;
// generated
using android::hardware::tests::ITypes;
using std::cerr;
using std::cout;
using std::endl;
namespace android {
namespace hardware {
namespace tests {
namespace client {
const char kServiceName[] = "android.hardware.tests.ITypes";
bool GetService(sp<ITypes>* service, hidl_version version) {
//cout << "Retrieving test service binder" << endl;
status_t status = getService(String16(kServiceName), version, service);
if (status != OK) {
cerr << "Failed to get service binder: '" << kServiceName
<< "' status=" << status << endl;
return false;
}
return true;
}
} // namespace client
} // namespace tests
} // namespace aidl
} // namespace android
void testHash(sp<ITypes> service, string message = "")
{
static int calls = 0;
calls++;
uint64_t hash;
service->getHash([&hash](auto ret){hash = ret;});
if (hash != getHash()) {
cout << "Hash mismatch: " << hash << " vs. " << getHash();
cout << " on call # " << calls << " - " << message << endl;
}
}
using eu8 = ::android::hardware::tests::ITypes::eu8;
using es8 = ::android::hardware::tests::ITypes::es8;
using eu16 = ::android::hardware::tests::ITypes::eu16;
using es16 = ::android::hardware::tests::ITypes::es16;
using eu32 = ::android::hardware::tests::ITypes::eu32;
using es32 = ::android::hardware::tests::ITypes::es32;
using eu64 = ::android::hardware::tests::ITypes::eu64;
using es64 = ::android::hardware::tests::ITypes::es64;
using ec = ::android::hardware::tests::ITypes::ec;
void enumTestSmall(sp<ITypes> service)
{
service->echoEnum(eu8::U8F, es8::S8F, eu16::U16F, es16::S16F, eu32::U32F, es32::S32F, eu64::U64F, es64::S64F, ec::CF,
[](eu8 a, es8 b, eu16 c, es16 d, eu32 e, es32 f, eu64 g, es64 h, ec i) {
// enum elements have gone through hidl-gen, so I don't fully trust them in a
// test program - it's ugly but I'd rather retype all the numbers.
if (sizeof(a) != 1 || sizeof(b) != 1 || sizeof(c) != 2 || sizeof(d) != 2 ||
sizeof(e) != 4 || sizeof(f) != 4 || sizeof(g) != 8 || sizeof(h) != 8 ||
sizeof(i) != 1) {
cout << "Wrong size of enum" << endl;
}
if ((uint8_t)a != 34) cout << "a wrong" << endl;
if ((int8_t)b != 104) cout << "b wrong" << endl;
if ((uint16_t)c != 234) cout << "c wrong" << endl;
if ((int16_t)d != 334) cout << "d wrong" << endl;
if ((uint32_t)e != 434) cout << "e wrong" << endl;
if ((int32_t)f != 534) cout << "f wrong" << endl;
if ((uint64_t)g != 634) cout << "g wrong" << endl;
if ((int64_t)h != 734) cout << "h wrong" << endl;
if ((uint8_t)i != 43) cout << "i wrong" << endl;
addHash((uint8_t)a);
addHash((int8_t)b);
addHash((uint16_t)c);
addHash((int16_t)d);
addHash((uint32_t)e);
addHash((int32_t)f);
addHash((uint64_t)g);
addHash((int64_t)h);
addHash((uint8_t)i);
});
testHash(service, "after enumTestSmall");
}
void enumTestMin(sp<ITypes> service)
{
service->echoEnum(eu8::min, es8::min, eu16::min, es16::min, eu32::min, es32::min, eu64::min, es64::min, ec::min,
[](eu8 a, es8 b, eu16 c, es16 d, eu32 e, es32 f, eu64 g, es64 h, ec i) {
if ((uint8_t)a != 0) cout << "a wrong" << endl;
if ((int8_t)b != -128) cout << "b wrong" << endl;
if ((uint16_t)c != 0) cout << "c wrong" << endl;
if ((int16_t)d != -32768) cout << "d wrong" << endl;
if ((uint32_t)e != 0) cout << "e wrong" << endl;
if ((int32_t)f != -2147483648) cout << "f wrong" << endl;
if ((uint64_t)g != 0) cout << "g wrong" << endl;
if ((int64_t)h != -9223372036854775807LL) cout << "h wrong" << endl;
if ((uint8_t)i != 0) cout << "i wrong" << endl;
addHash((uint8_t)a);
addHash((int8_t)b);
addHash((uint16_t)c);
addHash((int16_t)d);
addHash((uint32_t)e);
addHash((int32_t)f);
addHash((uint64_t)g);
addHash((int64_t)h);
addHash((uint8_t)i);
});
testHash(service, "after enumTestMin");
}
void enumTestMax(sp<ITypes> service)
{
service->echoEnum(eu8::max, es8::max, eu16::max, es16::max, eu32::max, es32::max, eu64::max, es64::max, ec::max,
[](eu8 a, es8 b, eu16 c, es16 d, eu32 e, es32 f, eu64 g, es64 h, ec i) {
if ((uint8_t)a != 255) cout << "a wrong" << endl;
if ((int8_t)b != 127) cout << "b wrong" << endl;
if ((uint16_t)c != 65535) cout << "c wrong" << endl;
if ((int16_t)d != 32767) cout << "d wrong" << endl;
if ((uint32_t)e != 0xffffffff) cout << "e wrong" << endl;
if ((int32_t)f != 2147483647) cout << "f wrong" << endl;
if ((uint64_t)g != 0xffff'ffff'ffffffffLL) cout << "g wrong" << endl;
if ((int64_t)h != 0x7fff'ffff'ffffffffLL) cout << "h wrong" << endl;
if ((uint8_t)i != 255) cout << "i wrong" << endl;
addHash((uint8_t)a);
addHash((int8_t)b);
addHash((uint16_t)c);
addHash((int16_t)d);
addHash((uint32_t)e);
addHash((int32_t)f);
addHash((uint64_t)g);
addHash((int64_t)h);
addHash((uint8_t)i);
});
testHash(service, "after enumTestMax");
}
void scalarTestSmall(sp<ITypes> service)
{
service->echoScalar(34, 104, 234, 334, 434, 534, 634, 734, 43,
[](uint8_t a, int8_t b, uint16_t c, int16_t d, uint32_t e, int32_t f, uint64_t g, int64_t h, char i) {
if (a != 34) cout << "a wrong" << endl;
if (b != 104) cout << "b wrong" << endl;
if (c != 234) cout << "c wrong" << endl;
if (d != 334) cout << "d wrong" << endl;
if (e != 434) cout << "e wrong" << endl;
if (f != 534) cout << "f wrong" << endl;
if (g != 634) cout << "g wrong" << endl;
if (h != 734) cout << "h wrong" << endl;
if (i != 43) cout << "i wrong" << endl;
addHash(a);
addHash(b);
addHash(c);
addHash(d);
addHash(e);
addHash(f);
addHash(g);
addHash(h);
addHash(i);
});
testHash(service, "after scalarTestSmall");
}
void scalarTestMin(sp<ITypes> service)
{
service->echoScalar(0, -128, 0, -32768, 0, -2147483648,
0, -9223372036854775807LL, 0,
[](uint8_t a, int8_t b, uint16_t c, int16_t d, uint32_t e, int32_t f, uint64_t g, int64_t h, char i) {
if (a != 0) cout << "a wrong" << endl;
if (b != -128) cout << "b wrong" << endl;
if (c != 0) cout << "c wrong" << endl;
if (d != -32768) cout << "d wrong" << endl;
if (e != 0) cout << "e wrong" << endl;
if (f != -2147483648) cout << "f wrong" << endl;
if (g != 0) cout << "g wrong" << endl;
if (h != -9223372036854775807LL) cout << "h wrong" << endl;
if (i != 0) cout << "i wrong" << endl;
addHash(a);
addHash(b);
addHash(c);
addHash(d);
addHash(e);
addHash(f);
addHash(g);
addHash(h);
addHash(i);
});
testHash(service, "after scalarTestMin");
}
void scalarTestMax(sp<ITypes> service)
{
service->echoScalar(255, 127, 65535, 32767, 0xffffffff, 0x7fffffff,
0xffff'ffff'ffffffffLL, 0x7fff'ffff'ffffffffLL, 255,
[](uint8_t a, int8_t b, uint16_t c, int16_t d, uint32_t e, int32_t f, uint64_t g, int64_t h, char i) {
if (a != 255) cout << "a wrong" << endl;
if (b != 127) cout << "b wrong" << endl;
if (c != 65535) cout << "c wrong" << endl;
if (d != 32767) cout << "d wrong" << endl;
if (e != 0xffffffff) cout << "e wrong" << endl;
if (f != 2147483647) cout << "f wrong" << endl;
if (g != 0xffff'ffff'ffffffffLL) cout << "g wrong" << endl;
if (h != 0x7fff'ffff'ffffffffLL) cout << "h wrong" << endl;
if (i != 255) cout << "i wrong" << endl;
addHash(a);
addHash(b);
addHash(c);
addHash(d);
addHash(e);
addHash(f);
addHash(g);
addHash(h);
addHash(i);
});
testHash(service, "after scalarTestMax");
}
using disc = ::android::hardware::tests::ITypes::disc;
void nestedTest(sp<ITypes> service)
{
char cs1[]{"HiWorld"};
char cs2[]{"JiWorldFoo"};
char cs3[]{"QiWorld"};
char cs4[]{"FiWorld"};
char cs5[]{"WiWorld"};
ITypes::s0 v0;
ITypes::s1s v1[2];
v0.s1v2.count = 2;
v0.s1v2.buffer = v1;
v0.s1m1.str1.buffer = cs1;
v0.s1m1.str1.length = -1;
v1[0].str1.buffer = cs3;
v1[0].str1.length = -1;
v1[1].str1.buffer = cs4;
v1[1].str1.length = 5;
// v0.s1m1.dm1 = disc::US;
// v0.s1m1.u1m1.s.buffer = cs1;
// v0.s1m1.u1m1.s.length = -1;
// v1[0].dm1 = disc::UF;
/* int32_t *data_ptr;
int fd = -1;
gen_ref(&fd, &data_ptr);
*data_ptr = 0xbeefcafe;
if (fd >= 0) {
v1[0].u1m1.fd = fd;
} else {
cout << "Couldn't get fd in nestedTest" << endl;
}*/
// v1[1].dm1 = disc::UI;
// v1[1].u1m1.i = 0xada;
// v0.s1m3.dm1 = disc::UC;
// v0.s1m3.u1m1.s2m.i = 0xabcdef;
cout << "Client: About to call echoStruct" << endl;
printf("C: &v0 %p v0.s1m1.str1.buf %p v0.s1v2.buf %p v0.s1v2.buf[0].str1.buf %p [1] %p\n",
&v0, v0.s1m1.str1.buffer, v0.s1v2.buffer, v0.s1v2.buffer[0].str1.buffer, v0.s1v2.buffer[1].str1.buffer);
service->echoStruct(v0, [](const /*android::hardware::tests::ITypes::s0 */ auto & s){
cout << "Client: in callback, s is " << &s << endl;
printf("C: s %p s.s1m1.str1.buf %p s.s1v2.buf %p s.s1v2.buf[0].str1.buf %p [1] %p\n",
&s, s.s1m1.str1.buffer, s.s1v2.buffer, s.s1v2.buffer[0].str1.buffer, s.s1v2.buffer[1].str1.buffer);
int i = s.s1v2.count;
cout << "Client: vec count(2?): " << i << endl;
printf("s1m1 len is %ld\n", s.s1m1.str1.length);
printf("s1m1 str is %s\n", s.s1m1.str1.buffer);
printf("s1v2[0] len is %ld\n", s.s1v2.buffer[0].str1.length);
printf("s1v2[0] str is %s\n", s.s1v2.buffer[0].str1.buffer);
printf("s1v2[1] len is %ld\n", s.s1v2.buffer[0].str1.length);
printf("s1v2[1] bytes is %c%c%c%c%c\n", s.s1v2.buffer[0].str1.buffer[0],
s.s1v2.buffer[0].str1.buffer[1],s.s1v2.buffer[0].str1.buffer[2],
s.s1v2.buffer[0].str1.buffer[3],s.s1v2.buffer[0].str1.buffer[4]);
});
}
// This implementation of BnSmallTest is used to verify that interfaces
// can be passed around as parameters.
class CallbackTester : public android::hardware::tests::BnSmallTest {
public:
CallbackTester() {}
virtual ~CallbackTester() = default;
virtual android::hardware::Status echoNumber(
uint32_t some_number,
ISmallTest::echoNumber_cb the_callback) {
// Simply echo the given number back to the caller.
the_callback(some_number);
return android::hardware::Status::ok();
}
};
// Passes a CallbackTester object to the server, gets it back,
// and verifies that it works.
void RunCallbackTest(sp<ITypes> service)
{
android::sp<CallbackTester> call_server = new CallbackTester;
bool all_is_happy = false;
service->echoInterface(
call_server,
[&](android::sp<android::hardware::tests::ISmallTest> cb) {
// cb should be a working CallbackTester object. Here we
// verify that it works, echoing the given integer.
cb->echoNumber(42, [&](const uint32_t should_be_42) {
if (should_be_42 == 42) {
all_is_happy = true;
} else {
// TODO(cphoenix): Printf's aren't the right way to deal with errors
printf("Bad value %d received in client callback test\n",
should_be_42);
}
});
});
if (!all_is_happy) {
printf("Error in callbackTest (check if callback was called)\n");
}
}
int main(int /* argc */, char * argv []) {
cout << " Running tests" << endl;
android::base::InitLogging(argv, android::base::StderrLogger);
sp<ITypes> service;
namespace client_tests = android::hardware::tests::client;
hidl_version version = make_hidl_version(4,0);
if (!client_tests::GetService(&service, version)) {
cout << " * * Client couldn't find server * * " << endl;
return 1;
}
ITypes::simple_t sts;
sts.int1 = sts.int2 = 17;
service->echoInteger(42, sts, [](int ret){
if (ret != 42) cout << "Client: echoInteger returned " << ret << " instead of 42" << endl;});
addHash(42);
addHash(sts.int1);
addHash(sts.int2);
enumTestSmall(service);
enumTestMin(service);
enumTestMax(service);
scalarTestSmall(service);
scalarTestMin(service);
scalarTestMax(service);
nestedTest(service);
RunCallbackTest(service);
service->quit();
cout << " Tests completed" << endl;
return 0;
}