blob: 29b45eab181ee5d52a27b7a2cee07764e70ce4a0 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <loader-service/loader-service.h>
#include <ldmsg/ldmsg.h>
#include <zircon/dlfcn.h>
#include <zircon/processargs.h>
#include <zircon/sanitizer.h>
#include <zircon/syscalls.h>
#include <unittest/unittest.h>
#define TEST_SINK_NAME "test-sink"
#define TEST_CONFIG_GOOD_NAME "/test-config-exists"
#define TEST_CONFIG_BAD_NAME "/test-config-does-not-exist"
static atomic_bool my_loader_service_ok;
static atomic_int my_loader_service_calls;
static zx_status_t my1_load_object(void* ctx, const char* name, zx_handle_t* out) {
return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t my1_load_abspath(void* ctx, const char* name, zx_handle_t* out) {
return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t my1_publish_data_sink(void* ctx, const char* name, zx_handle_t vmo) {
++my_loader_service_calls;
EXPECT_STR_EQ(TEST_SINK_NAME, name,
"called with unexpected name");
EXPECT_NE(vmo, ZX_HANDLE_INVALID,
"called with invalid handle");
char vmo_name[ZX_MAX_NAME_LEN];
EXPECT_EQ(zx_object_get_property(vmo, ZX_PROP_NAME, vmo_name, sizeof(vmo_name)),
ZX_OK, "get ZX_PROP_NAME");
EXPECT_STR_EQ(TEST_SINK_NAME, vmo_name,
"not called with expected VMO handle");
EXPECT_EQ(zx_handle_close(vmo), ZX_OK, "");
my_loader_service_ok = current_test_info->all_ok;
return ZX_OK;
}
static loader_service_ops_t my1_loader_ops = {
.load_object = my1_load_object,
.load_abspath = my1_load_abspath,
.publish_data_sink = my1_publish_data_sink,
};
bool publish_data_test(void) {
BEGIN_TEST;
my_loader_service_ok = false;
my_loader_service_calls = 0;
// Spin up our test service.
loader_service_t* svc = NULL;
zx_status_t status = loader_service_create(NULL, &my1_loader_ops, NULL, &svc);
EXPECT_EQ(status, ZX_OK, "loader_service_create");
zx_handle_t my_service = ZX_HANDLE_INVALID;
status = loader_service_connect(svc, &my_service);
EXPECT_EQ(status, ZX_OK, "loader_service_connect");
// Install the service.
zx_handle_t old = dl_set_loader_service(my_service);
EXPECT_NE(old, ZX_HANDLE_INVALID, "dl_set_loader_service");
// Make up a VMO to publish.
zx_handle_t vmo;
ASSERT_EQ(zx_vmo_create(0, 0, &vmo), ZX_OK, "");
EXPECT_EQ(zx_object_set_property(vmo, ZX_PROP_NAME,
TEST_SINK_NAME, sizeof(TEST_SINK_NAME)),
ZX_OK, "");
// Publish the VMO to our data sink.
__sanitizer_publish_data(TEST_SINK_NAME, vmo);
EXPECT_EQ(my_loader_service_calls, 1,
"loader-service not called exactly once");
EXPECT_TRUE(my_loader_service_ok, "loader service thread not happy");
// Put things back to how they were.
zx_handle_t old2 = dl_set_loader_service(old);
EXPECT_EQ(old2, my_service, "unexpected previous service handle");
zx_handle_close(old2);
END_TEST;
}
static zx_handle_t test_config_vmo = ZX_HANDLE_INVALID;
static zx_status_t my2_load_object(void* ctx, const char* name, zx_handle_t* out) {
return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t my2_load_abspath(void* ctx, const char* name, zx_handle_t* out) {
++my_loader_service_calls;
zx_handle_t result = ZX_HANDLE_INVALID;
if (!strcmp(TEST_CONFIG_GOOD_NAME, name)) {
EXPECT_NE(test_config_vmo, ZX_HANDLE_INVALID, "");
*out = test_config_vmo;
result = ZX_OK;
} else {
EXPECT_STR_EQ(TEST_CONFIG_BAD_NAME,
name,
"called with unexpected name");
result = ZX_ERR_NOT_FOUND;
}
my_loader_service_ok = current_test_info->all_ok;
return result;
}
static zx_status_t my2_publish_data_sink(void* ctx, const char* name, zx_handle_t vmo) {
zx_handle_close(vmo);
return ZX_ERR_NOT_SUPPORTED;
}
static loader_service_ops_t my2_loader_ops = {
.load_object = my2_load_object,
.load_abspath = my2_load_abspath,
.publish_data_sink = my2_publish_data_sink,
};
bool debug_config_test(void) {
BEGIN_TEST;
my_loader_service_ok = false;
my_loader_service_calls = 0;
// Spin up our test service.
loader_service_t* svc = NULL;
zx_status_t status = loader_service_create(NULL, &my2_loader_ops, NULL, &svc);
EXPECT_EQ(status, ZX_OK, "loader_service_create");
zx_handle_t my_service = ZX_HANDLE_INVALID;
status = loader_service_connect(svc, &my_service);
EXPECT_EQ(status, ZX_OK, "loader_service_connect");
// Install the service.
zx_handle_t old = dl_set_loader_service(my_service);
EXPECT_NE(old, ZX_HANDLE_INVALID, "dl_set_loader_service");
// Make up a VMO that we'll get back from the service.
ASSERT_EQ(zx_vmo_create(0, 0, &test_config_vmo), ZX_OK, "");
// Test the success case.
zx_handle_t vmo = ZX_HANDLE_INVALID;
EXPECT_EQ(__sanitizer_get_configuration(TEST_CONFIG_GOOD_NAME, &vmo),
ZX_OK, "__sanitizer_get_configuration on valid name");
EXPECT_EQ(vmo, test_config_vmo, "not the expected VMO handle");
EXPECT_EQ(my_loader_service_calls, 1,
"loader-service not called exactly once");
EXPECT_TRUE(my_loader_service_ok, "loader service thread not happy");
EXPECT_EQ(zx_handle_close(test_config_vmo), ZX_OK, "");
test_config_vmo = ZX_HANDLE_INVALID;
my_loader_service_ok = false;
my_loader_service_calls = 0;
// Test the failure case.
EXPECT_EQ(__sanitizer_get_configuration(TEST_CONFIG_BAD_NAME, &vmo),
ZX_ERR_NOT_FOUND,
"__sanitizer_get_configuration on invalid name");
EXPECT_EQ(my_loader_service_calls, 1,
"loader-service not called exactly once");
EXPECT_TRUE(my_loader_service_ok, "loader service thread not happy");
// Put things back to how they were.
zx_handle_t old2 = dl_set_loader_service(old);
EXPECT_EQ(old2, my_service, "unexpected previous service handle");
zx_handle_close(old2);
END_TEST;
}
BEGIN_TEST_CASE(sanitizer_utils_tests)
RUN_TEST(publish_data_test);
RUN_TEST(debug_config_test);
END_TEST_CASE(sanitizer_utils_tests)
int main(int argc, char** argv) {
bool success = unittest_run_all_tests(argc, argv);
return success ? 0 : -1;
}