From 591853fa5855430b5058a19a97ce9d8e28a9caab Mon Sep 17 00:00:00 2001 From: "Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)" Date: Tue, 8 Oct 2024 18:06:39 +0100 Subject: [PATCH] Add C Result link test based on Ken's description of link failure. --- CMakeLists.txt | 9 ++- include/outcome/detail/revision.hpp | 6 +- test/link/CMakeLists.txt | 62 ++++++++++++++++++++ test/link/experimental-c-result/lib.c | 35 ++++++++++++ test/link/experimental-c-result/lib.cpp | 26 +++++++++ test/link/experimental-c-result/lib.h | 75 +++++++++++++++++++++++++ test/link/experimental-c-result/main.c | 57 +++++++++++++++++++ 7 files changed, 264 insertions(+), 6 deletions(-) create mode 100644 test/link/CMakeLists.txt create mode 100644 test/link/experimental-c-result/lib.c create mode 100644 test/link/experimental-c-result/lib.cpp create mode 100644 test/link/experimental-c-result/lib.h create mode 100644 test/link/experimental-c-result/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 732f70f863..14e490bb85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Outcome cmake -# (C) 2016-2023 Niall Douglas +# (C) 2016-2024 Niall Douglas # File Created: June 2016 # # @@ -184,7 +184,7 @@ endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (NOT DEFINED BUILD_TESTING OR BUILD_TESTING)) # For all possible configurations of this library, add each test - list_filter(outcome_TESTS EXCLUDE REGEX "constexprs") + list_filter(outcome_TESTS EXCLUDE REGEX "constexprs|link") set(outcome_TESTS_DISABLE_PRECOMPILE_HEADERS "outcome_hl--coroutine-support" "outcome_hl--core-result" @@ -359,9 +359,12 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND ( endforeach() endif() +# Add in link tests +add_subdirectory("test/link") + # Turn on pedantic warnings for all tests, examples and snippets if(NOT MSVC) - foreach(target ${outcome_TEST_TARGETS} ${outcome_EXAMPLE_TARGETS} ${example_bins}) + foreach(target ${outcome_TEST_TARGETS} ${outcome_EXAMPLE_TARGETS} ${outcome_LINK_TARGETS} ${example_bins}) target_compile_options(${target} PUBLIC "-Wpedantic") endforeach() endif() diff --git a/include/outcome/detail/revision.hpp b/include/outcome/detail/revision.hpp index 982e095bb8..24a7d6ee3f 100644 --- a/include/outcome/detail/revision.hpp +++ b/include/outcome/detail/revision.hpp @@ -22,6 +22,6 @@ Distributed under the Boost Software License, Version 1.0. */ // Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time -#define OUTCOME_PREVIOUS_COMMIT_REF 36beb5b34b24cf25d93ac421370ef5578f2f65ed -#define OUTCOME_PREVIOUS_COMMIT_DATE "2024-09-04 13:14:36 +00:00" -#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 36beb5b3 +#define OUTCOME_PREVIOUS_COMMIT_REF 2a8ff2b0ca37e4627b0d9919b653fee7d4cc6968 +#define OUTCOME_PREVIOUS_COMMIT_DATE "2024-09-04 14:48:43 +00:00" +#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 2a8ff2b0 diff --git a/test/link/CMakeLists.txt b/test/link/CMakeLists.txt new file mode 100644 index 0000000000..c0e822cb40 --- /dev/null +++ b/test/link/CMakeLists.txt @@ -0,0 +1,62 @@ +# Outcome cmake +# (C) 2016-2024 Niall Douglas +# File Created: June 2016 +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License in the accompanying file +# Licence.txt or at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file Licence.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +cmake_minimum_required(VERSION 3.9 FATAL_ERROR) + +set(outcome_LINK_TARGETS) +foreach(type STATIC SHARED) + foreach(visibility default hidden) + set(target outcome-link-test-experimental-c-result-type_${type}-vis_${visibility}) + add_library(${target}-lib ${type} + "experimental-c-result/lib.c" + "experimental-c-result/lib.cpp") + target_compile_definitions(${target}-lib PRIVATE MYLIB_SOURCE=1) + set_target_properties(${target}-lib PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + POSITION_INDEPENDENT_CODE ON + C_VISIBILITY_PRESET "${visibility}" + CXX_VISIBILITY_PRESET "${visibility}" + DISABLE_PRECOMPILE_HEADERS On + ) + target_link_libraries(${target}-lib PRIVATE outcome::hl) + list(APPEND outcome_LINK_TARGETS ${target}-lib) + + add_executable(${target} "experimental-c-result/main.c") + set_target_properties(${target} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + POSITION_INDEPENDENT_CODE ON + C_VISIBILITY_PRESET "${visibility}" + CXX_VISIBILITY_PRESET "${visibility}" + DISABLE_PRECOMPILE_HEADERS On + ) + target_link_libraries(${target} PRIVATE ${target}-lib outcome::hl) + if(target MATCHES ".*-type_SHARED-vis_hidden") + # The shared library won't export the C++ helper machinery if visibility is hidden, + # so without including a copy of the C++ helpers it would correctly fail to link. + add_library(${target}-cxx-helpers OBJECT "experimental-c-result/lib.cpp") + target_link_libraries(${target}-cxx-helpers PRIVATE outcome::hl) + target_link_libraries(${target} PRIVATE ${target}-cxx-helpers) + endif() + list(APPEND outcome_LINK_TARGETS ${target}) + endforeach() +endforeach() diff --git a/test/link/experimental-c-result/lib.c b/test/link/experimental-c-result/lib.c new file mode 100644 index 0000000000..e0900a159c --- /dev/null +++ b/test/link/experimental-c-result/lib.c @@ -0,0 +1,35 @@ +/* Link testing for outcomes +(C) 2024 Niall Douglas (6 commits) + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include "lib.h" + +#include + +mylib_result test_function(int x) +{ + if(x < 0) + { + return make_failure_result(EINVAL); + } + return make_success_result(x); +} diff --git a/test/link/experimental-c-result/lib.cpp b/test/link/experimental-c-result/lib.cpp new file mode 100644 index 0000000000..4aa487f9e6 --- /dev/null +++ b/test/link/experimental-c-result/lib.cpp @@ -0,0 +1,26 @@ +/* Link testing for outcomes +(C) 2024 Niall Douglas (6 commits) + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +// This should be all that is necessary to create the C++ runtime +// side of things for the C code +#include "lib.h" // NOLINT diff --git a/test/link/experimental-c-result/lib.h b/test/link/experimental-c-result/lib.h new file mode 100644 index 0000000000..31e14e368f --- /dev/null +++ b/test/link/experimental-c-result/lib.h @@ -0,0 +1,75 @@ +/* Link testing for outcomes +(C) 2024 Niall Douglas (6 commits) + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +#ifndef OUTCOME_TEST_LINK_EXPERIMENTAL_C_RESULT_H +#define OUTCOME_TEST_LINK_EXPERIMENTAL_C_RESULT_H + +#include + +#if MYLIB_SOURCE +#ifdef _MSC_VER +#define MYLIB_DECL __declspec(dllexport) +#else +#define MYLIB_DECL __attribute__((visibility("default"))) +#endif +#else +#define MYLIB_DECL +#endif + +CXX_DECLARE_RESULT_SYSTEM(mylib, intptr_t); + +typedef CXX_RESULT_SYSTEM(mylib) mylib_result; + +static int is_result_ok(mylib_result r) +{ + return CXX_RESULT_HAS_VALUE(r); +} + +static int is_result_failed(mylib_result r) +{ + return CXX_RESULT_HAS_ERROR(r); +} + +static mylib_result make_success_result(intptr_t v) +{ + return CXX_MAKE_RESULT_SYSTEM_SUCCESS(mylib, v); +} + +static mylib_result make_failure_result(int v) +{ + return CXX_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(mylib, v); +} + +static int is_result_equivalent(mylib_result r, int errcode) +{ + return outcome_status_code_equal_generic(&r, errcode); +} + +static const char *result_failure_message(mylib_result r) +{ + return outcome_status_code_message(&r); +} + +extern MYLIB_DECL mylib_result test_function(int x); + +#endif diff --git a/test/link/experimental-c-result/main.c b/test/link/experimental-c-result/main.c new file mode 100644 index 0000000000..8115e8bd25 --- /dev/null +++ b/test/link/experimental-c-result/main.c @@ -0,0 +1,57 @@ +/* Link testing for outcomes +(C) 2024 Niall Douglas (6 commits) + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include "lib.h" + +#include +#include +#include +#include + +int main(void) +{ + mylib_result r = test_function(5); + if(is_result_failed(r)) + { + fprintf(stderr, "FATAL: test_function(5) failed with '%s'\n", result_failure_message(r)); + abort(); + } + if(r.value != 5) + { + fprintf(stderr, "FATAL: test_function(5) did not return 5\n"); + abort(); + } + r = test_function(-5); + if(!is_result_failed(r)) + { + fprintf(stderr, "FATAL: test_function(-5) did not fail\n"); + abort(); + } + const char *msg = result_failure_message(r); + printf("test_function(-5) should fail with 'Invalid argument'\nIt failed with '%s'\n", msg); + if(0 != strcmp(msg, "Invalid argument")) + { + abort(); + } + return 0; +} \ No newline at end of file