Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions cmake/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,54 @@ function(ppc_configure_subproject SUBDIR)
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}")
endforeach()
endfunction()

function(ppc_configure_meta_part PROJ_NAME BASE_DIR)
set(TEST_DIR "${BASE_DIR}/tests")
set(TEST_EXECUTABLES "")

add_tests(USE_FUNC_TESTS ${FUNC_TEST_EXEC} functional)
add_tests(USE_PERF_TESTS ${PERF_TEST_EXEC} performance)

message(STATUS " -- ${PROJ_NAME}")

foreach(IMPL IN LISTS PPC_IMPLEMENTATIONS)
setup_implementation(
NAME
${IMPL}
PROJ_NAME
${PROJ_NAME}
TESTS
"${TEST_EXECUTABLES}"
BASE_DIR
"${BASE_DIR}")
endforeach()
endfunction()

function(ppc_configure_meta_project SUBDIR)
add_compile_definitions(
PPC_SETTINGS_${SUBDIR}="${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/settings.json"
PPC_ID_${SUBDIR}="${SUBDIR}")

project(${SUBDIR})
message(STATUS "${SUBDIR}")

if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/threads")
ppc_configure_meta_part(${SUBDIR}_threads
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/threads")
endif()

file(
GLOB process_task_dirs
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/processes"
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/processes/*")
list(SORT process_task_dirs)
foreach(PROCESS_TASK IN LISTS process_task_dirs)
if(NOT IS_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/processes/${PROCESS_TASK}")
continue()
endif()
ppc_configure_meta_part(
${SUBDIR}_processes_${PROCESS_TASK}
"${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/processes/${PROCESS_TASK}")
endforeach()
endfunction()
38 changes: 34 additions & 4 deletions modules/task/include/task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ inline std::string GetStringTaskStatus(StatusOfTask status_of_task) {
/// @brief Returns a string representation of the task type based on the JSON settings file.
/// @param type_of_task Type of the task.
/// @param settings_file_path Path to the JSON file containing task type strings.
/// @param settings_task_path Optional dot-separated nested path inside the `tasks` object.
/// @return Formatted string combining the task type and its corresponding value from the file.
/// @throws std::runtime_error If the file cannot be opened.
inline std::string GetStringTaskType(TypeOfTask type_of_task, const std::string &settings_file_path) {
/// @throws std::runtime_error If the file cannot be opened or the requested settings key is missing.
inline std::string GetStringTaskType(TypeOfTask type_of_task, const std::string &settings_file_path,
std::string_view settings_task_path = {}) {
std::ifstream file(settings_file_path);
if (!file.is_open()) {
throw std::runtime_error("Failed to open " + settings_file_path);
Expand All @@ -94,8 +96,36 @@ inline std::string GetStringTaskType(TypeOfTask type_of_task, const std::string
return std::string(type_str);
}

const auto &tasks = list_settings->at("tasks");
return std::string(type_str) + "_" + std::string(tasks.at(std::string(type_str)));
auto get_required_node = [&settings_file_path](const nlohmann::json &node, const std::string &key,
const std::string &settings_key_path) -> const nlohmann::json & {
if (!node.is_object() || !node.contains(key)) {
throw std::runtime_error("Missing settings key '" + settings_key_path + "' in " + settings_file_path);
}
return *node.find(key);
};

std::string settings_key_path = "tasks";
const auto *settings_node = &get_required_node(*list_settings, "tasks", settings_key_path);
for (size_t start = 0; start < settings_task_path.size();) {
const size_t separator = settings_task_path.find('.', start);
const size_t key_size = separator == std::string_view::npos ? settings_task_path.size() - start : separator - start;
if (key_size == 0) {
throw std::runtime_error("Empty settings key in '" + std::string(settings_task_path) + "' from " +
settings_file_path);
}
const std::string key(settings_task_path.substr(start, key_size));
settings_key_path += "." + key;
settings_node = &get_required_node(*settings_node, key, settings_key_path);
if (separator == std::string_view::npos) {
break;
}
start = separator + 1;
}

const std::string type_key(type_str);
settings_key_path += "." + type_key;
const auto &type_node = get_required_node(*settings_node, type_key, settings_key_path);
return type_key + "_" + type_node.get<std::string>();
}

enum class StateOfTesting : uint8_t {
Expand Down
26 changes: 26 additions & 0 deletions modules/task/tests/task_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,32 @@ TEST(TaskTest, GetStringTaskTypeEachTypeWithValidFile) {
EXPECT_NO_THROW(GetStringTaskType(TypeOfTask::kSEQ, path));
}

TEST(TaskTest, GetStringTaskTypeReadsNestedTaskPath) {
std::string path = "settings_nested.json";
ScopedFile cleaner(path);
std::ofstream file(path);
file << R"({"tasks": {"processes": {"t2": {"mpi": "disabled", "seq": "enabled"}}}})";
file.close();

EXPECT_EQ(GetStringTaskType(TypeOfTask::kMPI, path, "processes.t2"), "mpi_disabled");
EXPECT_EQ(GetStringTaskType(TypeOfTask::kSEQ, path, "processes.t2"), "seq_enabled");
}

TEST(TaskTest, GetStringTaskTypeReportsMissingNestedTaskPath) {
std::string path = "settings_missing_nested.json";
ScopedFile cleaner(path);
std::ofstream file(path);
file << R"({"tasks": {"processes": {"t1": {"mpi": "enabled"}}}})";
file.close();

try {
GetStringTaskType(TypeOfTask::kMPI, path, "processes.t2");
FAIL() << "Expected std::runtime_error";
} catch (const std::runtime_error &e) {
EXPECT_NE(std::string(e.what()).find("tasks.processes.t2"), std::string::npos);
}
}

TEST(TaskTest, GetStringTaskTypeReturnsUnknownOnDefault) {
std::string path = "settings_valid_unknown.json";
ScopedFile cleaner(path);
Expand Down
23 changes: 13 additions & 10 deletions modules/util/include/func_test_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
#include <tbb/tick_count.h>

#include <concepts>
#include <csignal>
#include <cstddef>
#include <functional>
#include <iostream>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -133,22 +133,25 @@ auto ExpandToValues(const Tuple &t) {

template <typename Task, typename InType, typename SizesContainer, std::size_t... Is>
auto GenTaskTuplesImpl(const SizesContainer &sizes, const std::string &settings_path,
std::index_sequence<Is...> /*unused*/) {
return std::make_tuple(std::make_tuple(ppc::task::TaskGetter<Task, InType>,
std::string(GetNamespace<Task>()) + "_" +
ppc::task::GetStringTaskType(Task::GetStaticTypeOfTask(), settings_path),
std::get<Is>(sizes))...);
std::string_view settings_task_path, std::index_sequence<Is...> /*unused*/) {
return std::make_tuple(
std::make_tuple(ppc::task::TaskGetter<Task, InType>,
std::string(GetNamespace<Task>()) + "_" +
ppc::task::GetStringTaskType(Task::GetStaticTypeOfTask(), settings_path, settings_task_path),
std::get<Is>(sizes))...);
}

template <typename Task, typename InType, typename SizesContainer>
auto TaskListGenerator(const SizesContainer &sizes, const std::string &settings_path) {
return GenTaskTuplesImpl<Task, InType>(sizes, settings_path,
auto TaskListGenerator(const SizesContainer &sizes, const std::string &settings_path,
std::string_view settings_task_path = {}) {
return GenTaskTuplesImpl<Task, InType>(sizes, settings_path, settings_task_path,
std::make_index_sequence<std::tuple_size_v<std::decay_t<SizesContainer>>>{});
}

template <typename Task, typename InType, typename SizesContainer>
constexpr auto AddFuncTask(const SizesContainer &sizes, const std::string &settings_path) {
return TaskListGenerator<Task, InType>(sizes, settings_path);
constexpr auto AddFuncTask(const SizesContainer &sizes, const std::string &settings_path,
std::string_view settings_task_path = {}) {
return TaskListGenerator<Task, InType>(sizes, settings_path, settings_task_path);
}

} // namespace ppc::util
13 changes: 7 additions & 6 deletions modules/util/include/perf_test_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
#include <tbb/tick_count.h>

#include <chrono>
#include <csignal>
#include <cstddef>
#include <functional>
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -77,7 +77,8 @@ class BaseRunPerfTests : public ::testing::TestWithParam<PerfTestParam<InType, O

ASSERT_FALSE(test_name.find("unknown") != std::string::npos);
if (test_name.find("disabled") != std::string::npos) {
GTEST_SKIP();
// A single perf test body may execute several implementations; do not abort the enabled ones.
return;
Comment thread
aobolensk marked this conversation as resolved.
}

const auto test_env_scope = ppc::util::test::MakePerTestEnvForCurrentGTest(test_name);
Expand Down Expand Up @@ -111,9 +112,9 @@ class BaseRunPerfTests : public ::testing::TestWithParam<PerfTestParam<InType, O
};

template <typename TaskType, typename InputType>
auto MakePerfTaskTuples(const std::string &settings_path) {
auto MakePerfTaskTuples(const std::string &settings_path, std::string_view settings_task_path = {}) {
const auto name = std::string(GetNamespace<TaskType>()) + "_" +
ppc::task::GetStringTaskType(TaskType::GetStaticTypeOfTask(), settings_path);
ppc::task::GetStringTaskType(TaskType::GetStaticTypeOfTask(), settings_path, settings_task_path);

return std::make_tuple(std::make_tuple(ppc::task::TaskGetter<TaskType, InputType>, name,
ppc::performance::PerfResults::TypeOfRunning::kPipeline),
Expand All @@ -133,8 +134,8 @@ auto TupleToGTestValues(Tuple &&tup) {
}

template <typename InputType, typename... TaskTypes>
auto MakeAllPerfTasks(const std::string &settings_path) {
return std::tuple_cat(MakePerfTaskTuples<TaskTypes, InputType>(settings_path)...);
auto MakeAllPerfTasks(const std::string &settings_path, std::string_view settings_task_path = {}) {
return std::tuple_cat(MakePerfTaskTuples<TaskTypes, InputType>(settings_path, settings_task_path)...);
}

} // namespace ppc::util
4 changes: 2 additions & 2 deletions scoreboard/data/copying.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ threads:
processes:
copying:
mpi:
- example_processes
- example_processes_t1
seq:
- example_processes
- example_processes_t1
Loading
Loading