| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- //
- // either_stream.t.h
- // optional.stream
- //
- // Created by Sam Jaffe on 1/30/17.
- //
- #include <gmock/gmock.h>
- #include <cmath>
- #include "stream/either_stream.hpp"
- enum class MathError {
- OutOfBounds,
- DivideByZero,
- DomainError
- };
- using MathObject = either<double, MathError>;
- MathObject divide(double num, double den) {
- if (std::abs(den) < 0.000000001) {
- return MathError::DivideByZero;
- } else {
- return num / den;
- }
- }
- double multiply(double lhs, double rhs) { return lhs * rhs; }
- MathObject log(double value, double base) {
- if (value <= 0) {
- return MathError::DomainError;
- } else {
- return divide(std::log(value), std::log(base));
- }
- }
- using ::testing::DoubleNear;
- using ::testing::Eq;
- TEST(EitherStreamTest, becomes_error) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- strm.flatmap([](double d) { return divide(d, 0); })
- .match([](double) { throw std::runtime_error("Expected error"); },
- [](MathError e) { EXPECT_THAT(e, Eq(MathError::DivideByZero)); });
- }
- TEST(EitherStreamTest, computes_result) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- strm.map([](double d) { return multiply(d, 10.0); })
- .match([](double d) { EXPECT_THAT(10.0, DoubleNear(d, 0.00001)); },
- [](MathError) { throw std::runtime_error("Expected concrete"); });
- }
- TEST(EitherStreamTest, computes_result2) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- bool is_error = strm.map([](double d) { return multiply(d, 10.0); })
- .match([](double) { return false; },
- [](MathError) { return true; });
- EXPECT_FALSE(is_error);
- }
- TEST(EitherStreamTest, propogates_error) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- strm.flatmap([](double d) { return divide(d, 0); })
- .map([](double) { throw std::runtime_error("Mapping while invalid"); return 0; })
- .match([](double) { throw std::runtime_error("Expected error"); },
- [](MathError e) { EXPECT_THAT(e, Eq(MathError::DivideByZero)); });
- }
- TEST(EitherStreamTest, propogates_same_error) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- strm.flatmap([](double d) { return log(1.0, d); })
- .flatmap([](double d) { return log(d, 1.0); })
- .match([](double) { throw std::runtime_error("Expected error"); },
- [](MathError e) { EXPECT_THAT(e, Eq(MathError::DivideByZero)); });
- }
- TEST(EitherStreamTest, propogates_same_error2) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- strm.flatmap([](double d) { return log(0.0, d); })
- .flatmap([](double d) { return log(d, 1.0); })
- .match([](double) { throw std::runtime_error("Expected error"); },
- [](MathError e) { EXPECT_THAT(e, Eq(MathError::DomainError)); });
- }
- TEST(EitherStreamTest, propogates_same_error3) {
- auto strm = stream::either::make_stream<MathObject>(1.0);
- bool is_error = strm.flatmap([](double d) { return log(0.0, d); })
- .flatmap([](double d) { return log(d, 1.0); })
- .match([](double) { return false; },
- [](MathError) { return true; });
- EXPECT_TRUE(is_error);
- }
|