either_stream_test.cxx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //
  2. // either_stream.t.h
  3. // optional.stream
  4. //
  5. // Created by Sam Jaffe on 1/30/17.
  6. //
  7. #pragma once
  8. #include <cxxtest/TestSuite.h>
  9. #include "either_stream.hpp"
  10. enum class MathError {
  11. OutOfBounds,
  12. DivideByZero,
  13. DomainError
  14. };
  15. using MathObject = either<double, MathError>;
  16. MathObject divide(double num, double den) {
  17. if (std::abs(den) < 0.000000001) {
  18. return MathError::DivideByZero;
  19. } else {
  20. return num / den;
  21. }
  22. }
  23. double multiply(double lhs, double rhs) { return lhs * rhs; }
  24. MathObject log(double value, double base) {
  25. if (value <= 0) {
  26. return MathError::DomainError;
  27. } else {
  28. return divide(std::log(value), std::log(base));
  29. }
  30. }
  31. class either_stream_TestSuite : public CxxTest::TestSuite {
  32. public:
  33. void test_either_becomes_error() {
  34. auto strm = stream::either::make_stream<MathObject>(1.0);
  35. strm.flatmap([](double d) { return divide(d, 0); })
  36. .match([](double) { TS_FAIL("Expected Error Type"); },
  37. [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); });
  38. }
  39. void test_either_computes_result() {
  40. auto strm = stream::either::make_stream<MathObject>(1.0);
  41. strm.map([](double d) { return multiply(d, 10.0); })
  42. .match([](double d) { TS_ASSERT_DELTA(10.0, d, 0.00001); },
  43. [](MathError) { TS_FAIL("Expected Value"); });
  44. }
  45. void test_either_computes_result2() {
  46. auto strm = stream::either::make_stream<MathObject>(1.0);
  47. bool is_error = strm.map([](double d) { return multiply(d, 10.0); })
  48. .match([](double) { return false; },
  49. [](MathError) { return true; });
  50. TS_ASSERT(!is_error);
  51. }
  52. void test_either_propogates_error() {
  53. auto strm = stream::either::make_stream<MathObject>(1.0);
  54. strm.flatmap([](double d) { return divide(d, 0); })
  55. .map([](double) { TS_FAIL("Operating on bad data"); return 0; })
  56. .match([](double) { TS_FAIL("Expected Error Type"); },
  57. [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); });
  58. }
  59. void test_either_propogates_same_error() {
  60. auto strm = stream::either::make_stream<MathObject>(1.0);
  61. strm.flatmap([](double d) { return log(1.0, d); })
  62. .flatmap([](double d) { return log(d, 1.0); })
  63. .match([](double) { TS_FAIL("Expected Error Type"); },
  64. [](MathError e) { TS_ASSERT_EQUALS( MathError::DivideByZero, e ); });
  65. }
  66. void test_either_propogates_same_error2() {
  67. auto strm = stream::either::make_stream<MathObject>(1.0);
  68. strm.flatmap([](double d) { return log(0.0, d); })
  69. .flatmap([](double d) { return log(d, 1.0); })
  70. .match([](double) { TS_FAIL("Expected Error Type"); },
  71. [](MathError e) { TS_ASSERT_EQUALS( MathError::DomainError, e ); });
  72. }
  73. void test_either_propogates_same_error3() {
  74. auto strm = stream::either::make_stream<MathObject>(1.0);
  75. bool is_error = strm.flatmap([](double d) { return log(0.0, d); })
  76. .flatmap([](double d) { return log(d, 1.0); })
  77. .match([](double) { return false; },
  78. [](MathError) { return true; });
  79. TS_ASSERT(is_error);
  80. }
  81. };