libgbinder/unit/unit_reader/unit_reader.c

2664 lines
85 KiB
C

/*
* Copyright (C) 2018-2022 Jolla Ltd.
* Copyright (C) 2018-2024 Slava Monich <slava@monich.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_common.h"
#include "test_binder.h"
#include "gbinder_buffer_p.h"
#include "gbinder_driver.h"
#include "gbinder_ipc.h"
#include "gbinder_reader_p.h"
#include "gbinder_remote_object_p.h"
#include "gbinder_io.h"
#include <gutil_misc.h>
#include <unistd.h>
#include <fcntl.h>
static TestOpt test_opt;
typedef struct binder_buffer_object_64 {
guint32 type;
guint32 flags;
union {
const void* ptr;
guint64 value;
} buffer;
guint64 length;
guint64 parent;
guint64 parent_offset;
} BinderObject64;
#define BINDER_TYPE_(c1,c2,c3) GBINDER_FOURCC(c1,c2,c3,0x85)
#define BINDER_TYPE_FD BINDER_TYPE_('f', 'd', '*')
#define BINDER_BUFFER_FLAG_HAS_PARENT 0x01
#define BINDER_FLAG_ACCEPTS_FDS 0x100
G_STATIC_ASSERT(sizeof(BinderObject64) == BUFFER_OBJECT_SIZE_64);
static
void
test_init_reader(
GBinderDriver* driver,
GBinderReaderData* data,
GBinderReader* reader,
const void* bytes,
gsize size)
{
data->buffer = gbinder_buffer_new(driver, gutil_memdup(bytes, size),
size, NULL);
gbinder_reader_init(reader, data, 0, size);
}
/*==========================================================================*
* null
*==========================================================================*/
static
void
test_null(
void)
{
GBinderReader reader;
/* NULL const pointers are tolerated */
g_assert(gbinder_reader_at_end(NULL));
g_assert(!gbinder_reader_bytes_read(NULL));
g_assert(!gbinder_reader_bytes_remaining(NULL));
g_assert(!gbinder_reader_get_data(NULL, NULL));
gbinder_reader_copy(&reader, NULL);
g_assert(gbinder_reader_at_end(&reader));
}
/*==========================================================================*
* empty
*==========================================================================*/
static
void
test_empty(
void)
{
GBinderReader reader;
gsize count = 1, elemsize = 1;
gsize size = 1;
gbinder_reader_init(&reader, NULL, 0, 0);
g_assert(gbinder_reader_at_end(&reader));
g_assert(!gbinder_reader_get_data(&reader, NULL));
g_assert(!gbinder_reader_get_data(&reader, &size));
g_assert(!size);
g_assert(!gbinder_reader_bytes_read(&reader));
g_assert(!gbinder_reader_bytes_remaining(&reader));
g_assert(!gbinder_reader_read_byte(&reader, NULL));
g_assert(!gbinder_reader_read_bool(&reader, NULL));
g_assert(!gbinder_reader_read_int8(&reader, NULL));
g_assert(!gbinder_reader_read_int16(&reader, NULL));
g_assert(!gbinder_reader_read_int32(&reader, NULL));
g_assert(!gbinder_reader_read_uint32(&reader, NULL));
g_assert(!gbinder_reader_read_int64(&reader, NULL));
g_assert(!gbinder_reader_read_uint64(&reader, NULL));
g_assert(!gbinder_reader_read_float(&reader, NULL));
g_assert(!gbinder_reader_read_double(&reader, NULL));
g_assert(!gbinder_reader_read_object(&reader));
g_assert(!gbinder_reader_read_nullable_object(&reader, NULL));
g_assert(!gbinder_reader_read_buffer(&reader));
g_assert(!gbinder_reader_read_parcelable(&reader, NULL));
g_assert(!gbinder_reader_read_hidl_struct1(&reader, 1));
g_assert(!gbinder_reader_read_hidl_vec(&reader, NULL, NULL));
g_assert(!gbinder_reader_read_hidl_vec(&reader, &count, &elemsize));
g_assert(!gbinder_reader_read_hidl_vec1(&reader, NULL, 1));
g_assert(!gbinder_reader_read_hidl_vec1(&reader, &count, 1));
g_assert(!count);
g_assert(!elemsize);
g_assert(!gbinder_reader_skip_hidl_string(&reader));
g_assert(!gbinder_reader_read_hidl_string(&reader));
g_assert(!gbinder_reader_read_hidl_string_vec(&reader));
g_assert(!gbinder_reader_skip_buffer(&reader));
g_assert(!gbinder_reader_read_string8(&reader));
g_assert(!gbinder_reader_read_string16(&reader));
g_assert(!gbinder_reader_skip_string16(&reader));
g_assert(!gbinder_reader_read_byte_array(&reader, &size));
}
/*==========================================================================*
* byte
*==========================================================================*/
static
void
test_byte(
void)
{
const guint8 in = 42;
guint8 out = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_byte(&reader, &out));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpuint(in, == ,out);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_byte(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* bool
*==========================================================================*/
static
void
test_bool(
void)
{
const guint8 in_short[] = { 0 };
const guint8 in_true[] = { TEST_INT8_BYTES_4(TRUE) };
const guint8 in_false[] = { TEST_INT8_BYTES_4(FALSE) };
gboolean out = FALSE;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
/* not enough data */
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(in_short)), sizeof(in_short), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(!gbinder_reader_read_bool(&reader, NULL));
g_assert(!gbinder_reader_read_bool(&reader, &out));
g_assert(!gbinder_reader_at_end(&reader));
/* true */
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(in_true)), sizeof(in_true), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, &out));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpuint(out, == ,TRUE);
/* false */
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(in_false)), sizeof(in_false), NULL);
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(gbinder_reader_read_bool(&reader, &out));
g_assert(gbinder_reader_at_end(&reader));
g_assert(out == FALSE);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* int8
*==========================================================================*/
static
void
test_int8(
void)
{
const guint8 in = 0x2a;
const guint8 in4[] = { 0x2a, 0x00, 0x00, 0x00 };
guint8 out1 = 0;
gint8 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
/* Not enough data */
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(!gbinder_reader_read_uint8(&reader, &out1));
g_assert(!gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
/* Enough data */
data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
sizeof(in4), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_uint8(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpuint(in, == ,out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_int8(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpint(in, == ,out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_int8(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* int16
*==========================================================================*/
static
void
test_int16(
void)
{
const guint16 in = 42;
const guint8 in4[] = { TEST_INT16_BYTES(42), 0x00, 0x00 };
guint16 out1 = 0;
gint16 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
/* Not enough data */
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(!gbinder_reader_read_uint16(&reader, &out1));
g_assert(!gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
/* Enough data */
data.buffer = gbinder_buffer_new(driver, g_memdup(in4, sizeof(in4)),
sizeof(in4), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_uint16(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpuint(in, == ,out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_int16(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpint(in, == ,out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in4));
g_assert(gbinder_reader_read_int16(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* int32
*==========================================================================*/
static
void
test_int32(
void)
{
const guint32 in = 42;
guint32 out1 = 0;
gint32 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_uint32(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_int32(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == (guint32)out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_int32(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* int64
*==========================================================================*/
static
void
test_int64(
void)
{
const guint64 in = 42;
guint64 out1 = 0;
gint64 out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_uint64(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_int64(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == (guint64)out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_int64(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* float
*==========================================================================*/
static
void
test_float(
void)
{
const gfloat in = 42;
gfloat out1 = 0;
gfloat out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_float(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_float(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == (gfloat)out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_float(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* double
*==========================================================================*/
static
void
test_double(
void)
{
const gdouble in = 42;
gdouble out1 = 0;
gdouble out2 = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(&in, sizeof(in)),
sizeof(in), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_double(&reader, &out1));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == out1);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_double(&reader, &out2));
g_assert(gbinder_reader_at_end(&reader));
g_assert(in == (gdouble)out2);
gbinder_reader_init(&reader, &data, 0, sizeof(in));
g_assert(gbinder_reader_read_double(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* cstring
*==========================================================================*/
typedef struct test_string_data {
const char* name;
const guint8* in;
guint in_size;
const char* out;
gboolean remaining;
} TestStringData;
static const guint8 test_cstring_in_short [] = {
't', 'e', 's', 't', 0, 0, 0
};
static const guint8 test_cstring_in_basic1 [] = {
't', 'e', 's', 't', 0, 0, 0, 0
};
static const guint8 test_cstring_in_basic2 [] = {
't', 'e', 's', 't', 0, 0, 0, 0, 0
};
static const TestStringData test_cstring_tests [] = {
{ "err", TEST_ARRAY_AND_SIZE(test_cstring_in_short), NULL,
sizeof(test_cstring_in_short)},
{ "ok1", TEST_ARRAY_AND_SIZE(test_cstring_in_basic1), "test", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_cstring_in_basic2), "test", 1 }
};
static
void
test_cstring(
gconstpointer test_data)
{
const TestStringData* test = test_data;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
const char* str;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
test->in_size, NULL);
gbinder_reader_init(&reader, &data, 0, test->in_size);
str = gbinder_reader_read_string8(&reader);
g_assert(!g_strcmp0(str, test->out));
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string8
*==========================================================================*/
static const guint8 test_string8_in_null [] = {
TEST_INT32_BYTES(-1)
};
static const guint8 test_string8_in_invalid [] = {
TEST_INT32_BYTES(-2)
};
static const guint8 test_string8_in_short1 [] = {
0x00
};
static const guint8 test_string8_in_short2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o'
};
static const guint8 test_string8_in_noterm [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 'x' /* Missing terminator */
};
static const guint8 test_string8_in_basic1 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00
};
static const guint8 test_string8_in_basic2 [] = {
TEST_INT32_BYTES(3), 'f', 'o', 'o', 0x00, 0x00
};
static const TestStringData test_string8_tests [] = {
{ "invalid", TEST_ARRAY_AND_SIZE(test_string8_in_invalid), NULL,
sizeof(test_string8_in_invalid) },
{ "short1", TEST_ARRAY_AND_SIZE(test_string8_in_short1), NULL,
sizeof(test_string8_in_short1) },
{ "short2", TEST_ARRAY_AND_SIZE(test_string8_in_short2), NULL,
sizeof(test_string8_in_short2) },
{ "noterm", TEST_ARRAY_AND_SIZE(test_string8_in_noterm), NULL,
sizeof(test_string8_in_noterm) },
{ "ok1", TEST_ARRAY_AND_SIZE(test_string8_in_basic1), "foo", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string8_in_basic2), "foo", 1 }
};
static
void
test_string8_null(
void)
{
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
gsize len = 1;
char dummy;
const char* out = &dummy;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(test_string8_in_null)),
sizeof(test_string8_in_null), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_skip_nullable_string8(&reader));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string8_in_null));
g_assert(gbinder_reader_read_nullable_string8(&reader, &out, &len));
g_assert(gbinder_reader_at_end(&reader));
g_assert(!out);
g_assert(!len);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
static
void
test_string8(
gconstpointer test_data)
{
const TestStringData* test = test_data;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader r;
GBinderReaderData data;
const gboolean valid = (test->out != NULL);
const char* out = NULL;
gsize len = 0;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
test->in_size, NULL);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_skip_nullable_string8(&r) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
gbinder_reader_init(&r, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string8(&r, &out, &len) == valid);
g_assert(gbinder_reader_at_end(&r) == (!test->remaining));
g_assert_cmpuint(gbinder_reader_bytes_remaining(&r), == ,test->remaining);
if (valid) {
g_assert_cmpstr(out, ==, test->out);
g_assert_cmpuint(len, == ,strlen(test->out));
}
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* string16
*==========================================================================*/
static const guint8 test_string16_in_null [] = {
TEST_INT32_BYTES(-1)
};
static const guint8 test_string16_in_invalid [] = {
TEST_INT32_BYTES(-2)
};
static const guint8 test_string16_in_short [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
TEST_INT16_BYTES('o'), 0x00
};
static const guint8 test_string16_in_noterm [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
TEST_INT16_BYTES('o'), TEST_INT16_BYTES('o') /* Missing terminator */
};
static const guint8 test_string16_in_basic1 [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
TEST_INT16_BYTES('o'), 0x00, 0x00
};
static const guint8 test_string16_in_basic2 [] = {
TEST_INT32_BYTES(3),
TEST_INT16_BYTES('f'), TEST_INT16_BYTES('o'),
TEST_INT16_BYTES('o'), 0x00, 0x00, 0x00
};
static const TestStringData test_string16_tests [] = {
{ "invalid", TEST_ARRAY_AND_SIZE(test_string16_in_invalid), NULL,
sizeof(test_string16_in_invalid) },
{ "short", TEST_ARRAY_AND_SIZE(test_string16_in_short), NULL,
sizeof(test_string16_in_short) },
{ "noterm", TEST_ARRAY_AND_SIZE(test_string16_in_noterm), NULL,
sizeof(test_string16_in_noterm) },
{ "ok1", TEST_ARRAY_AND_SIZE(test_string16_in_basic1), "foo", 0 },
{ "ok2", TEST_ARRAY_AND_SIZE(test_string16_in_basic2), "foo", 1 }
};
static
void
test_string16_null(
void)
{
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
const gunichar2* out2 = NULL;
gsize len = 1;
char dummy;
char* out = &dummy;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver,
g_memdup(TEST_ARRAY_AND_SIZE(test_string16_in_null)),
sizeof(test_string16_in_null), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, NULL, NULL));
g_assert(gbinder_reader_at_end(&reader));
len = 1;
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, &out2, &len));
g_assert(gbinder_reader_at_end(&reader));
g_assert(!out2);
g_assert(!len);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(!gbinder_reader_read_string16_utf16(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
len = 1;
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(!gbinder_reader_read_string16_utf16(&reader, &len));
g_assert(gbinder_reader_at_end(&reader));
g_assert(!len);
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(gbinder_reader_read_nullable_string16(&reader, NULL));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(gbinder_reader_read_nullable_string16(&reader, &out));
g_assert(!out);
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(!gbinder_reader_read_string16(&reader));
g_assert(gbinder_reader_at_end(&reader));
gbinder_reader_init(&reader, &data, 0, sizeof(test_string16_in_null));
g_assert(gbinder_reader_skip_string16(&reader));
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
static
void
test_string16(
gconstpointer test_data)
{
const TestStringData* test = test_data;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
const gboolean valid = (test->out != NULL);
const gunichar2* out2 = NULL;
gsize len = 0;
char* str = NULL;
g_assert(driver);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, g_memdup(test->in, test->in_size),
test->in_size, NULL);
gbinder_reader_init(&reader, &data, 0, test->in_size);
if (valid) {
out2 = gbinder_reader_read_string16_utf16(&reader, &len);
g_assert(out2);
g_assert((gsize)len == strlen(test->out));
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
} else {
g_assert(!gbinder_reader_read_string16_utf16(&reader, NULL));
}
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, NULL,
NULL) == valid);
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string16_utf16(&reader, &out2,
&len) == valid);
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
if (valid) {
g_assert(out2);
g_assert((gsize)len == strlen(test->out));
}
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string16(&reader, NULL) == valid);
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_nullable_string16(&reader, &str) == valid);
g_assert(!g_strcmp0(str, test->out));
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
g_free(str);
gbinder_reader_init(&reader, &data, 0, test->in_size);
str = gbinder_reader_read_string16(&reader);
g_assert(!g_strcmp0(str, test->out));
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
g_free(str);
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_skip_string16(&reader) == (test->out != NULL));
g_assert(gbinder_reader_at_end(&reader) == (!test->remaining));
g_assert(gbinder_reader_bytes_remaining(&reader) == test->remaining);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* hidl_struct
*==========================================================================*/
typedef struct test_hidl_struct {
const char* name;
const void* in;
guint in_size;
guint struct_size;
const void* data;
} TestHidlStruct;
typedef struct test_hidl_struct_type {
guint32 x;
} TestHidlStructType;
static const TestHidlStructType test_hidl_struct_data = { 0 };
static const BinderObject64 test_hidl_struct_ok_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_struct_data },
sizeof(test_hidl_struct_data), 0, 0
}
};
static const BinderObject64 test_hidl_struct_big_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_struct_data },
2 * sizeof(test_hidl_struct_data), 0, 0
}
};
static const TestHidlStruct test_hidl_struct_tests[] = {
{ "ok", TEST_ARRAY_AND_SIZE(test_hidl_struct_ok_buf),
sizeof(TestHidlStructType), &test_hidl_struct_data },
{ "badsize", TEST_ARRAY_AND_SIZE(test_hidl_struct_big_buf),
sizeof(TestHidlStructType), NULL }
};
static
void
test_hidl_struct(
gconstpointer test_data)
{
const TestHidlStruct* test = test_data;
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(test->in, test->in_size), test->in_size, NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new0(void*, 2);
data.objects[0] = buf->data;
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_hidl_struct1(&reader, test->struct_size) ==
test->data);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* hidl_vec
*==========================================================================*/
typedef struct test_hidl_vec {
const char* name;
const void* in;
guint in_size;
const guint* offset;
guint offset_count;
const void* data;
guint count;
guint elemsize;
} TestHidlVec;
static const guint test_hidl_vec_2offsets [] = { 0, BUFFER_OBJECT_SIZE_64 };
static const guint8 test_hidl_vec_2bytes_data [] = { 0x01, 0x02 };
static const GBinderHidlVec test_hidl_vec_2bytes = {
.data.ptr = test_hidl_vec_2bytes_data,
sizeof(test_hidl_vec_2bytes_data),
TRUE
};
static const BinderObject64 test_hidl_vec_2bytes_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_2bytes },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_2bytes_data },
sizeof(test_hidl_vec_2bytes_data), 0,
GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
static const GBinderHidlVec test_hidl_vec_empty = {
.data.ptr = test_hidl_vec_2bytes_data, 0, TRUE
};
static const BinderObject64 test_hidl_vec_empty_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_empty },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_2bytes_data },
0, 0, GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
static const guint test_hidl_vec_1offset [] = {0};
static const GBinderHidlVec test_hidl_vec_null = {{0}, 0, TRUE};
static const BinderObject64 test_hidl_vec_null_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_null },
sizeof(GBinderHidlVec), 0, 0
}
};
/* Buffer smaller than GBinderHidlVec */
static const BinderObject64 test_hidl_vec_short_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_empty },
sizeof(GBinderHidlVec) - 1, 0, 0
}
};
/* NULL buffer with size 1 */
static const GBinderHidlVec test_hidl_vec_badnull = {{0}, 1, TRUE};
static const BinderObject64 test_hidl_vec_badnull_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_badnull },
sizeof(GBinderHidlVec), 0, 0
}
};
/* Buffer size not divisible by count */
static const guint8 test_hidl_vec_badsize_data [] = { 0x01, 0x02, 0x03 };
static const GBinderHidlVec test_hidl_vec_badsize = {
.data.ptr = test_hidl_vec_badsize_data, 2, TRUE
};
static const BinderObject64 test_hidl_vec_badsize_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_badsize },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_badsize_data },
sizeof(test_hidl_vec_badsize_data), 0,
GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
/* Bad buffer address */
static const guint8 test_hidl_vec_badbuf_data [] = { 0x01, 0x02, 0x03 };
static const GBinderHidlVec test_hidl_vec_badbuf = {
.data.ptr = test_hidl_vec_badbuf_data,
sizeof(test_hidl_vec_badbuf_data), TRUE
};
static const BinderObject64 test_hidl_vec_badbuf_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_badbuf },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_badsize_data },
sizeof(test_hidl_vec_badsize_data), 0,
GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
/* Non-zero count and zero size */
static const GBinderHidlVec test_hidl_vec_badcount1 = {
.data.ptr = test_hidl_vec_badsize_data, 1, TRUE
};
static const BinderObject64 test_hidl_vec_badcount1_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_badcount1 },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_badsize_data }, 0, 0,
GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
/* Zero count0 and non-zero size */
static const GBinderHidlVec test_hidl_vec_badcount2 = {
.data.ptr = test_hidl_vec_badsize_data, 0, TRUE
};
static const BinderObject64 test_hidl_vec_badcount2_buf [] = {
{
BINDER_TYPE_PTR, 0,
{ &test_hidl_vec_badcount2 },
sizeof(GBinderHidlVec), 0, 0
},{
BINDER_TYPE_PTR, BINDER_BUFFER_FLAG_HAS_PARENT,
{ test_hidl_vec_badsize_data },
sizeof(test_hidl_vec_badsize_data), 0,
GBINDER_HIDL_VEC_BUFFER_OFFSET
}
};
static const TestHidlVec test_hidl_vec_tests[] = {
{ "2bytes", TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2bytes_data), 1 },
{ "empty", TEST_ARRAY_AND_SIZE(test_hidl_vec_empty_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets),
test_hidl_vec_2bytes_data, 0, 0 },
{ "null", TEST_ARRAY_AND_SIZE(test_hidl_vec_null_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset),
&test_hidl_vec_null, 0, 0 },
{ "missingbuf", test_hidl_vec_2bytes_buf,
sizeof(test_hidl_vec_2bytes_buf[0]),
TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
{ "shortbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_short_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
{ "badnull", TEST_ARRAY_AND_SIZE(test_hidl_vec_badnull_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_1offset), NULL, 0, 0 },
{ "badsize", TEST_ARRAY_AND_SIZE(test_hidl_vec_badsize_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
{ "badbuf", TEST_ARRAY_AND_SIZE(test_hidl_vec_badbuf_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
{ "badcount1", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount1_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 },
{ "badcount2", TEST_ARRAY_AND_SIZE(test_hidl_vec_badcount2_buf),
TEST_ARRAY_AND_SIZE(test_hidl_vec_2offsets), NULL, 0, 0 }
};
static
void
test_hidl_vec(
gconstpointer test_data)
{
const TestHidlVec* test = test_data;
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(test->in, test->in_size), test->in_size, NULL);
GBinderReaderData data;
GBinderReader reader;
gsize n = 0, elem = 0;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
if (test->offset) {
guint i;
data.objects = g_new(void*, test->offset_count + 1);
for (i = 0; i < test->offset_count; i++) {
data.objects[i] = (guint8*)buf->data + test->offset[i];
}
data.objects[i] = NULL;
}
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_hidl_vec(&reader, &n, &elem) == test->data);
g_assert(n == test->count);
g_assert(elem == test->elemsize);
if (test->data) {
n = 42;
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(gbinder_reader_read_hidl_vec1(&reader, &n, test->elemsize) ==
test->data);
g_assert(n == test->count);
/* Test invalid expected size */
gbinder_reader_init(&reader, &data, 0, test->in_size);
if (test->count) {
g_assert(!gbinder_reader_read_hidl_vec1(&reader, NULL,
test->elemsize + 1));
} else {
/* If total size is zero, we can't really check the element size */
g_assert(gbinder_reader_read_hidl_vec1(&reader, NULL,
test->elemsize + 1) == test->data);
}
} else {
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(!gbinder_reader_read_hidl_vec1(&reader, &n, test->elemsize));
}
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* hidl_string_err
*==========================================================================*/
typedef struct test_hidl_string_err {
const char* name;
const guint8* in;
guint in_size;
const guint* offset;
guint offset_count;
} TestHidlStringErr;
static const guint8 test_hidl_string_err_short [] = { 0x00 };
static const guint8 test_hidl_string_err_bad_obj [] = {
TEST_INT32_BYTES(BINDER_TYPE_HANDLE),
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
static const guint8 test_hidl_string_err_empty [] = {
TEST_INT32_BYTES(BINDER_TYPE_PTR),
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
static const guint test_hidl_string_err_bad_offset [] = { 100 };
static const guint test_hidl_string_err_one_offset [] = { 0 };
static const TestHidlStringErr test_hidl_string_err_tests [] = {
{ "no-data", TEST_ARRAY_AND_SIZE(test_hidl_string_err_short), NULL },
{ "no-object", TEST_ARRAY_AND_SIZE(test_hidl_string_err_bad_obj), NULL },
{ "no-offset", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty), NULL },
{ "empty-offset", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty),
test_hidl_string_err_one_offset, 0 },
{ "bad-offset", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty),
TEST_ARRAY_AND_COUNT(test_hidl_string_err_bad_offset) },
{ "short-buffer", TEST_ARRAY_AND_SIZE(test_hidl_string_err_short),
TEST_ARRAY_AND_COUNT(test_hidl_string_err_one_offset) },
{ "empty-buffer", TEST_ARRAY_AND_SIZE(test_hidl_string_err_empty),
TEST_ARRAY_AND_COUNT(test_hidl_string_err_one_offset) }
};
static
void
test_hidl_string_err(
gconstpointer test_data)
{
const TestHidlStringErr* test = test_data;
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(test->in, test->in_size), test->in_size, NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
if (test->offset) {
guint i;
data.objects = g_new(void*, test->offset_count + 1);
for (i = 0; i < test->offset_count; i++) {
data.objects[i] = (guint8*)buf->data + test->offset[i];
}
data.objects[i] = NULL;
}
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(!gbinder_reader_read_hidl_string(&reader));
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static
void
test_hidl_string_err_skip(
gconstpointer test_data)
{
const TestHidlStringErr* test = test_data;
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(test->in, test->in_size), test->in_size, NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
if (test->offset) {
guint i;
data.objects = g_new(void*, test->offset_count + 1);
for (i = 0; i < test->offset_count; i++) {
data.objects[i] = (guint8*)buf->data + test->offset[i];
}
data.objects[i] = NULL;
}
gbinder_reader_init(&reader, &data, 0, test->in_size);
g_assert(!gbinder_reader_skip_hidl_string(&reader));
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* fd_ok
*==========================================================================*/
static
void
test_fd_ok(
void)
{
/* Using 64-bit I/O */
const int fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_FD),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS),
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_fd(&reader) == fd);
gbinder_driver_close_fds(ipc->driver, data.objects,
(guint8*)buf->data + buf->size);
/* The above call must have closed the descriptor */
g_assert(close(fd) < 0);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* fd_shortbuf
*==========================================================================*/
static
void
test_fd_shortbuf(
void)
{
/* Using 64-bit I/O */
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_FD),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_fd(&reader) < 0);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* fd_badtype
*==========================================================================*/
static
void
test_fd_badtype(
void)
{
/* Using 64-bit I/O */
const int fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS),
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_fd(&reader) < 0);
gbinder_driver_close_fds(ipc->driver, data.objects,
(guint8*)buf->data + buf->size);
/* The above call doesn't close the descriptor */
g_assert(close(fd) == 0);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* dupfd_ok
*==========================================================================*/
static
void
test_dupfd_ok(
void)
{
/* Using 64-bit I/O */
const int fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_FD),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS),
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
int fd2;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
fd2 = gbinder_reader_read_dup_fd(&reader);
g_assert(fd2 >= 0);
g_assert(fd2 != fd);
gbinder_driver_close_fds(ipc->driver, data.objects,
(guint8*)buf->data + buf->size);
/* The above call closes fd*/
g_assert(close(fd) < 0);
g_assert(close(fd2) == 0);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* dupfd_badtype
*==========================================================================*/
static
void
test_dupfd_badtype(
void)
{
/* Using 64-bit I/O */
const int fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS),
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_dup_fd(&reader) < 0);
gbinder_driver_close_fds(ipc->driver, data.objects,
(guint8*)buf->data + buf->size);
/* The above call doesn't close fd*/
g_assert(close(fd) == 0);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* dupfd_badfd
*==========================================================================*/
static
void
test_dupfd_badfd(
void)
{
/* Using 64-bit I/O */
const int fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_FD),
TEST_INT32_BYTES(0x7f | BINDER_FLAG_ACCEPTS_FDS),
TEST_INT32_BYTES(fd), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
/* Invalidate the descriptor by closing it */
g_assert(close(fd) == 0);
g_assert(gbinder_reader_read_dup_fd(&reader) < 0);
gbinder_driver_close_fds(ipc->driver, data.objects,
(guint8*)buf->data + buf->size);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* hidl_string
*==========================================================================*/
static
void
test_hidl_string(
const guint8* input,
gsize size,
const guint* offsets,
guint bufcount,
const char* result)
{
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
size, NULL);
GBinderRemoteObject* obj = NULL;
GBinderReaderData data;
GBinderReader reader;
guint i;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, bufcount + 1);
for (i = 0; i < bufcount; i++) {
data.objects[i] = buf->data + offsets[i];
}
data.objects[i] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_hidl_string_c(&reader) == result);
g_free(data.objects);
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static
void
test_hidl_string1(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), contents);
}
static
void
test_hidl_string2(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Invalid object type */
TEST_INT32_BYTES(BINDER_TYPE_HANDLE),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
static
void
test_hidl_string3(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* No parent */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
static
void
test_hidl_string4(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Invalid length */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(sizeof(contents) - 1),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
static
void
test_hidl_string5(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Invalid pointer */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents + 1),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
static
void
test_hidl_string6(
void)
{
/* No NULL-terminated */
const char contents[] = "testx";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = 4,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(5),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
static
void
test_hidl_string7(
void)
{
const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&str), TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Invalid parent offset */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)contents),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(0),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET + 1)
};
static const guint offsets[] = { 0, BUFFER_OBJECT_SIZE_64 };
test_hidl_string(TEST_ARRAY_AND_SIZE(input),
TEST_ARRAY_AND_COUNT(offsets), NULL);
}
/*==========================================================================*
* buffer
*==========================================================================*/
static
void
test_buffer(
void)
{
/* Using 64-bit I/O */
const int data1 = 0x1234;
const int data2 = 0x5678;
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR), TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&data1), TEST_INT64_BYTES(sizeof(data1)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)&data2), TEST_INT64_BYTES(sizeof(data2)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Not a buffer object */
TEST_INT32_BYTES(BINDER_TYPE_HANDLE), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderRemoteObject* obj = NULL;
GBinderReaderData data;
GBinderReader reader;
GBinderBuffer* res;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 4);
data.objects[0] = buf->data;
data.objects[1] = buf->data + BUFFER_OBJECT_SIZE_64;
data.objects[2] = buf->data + 2 * BUFFER_OBJECT_SIZE_64;
data.objects[3] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_skip_buffer(&reader));
res = gbinder_reader_read_buffer(&reader);
g_assert(res);
g_assert(res->data == &data2);
/* The next one is not a buffer object */
g_assert(!gbinder_reader_skip_buffer(&reader));
gbinder_buffer_free(res);
g_free(data.objects);
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* parcelable
*==========================================================================*/
static
void
test_parcelable(
void)
{
const guint8 input_null_header[] = {
TEST_INT32_BYTES(0)
};
const guint8 input_broken_header[] = {
TEST_INT32_BYTES(1),
TEST_INT32_BYTES(1)
};
const guint8 input_non_null_header[] = {
TEST_INT32_BYTES(1),
/* Size must be size of itself + payload */
TEST_INT32_BYTES(sizeof(gint32) * 3)
};
const guint8 input_non_null_payload[] = {
TEST_INT32_BYTES(10),
TEST_INT32_BYTES(20)
};
gpointer in;
gsize in_size, out_size;
const void* out = 0;
GBinderDriver* driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL);
GBinderReader reader;
GBinderReaderData data;
g_assert(driver);
memset(&data, 0, sizeof(data));
/* Missing payload */
test_init_reader(driver, &data, &reader,
TEST_ARRAY_AND_SIZE(input_non_null_header));
out = gbinder_reader_read_parcelable(&reader, &out_size);
g_assert(!out);
g_assert_cmpuint(out_size, == ,0);
gbinder_buffer_free(data.buffer);
/* Broken headers */
test_init_reader(driver, &data, &reader, input_broken_header, 4);
out = gbinder_reader_read_parcelable(&reader, &out_size);
g_assert(!out);
g_assert_cmpuint(out_size, == ,0);
gbinder_buffer_free(data.buffer);
test_init_reader(driver, &data, &reader,
TEST_ARRAY_AND_SIZE(input_broken_header));
out = gbinder_reader_read_parcelable(&reader, &out_size);
g_assert(!out);
g_assert_cmpuint(out_size, == ,0);
gbinder_buffer_free(data.buffer);
/* Null */
test_init_reader(driver, &data, &reader,
TEST_ARRAY_AND_SIZE(input_null_header));
gbinder_reader_init(&reader, &data, 0, sizeof(input_null_header));
out = gbinder_reader_read_parcelable(&reader, &out_size);
g_assert(!out);
g_assert_cmpuint(out_size, == ,0);
g_assert(gbinder_reader_at_end(&reader));
gbinder_buffer_free(data.buffer);
/* Non-null */
in_size = sizeof(input_non_null_header) + sizeof(input_non_null_payload);
in = g_malloc(in_size);
memcpy(in, &input_non_null_header, sizeof(input_non_null_header));
memcpy(in + sizeof(input_non_null_header), &input_non_null_payload,
sizeof(input_non_null_payload));
data.buffer = gbinder_buffer_new(driver, in, in_size, NULL);
gbinder_reader_init(&reader, &data, 0, in_size);
out = gbinder_reader_read_parcelable(&reader, &out_size);
g_assert(memcmp(&input_non_null_payload, out,
sizeof(input_non_null_payload)) == 0);
g_assert_cmpuint(out_size, == ,sizeof(input_non_null_payload));
g_assert(gbinder_reader_at_end(&reader));
/* And verify NULL tolerance for the size parameter */
gbinder_reader_init(&reader, &data, 0, in_size);
out = gbinder_reader_read_parcelable(&reader, NULL);
g_assert(memcmp(&input_non_null_payload, out,
sizeof(input_non_null_payload)) == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* object
*==========================================================================*/
static
void
test_object(
void)
{
/* Using 64-bit I/O */
static const guint8 input[] = {
TEST_INT32_BYTES(BINDER_TYPE_HANDLE), TEST_INT32_BYTES(0),
TEST_INT32_BYTES(1 /* handle*/), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderRemoteObject* obj = NULL;
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(gbinder_reader_read_nullable_object(&reader, &obj));
g_assert(obj);
g_assert_cmpuint(obj->handle, == ,1);
g_free(data.objects);
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* hidl_object_no_reg
*==========================================================================*/
static
void
test_object_no_reg(
void)
{
GBinderReaderData data;
GBinderReader reader;
memset(&data, 0, sizeof(data));
gbinder_reader_init(&reader, &data, 0, 0);
g_assert(!gbinder_reader_read_hidl_string(&reader));
g_assert(!gbinder_reader_read_object(&reader));
}
/*==========================================================================*
* object_invalid
*==========================================================================*/
static
void
test_object_invalid(
void)
{
/* Using 64-bit I/O */
static const guint8 input[] = {
TEST_INT32_BYTES(42 /* invalid type */), TEST_INT32_BYTES(0),
TEST_INT64_BYTES(1 /* handle*/), TEST_INT64_BYTES(0)
};
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver,
g_memdup(input, sizeof(input)), sizeof(input), NULL);
GBinderRemoteObject* obj = NULL;
GBinderReaderData data;
GBinderReader reader;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = buf->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
g_assert(!gbinder_reader_read_nullable_object(&reader, &obj));
g_assert(!obj);
g_free(data.objects);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* vec
*==========================================================================*/
static
void
test_vec(
void)
{
/* Using 64-bit I/O */
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderReaderData data;
GBinderReader reader;
BinderObject64 obj;
GBinderHidlVec vec;
char** out;
g_assert(ipc);
memset(&data, 0, sizeof(data));
memset(&vec, 0, sizeof(vec));
memset(&obj, 0, sizeof(obj));
obj.type = BINDER_TYPE_PTR;
obj.buffer.ptr = &vec;
/* This one will fail because the buffer is one byte short */
obj.length = sizeof(vec) - 1;
data.buffer = gbinder_buffer_new(ipc->driver,
g_memdup(&obj, sizeof(obj)), sizeof(obj), NULL);
data.reg = gbinder_ipc_object_registry(ipc);
data.objects = g_new(void*, 2);
data.objects[0] = data.buffer->data;
data.objects[1] = NULL;
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
g_assert(!gbinder_reader_read_hidl_string_vec(&reader));
/* This one will read empty array */
obj.length = sizeof(vec);
gbinder_buffer_free(data.buffer);
data.buffer = gbinder_buffer_new(ipc->driver,
g_memdup(&obj, sizeof(obj)), sizeof(obj), NULL);
data.objects[0] = data.buffer->data;
gbinder_reader_init(&reader, &data, 0, data.buffer->size);
out = gbinder_reader_read_hidl_string_vec(&reader);
g_assert(out);
g_assert(!out[0]);
g_strfreev(out);
g_free(data.objects);
gbinder_buffer_free(data.buffer);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
/*==========================================================================*
* hidl_string_vec
*==========================================================================*/
static
void
test_hidl_string_vec(
const guint8* input,
gsize size,
const char* const* result)
{
GBinderIpc* ipc = gbinder_ipc_new(GBINDER_DEFAULT_HWBINDER, NULL);
GBinderBuffer* buf = gbinder_buffer_new(ipc->driver, g_memdup(input, size),
size, NULL);
GBinderRemoteObject* obj = NULL;
GBinderReaderData data;
GBinderReader reader;
char** out;
guint i;
g_assert(ipc);
memset(&data, 0, sizeof(data));
data.buffer = buf;
data.reg = gbinder_ipc_object_registry(ipc);
/* We assume that input consists only from buffer objects */
g_assert(!(size % BUFFER_OBJECT_SIZE_64));
data.objects = g_new(void*, size/BUFFER_OBJECT_SIZE_64 + 1);
for (i = 0; i < size/BUFFER_OBJECT_SIZE_64; i++) {
data.objects[i] = buf->data + i * BUFFER_OBJECT_SIZE_64;
}
data.objects[i] = NULL;
gbinder_reader_init(&reader, &data, 0, buf->size);
out = gbinder_reader_read_hidl_string_vec(&reader);
if (out) {
const guint n = g_strv_length(out);
g_assert(result);
g_assert(n == g_strv_length((char**)result));
for (i = 0; i < n; i++) {
g_assert(!g_strcmp0(out[i], result[i]));
}
} else {
g_assert(!result);
}
g_strfreev(out);
g_free(data.objects);
gbinder_remote_object_unref(obj);
gbinder_buffer_free(buf);
gbinder_ipc_unref(ipc);
test_binder_exit_wait(&test_opt, NULL);
}
static
void
test_hidl_string_vec1(
void)
{
static const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
const GBinderHidlVec vec = {
.data = { .ptr = &str },
.count = 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&vec),
TEST_INT64_BYTES(sizeof(vec)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)&str),
TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(1),
TEST_INT64_BYTES(GBINDER_HIDL_VEC_BUFFER_OFFSET),
/* Buffer object #3 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)&contents),
TEST_INT64_BYTES(sizeof(contents)),
TEST_INT64_BYTES(2),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const char* const result[] = { contents, NULL };
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), result);
}
static
void
test_hidl_string_vec2(
void)
{
static const char str1[] = "meh";
static const char str2[] = "foobar";
const GBinderHidlString str[] = {
{
.data = { (uintptr_t)str1 },
.len = sizeof(str1) - 1,
.owns_buffer = TRUE
},{
.data = { (uintptr_t)str2 },
.len = sizeof(str2) - 1,
.owns_buffer = TRUE
}
};
const GBinderHidlVec vec = {
.data = { .ptr = &str },
.count = 2,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&vec),
TEST_INT64_BYTES(sizeof(vec)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str),
TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(1),
TEST_INT64_BYTES(GBINDER_HIDL_VEC_BUFFER_OFFSET),
/* Buffer object #3 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str1),
TEST_INT64_BYTES(sizeof(str1)),
TEST_INT64_BYTES(2),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET),
/* Buffer object #4 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str2),
TEST_INT64_BYTES(sizeof(str2)),
TEST_INT64_BYTES(2),
TEST_INT64_BYTES(sizeof(GBinderHidlString) +
GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
static const char* const result[] = { str1, str2, NULL };
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), result);
}
static
void
test_hidl_string_vec3(
void)
{
static const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
const GBinderHidlVec vec = {
.data = { .ptr = &str },
.count = 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&vec),
TEST_INT64_BYTES(sizeof(vec)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)&str),
TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(1),
TEST_INT64_BYTES(GBINDER_HIDL_VEC_BUFFER_OFFSET)
/* The next buffer is missing */
};
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), NULL);
}
static
void
test_hidl_string_vec4(
void)
{
static const char contents[] = "test";
const GBinderHidlString str = {
.data = { (uintptr_t)contents },
.len = sizeof(contents) - 1,
.owns_buffer = TRUE
};
const GBinderHidlVec vec = {
.data = { .ptr = &str },
.count = 1,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&vec),
TEST_INT64_BYTES(sizeof(vec)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* The next buffer is missing */
};
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), NULL);
}
static
void
test_hidl_string_vec5(
void)
{
static const char str1[] = "meh";
static const char str2[] = "foobar";
const GBinderHidlString str[] = {
{
.data = { (uintptr_t)str1 },
.len = sizeof(str1) - 1,
.owns_buffer = TRUE
},{
.data = { (uintptr_t)str2 },
.len = sizeof(str2) - 1,
.owns_buffer = TRUE
}
};
const GBinderHidlVec vec = {
.data = { .ptr = &str },
.count = 2,
.owns_buffer = TRUE
};
/* Using 64-bit I/O */
const guint8 input[] = {
/* Buffer object #1 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(0),
TEST_INT64_BYTES((uintptr_t)&vec),
TEST_INT64_BYTES(sizeof(vec)),
TEST_INT64_BYTES(0), TEST_INT64_BYTES(0),
/* Buffer object #2 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str),
TEST_INT64_BYTES(sizeof(str)),
TEST_INT64_BYTES(1),
TEST_INT64_BYTES(GBINDER_HIDL_VEC_BUFFER_OFFSET),
/* Buffer object #3 */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str1),
TEST_INT64_BYTES(sizeof(str1)),
TEST_INT64_BYTES(2),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET),
/* Buffer object #4 (with invalid offset) */
TEST_INT32_BYTES(BINDER_TYPE_PTR),
TEST_INT32_BYTES(BINDER_BUFFER_FLAG_HAS_PARENT),
TEST_INT64_BYTES((uintptr_t)str2),
TEST_INT64_BYTES(sizeof(str2)),
TEST_INT64_BYTES(2),
TEST_INT64_BYTES(GBINDER_HIDL_STRING_BUFFER_OFFSET)
};
test_hidl_string_vec(TEST_ARRAY_AND_SIZE(input), NULL);
}
/*==========================================================================*
* byte_array
*==========================================================================*/
static
void
test_byte_array(
void)
{
const char in_data[] = "1234abcd";
gint32 in_len = sizeof(in_data) - 1;
const void* out_data = NULL;
gsize out_len = 0;
void* tmp;
gsize tmp_len = sizeof(in_len) + in_len;
gint32 null_len = -1;
GBinderDriver* driver;
GBinderReader reader;
GBinderReaderData data;
/* test for failed read (wrong len part of byte array) */
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
tmp = g_malloc0(1);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, tmp, 1, NULL);
gbinder_reader_init(&reader, &data, 0, 1);
g_assert(!gbinder_reader_read_byte_array(&reader, &out_len));
g_assert(!gbinder_reader_at_end(&reader));
g_assert(out_len == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
/* test for failed read (wrong data part of byte array) */
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
tmp = g_malloc0(in_len - 1);
memcpy(tmp, &in_len, sizeof(in_len));
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, tmp, in_len - 1, NULL);
gbinder_reader_init(&reader, &data, 0, in_len - 1);
g_assert(!gbinder_reader_read_byte_array(&reader, &out_len));
g_assert(!gbinder_reader_at_end(&reader));
g_assert(out_len == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
/* test for empty (len 0) byte array */
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
tmp = g_malloc0(sizeof(null_len));
memcpy(tmp, &null_len, sizeof(null_len));
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, tmp, sizeof(null_len), NULL);
gbinder_reader_init(&reader, &data, 0, sizeof(null_len));
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
g_assert(gbinder_reader_at_end(&reader));
g_assert(out_len == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
/* test for data */
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
tmp = g_malloc0(tmp_len);
memcpy(tmp, &in_len, sizeof(in_len));
memcpy(tmp + sizeof(in_len), in_data, in_len);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, tmp, tmp_len, NULL);
gbinder_reader_init(&reader, &data, 0, tmp_len);
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
g_assert(gbinder_reader_at_end(&reader));
g_assert((gsize)in_len == out_len);
g_assert(memcmp(in_data, out_data, in_len) == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* copy
*==========================================================================*/
static
void
test_copy(
void)
{
const char in_data1[] = "12345678";
const char in_data2[] = "abcdefgh";
gint32 in_len1 = sizeof(in_data1) - 1;
gint32 in_len2 = sizeof(in_data2) - 1;
const void* out_data = NULL;
gsize out_len = 0;
guint8* ptr;
void* buf;
gsize buf_len = 2 * sizeof(guint32) + in_len1 + in_len2;
GBinderDriver* driver;
GBinderReader reader;
GBinderReader reader2;
GBinderReaderData data;
/* test for data */
g_assert((driver = gbinder_driver_new(GBINDER_DEFAULT_BINDER, NULL)));
ptr = buf = g_malloc0(buf_len);
memcpy(ptr, &in_len1, sizeof(in_len1));
ptr += sizeof(in_len1);
memcpy(ptr, in_data1, in_len1);
ptr += in_len1;
memcpy(ptr, &in_len2, sizeof(in_len2));
ptr += sizeof(in_len2);
memcpy(ptr, in_data2, in_len2);
memset(&data, 0, sizeof(data));
data.buffer = gbinder_buffer_new(driver, buf, buf_len, NULL);
gbinder_reader_init(&reader, &data, 0, buf_len);
/* Read the first array */
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
g_assert_cmpuint(in_len1, == ,out_len);
g_assert(memcmp(in_data1, out_data, in_len1) == 0);
/* Fetch raw data */
g_assert((out_data = gbinder_reader_get_data(&reader, &out_len)));
g_assert(out_data == gbinder_reader_get_data(&reader, NULL));
g_assert_cmpuint(out_len, == ,buf_len);
g_assert(memcmp(out_data, buf, buf_len) == 0);
/* Copy the reader */
gbinder_reader_copy(&reader2, &reader);
/* Read both and compare the output */
g_assert((out_data = gbinder_reader_read_byte_array(&reader, &out_len)));
g_assert(gbinder_reader_at_end(&reader));
g_assert_cmpuint(in_len1, == ,out_len);
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
g_assert((out_data = gbinder_reader_read_byte_array(&reader2, &out_len)));
g_assert(gbinder_reader_at_end(&reader2));
g_assert_cmpuint(in_len2, == ,out_len);
g_assert(memcmp(in_data2, out_data, in_len2) == 0);
/* Fetch raw data from the copied reader */
g_assert((out_data = gbinder_reader_get_data(&reader2, &out_len)));
g_assert(out_data == gbinder_reader_get_data(&reader2, NULL));
g_assert_cmpuint(out_len, == ,buf_len);
g_assert(memcmp(out_data, buf, buf_len) == 0);
gbinder_buffer_free(data.buffer);
gbinder_driver_unref(driver);
}
/*==========================================================================*
* Common
*==========================================================================*/
#define TEST_PREFIX "/reader/"
#define TEST_(t) TEST_PREFIX t
int main(int argc, char* argv[])
{
guint i;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_type_init();
G_GNUC_END_IGNORE_DEPRECATIONS;
g_test_init(&argc, &argv, NULL);
g_test_add_func(TEST_("null"), test_null);
g_test_add_func(TEST_("empty"), test_empty);
g_test_add_func(TEST_("byte"), test_byte);
g_test_add_func(TEST_("bool"), test_bool);
g_test_add_func(TEST_("int8"), test_int8);
g_test_add_func(TEST_("int16"), test_int16);
g_test_add_func(TEST_("int32"), test_int32);
g_test_add_func(TEST_("int64"), test_int64);
g_test_add_func(TEST_("float"), test_float);
g_test_add_func(TEST_("double"), test_double);
for (i = 0; i < G_N_ELEMENTS(test_cstring_tests); i++) {
const TestStringData* test = test_cstring_tests + i;
char* path = g_strconcat(TEST_("cstring/"), test->name, NULL);
g_test_add_data_func(path, test, test_cstring);
g_free(path);
}
g_test_add_func(TEST_("string8/null"), test_string8_null);
for (i = 0; i < G_N_ELEMENTS(test_string8_tests); i++) {
const TestStringData* test = test_string8_tests + i;
char* path = g_strconcat(TEST_("string8/"), test->name, NULL);
g_test_add_data_func(path, test, test_string8);
g_free(path);
}
g_test_add_func(TEST_("string16/null"), test_string16_null);
for (i = 0; i < G_N_ELEMENTS(test_string16_tests); i++) {
const TestStringData* test = test_string16_tests + i;
char* path = g_strconcat(TEST_("string16/"), test->name, NULL);
g_test_add_data_func(path, test, test_string16);
g_free(path);
}
for (i = 0; i < G_N_ELEMENTS(test_hidl_struct_tests); i++) {
const TestHidlStruct* test = test_hidl_struct_tests + i;
char* path = g_strconcat(TEST_("hidl_struct/"), test->name,
NULL);
g_test_add_data_func(path, test, test_hidl_struct);
g_free(path);
}
for (i = 0; i < G_N_ELEMENTS(test_hidl_vec_tests); i++) {
const TestHidlVec* test = test_hidl_vec_tests + i;
char* path = g_strconcat(TEST_("hidl_vec/"), test->name,
NULL);
g_test_add_data_func(path, test, test_hidl_vec);
g_free(path);
}
for (i = 0; i < G_N_ELEMENTS(test_hidl_string_err_tests); i++) {
const TestHidlStringErr* test = test_hidl_string_err_tests + i;
char* path = g_strconcat(TEST_("hidl_string/err-"), test->name,
NULL);
g_test_add_data_func(path, test, test_hidl_string_err);
g_free(path);
path = g_strconcat(TEST_("hidl_string/err-skip-"), test->name,
NULL);
g_test_add_data_func(path, test, test_hidl_string_err_skip);
g_free(path);
}
g_test_add_func(TEST_("fd/ok"), test_fd_ok);
g_test_add_func(TEST_("fd/shortbuf"), test_fd_shortbuf);
g_test_add_func(TEST_("fd/badtype"), test_fd_badtype);
g_test_add_func(TEST_("dupfd/ok"), test_dupfd_ok);
g_test_add_func(TEST_("dupfd/badtype"), test_dupfd_badtype);
g_test_add_func(TEST_("dupfd/badfd"), test_dupfd_badfd);
g_test_add_func(TEST_("hidl_string/1"), test_hidl_string1);
g_test_add_func(TEST_("hidl_string/2"), test_hidl_string2);
g_test_add_func(TEST_("hidl_string/3"), test_hidl_string3);
g_test_add_func(TEST_("hidl_string/4"), test_hidl_string4);
g_test_add_func(TEST_("hidl_string/5"), test_hidl_string5);
g_test_add_func(TEST_("hidl_string/6"), test_hidl_string6);
g_test_add_func(TEST_("hidl_string/7"), test_hidl_string7);
g_test_add_func(TEST_("buffer"), test_buffer);
g_test_add_func(TEST_("parcelable"), test_parcelable);
g_test_add_func(TEST_("object/valid"), test_object);
g_test_add_func(TEST_("object/invalid"), test_object_invalid);
g_test_add_func(TEST_("object/no_reg"), test_object_no_reg);
g_test_add_func(TEST_("vec"), test_vec);
g_test_add_func(TEST_("hidl_string_vec/1"), test_hidl_string_vec1);
g_test_add_func(TEST_("hidl_string_vec/2"), test_hidl_string_vec2);
g_test_add_func(TEST_("hidl_string_vec/3"), test_hidl_string_vec3);
g_test_add_func(TEST_("hidl_string_vec/4"), test_hidl_string_vec4);
g_test_add_func(TEST_("hidl_string_vec/5"), test_hidl_string_vec5);
g_test_add_func(TEST_("byte_array"), test_byte_array);
g_test_add_func(TEST_("copy"), test_copy);
test_init(&test_opt, argc, argv);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/