| // 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 |