From 8f7e60dce44f682540247981b46aa644c9f6a370 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 26 Oct 2022 19:32:34 +0200 Subject: [PATCH] :alembic: (stl): Test std::ranges support for arm-gcc + clang --- libs/Utils/CMakeLists.txt | 1 + libs/Utils/include/RangesUtils.h | 33 ++++ libs/Utils/include/Utils.h | 1 + libs/Utils/tests/RangesUtils_test.cpp | 138 +++++++++++++++ spikes/stl_cxxsupport/main.cpp | 27 +++ tests/functional/CMakeLists.txt | 2 + .../tests/stl_features/CMakeLists.txt | 15 ++ .../tests/stl_features/suite_std_ranges.cpp | 159 ++++++++++++++++++ 8 files changed, 376 insertions(+) create mode 100644 libs/Utils/include/RangesUtils.h create mode 100644 libs/Utils/tests/RangesUtils_test.cpp create mode 100644 tests/functional/tests/stl_features/CMakeLists.txt create mode 100644 tests/functional/tests/stl_features/suite_std_ranges.cpp diff --git a/libs/Utils/CMakeLists.txt b/libs/Utils/CMakeLists.txt index d14546c812..56b06eda68 100644 --- a/libs/Utils/CMakeLists.txt +++ b/libs/Utils/CMakeLists.txt @@ -25,5 +25,6 @@ if(${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests") tests/MathUtils_test_map.cpp tests/MathUtils_test_random8.cpp tests/MemoryUtils_test.cpp + tests/RangesUtils_test.cpp ) endif() diff --git a/libs/Utils/include/RangesUtils.h b/libs/Utils/include/RangesUtils.h new file mode 100644 index 0000000000..1d817ec8e7 --- /dev/null +++ b/libs/Utils/include/RangesUtils.h @@ -0,0 +1,33 @@ +// Leka - LekaOS +// Copyright 2022 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +namespace leka::utils::ranges { + +struct SequenceFromTo { + int start; + int end; +}; + +constexpr auto sequence(const SequenceFromTo seq) +{ + auto values = std::ranges::views::iota(seq.start, seq.end + 1); + return values; +} + +struct SequenceFromSize { + int from; + int size; +}; + +constexpr auto sequence(const SequenceFromSize seq) +{ + auto values = std::ranges::views::iota(seq.from, seq.from + seq.size); + return values; +} + +} // namespace leka::utils::ranges diff --git a/libs/Utils/include/Utils.h b/libs/Utils/include/Utils.h index 1a8c49d552..b42a890d2a 100644 --- a/libs/Utils/include/Utils.h +++ b/libs/Utils/include/Utils.h @@ -7,3 +7,4 @@ #include "CastUtils.h" #include "MathUtils.h" #include "MemoryUtils.h" +#include "RangesUtils.h" diff --git a/libs/Utils/tests/RangesUtils_test.cpp b/libs/Utils/tests/RangesUtils_test.cpp new file mode 100644 index 0000000000..36d024e1ea --- /dev/null +++ b/libs/Utils/tests/RangesUtils_test.cpp @@ -0,0 +1,138 @@ +// Leka - LekaOS +// Copyright 2022 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include "Utils.h" +#include "gtest/gtest.h" + +using namespace leka::utils::ranges; + +TEST(RangesTests, fromStart0ToEnd5) +{ + auto expected = std::to_array({0, 1, 2, 3, 4, 5}); + + auto i = 0; + for (auto value: sequence({.start = 0, .end = 5})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 5 + 1) << "Loop ran " << i << " times, should run " << 5 + 1 << " times"; +} + +TEST(RangesTests, fromStart10ToEnd20) +{ + auto expected = std::to_array({10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}); + + auto i = 0; + for (auto value: sequence({.start = 10, .end = 20})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 10 + 1) << "Loop ran " << i << " times, should run " << 10 + 1 << " times"; +} + +TEST(RangesTests, fromStart0ToEnd0) +{ + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: sequence({.start = 0, .end = 0})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 1) << "Loop ran " << i << " times, should run " << 0 + 1 << " times"; +} + +TEST(RangesTests, fromStart1ToEnd1) +{ + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: sequence({.start = 1, .end = 1})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 1) << "Loop ran " << i << " times, should run " << 0 + 1 << " times"; +} + +TEST(RangesTests, from0Size5) +{ + auto expected = std::to_array({0, 1, 2, 3, 4}); + + auto i = 0; + for (auto value: sequence({.from = 0, .size = 5})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 5) << "Loop ran " << i << " times, should run " << 5 << " times"; +} + +TEST(RangesTests, from10Size10) +{ + auto expected = std::to_array({10, 11, 12, 13, 14, 15, 16, 17, 18, 19}); + + auto i = 0; + for (auto value: sequence({.from = 10, .size = 10})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 10) << "Loop ran " << i << " times, should run " << 10 << " times"; +} + +TEST(RangesTests, from0Size0) +{ + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: sequence({.from = 0, .size = 0})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 0) << "Loop ran " << i << " times, should run " << 0 << " times"; +} + +TEST(RangesTests, from0Size1) +{ + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: sequence({.from = 0, .size = 1})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 1) << "Loop ran " << i << " times, should run " << 1 << " times"; +} + +TEST(RangesTests, from1Size0) +{ + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: sequence({.from = 1, .size = 0})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 0) << "Loop ran " << i << " times, should run " << 0 << " times"; +} + +TEST(RangesTests, from1Size1) +{ + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: sequence({.from = 1, .size = 1})) { + EXPECT_EQ(value, expected.at(i)); + ++i; + } + + EXPECT_EQ(i, 1) << "Loop ran " << i << " times, should run " << 1 << " times"; +} diff --git a/spikes/stl_cxxsupport/main.cpp b/spikes/stl_cxxsupport/main.cpp index eff0ebd85a..4ba3ea1656 100644 --- a/spikes/stl_cxxsupport/main.cpp +++ b/spikes/stl_cxxsupport/main.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include #include "drivers/BufferedSerial.h" @@ -10,6 +11,7 @@ #include "HelloWorld.h" #include "LogKit.h" +#include "RangesUtils.h" using namespace leka; using namespace std::chrono; @@ -94,5 +96,30 @@ auto main() -> int auto back = span0.back(); log_info("span0.back() = %i", back); + log_info("Test std::range features"); + + constexpr auto range = [](const auto a, const auto b) { + auto x = std::ranges::views::iota(a) | std::ranges::views::take(b - a + 1); + return std::ranges::views::all(x); + }; + + for (auto x: range(1, 10)) { + log_info("x: %i", x); + } + + for (auto y: range(20, 25)) { + log_info("y: %i", y); + } + + log_info("Test utils::ranges::sequences features"); + + for (auto val: utils::ranges::sequence({.start = 0, .end = 5})) { + log_info("x: %i", val); + } + + for (auto val: utils::ranges::sequence({.start = 10, .end = 20})) { + log_info("y: %i", val); + } + return 1; } diff --git a/tests/functional/CMakeLists.txt b/tests/functional/CMakeLists.txt index c79973d95c..7597944f48 100644 --- a/tests/functional/CMakeLists.txt +++ b/tests/functional/CMakeLists.txt @@ -45,3 +45,5 @@ add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/deep_sleep_mbed_hal) add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/file_manager) add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/io_expander) add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/qdac) + +add_subdirectory(${TESTS_FUNCTIONAL_TESTS_DIR}/stl_features) diff --git a/tests/functional/tests/stl_features/CMakeLists.txt b/tests/functional/tests/stl_features/CMakeLists.txt new file mode 100644 index 0000000000..78108634ba --- /dev/null +++ b/tests/functional/tests/stl_features/CMakeLists.txt @@ -0,0 +1,15 @@ +# Leka - LekaOS +# Copyright 2022 APF France handicap +# SPDX-License-Identifier: Apache-2.0 + +register_functional_test( + TARGET + functional_ut_std_features + + INCLUDE_DIRECTORIES + + SOURCES + suite_std_ranges.cpp + + LINK_LIBRARIES +) diff --git a/tests/functional/tests/stl_features/suite_std_ranges.cpp b/tests/functional/tests/stl_features/suite_std_ranges.cpp new file mode 100644 index 0000000000..b45dbd4129 --- /dev/null +++ b/tests/functional/tests/stl_features/suite_std_ranges.cpp @@ -0,0 +1,159 @@ +// Leka - LekaOS +// Copyright 2022 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include "RangesUtils.h" +#include "tests/config.h" + +using namespace boost::ut; +using namespace leka; + +constexpr auto std_ranges_iota_generator = [](auto a, auto b) { + auto x = std::ranges::views::iota(a) | std::ranges::views::take(b - a + 1); + return std::ranges::views::all(x); +}; + +suite suite_std_ranges = [] { + "generate range of 5 values from 1 to 5"_test = [] { + auto data = std::to_array({1, 2, 3, 4, 5}); + auto i = 0; + for (auto v: std_ranges_iota_generator(1, 5)) { + expect(data[i] == v); + ++i; + } + }; + + "store range in variable and compare"_test = [&] { + auto data = std_ranges_iota_generator(10, 20); + auto i = 0; + + for (auto v: std_ranges_iota_generator(10, 20)) { + expect(data[i] == v); + ++i; + } + }; +}; + +suite suite_utils_ranges = [] { + "generate range of 6 values from 0 to 5 included"_test = [] { + auto expected = std::to_array({0, 1, 2, 3, 4, 5}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.start = 0, .end = 5})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 5 + 1) << "Loop ran " << i << " times, should run " << 5 + 1 << " times"; + }; + + "generate range of 11 values from 10 to 20 included"_test = [] { + auto expected = std::to_array({0, 1, 2, 3, 4, 5}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.start = 0, .end = 5})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 5 + 1) << "Loop ran " << i << " times, should run " << 5 + 1 << " times"; + }; + + "generate range of 1 value from 0 to 0 included"_test = [] { + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.start = 0, .end = 0})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 1) << "Loop ran " << i << " times, should run " << 0 << " times"; + }; + + "generate range of 1 value from 1 to 1 included"_test = [] { + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.start = 1, .end = 1})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 1) << "Loop ran " << i << " times, should run " << 0 << " times"; + }; + + "generate range of 5 values starting from 0"_test = [] { + auto expected = std::to_array({0, 1, 2, 3, 4, 5}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 0, .size = 5})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 5) << "Loop ran " << i << " times, should run " << 5 << " times"; + }; + + "generate range of 10 values starting from 10"_test = [] { + auto expected = std::to_array({10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 10, .size = 10})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 10) << "Loop ran " << i << " times, should run " << 10 << " times"; + }; + + "generate range of 0 values starting from 0"_test = [] { + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 0, .size = 0})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 0) << "Loop ran " << i << " times, should run " << 0 << " times"; + }; + + "generate range of 0 values starting from 1"_test = [] { + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 1, .size = 0})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 0) << "Loop ran " << i << " times, should run " << 0 << " times"; + }; + + "generate range of 1 values starting from 0"_test = [] { + auto expected = std::to_array({0}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 0, .size = 1})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 1) << "Loop ran " << i << " times, should run " << 1 << " times"; + }; + + "generate range of 1 values starting from 1"_test = [] { + auto expected = std::to_array({1}); + + auto i = 0; + for (auto value: utils::ranges::sequence({.from = 1, .size = 1})) { + expect(value == expected.at(i)); + ++i; + } + + expect(i == 1) << "Loop ran " << i << " times, should run " << 1 << " times"; + }; +};