Theme Catppuccin
Make yourself at homeCatppuccin

A softer light for long learning sessions.

Appearance

Loading your preference…

Dark palette

Choose a dark palette to try it.

Light uses Latte. Your choices stay in this browser.

Back to your source shelf

Inside the companion

Modern C++ errors

Follow one pixel through validation, std::expected, and a complete-or-unchanged update.

Project files 6

Test both sides of expected

Known bytes, invalid and non-finite channels, and unchanged state after failure.

53 lines pixel_tests.cpp
#include "pixel/pixel.hpp"
#include <array>
#include <iostream>
#include <limits>
#include <utility>

int main() {
    int checks = 0;
    int failures = 0;
    const auto check = [&](bool condition, const char* name) {
        ++checks;
        if (!condition) { ++failures; std::cerr << name << '\n'; }
    };
    for (const auto [input, output] : std::array{
        std::pair{0.0, 0}, std::pair{0.25, 128}, std::pair{1.0, 255}}) {
        const auto result = pixel::encode_channel(input);
        check(result && *result == output, "independent gamma-2 value");
    }
    for (const double bad : {-0.01, 1.01}) {
        const auto result = pixel::encode_channel(bad);
        check(!result && result.error() == pixel::ChannelError::outside_unit_interval,
              "finite range rejection");
    }
    for (const double bad : {std::numeric_limits<double>::quiet_NaN(),
                            std::numeric_limits<double>::infinity(),
                            -std::numeric_limits<double>::infinity()}) {
        const auto result = pixel::encode_channel(bad);
        check(!result && result.error() == pixel::ChannelError::non_finite,
              "non-finite rejection");
    }
    const pixel::Pixel initial{12, 34, 56};
    for (std::size_t channel = 0; channel < 3; ++channel) {
        auto current = initial;
        std::array<double, 3> input{0.0, 0.25, 1.0};
        input[channel] = 2.0;
        const auto result = pixel::replace_pixel(current, input);
        check(!result && result.error().channel == channel
                      && result.error().reason == pixel::ChannelError::outside_unit_interval,
              "error propagated with correct channel");
        check(current == initial, "failed candidate preserves complete old pixel");
    }
    auto current = initial;
    const auto result = pixel::replace_pixel(current, {0.0, 0.25, 1.0});
    check(result.has_value(), "expected<void> success");
    check(current == pixel::Pixel{0, 128, 255}, "complete new pixel committed");
    const auto bad = pixel::prepare_pixel({1.1, 2.0, 3.0});
    check(!bad && bad.error().channel == 0, "first failure is reported");
    if (failures != 0) return 1;
    std::cout << checks << " expected contracts passed\n";
    std::cout.flush();
    return std::cout ? 0 : 1;
}

This is the file included with the course. Copy and download give you its complete source.

Taking your work offline? Download all course companions