Przeglądaj źródła

Improve test structuring.
Fix handling of string-is-terminal

Sam Jaffe 5 lat temu
rodzic
commit
d70bf7f09a

+ 11 - 4
include/iterator/detail/recursive_iterator_traits.hpp

@@ -56,17 +56,24 @@ namespace iterator { namespace detail {
     static constexpr typeclass const value{typeclass::TERMINAL};
   };
 
+  template <typename T> struct is_string_iterator : std::false_type {};
   template <>
-  struct typeclass_t<typename std::string::iterator> : typeclass_t<void> {};
+  struct is_string_iterator<std::string::iterator> : std::true_type {};
   template <>
-  struct typeclass_t<typename std::string::const_iterator> : typeclass_t<void> {
-  };
+  struct is_string_iterator<std::string::const_iterator> : std::true_type {};
 
   template <typename T>
-  struct typeclass_t<T, typename void_t<value_iterator<T>>::type> {
+  struct typeclass_t<
+      T, std::enable_if_t<!is_string_iterator<value_iterator<T>>::value>> {
     static constexpr typeclass const value{typeclass::CONTAINER};
   };
 
+  template <typename T>
+  struct typeclass_t<
+      T, std::enable_if_t<is_string_iterator<value_iterator<T>>::value>> {
+    static constexpr typeclass const value{typeclass::TERMINAL};
+  };
+
   template <typename T>
   struct typeclass_t<T, typename void_t<mapped_iterator<T>>::type> {
     static constexpr typeclass const value{typeclass::ASSOCIATIVE_CONTAINER};

+ 4 - 0
iterator.xcodeproj/project.pbxproj

@@ -17,6 +17,7 @@
 		CDCB3BDC24E1D5320029B771 /* filter_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD324E1D5320029B771 /* filter_iterator_test.cxx */; };
 		CDCB3BDD24E1D5320029B771 /* indexed_iterator_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD424E1D5320029B771 /* indexed_iterator_test.cxx */; };
 		CDCB3BDE24E1D5320029B771 /* recursive_iterator_map_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */; };
+		CDCB3BFC24E327CF0029B771 /* recursive_iterator_single_level_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -83,6 +84,7 @@
 		CDCB3BD324E1D5320029B771 /* filter_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filter_iterator_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD424E1D5320029B771 /* indexed_iterator_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indexed_iterator_test.cxx; sourceTree = "<group>"; };
 		CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_map_test.cxx; sourceTree = "<group>"; };
+		CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = recursive_iterator_single_level_test.cxx; sourceTree = "<group>"; };
 		CDEC1E01235167920091D9F2 /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -137,6 +139,7 @@
 				CDCB3BD124E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx */,
 				CDCB3BD524E1D5320029B771 /* recursive_iterator_map_test.cxx */,
 				CDCB3BCF24E1D5320029B771 /* recursive_iterator_vector_test.cxx */,
+				CDCB3BFB24E327CF0029B771 /* recursive_iterator_single_level_test.cxx */,
 				CDCB3BCE24E1D5320029B771 /* unkeyed_iterator_test.cxx */,
 			);
 			path = test;
@@ -338,6 +341,7 @@
 				CDCB3BD724E1D5320029B771 /* unkeyed_iterator_test.cxx in Sources */,
 				CDCB3BDA24E1D5320029B771 /* recursive_iterator_mixed_container_test.cxx in Sources */,
 				CDCB3BD924E1D5320029B771 /* recursive_iterator_accessors_test.cxx in Sources */,
