Skip to content
Open
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
33 changes: 31 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,32 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
COMPILE_OPTIONS -Wno-unsafe-buffer-usage)
endif()

find_package(Threads REQUIRED)

# Test support is a first-party, build-local library. It is intentionally not
# registered as a subsystem and is never installed or linked by runtime targets.
add_library(laghu_test_support STATIC tests/support/laghu_test_support.cpp)
laghu_apply_first_party_contract(laghu_test_support)
target_include_directories(laghu_test_support PUBLIC "${CMAKE_SOURCE_DIR}/tests/support")

add_executable(laghu_test_support_fixtures_test tests/support/fixtures.cpp)
laghu_apply_first_party_contract(laghu_test_support_fixtures_test)
target_link_libraries(laghu_test_support_fixtures_test PRIVATE laghu_test_support Threads::Threads)
Comment thread
niteshpurohit marked this conversation as resolved.
laghu_add_native_test(laghu.test_support.fixtures laghu_test_support_fixtures_test)

add_executable(laghu_test_support_runner_contract_test tests/support/runner_contract.cpp)
laghu_apply_first_party_contract(laghu_test_support_runner_contract_test)
target_link_libraries(laghu_test_support_runner_contract_test PRIVATE laghu_test_support)
laghu_add_native_test(laghu.test_support.runner_contract laghu_test_support_runner_contract_test)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# POSIX requires fixed C buffers for sockaddr, mkdtemp, and directory APIs.
# Keep the narrow diagnostic waiver confined to this non-installed test support.
set_source_files_properties(
tests/support/laghu_test_support.cpp
tests/support/fixtures.cpp
PROPERTIES COMPILE_OPTIONS -Wno-unsafe-buffer-usage)
endif()

laghu_declare_subsystem_graph()
laghu_configure_api_boundaries()
laghu_apply_first_party_contract(laghu_os)
Expand Down Expand Up @@ -79,6 +105,7 @@ add_executable(laghu_core_result_errors_test tests/core/result_errors.cpp)
laghu_apply_first_party_contract(laghu_core_result_errors_test)
laghu_configure_api_consumer(laghu_core_result_errors_test core)
target_link_libraries(laghu_core_result_errors_test PRIVATE laghu_core)
target_link_libraries(laghu_core_result_errors_test PRIVATE laghu_test_support)
laghu_add_native_test(laghu.core.result_errors laghu_core_result_errors_test)

add_executable(laghu_core_strong_identifiers_test tests/core/strong_identifiers.cpp)
Expand Down Expand Up @@ -136,7 +163,6 @@ laghu_configure_api_consumer(laghu_core_state_transitions_test core)
target_link_libraries(laghu_core_state_transitions_test PRIVATE laghu_core)
laghu_add_native_test(laghu.core.state_transitions laghu_core_state_transitions_test)

find_package(Threads REQUIRED)
add_executable(laghu_core_deadlines_cancellation_test tests/core/deadlines_cancellation.cpp)
laghu_apply_first_party_contract(laghu_core_deadlines_cancellation_test)
laghu_configure_api_consumer(laghu_core_deadlines_cancellation_test core)
Expand Down Expand Up @@ -180,6 +206,7 @@ if(TARGET laghu_crypto)
target_include_directories(laghu_crypto_provider_test PRIVATE
"${CMAKE_SOURCE_DIR}/src/adapters/private")
target_link_libraries(laghu_crypto_provider_test PRIVATE laghu_crypto)
target_link_libraries(laghu_crypto_provider_test PRIVATE laghu_test_support)
laghu_add_native_test(laghu.crypto.provider laghu_crypto_provider_test)
endif()

