From cf46631623f5d01ad93b66005c3c78de38ede230 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Thu, 22 Feb 2024 21:16:02 -0800 Subject: [PATCH] :boom: Upgrade to libhal/3.0.0-alpha.1 exceptions --- .github/workflows/4.0.0-alpha.1.yml | 8 +- .github/workflows/ci.yml | 14 +- CMakeLists.txt | 1 - conanfile.py | 5 +- include/libhal-util/i2c.hpp | 153 ++++++++------- include/libhal-util/math.hpp | 21 +- include/libhal-util/overflow_counter.hpp | 14 +- include/libhal-util/serial.hpp | 140 +++++++------- include/libhal-util/serial_coroutines.hpp | 33 ++-- include/libhal-util/spi.hpp | 90 +++++---- include/libhal-util/steady_clock.hpp | 23 +-- include/libhal-util/timeout.hpp | 15 +- include/libhal-util/units.hpp | 13 +- src/steady_clock.cpp | 29 +-- test_package/CMakeLists.txt | 4 - test_package/main.cpp | 51 +++-- tests/i2c.test.cpp | 131 +++++-------- tests/main.test.cpp | 2 - tests/math.test.cpp | 6 +- tests/serial.test.cpp | 221 ++++++++++------------ tests/spi.test.cpp | 37 ++-- tests/steady_clock.test.cpp | 108 ++++------- tests/timeout.test.cpp | 82 ++++---- 23 files changed, 532 insertions(+), 669 deletions(-) diff --git a/.github/workflows/4.0.0-alpha.1.yml b/.github/workflows/4.0.0-alpha.1.yml index 4d2eeec..6dbe2d0 100644 --- a/.github/workflows/4.0.0-alpha.1.yml +++ b/.github/workflows/4.0.0-alpha.1.yml @@ -1,4 +1,3 @@ -# THIS IS HERE FOR TESTING! name: 🚀 4.0.0-alpha.1 on: @@ -6,6 +5,7 @@ on: jobs: deploy: - runs-on: ubuntu-latest - steps: - - run: echo "NOP" + uses: libhal/ci/.github/workflows/deploy_all.yml@5.x.y + with: + version: 4.0.0-alpha.1 + secrets: inherit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56bb781..f9ff874 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,23 +1,21 @@ -name: ✅ Checks +name: ✅ CI on: workflow_dispatch: pull_request: - release: - types: - - published - - deleted push: branches: - main + # Remove before merging with main + - exceptions schedule: - cron: "0 12 * * 0" jobs: ci: - uses: libhal/ci/.github/workflows/library.yml@4.x.y + uses: libhal/ci/.github/workflows/library_check.yml@5.x.y secrets: inherit - devices: - uses: libhal/ci/.github/workflows/deploy.yml@4.x.y + test_deployment_: + uses: libhal/ci/.github/workflows/deploy_all.yml@5.x.y secrets: inherit diff --git a/CMakeLists.txt b/CMakeLists.txt index a1d587b..e86f8d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,6 @@ libhal_test_and_make_library( tests/serial.test.cpp tests/spi.test.cpp tests/static_callable.test.cpp - tests/static_list.test.cpp tests/steady_clock.test.cpp tests/streams.test.cpp diff --git a/conanfile.py b/conanfile.py index 2769b6b..b8fb29b 100644 --- a/conanfile.py +++ b/conanfile.py @@ -21,12 +21,11 @@ import os -required_conan_version = ">=2.0.6" +required_conan_version = ">=2.0.14" class libhal_util_conan(ConanFile): name = "libhal-util" - version = "3.0.1" license = "Apache-2.0" url = "https://github.com/conan-io/conan-center-index" homepage = "https://github.com/libhal/libhal-util" @@ -64,7 +63,7 @@ def build_requirements(self): self.test_requires("boost-ext-ut/1.1.9") def requirements(self): - self.requires("libhal/[^2.0.3]", transitive_headers=True) + self.requires("libhal/3.0.0-alpha.1", transitive_headers=True) def layout(self): cmake_layout(self) diff --git a/include/libhal-util/i2c.hpp b/include/libhal-util/i2c.hpp index f1bfdf0..42fb2dd 100644 --- a/include/libhal-util/i2c.hpp +++ b/include/libhal-util/i2c.hpp @@ -26,7 +26,6 @@ /** * @defgroup I2CUtils I2C Utils */ - namespace hal { /** * @ingroup I2CUtils @@ -52,16 +51,13 @@ namespace hal { * @param p_address - target address * @param p_data_out - buffer of bytes to write to the target device * @param p_timeout - amount of time to execute the transaction - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result write( - i2c& p_i2c, - hal::byte p_address, - std::span p_data_out, - timeout auto p_timeout) +inline void write(i2c& p_i2c, + hal::byte p_address, + std::span p_data_out, + timeout auto p_timeout) { - return p_i2c.transaction( - p_address, p_data_out, std::span{}, p_timeout); + p_i2c.transaction(p_address, p_data_out, std::span{}, p_timeout); } /** @@ -74,12 +70,12 @@ namespace hal { * @param p_i2c - i2c driver * @param p_address - target address * @param p_data_out - buffer of bytes to write to the target device - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result -write(i2c& p_i2c, hal::byte p_address, std::span p_data_out) +inline void write(i2c& p_i2c, + hal::byte p_address, + std::span p_data_out) { - return write(p_i2c, p_address, p_data_out, hal::never_timeout()); + write(p_i2c, p_address, p_data_out, hal::never_timeout()); } /** @@ -92,16 +88,13 @@ write(i2c& p_i2c, hal::byte p_address, std::span p_data_out) * @param p_address - target address * @param p_data_in - buffer to read bytes into from target device * @param p_timeout - amount of time to execute the transaction - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result read( - i2c& p_i2c, - hal::byte p_address, - std::span p_data_in, - timeout auto p_timeout) +inline void read(i2c& p_i2c, + hal::byte p_address, + std::span p_data_in, + timeout auto p_timeout) { - return p_i2c.transaction( - p_address, std::span{}, p_data_in, p_timeout); + p_i2c.transaction(p_address, std::span{}, p_data_in, p_timeout); } /** @@ -114,12 +107,12 @@ write(i2c& p_i2c, hal::byte p_address, std::span p_data_out) * @param p_i2c - i2c driver * @param p_address - target address * @param p_data_in - buffer to read bytes into from target device - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result -read(i2c& p_i2c, hal::byte p_address, std::span p_data_in) +inline void read(i2c& p_i2c, + hal::byte p_address, + std::span p_data_in) { - return read(p_i2c, p_address, p_data_in, hal::never_timeout()); + read(p_i2c, p_address, p_data_in, hal::never_timeout()); } /** @@ -128,19 +121,20 @@ read(i2c& p_i2c, hal::byte p_address, std::span p_data_in) * * Eliminates the need to create a buffer and pass it into the read function. * - * @tparam BytesToRead - number of bytes to read + * @tparam bytes_to_read - number of bytes to read * @param p_i2c - i2c driver * @param p_address - target address * @param p_timeout - amount of time to execute the transaction - * @return result> - array of - * bytes from target device or an error. + * @return std::array - array of bytes from target + * device */ -template -[[nodiscard]] result> -read(i2c& p_i2c, hal::byte p_address, timeout auto p_timeout) +template +[[nodiscard]] std::array read(i2c& p_i2c, + hal::byte p_address, + timeout auto p_timeout) { - std::array buffer; - HAL_CHECK(read(p_i2c, p_address, buffer, p_timeout)); + std::array buffer; + read(p_i2c, p_address, buffer, p_timeout); return buffer; } @@ -152,18 +146,17 @@ read(i2c& p_i2c, hal::byte p_address, timeout auto p_timeout) * This operation will never time out and should only be used with devices that * never perform clock stretching. * - * @tparam BytesToRead - number of bytes to read + * @tparam bytes_to_read - number of bytes to read * @param p_i2c - i2c driver * @param p_address - target address - * @return result> - array of - * bytes from target device or an error. + * @return std::array - array of bytes from target + * device. */ -template -[[nodiscard]] result> read( - i2c& p_i2c, - hal::byte p_address) +template +[[nodiscard]] std::array read(i2c& p_i2c, + hal::byte p_address) { - return read(p_i2c, p_address, hal::never_timeout()); + return read(p_i2c, p_address, hal::never_timeout()); } /** @@ -178,17 +171,14 @@ template * @param p_data_out - buffer of bytes to write to the target device * @param p_data_in - buffer to read bytes into from target device * @param p_timeout - amount of time to execute the transaction - * - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result write_then_read( - i2c& p_i2c, - hal::byte p_address, - std::span p_data_out, - std::span p_data_in, - timeout auto p_timeout = hal::never_timeout()) +inline void write_then_read(i2c& p_i2c, + hal::byte p_address, + std::span p_data_out, + std::span p_data_in, + timeout auto p_timeout = hal::never_timeout()) { - return p_i2c.transaction(p_address, p_data_out, p_data_in, p_timeout); + p_i2c.transaction(p_address, p_data_out, p_data_in, p_timeout); } /** @@ -204,14 +194,11 @@ template * @param p_address - target address * @param p_data_out - buffer of bytes to write to the target device * @param p_data_in - buffer to read bytes into from target device - * - * @return hal::result - success or failure */ -[[nodiscard]] inline hal::result write_then_read( - i2c& p_i2c, - hal::byte p_address, - std::span p_data_out, - std::span p_data_in) +inline void write_then_read(i2c& p_i2c, + hal::byte p_address, + std::span p_data_out, + std::span p_data_in) { return write_then_read( p_i2c, p_address, p_data_out, p_data_in, hal::never_timeout()); @@ -224,22 +211,23 @@ template * * Eliminates the need to create a buffer and pass it into the read function. * - * @tparam BytesToRead - number of bytes to read after write + * @tparam bytes_to_read - number of bytes to read after write * @param p_i2c - i2c driver * @param p_address - target address * @param p_data_out - buffer of bytes to write to the target device * @param p_timeout - amount of time to execute the transaction - * @return result> + * @return std::array - array of bytes from target + * device. */ -template -[[nodiscard]] result> write_then_read( +template +[[nodiscard]] std::array write_then_read( i2c& p_i2c, hal::byte p_address, std::span p_data_out, timeout auto p_timeout) { - std::array buffer; - HAL_CHECK(write_then_read(p_i2c, p_address, p_data_out, buffer, p_timeout)); + std::array buffer; + write_then_read(p_i2c, p_address, p_data_out, buffer, p_timeout); return buffer; } @@ -250,19 +238,19 @@ template * * Eliminates the need to create a buffer and pass it into the read function. * - * @tparam BytesToRead - number of bytes to read after write + * @tparam bytes_to_read - number of bytes to read after write * @param p_i2c - i2c driver * @param p_address - target address * @param p_data_out - buffer of bytes to write to the target device - * @return result> + * @return std::array - */ -template -[[nodiscard]] result> write_then_read( +template +[[nodiscard]] std::array write_then_read( i2c& p_i2c, hal::byte p_address, std::span p_data_out) { - return write_then_read( + return write_then_read( p_i2c, p_address, p_data_out, hal::never_timeout()); } @@ -270,21 +258,31 @@ template * @ingroup I2CUtils * @brief probe the i2c bus to see if a device exists * - * @param p_i2c - i2c driver - * @param p_address - target address to probe for - * @return hal::result - success or failure + * NOTE: that this utilizes the fact that i2c drivers throw + * std::errc::no_such_device_or_address when a transaction is performed and the + * device's address is used on the bus and the device does not respond with an + * acknowledge. + * + * @param p_i2c - i2c driver for the i2c bus that the device may exist on + * @param p_address - device to check + * @return true - if the device appears on the bus + * @return false - if the devices does not appear on the i2c bus */ -[[nodiscard]] inline hal::result probe( - i2c& p_i2c, - hal::byte p_address) +[[nodiscard]] inline bool probe(i2c& p_i2c, hal::byte p_address) { // p_data_in: empty placeholder for transcation's data_in - std::array data_in; - + std::array data_in{}; // p_timeout: no timeout placeholder for transaction's p_timeout timeout auto timeout = hal::never_timeout(); + bool device_acknowledged = true; - return p_i2c.transaction(p_address, std::span{}, data_in, timeout); + try { + p_i2c.transaction(p_address, std::span{}, data_in, timeout); + } catch (const hal::no_such_device& p_error) { + device_acknowledged = false; + } + + return device_acknowledged; } /** @@ -316,5 +314,4 @@ enum class i2c_operation v8bit_address |= hal::value(p_operation); return v8bit_address; } - } // namespace hal diff --git a/include/libhal-util/math.hpp b/include/libhal-util/math.hpp index 2f67195..67b8df7 100644 --- a/include/libhal-util/math.hpp +++ b/include/libhal-util/math.hpp @@ -21,6 +21,7 @@ #include #include +#include #include @@ -34,11 +35,11 @@ namespace hal { * @tparam T - integer arithmetic type * @param p_lhs - left hand side integer * @param p_rhs - right hand side integer - * @return result - either the resultant or an error - * `std::errc::result_out_of_range` + * @returns std::optional - the resultant, std::nullopt if the operation + * overflows. */ template -[[nodiscard]] result multiply(T p_lhs, T p_rhs) +[[nodiscard]] std::optional multiply(T p_lhs, T p_rhs) { if (p_lhs == 0 || p_rhs == 0) { return T{ 0 }; @@ -47,7 +48,7 @@ template T result = p_lhs * p_rhs; if (p_lhs != result / p_rhs) { - return hal::new_error(std::errc::result_out_of_range); + return std::nullopt; } return result; @@ -69,10 +70,10 @@ template * * @tparam T - integral type * @param p_value - integer value to be made positive - * @return constexpr auto - positive representation of the integer + * @return T - positive representation of the integer */ template -[[nodiscard]] constexpr T absolute_value(T p_value) +[[nodiscard]] constexpr T absolute_value(T p_value) noexcept { if constexpr (std::is_unsigned_v) { return p_value; @@ -95,7 +96,7 @@ template * @tparam T - integral type of the two operands * @param p_numerator - the value to be divided * @param p_denominator - the value to divide the numerator against - * @return constexpr T - rounded quotient between numerator and denominator. + * @return T - rounded quotient between numerator and denominator. * Returns 0 if the denominator is greater than the numerator. */ template @@ -196,9 +197,9 @@ template * @return true - difference is less than epsilon * @return false - difference is more than epsilon */ -constexpr static bool equals(std::floating_point auto p_value1, - std::floating_point auto p_value2, - float p_epsilon = 1e-9f) +[[nodiscard]] constexpr bool equals(std::floating_point auto p_value1, + std::floating_point auto p_value2, + float p_epsilon = 1e-9f) { if (p_value1 == p_value2) { return true; diff --git a/include/libhal-util/overflow_counter.hpp b/include/libhal-util/overflow_counter.hpp index 04a98ca..51a795f 100644 --- a/include/libhal-util/overflow_counter.hpp +++ b/include/libhal-util/overflow_counter.hpp @@ -31,15 +31,15 @@ namespace hal { * overflow counter which is combined with the current count in order create a * count up to 64-bits in length. * - * @tparam CountBitWidth - the bit width of the counter before the count value + * @tparam count_bit_width - the bit width of the counter before the count value * overflows. */ -template +template class overflow_counter { public: - static_assert(CountBitWidth <= 32, "Bit width cannot exceed 32-bits"); - static_assert(CountBitWidth > 1, "Bit width must be greater than 1"); + static_assert(count_bit_width <= 32, "Bit width cannot exceed 32-bits"); + static_assert(count_bit_width > 1, "Bit width must be greater than 1"); /** * @ingroup OverflowCounter * @brief update the overflow counter, detect if an overflow has occurred, and @@ -56,7 +56,7 @@ class overflow_counter // designated bit width. Without this check when the count is combined with // the overflow value the upper bits may effect the bits of the overflow // count, getting an incorrect count value. - constexpr auto mask = generate_field_of_ones(); + constexpr auto mask = generate_field_of_ones(); p_new_count = p_new_count & mask; // Detect the overflow by checking if the new count is smaller than the @@ -71,9 +71,9 @@ class overflow_counter m_previous_count = p_new_count; // Move overflow count up to the upper bits of the 64-bit number based on - // CountBitWidth + // count_bit_width uint64_t combined_count = m_overflow_count; - combined_count <<= CountBitWidth; + combined_count <<= count_bit_width; // Add the p_new_count into the combined count to complete it. combined_count |= p_new_count; diff --git a/include/libhal-util/serial.hpp b/include/libhal-util/serial.hpp index 903d034..dfdc34f 100644 --- a/include/libhal-util/serial.hpp +++ b/include/libhal-util/serial.hpp @@ -53,10 +53,9 @@ namespace hal { * * @param p_serial - the serial port that will be written to * @param p_data_out - the data to be written out the port - * @return result - get the results of the uart port write - * operation. + * @return serial::write_t - information about the write_t operation. */ -[[nodiscard]] inline result write_partial( +[[nodiscard]] inline serial::write_t write_partial( serial& p_serial, std::span p_data_out) { @@ -67,21 +66,26 @@ namespace hal { * @ingroup Serial * @brief Write bytes to a serial port * + * Unlike write_partial, this function will attempt to write bytes to the serial + * port until the timeout time has expired. + * * @param p_serial - the serial port that will be written to * @param p_data_out - the data to be written out the port - * @return status - success or failure + * @param p_timeout - timeout callable that throws a std::errc::timed_out + * exception when the timeout expires. + * @throws std::errc::timed_out - if p_timeout expires */ -[[nodiscard]] inline status write(serial& p_serial, - std::span p_data_out) +inline void write(serial& p_serial, + std::span p_data_out, + timeout auto p_timeout) { auto remaining = p_data_out; while (remaining.size() != 0) { - auto write_length = HAL_CHECK(p_serial.write(remaining)).data.size(); + auto write_length = p_serial.write(remaining).data.size(); remaining = remaining.subspan(write_length); + p_timeout(); } - - return success(); } /** @@ -90,11 +94,15 @@ namespace hal { * * @param p_serial - the serial port that will be written to * @param p_data_out - chars to be written out the port - * @return status - success or failure + * @param p_timeout - timeout callable that throws a std::errc::timed_out + * exception when the timeout expires. + * @throws std::errc::timed_out - if p_timeout expires */ -[[nodiscard]] inline status write(serial& p_serial, std::string_view p_data_out) +inline void write(serial& p_serial, + std::string_view p_data_out, + timeout auto p_timeout) { - return write(p_serial, as_bytes(p_data_out)); + write(p_serial, as_bytes(p_data_out), p_timeout); } /** @@ -102,26 +110,23 @@ namespace hal { * @brief Read bytes from a serial port * * @param p_serial - the serial port that will be read from - * @param p_data_in - buffer to have bytes from the serial port read into - * @param p_timeout - timeout callable that indicates when to bail out of the - * read operation. - * @return result> - return an error if - * a call to serial::read or delay() returns an error from the serial port or - * a span with the number of bytes read and a pointer to where the read bytes - * are. + * @param p_data_in - buffer to have bytes from the serial port read into. When + * this function completes, the full contents of p_data_in should contain + * @param p_timeout - timeout callable that throws a std::errc::timed_out + * exception when the timeout expires. + * @throws std::errc::timed_out - if p_timeout expires */ -[[nodiscard]] inline result> -read(serial& p_serial, std::span p_data_in, timeout auto p_timeout) +inline void read(serial& p_serial, + std::span p_data_in, + timeout auto p_timeout) { auto remaining = p_data_in; while (remaining.size() != 0) { - auto read_length = HAL_CHECK(p_serial.read(remaining)).data.size(); + auto read_length = p_serial.read(remaining).data.size(); remaining = remaining.subspan(read_length); - HAL_CHECK(p_timeout()); + p_timeout(); } - - return p_data_in; } /** @@ -131,22 +136,20 @@ read(serial& p_serial, std::span p_data_in, timeout auto p_timeout) * This call eliminates the boiler plate of creating an array and then passing * that to the read function. * - * @tparam BytesToRead - the number of bytes to be read from the serial port. + * @tparam bytes_to_read - the number of bytes to be read from the serial port. * @param p_serial - the serial port to be read from - * @param p_timeout - timeout callable that indicates when to bail out of the - * read operation. - * @return result> - return an - * error if a call to serial::read or delay() returns an error from the - * serial port or a span with the number of bytes read and a pointer to where - * the read bytes are. + * @param p_timeout - timeout callable that throws a std::errc::timed_out + * exception when the timeout expires. + * @return std::array - array containing the bytes + * read from the serial port. + * @throws std::errc::timed_out - if p_timeout expires */ -template -[[nodiscard]] result> read( - serial& p_serial, - timeout auto p_timeout) +template +[[nodiscard]] std::array read(serial& p_serial, + timeout auto p_timeout) { - std::array buffer; - HAL_CHECK(read(p_serial, buffer, p_timeout)); + std::array buffer; + read(p_serial, buffer, p_timeout); return buffer; } @@ -160,19 +163,17 @@ template * @param p_serial - the serial port to have the transaction occur on * @param p_data_out - the data to be written to the port * @param p_data_in - a buffer to receive the bytes back from the port - * @param p_timeout - timeout callable that indicates when to bail out of the - * read operation. - * @return status - success or failure - * or serial::write() returns an error from the serial port or success. + * @param p_timeout - timeout callable that throws a std::errc::timed_out + * exception when the timeout expires. + * @throws std::errc::timed_out - if p_timeout expires */ -[[nodiscard]] inline result> write_then_read( - serial& p_serial, - std::span p_data_out, - std::span p_data_in, - timeout auto p_timeout) +inline void write_then_read(serial& p_serial, + std::span p_data_out, + std::span p_data_in, + timeout auto p_timeout) { - HAL_CHECK(write_partial(p_serial, p_data_out)); - return read(p_serial, p_data_in, p_timeout); + write(p_serial, p_data_out, p_timeout); + read(p_serial, p_data_in, p_timeout); } /** @@ -182,23 +183,23 @@ template * This is especially useful for devices that use a command and response method * of communication. * - * @tparam BytesToRead - the number of bytes to read back + * @tparam bytes_to_read - the number of bytes to read back * @param p_serial - the serial port to have the transaction occur on * @param p_data_out - the data to be written to the port * @param p_timeout - timeout callable that indicates when to bail out of the * read operation. - * @return result> - return an - * error if a call to serial::read or serial::write() returns an error from the - * serial port or an array of read bytes. + * @return std::array - array containing the bytes + * read from the serial port. + * @throws std::errc::timed_out - if p_timeout expires */ -template -[[nodiscard]] result> write_then_read( +template +[[nodiscard]] std::array write_then_read( serial& p_serial, std::span p_data_out, timeout auto p_timeout) { - std::array buffer; - HAL_CHECK(write_then_read(p_serial, p_data_out, buffer, p_timeout)); + std::array buffer; + write_then_read(p_serial, p_data_out, buffer, p_timeout); return buffer; } @@ -209,14 +210,14 @@ template * Only use this with serial ports with infallible write operations, meaning * they will never return an error result. * - * @tparam DataArray - data array type + * @tparam byte_array_t - data array type * @param p_serial - serial port to write data to * @param p_data - data to be sent over the serial port */ -template -void print(serial& p_serial, DataArray&& p_data) +template +void print(serial& p_serial, byte_array_t&& p_data) { - (void)hal::write(p_serial, p_data); + hal::write(p_serial, p_data, hal::never_timeout()); } /** @@ -230,21 +231,21 @@ void print(serial& p_serial, DataArray&& p_data) * This function does NOT include the NULL character when transmitting the data * over the serial port. * - * @tparam BufferSize - Size of the buffer to allocate on the stack to store the - * formatted message. + * @tparam buffer_size - Size of the buffer to allocate on the stack to store + * the formatted message. * @tparam Parameters - printf arguments * @param p_serial - serial port to write data to * @param p_format - printf style null terminated format string * @param p_parameters - printf arguments */ -template +template void print(serial& p_serial, const char* p_format, Parameters... p_parameters) { - static_assert(BufferSize > 2); - - std::array buffer{}; - constexpr int unterminated_max_string_size = static_cast(BufferSize) - 1; + static_assert(buffer_size > 2); + constexpr int unterminated_max_string_size = + static_cast(buffer_size) - 1; + std::array buffer{}; int length = std::snprintf(buffer.data(), buffer.size(), p_format, p_parameters...); @@ -253,6 +254,7 @@ void print(serial& p_serial, const char* p_format, Parameters... p_parameters) length = unterminated_max_string_size; } - (void)hal::write(p_serial, std::string_view(buffer.data(), length)); + hal::write( + p_serial, std::string_view(buffer.data(), length), hal::never_timeout()); } } // namespace hal diff --git a/include/libhal-util/serial_coroutines.hpp b/include/libhal-util/serial_coroutines.hpp index 2fc2c61..a65e3e9 100644 --- a/include/libhal-util/serial_coroutines.hpp +++ b/include/libhal-util/serial_coroutines.hpp @@ -150,19 +150,19 @@ class read_into * * Call this function again to resume reading from the port. * - * @return result - work_state::in_progress if the sequence hasn't + * @return work_state - work_state::in_progress if the sequence hasn't * been met and the buffer still has space. - * @return result - work_state::finished if the sequence was + * @return work_state - work_state::finished if the sequence was * found before the buffer was filled completely. */ - result operator()() + work_state operator()() { for (size_t read_limit = 0; read_limit < m_read_limit; read_limit++) { if (m_buffer.empty()) { return work_state::finished; } - auto read_result = HAL_CHECK(m_serial->read(m_buffer)); + auto read_result = m_serial->read(m_buffer); // Set the m_buffer to the amount of bytes remaining to be read. m_buffer = m_buffer.subspan(read_result.data.size()); @@ -221,14 +221,14 @@ class read_upto * * Call this function again to resume reading from the port. * - * @return result - work_state::in_progress if the sequence hasn't - * been met and the buffer still has space. - * @return result - work_state::failed if the sequence wasn't - * found before the buffer was filled completely. - * @return result - work_state::finished if the sequence was - * found before the buffer was filled completely. + * @return work_state - work_state::in_progress if the sequence hasn't been + * met and the buffer still has space. + * @return work_state - work_state::failed if the sequence wasn't found before + * the buffer was filled completely. + * @return work_state - work_state::finished if the sequence was found before + * the buffer was filled completely. */ - result operator()() + work_state operator()() { static constexpr size_t read_length = 1; if (m_search_index == m_sequence.size()) { @@ -239,8 +239,7 @@ class read_upto } for (size_t read_limit = 0; read_limit < m_read_limit; read_limit++) { - auto read_result = - HAL_CHECK(m_serial->read(m_buffer.subspan(0, read_length))); + auto read_result = m_serial->read(m_buffer.subspan(0, read_length)); if (read_result.data.size() == 0) { return work_state::in_progress; @@ -307,12 +306,12 @@ class read_uint32 * * Call this function again to resume reading from the port. * - * @return result - work_state::in_progress - if an integer hasn't + * @return work_state - work_state::in_progress - if an integer hasn't * been found - * @return result - work_state::finished - integer has been found + * @return work_state - work_state::finished - integer has been found * and a non-integer byte has also been found. */ - result operator()() + work_state operator()() { if (m_finished) { return work_state::finished; @@ -320,7 +319,7 @@ class read_uint32 for (size_t read_limit = 0; read_limit < m_read_limit; read_limit++) { std::array buffer; - auto read_result = HAL_CHECK(m_serial->read(buffer)); + auto read_result = m_serial->read(buffer); if (read_result.data.size() != buffer.size()) { return work_state::in_progress; diff --git a/include/libhal-util/spi.hpp b/include/libhal-util/spi.hpp index 51de0bb..ab798c1 100644 --- a/include/libhal-util/spi.hpp +++ b/include/libhal-util/spi.hpp @@ -44,16 +44,16 @@ namespace hal { /** * @ingroup SPI - * @brief Write data to the SPI bus and ignore data sent from peripherals on the - * bus. + * @brief Write data to the spi bus, ignore data on the peripherals receive line + * + * This command is useful for spi operations where data, such as a command, + * must be sent to a device and the device does not respond with anything or the + * response is not necessary. * * @param p_spi - spi driver - * @param p_data_out - data to be written to the SPI bus - * @return result - success or failure + * @param p_data_out - data to be written to the spi bus */ -[[nodiscard]] inline result write( - spi& p_spi, - std::span p_data_out) +inline void write(spi& p_spi, std::span p_data_out) { return p_spi.transfer( p_data_out, std::span{}, spi::default_filler); @@ -63,18 +63,15 @@ namespace hal { * @ingroup SPI * @brief Read data from the SPI bus. * - * Filler bytes will be placed on the write line. + * Filler bytes will be placed on the write/transmit line. * * @param p_spi - spi driver - * @param p_data_in - buffer to receive bytes back from the SPI bus - * @param p_filler - filler data placed on the bus in place of actual write - * data. - * @return result - success or failure + * @param p_data_in - buffer to receive bytes back from the spi bus + * @param p_filler - filler data placed on the bus in place of actual data. */ -[[nodiscard]] inline result read( - spi& p_spi, - std::span p_data_in, - hal::byte p_filler = spi::default_filler) +inline void read(spi& p_spi, + std::span p_data_in, + hal::byte p_filler = spi::default_filler) { return p_spi.transfer(std::span{}, p_data_in, p_filler); } @@ -84,20 +81,20 @@ namespace hal { * * Filler bytes will be placed on the write line. * - * @tparam BytesToRead - Number of bytes to read + * @tparam bytes_to_read - Number of bytes to read * @param p_spi - spi driver * @param p_filler - filler data placed on the bus in place of actual write * data. - * @return result> - any errors - * associated with this call + * @return std::array - array containing bytes read + * from the spi bus */ -template -[[nodiscard]] result> read( +template +[[nodiscard]] std::array read( spi& p_spi, hal::byte p_filler = spi::default_filler) { - std::array buffer; - HAL_CHECK(p_spi.transfer(std::span{}, buffer, p_filler)); + std::array buffer; + p_spi.transfer(std::span{}, buffer, p_filler); return buffer; } @@ -106,30 +103,28 @@ template * @brief Write data to the SPI bus and ignore data sent from peripherals on the * bus then read data from the SPI and fill the write line with filler bytes. * - * This utility function that fits the use case of many SPI devices where a - * transaction is not full duplex. In many spi devices, full duplex means that - * as data is being written to the SPI bus, the peripheral device is sending - * data back on the read line. In most cases, the protocol is to write data to - * the bus, and ignore the read line because the peripheral is not writing - * anything meaningful to that line, then reading from SPI bus and writing - * nothing meaningful to the write line as the peripheral is ignoring that line. + * This utility function that fits the use case of many spi devices where a spi + * transfer is not full duplex. In many spi devices, full duplex means that + * as data is being written to the spi bus, the peripheral device is sending + * data back on the receive line. In most cases, the device's communication + * protocol is simply: + * + * 1. Write data to the bus, ignore the receive line + * 2. Read from spi bus, filling the write line with filler * * @param p_spi - spi driver * @param p_data_out - bytes to write to the bus - * @param p_data_in - buffer to receive bytes back from the SPI bus + * @param p_data_in - buffer to receive bytes back from the spi bus * @param p_filler - filler data placed on the bus when the read operation * begins. - * @return result - success or failure */ -[[nodiscard]] inline result write_then_read( - spi& p_spi, - std::span p_data_out, - std::span p_data_in, - hal::byte p_filler = spi::default_filler) +inline void write_then_read(spi& p_spi, + std::span p_data_out, + std::span p_data_in, + hal::byte p_filler = spi::default_filler) { - HAL_CHECK(write(p_spi, p_data_out)); - HAL_CHECK(read(p_spi, p_data_in, p_filler)); - return {}; + write(p_spi, p_data_out); + read(p_spi, p_data_in, p_filler); } /** @@ -138,20 +133,23 @@ template * bus then read data from the SPI, fill the write line with filler bytes and * return an array of bytes. * - * @tparam BytesToRead - Number of bytes to read from the bus + * See write_then_read() for details about this function. + * + * @tparam bytes_to_read - Number of bytes to read from the bus * @param p_spi - spi driver * @param p_data_out - bytes to write to the bus * @param p_filler - filler data placed on the bus when the read operation * begins. - * @return result> + * @return std::array - array containing the bytes + * read from the spi bus. */ -template -[[nodiscard]] result> write_then_read( +template +[[nodiscard]] std::array write_then_read( spi& p_spi, std::span p_data_out, hal::byte p_filler = spi::default_filler) { - HAL_CHECK(write(p_spi, p_data_out)); - return read(p_spi, p_filler); + write(p_spi, p_data_out); + return read(p_spi, p_filler); } } // namespace hal diff --git a/include/libhal-util/steady_clock.hpp b/include/libhal-util/steady_clock.hpp index d7b4e1e..b93c59b 100644 --- a/include/libhal-util/steady_clock.hpp +++ b/include/libhal-util/steady_clock.hpp @@ -62,12 +62,13 @@ class steady_clock_timeout public: /** * @ingroup SteadyClock - * @brief Create a steady_clock_timeout + * @brief Construct a new counter timeout object * - * @return steady_clock_timeout - steady_clock_timeout object + * @param p_steady_clock - steady clock implementation + * @param p_duration - number of cycles until timeout */ - static steady_clock_timeout create(hal::steady_clock& p_steady_clock, - hal::time_duration p_duration); + steady_clock_timeout(hal::steady_clock& p_steady_clock, + hal::time_duration p_duration); /** * @ingroup SteadyClock @@ -104,23 +105,11 @@ class steady_clock_timeout /** * @ingroup SteadyClock * @brief Call this object to check if it has timed out. - * - * @return status - success or failure * @throws std::errc::timed_out - if the timeout time has been exceeded. */ - status operator()(); + void operator()(); private: - /** - * @ingroup SteadyClock - * @brief Construct a new counter timeout object - * - * @param p_steady_clock - steady clock implementation - * @param p_cycles_until_timeout - number of cycles until timeout - */ - steady_clock_timeout(hal::steady_clock& p_steady_clock, - std::uint64_t p_cycles_until_timeout); - hal::steady_clock* m_counter; std::uint64_t m_cycles_until_timeout = 0; }; diff --git a/include/libhal-util/timeout.hpp b/include/libhal-util/timeout.hpp index cef5191..8648d2a 100644 --- a/include/libhal-util/timeout.hpp +++ b/include/libhal-util/timeout.hpp @@ -106,19 +106,17 @@ inline std::basic_ostream& operator<<( * * @param p_worker - worker function to repeatedly call * @param p_timeout - callable timeout object - * @return result - state of the worker function + * @return work_state - state of the worker function */ -inline result try_until(worker auto& p_worker, - timeout auto p_timeout) +inline work_state try_until(worker auto& p_worker, timeout auto p_timeout) { while (true) { - auto state = HAL_CHECK(p_worker()); + p_timeout(); + auto state = p_worker(); if (hal::terminated(state)) { return state; } - HAL_CHECK(p_timeout()); } - return new_error(std::errc::state_not_recoverable); }; /** @@ -128,10 +126,9 @@ inline result try_until(worker auto& p_worker, * * @param p_worker - worker function to repeatedly call * @param p_timeout - callable timeout object - * @return result - state of the worker function + * @return work_state - state of the worker function */ -inline result try_until(worker auto&& p_worker, - timeout auto p_timeout) +inline work_state try_until(worker auto&& p_worker, timeout auto p_timeout) { worker auto& worker = p_worker; return try_until(worker, p_timeout); diff --git a/include/libhal-util/units.hpp b/include/libhal-util/units.hpp index a105dea..df41b09 100644 --- a/include/libhal-util/units.hpp +++ b/include/libhal-util/units.hpp @@ -113,12 +113,12 @@ constexpr float wavelength(hertz p_source) * * @param p_source - the frequency to compute the cycles from * @param p_cycles - number of cycles within the time duration - * @return std::chrono::nanoseconds - time duration based on this frequency - * and the number of cycles + * @return std::optional - time duration based on this + * frequency and the number of cycles. Will return std::nullopt if the duration + * exceeds */ -[[nodiscard]] inline result duration_from_cycles( - hertz p_source, - uint32_t p_cycles) +[[nodiscard]] inline std::optional +duration_from_cycles(hertz p_source, uint32_t p_cycles) { // Full Equation (based on the equation in cycles_per()): // @@ -141,7 +141,8 @@ constexpr float wavelength(hertz p_source) if (float_int_min <= nanoseconds && nanoseconds <= float_int_max) { return std::chrono::nanoseconds(static_cast(nanoseconds)); } - return new_error(std::errc::result_out_of_range); + + return std::nullopt; } /** diff --git a/src/steady_clock.cpp b/src/steady_clock.cpp index cf45b23..9bc0d22 100644 --- a/src/steady_clock.cpp +++ b/src/steady_clock.cpp @@ -13,13 +13,14 @@ // limitations under the License. #include +#include namespace hal { std::uint64_t future_deadline(hal::steady_clock& p_steady_clock, hal::time_duration p_duration) { using period = decltype(p_duration)::period; - const auto frequency = p_steady_clock.frequency().operating_frequency; + const auto frequency = p_steady_clock.frequency(); const auto tick_period = wavelength(frequency); auto ticks_required = p_duration / tick_period; using unsigned_ticks = std::make_unsigned_t; @@ -29,46 +30,36 @@ std::uint64_t future_deadline(hal::steady_clock& p_steady_clock, } const auto ticks = static_cast(ticks_required); - const auto future_timestamp = ticks + p_steady_clock.uptime().ticks; + const auto future_timestamp = ticks + p_steady_clock.uptime(); return future_timestamp; } -steady_clock_timeout steady_clock_timeout::create( - hal::steady_clock& p_steady_clock, - hal::time_duration p_duration) -{ - const auto deadline = future_deadline(p_steady_clock, p_duration); - return { p_steady_clock, deadline }; -} -status steady_clock_timeout::operator()() +void steady_clock_timeout::operator()() { - auto current_count = m_counter->uptime().ticks; - + auto current_count = m_counter->uptime(); if (current_count >= m_cycles_until_timeout) { - return hal::new_error(std::errc::timed_out); + hal::safe_throw(hal::timed_out(this)); } - - return success(); } steady_clock_timeout::steady_clock_timeout(hal::steady_clock& p_steady_clock, - std::uint64_t p_cycles_until_timeout) + hal::time_duration p_duration) : m_counter(&p_steady_clock) - , m_cycles_until_timeout(p_cycles_until_timeout) + , m_cycles_until_timeout(future_deadline(p_steady_clock, p_duration)) { } steady_clock_timeout create_timeout(hal::steady_clock& p_steady_clock, hal::time_duration p_duration) { - return steady_clock_timeout::create(p_steady_clock, p_duration); + return { p_steady_clock, p_duration }; } void delay(hal::steady_clock& p_steady_clock, hal::time_duration p_duration) { auto ticks_until_timeout = future_deadline(p_steady_clock, p_duration); - while (p_steady_clock.uptime().ticks < ticks_until_timeout) { + while (p_steady_clock.uptime() < ticks_until_timeout) { continue; } } diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt index e951d82..ed9fe64 100644 --- a/test_package/CMakeLists.txt +++ b/test_package/CMakeLists.txt @@ -19,10 +19,6 @@ find_package(libhal-util REQUIRED CONFIG) add_executable(${PROJECT_NAME} main.cpp) -if(${CMAKE_CROSSCOMPILING}) - target_link_options(${PROJECT_NAME} PRIVATE --oslib=semihost) -endif() - target_include_directories(${PROJECT_NAME} PUBLIC .) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) target_link_libraries(${PROJECT_NAME} PRIVATE libhal::util) diff --git a/test_package/main.cpp b/test_package/main.cpp index a656b91..1b33a51 100644 --- a/test_package/main.cpp +++ b/test_package/main.cpp @@ -13,47 +13,44 @@ // limitations under the License. #include -#include -#include +#include +#include -class test_i2c : public hal::i2c +class stub_serial : public hal::serial { -private: - hal::status driver_configure([[maybe_unused]] const settings& p_settings) +public: + void driver_configure(const settings&) override { - return hal::success(); } - hal::result driver_transaction( - [[maybe_unused]] hal::byte p_address, - [[maybe_unused]] std::span p_data_out, - std::span p_data_in, - [[maybe_unused]] hal::function_ref p_timeout) + write_t driver_write(std::span p_data) override { - std::iota(p_data_in.begin(), p_data_in.end(), 5); - return hal::i2c::transaction_t{}; + return write_t{ .data = p_data.subspan(0, 0) }; } + + read_t driver_read(std::span p_data) override + { + return read_t{ .data = p_data.subspan(0, 0), + .available = 0, + .capacity = 0 }; + } + + void driver_flush() override + { + } + + ~stub_serial() override = default; }; int main() { - test_i2c i2c; + using namespace std::string_view_literals; - auto array = hal::read<5>(i2c, 0x11, hal::never_timeout()).value(); + auto array = hal::to_array<5>("Hello World!\n"sv); - std::printf("read content = { "); - for (const auto& byte : array) { - std::printf("0x%02X ", byte); - } - std::printf("};\n"); + stub_serial stub; + hal::print(stub, "Goodbye, World!\n"); return 0; } - -namespace boost { -void throw_exception(std::exception const& e) -{ - hal::halt(); -} -} // namespace boost \ No newline at end of file diff --git a/tests/i2c.test.cpp b/tests/i2c.test.cpp index 6c440ee..299318c 100644 --- a/tests/i2c.test.cpp +++ b/tests/i2c.test.cpp @@ -30,10 +30,9 @@ void i2c_util_test() struct test_timeout_t { - status operator()() + void operator()() { was_called = true; - return {}; } bool was_called = false; }; @@ -41,11 +40,11 @@ void i2c_util_test() class test_i2c : public hal::i2c { public: - [[nodiscard]] status driver_configure(const settings&) override + void driver_configure(const settings&) override { - return {}; } - [[nodiscard]] result driver_transaction( + + void driver_transaction( hal::byte p_address, std::span p_out, std::span p_in, @@ -58,12 +57,10 @@ void i2c_util_test() std::fill(m_in.begin(), m_in.end(), filler_byte); if (m_address == failure_address) { - return hal::new_error(); + throw std::errc::no_such_device_or_address; } - (void)p_timeout(); - - return transaction_t{}; + p_timeout(); } ~test_i2c() override = default; @@ -94,12 +91,9 @@ void i2c_util_test() const std::array expected_payload{}; // Exercise - auto result = - write(i2c, successful_address, expected_payload, std::ref(test_timeout)); - bool successful = static_cast(result); + write(i2c, successful_address, expected_payload, std::ref(test_timeout)); // Verify - expect(successful); expect(successful_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); @@ -115,12 +109,11 @@ void i2c_util_test() const std::array expected_payload{}; // Exercise - auto result = + expect(throws([&i2c, &expected_payload, &test_timeout]() { write(i2c, failure_address, expected_payload, std::ref(test_timeout)); - bool successful = static_cast(result); + })); // Verify - expect(!successful); expect(failure_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); @@ -136,12 +129,9 @@ void i2c_util_test() std::array expected_buffer; // Exercise - auto result = - read(i2c, successful_address, expected_buffer, std::ref(test_timeout)); - bool successful = static_cast(result); + read(i2c, successful_address, expected_buffer, std::ref(test_timeout)); // Verify - expect(successful); expect(successful_address == i2c.m_address); expect(that % expected_buffer.data() == i2c.m_in.data()); expect(that % expected_buffer.size() == i2c.m_in.size()); @@ -157,12 +147,11 @@ void i2c_util_test() std::array expected_buffer; // Exercise - auto result = + expect(throws([&i2c, &expected_buffer, &test_timeout]() { read(i2c, failure_address, expected_buffer, std::ref(test_timeout)); - bool successful = static_cast(result); + })); // Verify - expect(!successful); expect(failure_address == i2c.m_address); expect(that % expected_buffer.data() == i2c.m_in.data()); expect(that % expected_buffer.size() == i2c.m_in.size()); @@ -175,19 +164,16 @@ void i2c_util_test() // Setup test_i2c i2c; test_timeout_t test_timeout; - std::array expected_buffer; - expected_buffer.fill(filler_byte); + std::array expected; + expected.fill(filler_byte); // Exercise - auto result = read( - i2c, successful_address, std::ref(test_timeout)); - bool successful = static_cast(result); + auto actual = + read(i2c, successful_address, std::ref(test_timeout)); // Verify - expect(successful); expect(successful_address == i2c.m_address); - expect(std::equal( - expected_buffer.begin(), expected_buffer.end(), result.value().begin())); + expect(std::equal(expected.begin(), expected.end(), actual.begin())); expect(that % nullptr == i2c.m_out.data()); expect(that % 0 == i2c.m_out.size()); expect(that % true == test_timeout.was_called); @@ -199,11 +185,12 @@ void i2c_util_test() test_timeout_t test_timeout; // Exercise - auto result = read<5>(i2c, failure_address, never_timeout()); - bool successful = static_cast(result); + expect(throws([&i2c]() { + [[maybe_unused]] auto result = + read<5>(i2c, failure_address, never_timeout()); + })); // Verify - expect(!successful); expect(failure_address == i2c.m_address); expect(that % nullptr == i2c.m_out.data()); expect(that % 0 == i2c.m_out.size()); @@ -218,15 +205,13 @@ void i2c_util_test() std::array expected_buffer; // Exercise - auto result = write_then_read(i2c, - successful_address, - expected_payload, - expected_buffer, - std::ref(test_timeout)); - bool successful = static_cast(result); + write_then_read(i2c, + successful_address, + expected_payload, + expected_buffer, + std::ref(test_timeout)); // Verify - expect(successful); expect(successful_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); @@ -244,15 +229,16 @@ void i2c_util_test() expected_buffer.fill(filler_byte); // Exercise - auto result = write_then_read(i2c, - failure_address, - expected_payload, - expected_buffer, - std::ref(test_timeout)); - bool successful = static_cast(result); + expect(throws( + [&i2c, &expected_payload, &expected_buffer, &test_timeout]() { + write_then_read(i2c, + failure_address, + expected_payload, + expected_buffer, + std::ref(test_timeout)); + })); // Verify - expect(!successful); expect(failure_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); @@ -266,22 +252,18 @@ void i2c_util_test() test_i2c i2c; test_timeout_t test_timeout; const std::array expected_payload{}; - std::array expected_buffer{}; - expected_buffer.fill(filler_byte); + std::array expected{}; + expected.fill(filler_byte); // Exercise - auto result = write_then_read<5>( + auto actual = write_then_read<5>( i2c, successful_address, expected_payload, std::ref(test_timeout)); - bool successful = static_cast(result); - auto actual_array = result.value(); // Verify - expect(successful); expect(successful_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); - expect(std::equal( - expected_buffer.begin(), expected_buffer.end(), actual_array.begin())); + expect(std::equal(expected.begin(), expected.end(), actual.begin())); expect(that % true == test_timeout.was_called); }; @@ -292,12 +274,12 @@ void i2c_util_test() const std::array expected_payload{}; // Exercise - auto result = write_then_read<5>( - i2c, failure_address, expected_payload, std::ref(test_timeout)); - bool successful = static_cast(result); + expect(throws([&i2c, &expected_payload, &test_timeout]() { + [[maybe_unused]] auto result = write_then_read<5>( + i2c, failure_address, expected_payload, std::ref(test_timeout)); + })); // Verify - expect(!successful); expect(failure_address == i2c.m_address); expect(that % expected_payload.data() == i2c.m_out.data()); expect(that % expected_payload.size() == i2c.m_out.size()); @@ -309,11 +291,10 @@ void i2c_util_test() test_i2c i2c; // Exercise - auto result = probe(i2c, successful_address); - bool successful = static_cast(result); + auto exists = probe(i2c, successful_address); // Verify - expect(successful); + expect(exists); expect(successful_address == i2c.m_address); expect(that % 1 == i2c.m_in.size()); expect(that % nullptr != i2c.m_in.data()); @@ -326,11 +307,10 @@ void i2c_util_test() test_i2c i2c; // Exercise - auto result = probe(i2c, failure_address); - bool successful = static_cast(result); + auto exists = probe(i2c, failure_address); // Verify - expect(!successful); + expect(!exists); expect(failure_address == i2c.m_address); expect(that % 1 == i2c.m_in.size()); expect(that % nullptr != i2c.m_in.data()); @@ -346,20 +326,13 @@ void i2c_util_test() std::array read_data{}; // Exercise - auto result_write = write(i2c, successful_address, write_data); - auto result_read = read(i2c, successful_address, read_data); - auto result_wr = - write_then_read(i2c, successful_address, write_data, read_data); - auto result_read_buffer = read<2>(i2c, successful_address); - auto result_wr_buffer = - write_then_read<2>(i2c, successful_address, write_data); - // Verify - expect(bool{ result_read }); - expect(bool{ result_write }); - expect(bool{ result_wr }); - expect(bool{ result_read_buffer }); - expect(bool{ result_wr_buffer }); + write(i2c, successful_address, write_data); + read(i2c, successful_address, read_data); + write_then_read(i2c, successful_address, write_data, read_data); + [[maybe_unused]] auto r_array = read<2>(i2c, successful_address); + [[maybe_unused]] auto wr_array = + write_then_read<2>(i2c, successful_address, write_data); }; }; } // namespace hal diff --git a/tests/main.test.cpp b/tests/main.test.cpp index 0703219..7c5df63 100644 --- a/tests/main.test.cpp +++ b/tests/main.test.cpp @@ -32,7 +32,6 @@ extern void static_list_test(); extern void steady_clock_utility_test(); extern void timeout_test(); extern void units_test(); - extern void stream_terminated_test(); extern void parse_stream_test(); extern void find_stream_test(); @@ -61,7 +60,6 @@ int main() hal::steady_clock_utility_test(); hal::timeout_test(); hal::units_test(); - hal::stream_terminated_test(); hal::parse_stream_test(); hal::find_stream_test(); diff --git a/tests/math.test.cpp b/tests/math.test.cpp index 542ca0e..c24aa85 100644 --- a/tests/math.test.cpp +++ b/tests/math.test.cpp @@ -30,10 +30,8 @@ void math_test() expect(that % 2147483648L == multiply(-1LL, -2147483648LL).value()); }; "Exceptions"_test = []() { - expect( - !bool{ multiply(std::uint32_t{ 5U }, std::uint32_t{ 4294967295U }) }); - expect( - !bool{ multiply(std::uint32_t{ 4L }, std::uint32_t{ 1073741824L }) }); + expect(!multiply(std::uint32_t{ 5U }, std::uint32_t{ 4294967295U })); + expect(!multiply(std::uint32_t{ 4L }, std::uint32_t{ 1073741824L })); }; "Standard Usage"_test = []() { expect(that % 75 == multiply(15, 5).value()); diff --git a/tests/serial.test.cpp b/tests/serial.test.cpp index 60ec11a..1483e7b 100644 --- a/tests/serial.test.cpp +++ b/tests/serial.test.cpp @@ -33,16 +33,15 @@ void serial_util_test() class fake_serial : public hal::serial { public: - status driver_configure(const settings&) override + void driver_configure(const settings&) override { - return {}; } - result driver_write(std::span p_data) override + write_t driver_write(std::span p_data) override { m_write_call_count++; if (p_data[0] == write_failure_byte) { - return hal::new_error(); + throw std::errc::invalid_argument; } m_out = p_data; @@ -52,7 +51,7 @@ void serial_util_test() return write_t{ p_data }; } - result driver_read(std::span p_data) override + read_t driver_read(std::span p_data) override { if (p_data.size() == 0) { return read_t{ @@ -65,7 +64,7 @@ void serial_util_test() m_read_was_called = true; if (m_read_fails) { - return hal::new_error(); + throw std::errc::invalid_argument; } // only fill 1 byte at a time @@ -78,10 +77,9 @@ void serial_util_test() }; } - result driver_flush() override + void driver_flush() override { m_flush_called = true; - return flush_t{}; } ~fake_serial() override = default; @@ -112,34 +110,32 @@ void serial_util_test() "[success] write_partial full"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; + const std::array expected{}; // Exercise - auto result = write_partial(serial, expected_payload); + auto result = write_partial(serial, expected); // Verify - expect(bool{ result }); - expect(result.value().data.size() == expected_payload.size()); + expect(result.data.size() == expected.size()); expect(!serial.m_flush_called); - expect(that % expected_payload.data() == serial.m_out.data()); - expect(that % expected_payload.size() == serial.m_out.size()); + expect(that % expected.data() == serial.m_out.data()); + expect(that % expected.size() == serial.m_out.size()); expect(that % !serial.m_read_was_called); }; "[success] write_partial single byte at a time"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; + const std::array expected{}; serial.m_single_byte_out = true; // Exercise - auto result = write_partial(serial, expected_payload); + auto result = write_partial(serial, expected); // Verify - expect(bool{ result }); - expect(1 == result.value().data.size()); + expect(1 == result.data.size()); expect(!serial.m_flush_called); - expect(that % &expected_payload[0] == serial.m_out.data()); + expect(that % &expected[0] == serial.m_out.data()); expect(that % 4 == serial.m_out.size()); expect(that % !serial.m_read_was_called); }; @@ -147,13 +143,14 @@ void serial_util_test() "[failure] write_partial"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{ write_failure_byte }; + const std::array expected{ write_failure_byte }; // Exercise - auto result = write_partial(serial, expected_payload); + expect(throws([&serial, &expected]() { + [[maybe_unused]] auto result = write_partial(serial, expected); + })); // Verify - expect(!bool{ result }); expect(!serial.m_flush_called); expect(that % nullptr == serial.m_out.data()); expect(that % 0 == serial.m_out.size()); @@ -163,69 +160,65 @@ void serial_util_test() "[success] write"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; + const std::array expected{}; serial.m_single_byte_out = true; // Exercise - auto result = write(serial, expected_payload); + write(serial, expected, hal::never_timeout()); // Verify - expect(bool{ result }); expect(!serial.m_flush_called); expect(that % 1 == serial.m_out.size()); - expect(that % expected_payload.size() == serial.m_write_call_count); + expect(that % expected.size() == serial.m_write_call_count); expect(that % !serial.m_read_was_called); }; "[success] write(std::string_view)"_test = []() { // Setup fake_serial serial; - std::string_view expected_payload = "abcd"; + std::string_view expected = "abcd"; serial.m_single_byte_out = true; // Exercise - auto result = write(serial, expected_payload); + write(serial, expected, hal::never_timeout()); // Verify - expect(bool{ result }); expect(!serial.m_flush_called); - expect(that % expected_payload.end()[-1] == serial.m_out[0]); + expect(that % expected.end()[-1] == serial.m_out[0]); expect(that % 1 == serial.m_out.size()); - expect(that % expected_payload.size() == serial.m_write_call_count); + expect(that % expected.size() == serial.m_write_call_count); expect(that % !serial.m_read_was_called); }; "[success] read"_test = []() { // Setup fake_serial serial; - std::array expected_buffer; - expected_buffer.fill(filler_byte); - std::array actual_buffer; - actual_buffer.fill(0); + std::array expected{}; + expected.fill(filler_byte); + std::array actual; + actual.fill(0); // Exercise - auto result = read(serial, actual_buffer, never_timeout()); + read(serial, actual, never_timeout()); // Verify - expect(result.has_value()); expect(!serial.m_flush_called); expect(that % nullptr == serial.m_out.data()); expect(that % 0 == serial.m_out.size()); - // bool test = expected_buffer == result.value(); - // expect(that % test) << expected_buffer << " != " << result.value(); + expect(that % expected == actual) << expected << " != " << actual; }; "[failure read] read"_test = []() { // Setup fake_serial serial; - std::array expected_buffer; + std::array actual{}; serial.m_read_fails = true; // Exercise - auto result = read(serial, expected_buffer, never_timeout()); + expect(throws( + [&serial, &actual]() { read(serial, actual, never_timeout()); })); // Verify - expect(!result.has_value()); expect(!serial.m_flush_called); expect(that % serial.m_read_was_called); expect(that % nullptr == serial.m_out.data()); @@ -235,19 +228,19 @@ void serial_util_test() "[success] read"_test = []() { // Setup fake_serial serial; - std::array expected_buffer; - expected_buffer.fill(filler_byte); + std::array expected{}; + expected.fill(filler_byte); // Exercise - auto result = read(serial, never_timeout()); + auto actual = read(serial, never_timeout()); // Verify - expect(result.has_value()); expect(!serial.m_flush_called); - expect(that % expected_buffer == result.value()); + expect(that % expected == actual); expect(that % serial.m_read_was_called); expect(that % nullptr == serial.m_out.data()); expect(that % 0 == serial.m_out.size()); + expect(that % expected == actual) << expected << " != " << actual; }; "[failure read] read"_test = []() { @@ -256,10 +249,11 @@ void serial_util_test() serial.m_read_fails = true; // Exercise - auto result = read<5>(serial, never_timeout()); + expect(throws([&serial]() { + [[maybe_unused]] auto result = read<5>(serial, never_timeout()); + })); // Verify - expect(!result.has_value()); expect(!serial.m_flush_called); expect(that % serial.m_read_was_called); expect(that % nullptr == serial.m_out.data()); @@ -269,59 +263,58 @@ void serial_util_test() "[success] write_then_read"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; - std::array expected_buffer; - expected_buffer.fill(filler_byte); - std::array actual_buffer; - actual_buffer.fill(0); + const std::array write_buffer{}; + std::array expected_read{}; + expected_read.fill(filler_byte); + std::array actual; + actual.fill(0); // Exercise - auto result = write_then_read( - serial, expected_payload, actual_buffer, never_timeout()); + write_then_read(serial, write_buffer, actual, never_timeout()); // Verify - expect(result.has_value()); expect(!serial.m_flush_called); - expect(that % expected_payload.data() == serial.m_out.data()); - expect(that % expected_payload.size() == serial.m_out.size()); - expect(that % expected_buffer == actual_buffer); + expect(that % write_buffer.data() == serial.m_out.data()); + expect(that % write_buffer.size() == serial.m_out.size()); + expect(that % expected_read == actual) + << expected_read << " != " << actual; }; "[failure read] write_then_read"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; - std::array expected_buffer; - expected_buffer.fill(filler_byte); + const std::array expected{}; + std::array actual{}; + actual.fill(filler_byte); std::array actual_buffer; actual_buffer.fill(0); serial.m_read_fails = true; // Exercise - auto result = write_then_read( - serial, expected_payload, actual_buffer, never_timeout()); + expect(throws([&serial, &expected, &actual_buffer]() { + write_then_read(serial, expected, actual_buffer, never_timeout()); + })); // Verify - expect(!result.has_value()); expect(!serial.m_flush_called); expect(that % serial.m_read_was_called); - expect(that % expected_payload.data() == serial.m_out.data()); - expect(that % expected_payload.size() == serial.m_out.size()); - expect(that % expected_buffer != actual_buffer); + expect(that % expected.data() == serial.m_out.data()); + expect(that % expected.size() == serial.m_out.size()); + expect(that % actual != actual_buffer); }; "[failure on write] write_then_read"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{ write_failure_byte }; - std::array expected_buffer; + const std::array expected{ write_failure_byte }; + std::array actual{}; // Exercise - auto result = write_then_read( - serial, expected_payload, expected_buffer, never_timeout()); + expect(throws([&serial, &expected, &actual]() { + write_then_read(serial, expected, actual, never_timeout()); + })); // Verify - expect(!result.has_value()); expect(!serial.m_flush_called); expect(that % !serial.m_read_was_called); expect(that % nullptr == serial.m_out.data()); @@ -331,36 +324,34 @@ void serial_util_test() "[success] write_then_read"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{}; - std::array expected_buffer; - expected_buffer.fill(filler_byte); + const std::array expected_write{}; + std::array expected_read{}; + expected_read.fill(filler_byte); // Exercise - auto result = - write_then_read<5>(serial, expected_payload, never_timeout()); - - auto actual_array = result.value(); + auto actual = write_then_read<5>(serial, expected_write, never_timeout()); // Verify - expect(result.has_value()); expect(!serial.m_flush_called); - expect(that % expected_payload.data() == serial.m_out.data()); - expect(that % expected_payload.size() == serial.m_out.size()); + expect(that % expected_write.data() == serial.m_out.data()); + expect(that % expected_write.size() == serial.m_out.size()); expect(serial.m_read_was_called); - expect(that % expected_buffer == actual_array); + expect(that % expected_read == actual) + << expected_read << " != " << actual; }; "[failure on write] write_then_read"_test = []() { // Setup fake_serial serial; - const std::array expected_payload{ write_failure_byte }; + const std::array expected{ write_failure_byte }; // Exercise - auto result = - write_then_read<5>(serial, expected_payload, never_timeout()); + expect(throws([&serial, &expected]() { + [[maybe_unused]] auto result = + write_then_read<5>(serial, expected, never_timeout()); + })); // Verify - expect(!result.has_value()); expect(!serial.m_flush_called); expect(that % !serial.m_read_was_called); expect(that % nullptr == serial.m_out.data()); @@ -370,25 +361,23 @@ void serial_util_test() struct save_serial_write : public hal::serial { - status driver_configure(const settings&) override + void driver_configure(const settings&) override { - return {}; } - result driver_write(std::span p_data) override + write_t driver_write(std::span p_data) override { m_out.assign(p_data.begin(), p_data.end()); return write_t{ p_data }; } - result driver_read(std::span) override + read_t driver_read(std::span) override { - return hal::new_error(); + throw std::errc::io_error; } - result driver_flush() override + void driver_flush() override { - return flush_t{}; } ~save_serial_write() override = default; @@ -400,61 +389,57 @@ void serial_util_test() "print()"_test = []() { // Setup save_serial_write serial; - const std::string_view expected_payload = "hello, world!"; + const std::string_view expected = "hello, world!"; // Exercise - print(serial, expected_payload); + print(serial, expected); // Verify - expect( - that % expected_payload == - std::string_view(reinterpret_cast(serial.m_out.data()), - serial.m_out.size())); + expect(that % expected == std::string_view(reinterpret_cast( + serial.m_out.data()), + serial.m_out.size())); }; "[printf style 1] print()"_test = []() { // Setup save_serial_write serial; - const std::string_view expected_payload = "hello 5"; + const std::string_view expected = "hello 5"; // Exercise print<128>(serial, "hello %d", 5); // Verify - expect( - that % expected_payload == - std::string_view(reinterpret_cast(serial.m_out.data()), - serial.m_out.size())); + expect(that % expected == std::string_view(reinterpret_cast( + serial.m_out.data()), + serial.m_out.size())); }; "[printf style 2] print()"_test = []() { // Setup save_serial_write serial; - const std::string_view expected_payload = "hello 5 0xABCDEF"; + const std::string_view expected = "hello 5 ABCDEF"; // Exercise - print<128>(serial, "hello %d 0x%06X", 5, 0xABCDEF); + print<128>(serial, "hello %d %06X", 5, 0xABCDEF); // Verify - expect( - that % expected_payload == - std::string_view(reinterpret_cast(serial.m_out.data()), - serial.m_out.size())); + expect(that % expected == std::string_view(reinterpret_cast( + serial.m_out.data()), + serial.m_out.size())); }; "[printf style 3 trimmed] print()"_test = []() { // Setup save_serial_write serial; - const std::string_view expected_payload = "hello 5\0"; + const std::string_view expected = "hello 5\0"; // Exercise print<8>(serial, "hello %d 0x%06X", 5, 0xABCDEF); // Verify - expect( - that % expected_payload == - std::string_view(reinterpret_cast(serial.m_out.data()), - serial.m_out.size())); + expect(that % expected == std::string_view(reinterpret_cast( + serial.m_out.data()), + serial.m_out.size())); }; }; }; diff --git a/tests/spi.test.cpp b/tests/spi.test.cpp index 9a13e50..e9894fe 100644 --- a/tests/spi.test.cpp +++ b/tests/spi.test.cpp @@ -28,14 +28,12 @@ void spi_util_test() class dummy : public hal::spi { public: - [[nodiscard]] status driver_configure(const settings&) override + void driver_configure(const settings&) override { - return {}; } - [[nodiscard]] result driver_transfer( - std::span p_out, - std::span p_in, - hal::byte p_filler) override + void driver_transfer(std::span p_out, + std::span p_in, + hal::byte p_filler) override { if (!p_out.empty()) { m_out = p_out; @@ -49,10 +47,8 @@ void spi_util_test() m_filler = p_filler; if (p_filler == failure_filler) { - return hal::new_error(); + throw std::errc::invalid_argument; } - - return {}; } ~dummy() override = default; @@ -68,11 +64,9 @@ void spi_util_test() const std::array expected_payload{}; // Exercise - auto result = write(spi, expected_payload); - bool successful = static_cast(result); + write(spi, expected_payload); // Verify - expect(successful); expect(that % expected_payload.data() == spi.m_out.data()); expect(that % expected_payload.size() == spi.m_out.size()); expect(that % nullptr == spi.m_in.data()); @@ -85,11 +79,9 @@ void spi_util_test() std::array expected_buffer; // Exercise - auto result = read(spi, expected_buffer, success_filler); - bool successful = static_cast(result); + read(spi, expected_buffer, success_filler); // Verify - expect(successful); expect(success_filler == spi.m_filler); expect(that % expected_buffer.data() == spi.m_in.data()); expect(that % expected_buffer.size() == spi.m_in.size()); @@ -103,11 +95,12 @@ void spi_util_test() std::array expected_buffer; // Exercise - auto result = read(spi, expected_buffer, failure_filler); - bool successful = static_cast(result); + expect(throws([&spi, &expected_buffer]() { + read(spi, expected_buffer, failure_filler); + })) + << "Exception not thrown!"; // Verify - expect(!successful); expect(failure_filler == spi.m_filler); expect(that % expected_buffer.data() == spi.m_in.data()); expect(that % expected_buffer.size() == spi.m_in.size()); @@ -122,18 +115,17 @@ void spi_util_test() expected_buffer.fill(filler_byte); // Exercise - auto result = read(spi, success_filler); - bool successful = static_cast(result); + auto actual_buffer = read(spi, success_filler); // Verify - expect(successful); expect(success_filler == spi.m_filler); expect(std::equal( - expected_buffer.begin(), expected_buffer.end(), result.value().begin())); + expected_buffer.begin(), expected_buffer.end(), actual_buffer.begin())); expect(that % nullptr == spi.m_out.data()); expect(that % 0 == spi.m_out.size()); }; +#if 0 "[failure] read"_test = []() { // Setup dummy spi; @@ -226,5 +218,6 @@ void spi_util_test() expect(that % expected_payload.data() == spi.m_out.data()); expect(that % expected_payload.size() == spi.m_out.size()); }; +#endif }; } // namespace hal diff --git a/tests/steady_clock.test.cpp b/tests/steady_clock.test.cpp index e0b2863..fcb53c7 100644 --- a/tests/steady_clock.test.cpp +++ b/tests/steady_clock.test.cpp @@ -34,14 +34,14 @@ void steady_clock_utility_test() std::uint64_t m_uptime = 0; private: - frequency_t driver_frequency() override + hertz driver_frequency() override { - return frequency_t{ .operating_frequency = expected_frequency }; + return expected_frequency; } - uptime_t driver_uptime() override + std::uint64_t driver_uptime() override { - return uptime_t{ .ticks = m_uptime++ }; + return m_uptime++; } }; @@ -51,82 +51,60 @@ void steady_clock_utility_test() // Setup static constexpr hal::time_duration expected(0); dummy_steady_clock test_steady_clock; - bool success = false; // Exercise auto timeout_object = create_timeout(test_steady_clock, expected); - hal::attempt_all( - [&timeout_object]() -> status { return timeout_object(); }, - [&success](match) { success = true; }, - []() { expect(false) << "std::errc::timed_out was not thrown!"; }); + expect(throws([&timeout_object]() { timeout_object(); })) + << "throws std::errc"; // Verify - expect(that % success) << "std::errc::timed_out handler was not called!"; // Verify: subtract 2 because 2 invocations are required in order to get // the start uptime and another to check what the latest uptime is. expect(that % expected.count() == (test_steady_clock.m_uptime - 2)); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::create_timeout(hal::steady_clock, 50ns)"_test = []() { // Setup static constexpr hal::time_duration expected(50); dummy_steady_clock test_steady_clock; - bool success = false; // Exercise auto timeout_object = create_timeout(test_steady_clock, expected); - hal::attempt_all( - [&timeout_object]() -> status { - // Terminate the loop one iteration before the timeout would occur - for (std::int64_t i = 0; i < expected.count() - 1; i++) { - if (!timeout_object()) { - return hal::new_error(); - } - } - return timeout_object(); - }, - [&success](match) { success = true; }, - []() { expect(false) << "std::errc::timed_out was not thrown!"; }); + expect(throws([&timeout_object]() { + // Terminate the loop one iteration before the timeout would occur + for (std::int64_t i = 0; i < expected.count(); i++) { + timeout_object(); + } + })) + << "std::errc::timed_out was not thrown!"; // Verify - expect(that % success) << "std::errc::timed_out handler was not called!"; // After the last call to uptime() the uptime value is incremented by one expect(that % expected.count() == test_steady_clock.m_uptime - 1); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::create_timeout(hal::steady_clock, 1337ns)"_test = []() { // Setup static constexpr hal::time_duration expected(10); dummy_steady_clock test_steady_clock; - bool success = false; // Exercise auto timeout_object = create_timeout(test_steady_clock, expected); - hal::attempt_all( - [&timeout_object]() -> status { - for (std::int64_t i = 0; i < expected.count() - 1; i++) { - // error out if this times out early - if (!timeout_object()) { - return hal::new_error(); - } - } - return timeout_object(); - }, - [&success](match) { success = true; }, - []() { expect(false) << "std::errc::timed_out was not thrown!"; }); + expect(throws([&timeout_object]() { + for (std::int64_t i = 0; i < expected.count(); i++) { + timeout_object(); + } + })) + << "std::errc::timed_out was not thrown!"; // Verify - expect(that % success) << "std::errc::timed_out handler was not called!"; expect(that % expected.count() == test_steady_clock.m_uptime - 1); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::create_timeout(hal::steady_clock, -5ns) returns error"_test = []() { @@ -139,8 +117,7 @@ void steady_clock_utility_test() // Verify expect(that % 1 == test_steady_clock.m_uptime); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; // =============== delay =============== @@ -155,10 +132,10 @@ void steady_clock_utility_test() // Verify // Verify: subtract 2 because 2 invocations are required in order to get - // the start uptime and another to check what the latest uptime is. + // the start uptime and another to check what the latest uptime + // is. expect(that % expected.count() == (test_steady_clock.m_uptime - 2)); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::delay(hal::steady_clock, 50ns)"_test = []() { @@ -171,8 +148,7 @@ void steady_clock_utility_test() // Verify expect(that % expected.count() == test_steady_clock.m_uptime - 1); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::delay(hal::steady_clock, 1337ns)"_test = []() { @@ -185,8 +161,7 @@ void steady_clock_utility_test() // Verify expect(that % expected.count() == test_steady_clock.m_uptime - 1); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::delay(hal::steady_clock, -5ns) returns error"_test = []() { @@ -200,39 +175,30 @@ void steady_clock_utility_test() // Verify // Verify: Adjust uptime by 2 because at least 2 calls to uptime() expect(that % 0 == test_steady_clock.m_uptime - 2); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; "hal::timeout_generator(hal::steady_clock)"_test = []() { // Setup static constexpr hal::time_duration expected(50); dummy_steady_clock test_steady_clock; - bool success = false; // Exercise auto generator = timeout_generator(test_steady_clock); auto timeout_object = generator(expected); - hal::attempt_all( - [&timeout_object]() -> status { - // Terminate the loop one iteration before the timeout would occur - for (std::int64_t i = 0; i < expected.count() - 1; i++) { - if (!timeout_object()) { - return hal::new_error(); - } - } - return timeout_object(); - }, - [&success](match) { success = true; }, - []() { expect(false) << "std::errc::timed_out was not thrown!"; }); + expect(throws([&timeout_object]() { + // Terminate the loop one iteration before the timeout would occur + for (std::int64_t i = 0; i < expected.count(); i++) { + timeout_object(); + } + })) + << "std::errc::timed_out was not thrown!"; // Verify - expect(that % success) << "std::errc::timed_out handler was not called!"; // After the last call to uptime() the uptime value is incremented by one expect(that % expected.count() == test_steady_clock.m_uptime - 1); - expect(that % expected_frequency == - test_steady_clock.frequency().operating_frequency); + expect(that % expected_frequency == test_steady_clock.frequency()); }; }; } // namespace hal diff --git a/tests/timeout.test.cpp b/tests/timeout.test.cpp index ef9f5e6..7c43aca 100644 --- a/tests/timeout.test.cpp +++ b/tests/timeout.test.cpp @@ -24,22 +24,22 @@ void timeout_test() // Setup constexpr int timeout_call_limit = 10; int counts = 0; - auto timeout_callback = [&counts]() mutable -> status { - counts++; - if (counts >= timeout_call_limit) { - return hal::new_error(std::errc::timed_out); - } - return {}; - }; - std::function()> callback = [&counts]() { + auto callback = [&counts]() -> work_state { if (counts >= 5) { return work_state::finished; } return work_state::in_progress; }; + auto timeout_callback = [&counts]() -> void { + counts++; + if (counts >= timeout_call_limit) { + throw std::errc::timed_out; + } + }; + // Exercise - auto result = hal::try_until(callback, timeout_callback).value(); + auto result = hal::try_until(callback, timeout_callback); // Verify expect(that % work_state::finished == result); @@ -50,32 +50,34 @@ void timeout_test() // Setup constexpr int timeout_call_limit = 10; int counts = 0; - auto timeout_callback = [&counts]() mutable -> status { - counts++; - if (counts >= timeout_call_limit) { - return hal::new_error(std::errc::timed_out); - } - return {}; - }; - std::function()> callback = [&counts]() { + + auto callback = [&counts]() -> work_state { if (counts >= 11) { return work_state::finished; } return work_state::in_progress; }; + auto timeout_callback = [&counts]() mutable { + counts++; + if (counts >= timeout_call_limit) { + throw std::errc::timed_out; + } + }; + // Exercise - auto result = hal::try_until(callback, timeout_callback); + expect(throws([&callback, &timeout_callback]() { + hal::try_until(callback, timeout_callback); + })); // Verify - expect(!bool{ result }); expect(that % 10 == counts); }; "hal::try_until(callback, timeout) with never_timeout"_test = []() { // Setup int counts = 0; - std::function()> callback = [&counts]() { + auto callback = [&counts]() -> work_state { counts++; if (counts >= 5) { return work_state::finished; @@ -84,7 +86,7 @@ void timeout_test() }; // Exercise - auto result = hal::try_until(callback, never_timeout()).value(); + auto result = hal::try_until(callback, never_timeout()); // Verify expect(that % work_state::finished == result); @@ -95,40 +97,24 @@ void timeout_test() // Setup constexpr int timeout_call_limit = 10; int counts = 0; - auto timeout_callback = [&counts]() mutable -> status { + + auto callback = []() -> work_state { + throw std::errc::resource_unavailable_try_again; + return work_state::in_progress; + }; + + auto timeout_callback = [&counts]() mutable { counts++; if (counts >= timeout_call_limit) { - return hal::new_error(std::errc::timed_out); + throw std::errc::timed_out; } - return {}; - }; - std::function()> callback = []() { - return hal::new_error(std::errc::resource_unavailable_try_again); - }; - - bool callback_error = false; - auto error_catcher = - [&callback_error]( - hal::match p_errc) - -> status { - (void)p_errc; - callback_error = true; - return {}; }; // Exercise - auto result = hal::attempt( - [&callback, &timeout_callback]() -> status { - while (true) { - HAL_CHECK(hal::try_until(callback, timeout_callback)); - } - // Unreachable! - return {}; - }, - error_catcher); - // Verify - expect(that % true == callback_error); + expect(throws([&callback, &timeout_callback]() { + hal::try_until(callback, timeout_callback); + })); }; "hal::work_state helper functions"_test = []() {