瀏覽代碼

refactor: clean up common view test

Sam Jaffe 2 年之前
父節點
當前提交
a8f837c7d8
共有 7 個文件被更改,包括 135 次插入96 次删除
  1. 1 1
      external/iterator
  2. 4 2
      stream.xcodeproj/project.pbxproj
  3. 2 2
      test/all_test.cxx
  4. 23 52
      test/common_test.cxx
  5. 76 0
      test/stream_helpers.h
  6. 29 0
      test/stream_matchers.h
  7. 0 39
      test/stream_test.h

+ 1 - 1
external/iterator

@@ -1 +1 @@
-Subproject commit 5ee6fea85eeab110cd4341edc6adc7b88f1d4eab
+Subproject commit 4dda725401bc328b511f1e9a6ab13960e702cc30

+ 4 - 2
stream.xcodeproj/project.pbxproj

@@ -87,6 +87,7 @@
 		CD52827F29D50E24001A84DE /* fold.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fold.h; sourceTree = "<group>"; };
 		CD52828029D51166001A84DE /* identity.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = identity.h; sourceTree = "<group>"; };
 		CD52828129D5133C001A84DE /* map.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = map.h; sourceTree = "<group>"; };
+		CD5A559429DCD12300881E7E /* stream_helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stream_helpers.h; sourceTree = "<group>"; };
 		CD5A8D3529D63C05008C2A4F /* count.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = count.h; sourceTree = "<group>"; };
 		CD5A8D3B29D63DF5008C2A4F /* named_pair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = named_pair.h; sourceTree = "<group>"; };
 		CD64CCB926232D6900770A30 /* xcode_gtest_helper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xcode_gtest_helper.h; sourceTree = "<group>"; };
@@ -103,7 +104,7 @@
 		CDA37D4129D9D3F5000A1F97 /* algorithm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = algorithm.h; sourceTree = "<group>"; };
 		CDA37D4229D9D417000A1F97 /* iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = "<group>"; };
 		CDA37D4329D9D434000A1F97 /* view.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = view.h; sourceTree = "<group>"; };
-		CDA37D4429D9D55D000A1F97 /* stream_test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stream_test.h; sourceTree = "<group>"; };
+		CDA37D4429D9D55D000A1F97 /* stream_matchers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stream_matchers.h; sourceTree = "<group>"; };
 		CDA37D4C29DA2150000A1F97 /* count_if.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = count_if.h; sourceTree = "<group>"; };
 		CDA37D4D29DA217C000A1F97 /* any_of.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = any_of.h; sourceTree = "<group>"; };
 		CDA37D4E29DA2186000A1F97 /* all_of.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = all_of.h; sourceTree = "<group>"; };
@@ -215,7 +216,8 @@
 			isa = PBXGroup;
 			children = (
 				CD64CCB926232D6900770A30 /* xcode_gtest_helper.h */,
-				CDA37D4429D9D55D000A1F97 /* stream_test.h */,
+				CDA37D4429D9D55D000A1F97 /* stream_matchers.h */,
+				CD5A559429DCD12300881E7E /* stream_helpers.h */,
 				CD9337281E3CD78B00699FF5 /* stream_test.cxx */,
 				CDA37D3E29D9D38E000A1F97 /* all_test.cxx */,
 				CDA54F9D29DA59C4006C0FAA /* common_test.cxx */,

+ 2 - 2
test/all_test.cxx

@@ -7,9 +7,9 @@
 
 #include "stream/view/all.h"
 
-#include "stream_test.h"
+#include "stream_helpers.h"
+#include "stream_matchers.h"
 