+				CDCB3BFC24E327CF0029B771 /* recursive_iterator_single_level_test.cxx in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 25 - 18
test/recursive_iterator_accessors_test.cxx

@@ -1,11 +1,18 @@
 #include "iterator/recursive_iterator.hpp"
 
 #include <map>
+#include <string>
+#include <tuple>
 #include <vector>
 
 #include <gmock/gmock.h>
 
-// TODO: std::string should not be unwrapped
+TEST(RecursiveIteratorTest, DoesNotUnwrapString) {
+  std::vector<std::string> obj{"A", "B", "C", "D"};
+  auto rit = make_recursive_iterator(obj);
+  testing::StaticAssertTypeEq<decltype(rit.operator->()), std::string *>();
+}
+
 TEST(RecursiveIteratorTest, CanArrowMultiVector) {
   std::vector<std::vector<int>> obj{{{0, 1}}, {{2, 3}}};
   auto rit = make_recursive_iterator(obj);
@@ -39,17 +46,17 @@ TEST(RecursiveIteratorTest, CanStdGetToAllLayersOfInternalIteration) {
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
   auto rit = make_recursive_iterator(obj);
-  testing::StaticAssertTypeEq<
-      decltype(std::get<0>(rit)),
-      iterator::end_aware_iterator<decltype(obj)::iterator>>();
+  using mvm_iterator = std::map<int, std::vector<std::map<int, int>>>::iterator;
+  testing::StaticAssertTypeEq<decltype(std::get<0>(rit)),
+                              iterator::end_aware_iterator<mvm_iterator>>();
+  using vm_iterator = std::vector<std::map<int, int>>::iterator;
   testing::StaticAssertTypeEq<decltype(std::get<1>(rit)),
-                              iterator::end_aware_iterator<
-                                  std::vector<std::map<int, int>>::iterator>>();
-  testing::StaticAssertTypeEq<
-      decltype(std::get<2>(rit)),
-      iterator::end_aware_iterator<std::map<int, int>::iterator>>();
-  testing::StaticAssertTypeEq<decltype(*rit),
-                              std::tuple<int const &, int const &, int &>>();
+                              iterator::end_aware_iterator<vm_iterator>>();
+  using m_iterator = std::map<int, int>::iterator;
+  testing::StaticAssertTypeEq<decltype(std::get<2>(rit)),
+                              iterator::end_aware_iterator<m_iterator>>();
+  using tup_i_i_i = std::tuple<int const &, int const &, int &>;
+  testing::StaticAssertTypeEq<decltype(*rit), tup_i_i_i>();
 }
 
 TEST(RecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {
@@ -91,14 +98,14 @@ TEST(BoundedRecursiveIteratorTest, CanStdGetToNLayersOfInternalIteration) {
       {2, {{{3, 3}, {4, 4}}}}    // 1 2-element map
   };
   auto rit = make_recursive_iterator<2>(obj);
-  testing::StaticAssertTypeEq<
-      decltype(std::get<0>(rit)),
-      iterator::end_aware_iterator<decltype(obj)::iterator>>();
+  using mvm_iterator = std::map<int, std::vector<std::map<int, int>>>::iterator;
+  testing::StaticAssertTypeEq<decltype(std::get<0>(rit)),
+                              iterator::end_aware_iterator<mvm_iterator>>();
+  using vm_iterator = std::vector<std::map<int, int>>::iterator;
   testing::StaticAssertTypeEq<decltype(std::get<1>(rit)),
-                              iterator::end_aware_iterator<
-                                  std::vector<std::map<int, int>>::iterator>>();
-  testing::StaticAssertTypeEq<decltype(*rit),
-                              std::tuple<int const &, std::map<int, int> &>>();
+                              iterator::end_aware_iterator<vm_iterator>>();
+  using tup_i_mii = std::tuple<int const &, std::map<int, int> &>;
+  testing::StaticAssertTypeEq<decltype(*rit), tup_i_mii>();
 }
 
 TEST(BoundedRecursiveIteratorTest, CanAccessInternalIteratorsWithGet) {

+ 34 - 42
test/recursive_iterator_map_test.cxx

@@ -6,64 +6,56 @@
 
 #include <gmock/gmock.h>
 
-TEST(RecursiveIteratorSingleMapTest, IterDistanceIsContainerSize) {
-  std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+TEST(RecursiveIteratorMapTest, IterDistanceIsSumOfInnerContainerSizes) {
+  std::map<int, std::map<int, std::map<int, int>>> const map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
   auto rit = make_recursive_iterator(map);
   decltype(rit) end{};
-  EXPECT_THAT(std::distance(rit, end), map.size());
+  // TODO: Actually perform the summation?
+  EXPECT_THAT(std::distance(rit, end), 4);
 }
 
-TEST(RecursiveIteratorSingleMapTest, DataMatchesContainerIterator) {
-  std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+TEST(RecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
+  std::map<int, std::map<int, std::map<int, int>>> const map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
+  std::vector<std::tuple<int, int, int, int>> const expected{
+      {1, 1, 1, 1}, {2, 2, 2, 2}, {2, 3, 3, 3}, {2, 3, 4, 4}};
   auto rit = make_recursive_iterator(map);
-  decltype(map) result(rit, decltype(rit)());
-  EXPECT_THAT(result, map);
+  decltype(expected) result(rit, decltype(rit)());
+  EXPECT_THAT(result, expected);
 }
 
-TEST(RecursiveIteratorSingleMapTest, CanMutatePointedToData) {
-  std::map<int, int> map{{1, 1}, {2, 2}, {3, 3}};
+TEST(RecursiveIteratorMapTest, CanMutatePointedToData) {
+  std::map<int, std::map<int, std::map<int, int>>> map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
   auto rit = make_recursive_iterator(map);
-  std::get<1>(*rit) = 4;
-  EXPECT_THAT(map[1], 4);
+  std::get<3>(*rit) = 4;
+  EXPECT_THAT(map[1][1][1], 4);
 }
 
-TEST(RecursiveIteratorMapMapTest, IterDistanceIsSumOfInnerContainerSizes) {
-  std::map<int, std::map<int, int>> const map{{1, {{1, 1}}},
-                                              {2, {{2, 2}, {3, 3}}}};
-  auto rit = make_recursive_iterator(map);
+TEST(BoundRecursiveIteratorMapTest, IterDistanceSumOnNLayersSize) {
+  std::map<int, std::map<int, std::map<int, int>>> const map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
+  auto rit = make_recursive_iterator<2>(map);
   decltype(rit) end{};
-  // TODO: Actually perform the summation?
+
   EXPECT_THAT(std::distance(rit, end), 3);
 }
 
-TEST(RecursiveIteratorMapMapTest, ElementsAreUnwrappedAsATuple) {
-  std::map<int, std::map<int, int>> const map{{1, {{1, 1}}},
-                                              {2, {{2, 2}, {3, 3}}}};
-  std::vector<std::tuple<int, int, int>> const expected{
-      {1, 1, 1}, {2, 2, 2}, {2, 3, 3}};
-  auto rit = make_recursive_iterator(map);
+TEST(BoundRecursiveIteratorMapTest, ElementsAreUnwrappedAsATuple) {
+  std::map<int, std::map<int, std::map<int, int>>> const map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
+  std::vector<std::tuple<int, int, std::map<int, int>>> const expected{
+      {1, 1, {{1, 1}}}, {2, 2, {{2, 2}}}, {2, 3, {{3, 3}, {4, 4}}}};
+  auto rit = make_recursive_iterator<2>(map);
   decltype(expected) result(rit, decltype(rit)());
   EXPECT_THAT(result, expected);
 }
 
-TEST(RecursiveIteratorMapMapTest, CanMutatePointedToData) {
-  std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
-  auto rit = make_recursive_iterator(map);
-  std::get<2>(*rit) = 4;
-  EXPECT_THAT(map[1][1], 4);
-}
-
-TEST(BoundRecursiveIteratorMapMapTest, IterDistanceSumOnNLayersSize) {
-  std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
-  auto rit = make_recursive_iterator<1>(map);
-  decltype(rit) end{};
-
-  EXPECT_THAT(std::distance(rit, end), map.size());
-}
-
-TEST(BoundRecursiveIteratorMapMapTest, ElementsAreUnwrappedAsATuple) {
-  std::map<int, std::map<int, int>> map{{1, {{1, 1}}}, {2, {{2, 2}, {3, 3}}}};
-  auto rit = make_recursive_iterator<1>(map);
-  decltype(map) result(rit, decltype(rit)());
-  EXPECT_THAT(result, map);
+TEST(BoundedRecursiveIteratorMapTest, CanMutatePointedToData) {
+  std::map<int, std::map<int, std::map<int, int>>> map{
+      {1, {{1, {{1, 1}}}}}, {2, {{2, {{2, 2}}}, {3, {{3, 3}, {4, 4}}}}}};
+  auto rit = make_recursive_iterator<2>(map);
+  std::get<2>(*rit).clear();
+  EXPECT_THAT(map[1][1], testing::IsEmpty());
 }

+ 56 - 0
test/recursive_iterator_single_level_test.cxx

@@ -0,0 +1,56 @@
+//
+//  recursive_iterator_single_level_test.cxx
+//  iterator-test
+//
+//  Created by Sam Jaffe on 8/11/20.
+//  Copyright © 2020 Sam Jaffe. All rights reserved.
+//
+
+#include "iterator/recursive_iterator.hpp"
+
+#include <map>
+#include <vector>
+
+#include <gmock/gmock.h>
+
+TEST(RecursiveIteratorSingleVectorTest, IterDistanceIsContainerSize) {
+  std::vector<int> const vec{1, 2, 3, 4, 5};
+  auto rit = make_recursive_iterator(vec);
+  decltype(rit) end{};
+  EXPECT_THAT(std::distance(rit, end), vec.size());
+}
+
+TEST(RecursiveIteratorSingleVectorTest, DataMatchesContainerIterator) {
+  std::vector<int> const vec{1, 2, 3, 4, 5};
+  auto rit = make_recursive_iterator(vec);
+  decltype(vec) result(rit, decltype(rit)());
+  EXPECT_THAT(result, vec);
+}
+
+TEST(RecursiveIteratorSingleVectorTest, CanMutatePointedToData) {
+  std::vector<int> vec{1, 2, 3, 4, 5};
+  auto rit = make_recursive_iterator(vec);
+  *rit = 6;
+  EXPECT_THAT(vec[0], 6);
+}
+
+TEST(RecursiveIteratorSingleMapTest, IterDistanceIsContainerSize) {
+  std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+  auto rit = make_recursive_iterator(map);
+  decltype(rit) end{};
+  EXPECT_THAT(std::distance(rit, end), map.size());
+}
+
+TEST(RecursiveIteratorSingleMapTest, DataMatchesContainerIterator) {
+  std::map<int, int> const map{{1, 1}, {2, 2}, {3, 3}};
+  auto rit = make_recursive_iterator(map);
+  decltype(map) result(rit, decltype(rit)());
+  EXPECT_THAT(result, map);
+}
+
+TEST(RecursiveIteratorSingleMapTest, CanMutatePointedToData) {
+  std::map<int, int> map{{1, 1}, {2, 2}, {3, 3}};
+  auto rit = make_recursive_iterator(map);
+  std::get<1>(*rit) = 4;
+  EXPECT_THAT(map[1], 4);
+}

+ 24 - 38
test/recursive_iterator_vector_test.cxx

@@ -4,30 +4,8 @@
 
 #include <gmock/gmock.h>
 
-TEST(RecursiveIteratorSingleVectorTest, IterDistanceIsContainerSize) {
-  std::vector<int> const vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
-  decltype(rit) end{};
-  EXPECT_THAT(std::distance(rit, end), vec.size());
-}
-
-TEST(RecursiveIteratorSingleVectorTest, ElementsAreUnwrappedAsATuple) {
-  std::vector<int> const vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
-  decltype(vec) result(rit, decltype(rit)());
-  EXPECT_THAT(result, vec);
-}
-
-TEST(RecursiveIteratorSingleVectorTest, CanMutatePointedToData) {
-  std::vector<int> vec{1, 2, 3, 4, 5};
-  auto rit = make_recursive_iterator(vec);
-  *rit = 6;
-  EXPECT_THAT(vec[0], 6);
-}
-
-TEST(RecursiveIteratorVectorVectorTest,
-     IterDistanceIsSumOfInnerContainerSizes) {
-  std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+TEST(RecursiveIteratorVecTest, IterDistanceIsSumOfInnerContainerSizes) {
+  std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
   auto rit = make_recursive_iterator(vec);
   decltype(rit) end{};
 
@@ -35,32 +13,40 @@ TEST(RecursiveIteratorVectorVectorTest,
   EXPECT_THAT(std::distance(rit, end), 5);
 }
 
-TEST(RecursiveIteratorVectorVectorTest, ElementsAreUnwrappedAsATuple) {
-  std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
+TEST(RecursiveIteratorVecTest, FlattensVectorDataLikeJoinIterator) {
+  std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
   std::vector<int> const expected{1, 2, 3, 4, 5};
   auto rit = make_recursive_iterator(vec);
   decltype(expected) result(rit, decltype(rit)());
   EXPECT_THAT(result, expected);
 }
 
-TEST(RecursiveIteratorVectorVectorTest, CanMutatePointedToData) {
-  std::vector<std::vector<int>> vec{{1, 2}, {3, 4, 5}};
+TEST(RecursiveIteratorVecTest, CanMutatePointedToData) {
+  std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
   auto rit = make_recursive_iterator(vec);
   *rit = 6;
-  EXPECT_THAT(vec[0][0], 6);
+  EXPECT_THAT(vec[0][0][0], 6);
 }
 
-TEST(BoundedRecursiveIteratorVectorVectorTest, IterDistanceSumOnNLayersSize) {
-  std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
-  auto rit = make_recursive_iterator<1>(vec);
+TEST(BoundedRecursiveIteratorVecTest, IterDistanceSumOnNLayersSize) {
+  std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
+  auto rit = make_recursive_iterator<2>(vec);
   decltype(rit) end{};
 
-  EXPECT_THAT(std::distance(rit, end), vec.size());
+  EXPECT_THAT(std::distance(rit, end), 3);
+}
+
+TEST(BoundedRecursiveIteratorVecTest, ElementsAreUnwrappedAsATuple) {
+  std::vector<std::vector<std::vector<int>>> const vec{{{1, 2}}, {{3}, {4, 5}}};
+  std::vector<std::vector<int>> const expected{{1, 2}, {3}, {4, 5}};
+  auto rit = make_recursive_iterator<2>(vec);
+  decltype(expected) result(rit, decltype(rit)());
+  EXPECT_THAT(result, expected);
 }
 
-TEST(BoundedRecursiveIteratorVectorVectorTest, ElementsAreUnwrappedAsATuple) {
-  std::vector<std::vector<int>> const vec{{1, 2}, {3, 4, 5}};
-  auto rit = make_recursive_iterator<1>(vec);
-  decltype(vec) result(rit, decltype(rit)());
-  EXPECT_THAT(result, vec);
+TEST(BoundedRecursiveIteratorVecTest, CanMutatePointedToData) {
+  std::vector<std::vector<std::vector<int>>> vec{{{1, 2}}, {{3}, {4, 5}}};
+  auto rit = make_recursive_iterator<2>(vec);
+  rit->clear();
+  EXPECT_THAT(vec[0][0], testing::IsEmpty());
 }