Преглед изворни кода

Cleanup test cases to be less redundant and more descriptive.
Add value-accessor to either stream.

Sam Jaffe пре 6 година
родитељ
комит
c6edaab2f1
2 измењених фајлова са 51 додато и 55 уклоњено
  1. 13 11
      include/stream/either_stream.hpp
  2. 38 44
      test/either_stream_test.cxx

+ 13 - 11
include/stream/either_stream.hpp

@@ -37,37 +37,39 @@ namespace stream { namespace either {
       using flatmap_f = typename either_left<decltype(std::declval<F>()(std::declval<T2>()))>::type;
 
     public:
-      either_stream(E const & v) : value(v) {}
-      either_stream(E && v) : value(std::forward<E>(v)) {}
+      either_stream(E const & v) : value_(v) {}
+      either_stream(E && v) : value_(std::forward<E>(v)) {}
       
-      either_stream(T const & v) : value(v) {}
-      either_stream(T && v) : value(std::forward<T>(v)) {}
-      either_stream(::either<T, E> const & v) : value(v) {}
-      either_stream(::either<T, E> && v) : value(std::forward<::either<T, E>>(v)) {}
+      either_stream(T const & v) : value_(v) {}
+      either_stream(T && v) : value_(std::forward<T>(v)) {}
+      either_stream(::either<T, E> const & v) : value_(v) {}
+      either_stream(::either<T, E> && v) : value_(std::forward<::either<T, E>>(v)) {}
       
       template <typename F>
       either_stream<::either<map_f<F, T>, E>> map(F && fun) const {
         using next_t = either_stream<::either<map_f<F, T>, E>>;
-        return value.index() == 0 ? next_t{fun(std::get<0>(value))} : next_t{std::get<1>(value)};
+        return value_.index() == 0 ? next_t{fun(std::get<0>(value_))} : next_t{std::get<1>(value_)};
       }
       
       template <typename F>
       either_stream<::either<flatmap_f<F, T>, E>> flatmap(F && fun) const {
         using next_t = either_stream<::either<flatmap_f<F, T>, E>>;
-        return value.index() == 0 ? next_t{fun(std::get<0>(value))} : next_t{std::get<1>(value)};
+        return value_.index() == 0 ? next_t{fun(std::get<0>(value_))} : next_t{std::get<1>(value_)};
       }
       
       template <typename FT, typename FE, typename = typename std::enable_if<!(std::is_void<map_f<FT, T>>::value && std::is_void<map_f<FE, E>>::value)>::type>
       typename std::common_type<map_f<FT, T>, map_f<FE, E>>::type match(FT && left, FE && right) {
-        return value.index() == 0 ? left(std::get<0>(value)) : right(std::get<1>(value));
+        return value_.index() == 0 ? left(std::get<0>(value_)) : right(std::get<1>(value_));
       }
 
       template <typename FT, typename FE, typename = typename std::enable_if<std::is_void<map_f<FT, T>>::value && std::is_void<map_f<FE, E>>::value>::type>
       void match(FT && left, FE && right) {
-        value.index() == 0 ? left(std::get<0>(value)) : right(std::get<1>(value));
+        value_.index() == 0 ? left(std::get<0>(value_)) : right(std::get<1>(value_));
       }
+      
+      ::either<T, E> const & value() const { return value_; }
     private:
-      ::either<T, E> value;
+      ::either<T, E> value_;
     };
   }
   

+ 38 - 44
test/either_stream_test.cxx

@@ -39,57 +39,51 @@ MathObject log(double value, double 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, ContainsErrorValue) {
+  auto strm = stream::either::make_stream<MathObject>(1.0)
+      .flatmap([](double d) { return divide(d, 0); });
+  
+  EXPECT_THAT(strm.value().index(), Eq(1));
+  EXPECT_THAT(std::get<MathError>(strm.value()), 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, ErrorValueMatchesToErrorHandler) {
+  auto bad_value = [](double) { throw std::logic_error("Expected error"); };
+  auto strm = stream::either::make_stream<MathObject>(1.0)
+      .flatmap([](double d) { return divide(d, 0); });
+  
+  EXPECT_NO_THROW(strm.match(bad_value, [](MathError e) {}));
 }
 
-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, ConcreteValueMatchesToConreteHandler) {
+  auto bad_error = [](MathError) { throw std::logic_error("Expected value"); };
+  auto strm = stream::either::make_stream<MathObject>(1.0)
+      .map([](double d) { return multiply(d, 10.0); });
+  
+  EXPECT_NO_THROW(strm.match([](double d) {}, bad_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, ErrorPropogatesBypassingMap) {
+  auto bad_value = [](double) { throw std::logic_error("Expected error"); };
+  auto strm = stream::either::make_stream<MathObject>(1.0)
+      .flatmap([](double d) { return divide(d, 0); });
+  
+  EXPECT_NO_THROW(strm = strm.map([](double) {
+    throw std::runtime_error("Mapping while invalid");
+    return 0.0;
+  }));
+  EXPECT_NO_THROW(strm.match(bad_value, [](MathError e) {}));
 }
 
-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, ErrorPropogatesBypassingFlatmap) {
+  auto ex = stream::either::make_stream<MathObject>(1.0)
+      .flatmap([](double d) { return log(0.0, d); });
+  EXPECT_THAT(std::get<MathError>(ex.value()), 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);
+  auto strm = stream::either::make_stream<MathObject>(1.0)
+      .flatmap([](double d) { return log(1.0, d); });
+  EXPECT_THAT(std::get<MathError>(strm.value()), Eq(MathError::DivideByZero));
+  
+  strm = strm.flatmap([](double d) { return log(0.0, d); });
+  EXPECT_THAT(std::get<MathError>(strm.value()), Eq(MathError::DivideByZero));
 }