-using testing::Eq;
 using testing::Ne;
 
 TEST(AllView, IteratesOverNonConst) {

+ 23 - 52
test/common_test.cxx

@@ -7,67 +7,46 @@
 
 #include "stream/view/common.h"
 
-#include <iterator/facade.h>
-#include <iterator/sentinel.h>
-
-#include "stream_test.h"
+#include "stream_helpers.h"
+#include "stream_matchers.h"
 
 using testing::StaticAssertTypeEq;
 
-struct SizedIterator : iterator::facade<SizedIterator> {
-private:
-  // Default constructed SizedIterator should not be a vaguely valid state.
-  size_t i_{~0ul};
-  size_t n_{~0ul};
-
-public:
-  SizedIterator() = default;
-  SizedIterator(size_t i, size_t n) : i_(i), n_(n) {}
-
-  size_t dereference() const { return i_; }
-  void advance(std::ptrdiff_t off) { i_ += off; }
-  // Bad detection requires us to provide this...
-  // TODO: See if I can use one of these tests to why...
-  bool equal_to(SizedIterator const & other) const { return other.i_ == i_; }
-  std::ptrdiff_t distance_to(SizedIterator const & other) const {
-    return other.i_ - i_;
-  }
-  bool at_end() const { return i_ >= n_; }
-};
-
-MAKE_ITERATOR_FACADE_TYPEDEFS(SizedIterator);
-
-struct SentinelRange {
-private:
-  size_t size_;
-
-public:
-  SentinelRange(size_t size = 0) : size_(size) {}
-
-  SizedIterator begin() const { return {0, size_}; }
-  auto end() const { return iterator::sentinel; }
-  bool empty() const { return size_ == 0; }
-  size_t size() const { return size_; }
-};
-
 TEST(CommonView, CoercesSentinelIntoCommon) {
-  SentinelRange input(10);
+  Range<std::vector<int>, Sentinel> input;
 
   auto range = input | views::common();
 
   StaticAssertTypeEq<decltype(range.begin()), decltype(range.end())>();
 }
 
+TEST(CommonView, DoesNotWrapNonSentinelTypes) {
+  Range<std::vector<int>, Common> input{0, 1, 2, 3, 4};
+
+  auto range = input | views::common();
+
+  StaticAssertTypeEq<decltype(input), decltype(range)>();
+}
+
 TEST(CommonView, IteratesThroughSameValues) {
-  SentinelRange input(10);
+  Range<std::vector<int>, Sentinel> input{0, 1, 2, 3, 4};
 
   auto range = input | views::common();
 
   EXPECT_THAT(range, RangesEq(input));
 }
 
+TEST(CommonView, NotRequiredToProvideSizeOrEmpty) {
+  Range<std::vector<int>, Sentinel> input{0, 1, 2, 3, 4};
+
+  auto range = input | views::common();
+
+  static_assert(!stream::detail::has_size_v<decltype(range)>);
+  static_assert(!stream::detail::has_empty_v<decltype(range)>);
+}
+
 TEST(CommonView, PropagatesSize) {
-  SentinelRange input(10);
+  Range<std::vector<int>, Sentinel, Sized> input{0, 1, 2, 3, 4};
 
   auto range = input | views::common();
 
@@ -76,18 +55,10 @@ TEST(CommonView, PropagatesSize) {
 }
 
 TEST(CommonView, PropagatesEmpty) {
-  SentinelRange input(10);
+  Range<std::vector<int>, Sentinel, Sized> input{0, 1, 2, 3, 4};
 
   auto range = input | views::common();
 
   static_assert(stream::detail::has_empty_v<decltype(range)>);
   EXPECT_THAT(range.empty(), input.empty());
 }
-
-TEST(CommonView, PassesNonSentinelTypes) {
-  std::vector<size_t> input(10);
-
-  auto range = input | views::common();
-
-  StaticAssertTypeEq<decltype(input), decltype(range)>();
-}

+ 76 - 0
test/stream_helpers.h

@@ -0,0 +1,76 @@
+//
+//  stream_helpers.h
+//  stream
+//
+//  Created by Sam Jaffe on 4/4/23.
+//
+
+#pragma once
+
+#include <iterator/end_aware_iterator.h>
+#include <iterator/proxy.h>
+#include <stream/detail/traits.h>
+
+namespace ranges = stream::ranges;
+namespace views = stream::ranges::views;
+
+#include <iterator/detail/macro.h>
+
+#define SELF() (*static_cast<CRTP const *>(this))
+
+/**
+ * There are the following types of iterators/containers that we are interested
+ * in:
+ * - Does the object use common iterators or sentinel iterators
+ * - Does the object have a size/empty
+ */
+
+template <typename It>
+class remaining_iterator : public iterator::end_aware_iterator<It> {
+public:
+  using super_t = iterator::end_aware_iterator<It>;
+
+public:
+  using super_t::super_t;
+
+  friend auto operator-(remaining_iterator const & it, iterator::sentinel_t) {
+    return std::distance(super_t::impl(), super_t::end());
+  }
+};
+
+MAKE_ITERATOR_FACADE_TYPEDEFS_T(remaining_iterator);
+
+template <typename CRTP> struct Sized {
+  size_t size() const { return SELF().impl().size(); }
+  bool empty() const { return SELF().impl().size() == 0; }
+};
+
+template <typename CRTP> struct Common {
+  auto begin() const { return SELF().impl().begin(); }
+  auto end() const { return SELF().impl().end(); }
+};
+
+template <typename CRTP> struct Sentinel {
+  auto begin() const { return iterator::end_aware_iterator(SELF().impl()); }
+  auto end() const { return iterator::sentinel; }
+};
+
+template <typename CRTP> struct SizedSentinel {
+  auto begin() const { return remaining_iterator(SELF().impl()); }
+  auto end() const { return iterator::sentinel; }
+};
+
+template <typename C, template <typename> class... Traits>
+class Range : public Traits<Range<C, Traits...>>... {
+private:
+  C impl_;
+
+public:
+  Range() = default;
+  Range(C impl) : impl_(std::move(impl)) {}
+  template <typename T> Range(std::initializer_list<T> init) : impl_(init) {}
+
+  auto & impl() const { return impl_; }
+};
+
+#include <iterator/detail/undef.h>

+ 29 - 0
test/stream_matchers.h

@@ -0,0 +1,29 @@
+//
+//  stream_test.h
+//  stream
+//
+//  Created by Sam Jaffe on 4/2/23.
+//
+
+#pragma once
+
+#include "xcode_gtest_helper.h"
+
+MATCHER_P(RangesEq, to_range, "") {
+  auto it1 = arg.begin();
+  auto end1 = arg.end();
+  auto it2 = to_range.begin();
+  auto end2 = to_range.end();
+
+  size_t n = 0;
+  for (; it1 != end1 && it2 != end2; ++it1, ++it2, ++n) {
+    if (*it1 != *it2) {
+      *result_listener << "at index " << n << " where values were: [" << *it1
+                       << "," << *it2 << "] differ";
+      return false;
+    }
+  }
+
+  *result_listener << "whose sizes differ";
+  return (it1 == end1) && (it2 == end2);
+}

+ 0 - 39
test/stream_test.h

@@ -1,39 +0,0 @@
-//
-//  stream_test.h
-//  stream
-//
-//  Created by Sam Jaffe on 4/2/23.
-//
-
-#pragma once
-
-#include "xcode_gtest_helper.h"
-
-namespace ranges = stream::ranges;
-namespace views = stream::ranges::views;
-
-namespace stream::ranges::testing {
-template <typename It1, typename S1, typename It2, typename S2,
-          typename Cmp = std::equal_to<>>
-bool equal(It1 it1, S1 end1, It2 it2, S2 end2,
-           ::testing::MatchResultListener * result_listener, Cmp cmp = {}) {
-  size_t n = 0;
-  for (; it1 != end1 && it2 != end2; ++it1, ++it2, ++n) {
-    auto const & left = *it1;
-    auto const & right = *it2;
-    if (!std::invoke(cmp, left, right)) {
-      *result_listener << "at index " << n << " where values were: [" << left
-                       << "," << right << "] differ";
-      return false;
-    }
-  }
-  *result_listener << "whose sizes differ";
-  return (it1 == end1) && (it2 == end2);
-}
-}
-
-MATCHER_P(RangesEq, to_range, "") {
-  return stream::ranges::testing::equal(arg.begin(), arg.end(),
-                                        to_range.begin(), to_range.end(),
-                                        result_listener);
-}