blob: 06ac020ddfc8251438257229d5d89c8f74d88d82 [file] [log] [blame]
// Copyright 2022 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 <lib/zx/profile.h>
#include <lib/zx/result.h>
#include <string>
#include <unordered_set>
#include <zxtest/zxtest.h>
#include "src/zircon/bin/role_manager/src/config.h"
namespace {
using zircon_profile::LoadConfigs;
using zircon_profile::ProfileScope;
using zircon_profile::Role;
TEST(ProfileConfig, Parse) {
fit::result result = LoadConfigs("/pkg/data");
ASSERT_TRUE(result.is_ok());
{
const auto iter = result->thread.find(*Role::Create("fuchsia.default"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Builtin);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 16);
}
{
const auto iter = result->thread.find(*Role::Create("test.bringup.a:affinity"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Bringup);
EXPECT_EQ(iter->second.info.flags,
ZX_PROFILE_INFO_FLAG_CPU_MASK | ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 0);
EXPECT_EQ(iter->second.info.cpu_affinity_mask.mask[0], 0b001);
}
{
const auto iter = result->thread.find(*Role::Create("test.bringup.b:affinity"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags,
ZX_PROFILE_INFO_FLAG_CPU_MASK | ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 1);
EXPECT_EQ(iter->second.info.cpu_affinity_mask.mask[0], 0b011);
}
{
const auto iter = result->thread.find(*Role::Create("test.core.a"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 5'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 10'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 10'000'000);
}
{
const auto iter = result->thread.find(*Role::Create("test.bringup.a"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 10);
}
{
const auto iter = result->thread.find(*Role::Create("test.product.a"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Product);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 25);
}
{
const auto iter = result->thread.find(*Role::Create("test.core.a:affinity"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Product);
EXPECT_EQ(iter->second.info.flags,
ZX_PROFILE_INFO_FLAG_CPU_MASK | ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 6'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 15'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 20'000'000);
EXPECT_EQ(iter->second.info.cpu_affinity_mask.mask[0], 0b110);
}
{
const auto iter = result->thread.find(*Role::Create("test.bringup.b"));
ASSERT_TRUE(iter != result->thread.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Product);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 20);
}
// The next two test cases validate that the same role name with different selectors correctly
// fetches two different roles.
{
const auto iter = result->thread.find(*Role::Create("test.core.parameterized.role:input=foo"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 5'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 10'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 10'000'000);
EXPECT_EQ(iter->second.output_parameters.size(), 2);
EXPECT_EQ(iter->second.output_parameters[0].key(), "output1");
EXPECT_EQ(iter->second.output_parameters[0].value().int_value().value(), 1);
EXPECT_EQ(iter->second.output_parameters[1].key(), "output2");
EXPECT_EQ(iter->second.output_parameters[1].value().float_value().value(), 2.5);
}
{
const auto iter = result->thread.find(*Role::Create("test.core.parameterized.role:input=bar"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 6'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 9'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 10'000'000);
EXPECT_EQ(iter->second.output_parameters.size(), 2);
EXPECT_EQ(iter->second.output_parameters[0].key(), "output1");
EXPECT_EQ(iter->second.output_parameters[0].value().int_value().value(), 5);
EXPECT_EQ(iter->second.output_parameters[1].key(), "output2");
EXPECT_EQ(iter->second.output_parameters[1].value().float_value().value(), 42.6);
}
// The next two test cases validate that the order of selectors does not change the role that is
// fetched.
{
const auto iter =
result->thread.find(*Role::Create("test.core.parameterized.role:param1=foo,param2=bar"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 7'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 8'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 10'000'000);
EXPECT_EQ(iter->second.output_parameters.size(), 3);
EXPECT_EQ(iter->second.output_parameters[0].key(), "output1");
EXPECT_EQ(iter->second.output_parameters[0].value().int_value().value(), 489);
EXPECT_EQ(iter->second.output_parameters[1].key(), "output2");
EXPECT_EQ(iter->second.output_parameters[1].value().float_value().value(), 297.5);
EXPECT_EQ(iter->second.output_parameters[2].key(), "output3");
EXPECT_EQ(iter->second.output_parameters[2].value().string_value().value(), "Hello, World!");
}
{
const auto iter =
result->thread.find(*Role::Create("test.core.parameterized.role:param2=bar,param1=foo"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_DEADLINE);
EXPECT_EQ(iter->second.info.deadline_params.capacity, 7'000'000);
EXPECT_EQ(iter->second.info.deadline_params.relative_deadline, 8'000'000);
EXPECT_EQ(iter->second.info.deadline_params.period, 10'000'000);
EXPECT_EQ(iter->second.output_parameters.size(), 3);
EXPECT_EQ(iter->second.output_parameters[0].key(), "output1");
EXPECT_EQ(iter->second.output_parameters[0].value().int_value().value(), 489);
EXPECT_EQ(iter->second.output_parameters[1].key(), "output2");
EXPECT_EQ(iter->second.output_parameters[1].value().float_value().value(), 297.5);
EXPECT_EQ(iter->second.output_parameters[2].key(), "output3");
EXPECT_EQ(iter->second.output_parameters[2].value().string_value().value(), "Hello, World!");
}
{
const auto iter = result->memory.find(*Role::Create("fuchsia.default"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Builtin);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 16);
}
{
const auto iter = result->memory.find(*Role::Create("test.bringup.a"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 20);
}
{
const auto iter = result->memory.find(*Role::Create("test.bringup.b"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Bringup);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 24);
}
{
const auto iter = result->memory.find(*Role::Create("test.core.a"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 24);
}
{
const auto iter = result->memory.find(*Role::Create("test.core.mem"));
ASSERT_TRUE(iter != result->memory.end());
EXPECT_EQ(iter->second.scope, ProfileScope::Core);
EXPECT_EQ(iter->second.info.flags, ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY);
EXPECT_EQ(iter->second.info.priority, 20);
}
const std::unordered_set<std::string> expected_thread_profiles{
"test.product.a",
"test.core.a:affinity",
"test.bringup.a:affinity",
"test.bringup.b",
"test.bringup.b:affinity",
"test.core.a",
"test.core.parameterized.role:input=foo",
"test.core.parameterized.role:input=bar",
"test.core.parameterized.role:param1=foo,param2=bar",
"test.bringup.a",
"fuchsia.default",
};
EXPECT_EQ(result->thread.size(), expected_thread_profiles.size());
for (auto expected_thread_profile : expected_thread_profiles) {
fit::result role = zircon_profile::Role::Create(expected_thread_profile);
ASSERT_TRUE(role.is_ok());
EXPECT_NE(result->thread.cend(), result->thread.find(*role));
}
const std::unordered_set<std::string> expected_memory_profiles{
"test.bringup.a", "test.bringup.b", "test.core.a", "test.core.mem", "fuchsia.default",
};
EXPECT_EQ(result->memory.size(), expected_memory_profiles.size());
for (auto expected_memory_profile : expected_memory_profiles) {
fit::result role = zircon_profile::Role::Create(expected_memory_profile);
ASSERT_TRUE(role.is_ok());
EXPECT_NE(result->memory.cend(), result->memory.find(*role));
}
}
TEST(ProfileConfig, CreateRole) {
EXPECT_EQ(fit::success{}, Role::Create("abcd"));
EXPECT_EQ(fit::success{}, Role::Create("a.b.c.d"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123"));
EXPECT_EQ(fit::success{}, Role::Create("_abcd123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123.01234"));
EXPECT_EQ(fit::success{}, Role::Create("abcd-123.012-34"));
EXPECT_EQ(fit::success{}, Role::Create("abcd_123.012_34"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123.abc123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123._abc123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123._abc123:xyz123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123._abc123:xyz-123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123._abc123:xyz_123"));
EXPECT_EQ(fit::success{}, Role::Create("abcd123._abc123:xyz123,abc987=01234"));
EXPECT_EQ(fit::failed{}, Role::Create(""));
EXPECT_EQ(fit::failed{}, Role::Create("+abcd"));
EXPECT_EQ(fit::failed{}, Role::Create("-abcd"));
}
TEST(ProfileConfig, MaybeMediaRole) {
{
fit::result role = Role::Create("foo.bar:realm=media,capacity=1000000,deadline=1000000");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::success{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:realm=bar,capacity=1000000,deadline=1000000");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:realm=media,capacity=baz,deadline=1000000");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:realm=media,capacity=1000000,deadline=baz");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:capacity=1000000,deadline=baz");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:realm=media,deadline=1000000");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
{
fit::result role = Role::Create("foo.bar:realm=media,capacity=1000000");
ASSERT_TRUE(role.is_ok());
EXPECT_EQ(fit::failed{}, role->ToMediaRole());
}
}
} // anonymous namespace