blob: cb9ca16621ca9c111115cf5adbf7cecff3ef06ee [file] [log] [blame]
// Copyright 2019 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 <fuchsia/scheduler/c/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/zx/channel.h>
#include <lib/zx/object.h>
#include <lib/zx/profile.h>
#include <lib/zx/thread.h>
#include <threads.h>
#include <zircon/errors.h>
#include <zircon/syscalls.h>
#include <string>
#include <zxtest/zxtest.h>
namespace {
zx_status_t CreateProfile(const zx::channel& profile_provider, uint32_t priority,
const std::string& name, zx_status_t* server_status,
zx::profile* profile) {
zx_handle_t raw_profile_handle;
zx_status_t result = fuchsia_scheduler_ProfileProviderGetProfile(
profile_provider.get(), priority, name.data(), name.length(), server_status,
&raw_profile_handle);
if (result != ZX_OK) {
return ZX_OK;
}
*profile = zx::profile(raw_profile_handle);
return ZX_OK;
}
zx_status_t CreateDeadlineProfile(const zx::channel& profile_provider, zx_duration_t capacity,
zx_duration_t relative_deadline, zx_duration_t period,
const std::string& name, zx_status_t* server_status,
zx::profile* profile) {
zx_handle_t raw_profile_handle;
zx_status_t result = fuchsia_scheduler_ProfileProviderGetDeadlineProfile(
profile_provider.get(), capacity, relative_deadline, period, name.data(), name.length(),
server_status, &raw_profile_handle);
if (result != ZX_OK) {
return ZX_OK;
}
*profile = zx::profile(raw_profile_handle);
return ZX_OK;
}
zx_status_t SetProfileByRole(const zx::channel& profile_provider, zx::unowned_thread thread,
const std::string& role, zx_status_t* server_status) {
zx::thread duplicate;
if (zx_status_t status =
thread->duplicate(ZX_RIGHT_TRANSFER | ZX_RIGHT_MANAGE_THREAD, &duplicate);
status != ZX_OK) {
return status;
}
return fuchsia_scheduler_ProfileProviderSetProfileByRole(
profile_provider.get(), duplicate.release(), role.data(), role.length(), server_status);
}
void GetProfileProvider(zx::channel* channel) {
// Connect to ProfileProvider.
zx::channel server_endpoint;
ASSERT_OK(zx::channel::create(/*flags=*/0u, &server_endpoint, channel));
ASSERT_OK(fdio_service_connect("/svc/" fuchsia_scheduler_ProfileProvider_Name,
server_endpoint.release()),
"Could not connect to ProfileProvider.");
ASSERT_EQ(server_endpoint.get(), ZX_HANDLE_INVALID);
}
void CheckBasicDetails(const zx::profile& profile) {
// Ensure basic details are correct.
zx_info_handle_basic_t info;
ASSERT_OK(profile.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr),
"object_get_info for profile");
EXPECT_NE(info.koid, 0, "no koid for profile");
EXPECT_EQ(info.type, ZX_OBJ_TYPE_PROFILE, "incorrect type for profile");
}
// Test getting a profile via the GetProfile FIDL method.
TEST(Profile, GetProfile) {
zx::channel provider;
GetProfileProvider(&provider);
ASSERT_FALSE(CURRENT_TEST_HAS_FAILURES());
zx::profile profile;
zx_status_t status;
ASSERT_OK(CreateProfile(provider, /*priority=*/0u, "<test>", &status, &profile),
"Error creating profile.");
CheckBasicDetails(profile);
}
// Test getting a profile via the GetDeadlineProfile FIDL method.
TEST(Profile, GetDeadlineProfile) {
zx::channel provider;
GetProfileProvider(&provider);
ASSERT_FALSE(CURRENT_TEST_HAS_FAILURES());
zx::profile profile;
zx_status_t status;
ASSERT_OK(
CreateDeadlineProfile(provider, /*capacity=*/ZX_MSEC(2), /*relative_deadline=*/ZX_MSEC(10),
/*period=*/ZX_MSEC(10), "<test>", &status, &profile),
"Error creating deadline profile.");
CheckBasicDetails(profile);
}
// Test getting a profile via the GetCpuAffinityProfile FIDL method.
TEST(Profile, GetCpuAffinityProfile) {
zx::channel provider;
GetProfileProvider(&provider);
ASSERT_FALSE(CURRENT_TEST_HAS_FAILURES());
fuchsia_scheduler_CpuSet cpu_set = {};
cpu_set.mask[0] = 1;
zx::profile profile;
zx_status_t server_status;
ASSERT_OK(fuchsia_scheduler_ProfileProviderGetCpuAffinityProfile(
provider.get(), &cpu_set, &server_status, profile.reset_and_get_address()));
CheckBasicDetails(profile);
}
// Test setting a profile via the SetProfileByRole FIDL method.
TEST(Profile, SetProfileByRole) {
zx::channel provider;
GetProfileProvider(&provider);
ASSERT_FALSE(CURRENT_TEST_HAS_FAILURES());
zx_status_t server_status;
zx_status_t status;
status = SetProfileByRole(provider, zx::thread::self(), "fuchsia.test-role:ok", &server_status);
EXPECT_OK(status);
EXPECT_OK(server_status);
status = SetProfileByRole(provider, zx::unowned_thread{}, "fuchsia.test-role:ok", &server_status);
EXPECT_EQ(ZX_ERR_BAD_HANDLE, status);
EXPECT_OK(server_status);
status =
SetProfileByRole(provider, zx::thread::self(), "fuchsia.test-role:not-found", &server_status);
EXPECT_OK(status);
EXPECT_EQ(ZX_ERR_NOT_FOUND, server_status);
}
} // namespace