Expand All @@ -202,6 +229,7 @@ laghu_apply_first_party_contract(laghu_os_iovec_translation_test)
laghu_configure_api_consumer(laghu_os_iovec_translation_test os)
target_include_directories(laghu_os_iovec_translation_test PRIVATE "${CMAKE_SOURCE_DIR}/src/os/private")
target_link_libraries(laghu_os_iovec_translation_test PRIVATE laghu_os)
target_link_libraries(laghu_os_iovec_translation_test PRIVATE laghu_test_support)
laghu_add_native_test(laghu.os.iovec_translation laghu_os_iovec_translation_test)

add_executable(laghu
Expand Down Expand Up @@ -242,7 +270,8 @@ set(laghu_verify_targets
laghu_core_state_transitions_test laghu_core_deadlines_cancellation_test
laghu_core_shared_offsets_test laghu_core_mapped_regions_test
laghu_core_binary_envelope_test laghu_core_digest_primitives_test
laghu_os_iovec_translation_test laghu
laghu_os_iovec_translation_test laghu_test_support laghu_test_support_fixtures_test
laghu_test_support_runner_contract_test laghu
laghu_capability_header_parity laghu_visibility_probe visibility_negative_fixture)
if(TARGET laghu_crypto_provider_test)
list(APPEND laghu_verify_targets laghu_crypto laghu_crypto_provider_test)
Expand Down
54 changes: 54 additions & 0 deletions cmake/ExpectTestWrapper.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-License-Identifier: AGPL-3.0-only

if(NOT DEFINED SCRIPT)
message(FATAL_ERROR "Laghu test-wrapper expectation requires SCRIPT")
endif()
if(NOT DEFINED TEST_ROOT)
message(FATAL_ERROR "Laghu test-wrapper expectation requires TEST_ROOT")
endif()
if(NOT DEFINED TEST_BUILD)
message(FATAL_ERROR "Laghu test-wrapper expectation requires TEST_BUILD")
endif()

function(laghu_expect_test_wrapper expected_result)
execute_process(
COMMAND "${SCRIPT}" ${ARGN}
RESULT_VARIABLE actual_result
OUTPUT_VARIABLE output
ERROR_VARIABLE error)
if(NOT actual_result EQUAL expected_result)
message(FATAL_ERROR
"Laghu test-wrapper expectation failed: expected=${expected_result} actual=${actual_result} output=${output}${error}")
endif()
endfunction()

function(laghu_expect_test_wrapper_failure)
execute_process(
COMMAND "${SCRIPT}" ${ARGN}
RESULT_VARIABLE actual_result
OUTPUT_VARIABLE output
ERROR_VARIABLE error)
if(actual_result EQUAL 0)
message(FATAL_ERROR
"Laghu test-wrapper expectation failed: expected a failure output=${output}${error}")
endif()
endfunction()

file(MAKE_DIRECTORY "${TEST_ROOT}")
set(non_directory_build "${TEST_ROOT}/not-a-directory")
if(EXISTS "${non_directory_build}")
if(IS_DIRECTORY "${non_directory_build}")
message(FATAL_ERROR "Laghu test-wrapper fixture is unexpectedly a directory: ${non_directory_build}")
endif()
file(REMOVE "${non_directory_build}")
endif()
file(WRITE "${non_directory_build}" "fixture\n")

laghu_expect_test_wrapper(64)
laghu_expect_test_wrapper(64 --filter laghu)
laghu_expect_test_wrapper(64 --build "${TEST_ROOT}" --filter "")
laghu_expect_test_wrapper(64 --build "${TEST_ROOT}" --unknown)
laghu_expect_test_wrapper(66 --build "${non_directory_build}")
laghu_expect_test_wrapper_failure(
--build "${TEST_BUILD}"
--filter "^laghu\\.test_support\\.missing$")
12 changes: 12 additions & 0 deletions cmake/LaghuToolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ endfunction()

function(laghu_add_validation_tests)
set(expect_compile "${CMAKE_SOURCE_DIR}/cmake/ExpectCompile.cmake")
add_test(NAME laghu.test.wrapper.usage
COMMAND "${CMAKE_COMMAND}"
"-DSCRIPT=${CMAKE_SOURCE_DIR}/scripts/test"
"-DTEST_ROOT=${CMAKE_BINARY_DIR}/tests/test-wrapper"
"-DTEST_BUILD=${CMAKE_BINARY_DIR}"
-P "${CMAKE_SOURCE_DIR}/cmake/ExpectTestWrapper.cmake")
if(NOT CMAKE_CROSSCOMPILING)
add_test(NAME laghu.test.wrapper.selective
COMMAND "${CMAKE_SOURCE_DIR}/scripts/test"
--build "${CMAKE_BINARY_DIR}"
--filter "^laghu.test_support.fixtures$")
endif()
add_test(NAME laghu.build.cross_test_registration
COMMAND "${CMAKE_COMMAND}"
"-DLAGHU_SOURCE=${CMAKE_SOURCE_DIR}"
Expand Down
69 changes: 69 additions & 0 deletions scripts/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only

usage() {
printf '%s\n' 'usage: scripts/test --build <directory> [--filter <regex>] [--verbose]' >&2
}

build_directory=''
filter=''
filter_set=false
verbose=false

while [ "$#" -gt 0 ]; do
case "$1" in
--build)
if [ "$#" -lt 2 ] || [ -n "$build_directory" ]; then
usage
exit 64
fi
build_directory=$2
shift 2
;;
--filter)
if [ "$#" -lt 2 ] || [ "$filter_set" = true ] || [ -z "$2" ]; then
usage
exit 64
fi
filter=$2
filter_set=true
shift 2
;;
--verbose)
if [ "$verbose" = true ]; then
usage
exit 64
fi
verbose=true
shift
;;
*)
usage
exit 64
;;
esac
done

