// // either_stream.t.h // optional.stream // // Created by Sam Jaffe on 1/30/17. // #pragma once #include #include "either_stream.hpp" enum class MathError { OutOfBounds, DivideByZero, DomainError }; using MathObject = either; 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)); } } class either_stream_TestSuite : public CxxTest::TestSuite { public: void test_either_becomes_error() { auto strm = stream::either::make_stream(1.0); strm.flatmap([](double d) { return divide(d, 0); }) .match([](double) { TS_FAIL("Expected Error Type"); }, [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); }); } void test_either_computes_result() { auto strm = stream::either::make_stream(1.0); strm.map([](double d) { return multiply(d, 10.0); }) .match([](double d) { TS_ASSERT_DELTA(10.0, d, 0.00001); }, [](MathError) { TS_FAIL("Expected Value"); }); } void test_either_computes_result2() { auto strm = stream::either::make_stream(1.0); bool is_error = strm.map([](double d) { return multiply(d, 10.0); }) .match([](double) { return false; }, [](MathError) { return true; }); TS_ASSERT(!is_error); } void test_either_propogates_error() { auto strm = stream::either::make_stream(1.0); strm.flatmap([](double d) { return divide(d, 0); }) .map([](double) { TS_FAIL("Operating on bad data"); return 0; }) .match([](double) { TS_FAIL("Expected Error Type"); }, [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); }); } void test_either_propogates_same_error() { auto strm = stream::either::make_stream(1.0); strm.flatmap([](double d) { return log(1.0, d); }) .flatmap([](double d) { return log(d, 1.0); }) .match([](double) { TS_FAIL("Expected Error Type"); }, [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); }); } void test_either_propogates_same_error2() { auto strm = stream::either::make_stream(1.0); strm.flatmap([](double d) { return log(0.0, d); }) .flatmap([](double d) { return log(d, 1.0); }) .match([](double) { TS_FAIL("Expected Error Type"); }, [](MathError e) { TS_ASSERT_EQUALS( MathError::DomainError, e ); }); } void test_either_propogates_same_error3() { auto strm = stream::either::make_stream(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; }); TS_ASSERT(is_error); } };