if [ -z "$build_directory" ]; then
usage
exit 64
fi

if [ ! -d "$build_directory" ]; then
printf '%s\n' "scripts/test: build directory does not exist: $build_directory" >&2
exit 66
fi

if ! command -v ctest >/dev/null 2>&1; then
printf '%s\n' 'scripts/test: ctest is unavailable' >&2
exit 69
fi

set -- ctest --test-dir "$build_directory" --output-on-failure --no-tests=error
if [ -n "$filter" ]; then
set -- "$@" --tests-regex "$filter"
fi
if [ "$verbose" = true ]; then
set -- "$@" --verbose
fi
exec "$@"
29 changes: 19 additions & 10 deletions tests/adapters/crypto_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <string_view>
#include <type_traits>

#include "laghu_test_support.hpp"

#include <laghu/adapters/crypto_provider.hpp>
#include <laghu/adapters/internal/entropy.hpp>
#include <laghu/core/digest.hpp>
Expand Down Expand Up @@ -260,31 +262,38 @@ static_assert(std::is_trivially_copyable_v<laghu::core::CryptoProvider>);

} // namespace

int main() {
[[nodiscard]] bool check_crypto_provider() noexcept {
const auto provider = laghu::adapters::crypto_provider();
if (!provider.valid()) {
return 1;
return false;
}
if (!check_sha256(provider)) {
return 2;
return false;
}
if (!check_hmac_sha256(provider)) {
return 3;
return false;
}
if (!check_digest_primitives(provider)) {
return 8;
return false;
}
if (!check_ed25519(provider)) {
return 4;
return false;
}
if (!check_spki_pin(provider)) {
return 5;
return false;
}
if (!check_constant_time_equality(provider)) {
return 6;
return false;
}
if (!check_entropy(provider)) {
return 7;
return false;
}
return 0;
return true;
}

int main() {
constexpr std::array tests{
laghu::test::TestCase{"adapters.crypto_provider.contract", check_crypto_provider},
};
return laghu::test::run_tests(tests);
}
31 changes: 20 additions & 11 deletions tests/core/result_errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <string_view>
#include <type_traits>

#include "laghu_test_support.hpp"

#include <laghu/core/contract.hpp>

std::size_t allocation_attempts{};
Expand Down Expand Up @@ -69,11 +71,11 @@ static_assert(noexcept(laghu::core::Error::from_dependency(

} // namespace

int main() {
[[nodiscard]] bool check_result_errors() noexcept {
const std::size_t allocation_attempts_before = allocation_attempts;
const auto success = move_only_success();
if (!check(success.has_value() && success->value() == 47)) {
return 1;
return false;
}

const auto invalid_input = laghu::core::Error::from_errno(EINVAL, "invalid input");
Expand All @@ -82,13 +84,13 @@ int main() {
invalid_input.native_code() == EINVAL &&
invalid_input.retryability() == laghu::core::Retryability::never &&
invalid_input.security_relevance() == laghu::core::SecurityRelevance::ordinary)) {
return 2;
return false;
}

const auto deadline = laghu::core::Error::from_errno(ETIMEDOUT);
if (!check(deadline.code() == laghu::core::ErrorCode::deadline &&
deadline.retryability() == laghu::core::Retryability::may_retry)) {
return 3;
return false;
}

const auto dependency = laghu::core::Error::from_dependency(
Expand All @@ -97,7 +99,7 @@ int main() {
dependency.code() == laghu::core::ErrorCode::checksum &&
dependency.native_code() == -9 &&
dependency.security_relevance() == laghu::core::SecurityRelevance::security_relevant)) {
return 4;
return false;
}

const std::array<char, 3> embedded_nul{'a', '\0', 'b'};
Expand All @@ -107,7 +109,7 @@ int main() {
if (!check(embedded.diagnostic_context().size() == embedded_nul.size() &&
embedded.diagnostic_context()[1] == '\0' &&
embedded.diagnostic_bytes()[3] == '\0' && !embedded.diagnostic_truncated())) {
return 5;
return false;
}

std::array<char, laghu::core::Error::diagnostic_context_capacity + 1> oversized{};
Expand All @@ -122,23 +124,30 @@ int main() {
truncated.diagnostic_truncated() &&
truncated.diagnostic_bytes().front() == oversized.front() &&
truncated.diagnostic_bytes().back() == oversized[95])) {
return 6;
return false;
}

const auto short_context = laghu::core::Error{laghu::core::ErrorDomain::core,
laghu::core::ErrorCode::invalid_state, 0, "ok"};
if (!check(short_context.diagnostic_context() == std::string_view{"ok"} &&
short_context.diagnostic_bytes()[2] == '\0' &&
!short_context.diagnostic_truncated())) {
return 7;
return false;
}

laghu::core::Result<int> failure = std::unexpected{invalid_input};
if (!check(!failure.has_value() && failure.error().code() == laghu::core::ErrorCode::invalid_input)) {
return 8;
return false;
}
if (!check(allocation_attempts == allocation_attempts_before)) {
return 9;
return false;
}
return 0;
return true;
}

int main() {
constexpr std::array tests{
laghu::test::TestCase{"core.result_errors.contract", check_result_errors},
};
return laghu::test::run_tests(tests);
}
15 changes: 11 additions & 4 deletions tests/os/iovec_translation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <sys/uio.h>

#include "laghu_test_support.hpp"

#include <laghu/core/bounded_buffer.hpp>
#include <laghu/os/internal/io_slices.hpp>

Expand Down Expand Up @@ -90,9 +92,14 @@ using laghu::core::IoSliceList;

} // namespace

[[nodiscard]] bool check_iovec_translation() noexcept {
return check(check_translation_and_partial_consumption()) &&
check(check_capacity_and_zero_slices());
}

int main() {
if (!check(check_translation_and_partial_consumption())) {
return 1;
}
return check(check_capacity_and_zero_slices()) ? 0 : 2;
constexpr std::array tests{
laghu::test::TestCase{"os.iovec_translation.contract", check_iovec_translation},
};
return laghu::test::run_tests(tests);
}
Loading
Loading