TestPartition.cxx
Go to the documentation of this file.
1 /*===========================================================================================================
2  *
3  * SHA - Simple Hybesis Algorithms
4  *
5  * Copyright (c) Michael Jeulin-Lagarrigue
6  *
7  * Licensed under the MIT License, you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * https://github.com/michael-jeulinl/Simple-Hybesis-Algorithms/blob/master/LICENSE
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License is
13  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and limitations under the License.
15  *
16  * The above copyright notice and this permission notice shall be included in all copies or
17  * substantial portions of the Software.
18  *
19  *=========================================================================================================*/
20 #include <gtest/gtest.h>
21 #include <partition.hxx>
22 
23 // STD includes
24 #include <functional>
25 #include <vector>
26 #include <string>
27 
28 // Testing namespace
29 using namespace SHA_Sort;
30 
31 #ifndef DOXYGEN_SKIP
32 namespace {
33  // Simple sorted array of integers with negative values
34  const int SortedArrayInt[] = {-3, -2, 0, 2, 8, 15, 36, 212, 366};
35  // Simple sorted array of integers with negative values
36  const int InvSortedArrayInt[] = {366, 212, 36, 15, 8, 2, 0, -2, -3};
37  // Simple random array of integers with negative values
38  const int RandomArrayInt[] = {4, 3, 5, 2, -18, 3, 2, 3, 4, 5, -5};
39  // Random string
40  const std::string RandomStr = "xacvgeze";
41 
42  typedef std::vector<int> Container;
43  typedef Container::iterator IT;
44  typedef std::greater_equal<IT::value_type> GE_Compare;
45 
46  template<typename IT>
47  void CheckPartition (const IT& begin, const IT& end, const IT& newPivot,
48  typename std::iterator_traits<IT>::value_type pivotVal, bool inOrder = true)
49  {
50  // Value of the pivot not changed
51  EXPECT_EQ(pivotVal, *newPivot);
52 
53  // All elements before the pivot are smaller or equal
54  if (inOrder)
55  for (auto it = begin; it < newPivot; ++it)
56  EXPECT_GE(pivotVal, *it);
57  else
58  for (auto it = begin; it < newPivot; ++it)
59  EXPECT_LE(pivotVal, *it);
60 
61  // All elements before the pivot are bigger or equal
62  if (inOrder)
63  for (auto it = newPivot; it < end; ++it)
64  EXPECT_LE(pivotVal, *it);
65  else
66  for (auto it = newPivot; it < end; ++it)
67  EXPECT_GE(pivotVal, *it);
68  }
69 }
70 #endif /* DOXYGEN_SKIP */
71 
72 // Basic Partition tests
73 TEST(TestPartition, Partitions)
74 {
75  // Normal Run - Random Array
76  {
77  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
78  auto pivot = randomdArray.begin() + 5;
79  auto pivotVal = *pivot;
80 
81  // Run partition - Should result in: max[begin, pivot[ <= pivot <= min]pivot, end]
82  auto newPivot = Partition<IT>(randomdArray.begin(), pivot, randomdArray.end());
83  CheckPartition<IT>(randomdArray.begin(), randomdArray.end(), newPivot, pivotVal);
84  }
85 
86  // Already sortedArray - Array should not be affected
87  {
88  Container sortedArray(SortedArrayInt, SortedArrayInt + sizeof(SortedArrayInt) / sizeof(int));
89  auto pivot = sortedArray.begin() + 5;
90 
91  Partition<IT>(sortedArray.begin(), pivot, sortedArray.end());
92 
93  int i = 0;
94  for (auto it = sortedArray.begin(); it < sortedArray.end(); ++it, ++i)
95  EXPECT_EQ(SortedArrayInt[i], *it);
96  }
97 
98  // Begin and End inversed - Array should not be affected
99  {
100  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
101  auto pivot = randomdArray.begin() + 5;
102 
103  Partition<IT>(randomdArray.end(), pivot, randomdArray.begin());
104 
105  int i = 0;
106  for (auto it = randomdArray.begin(); it < randomdArray.end(); ++it, ++i)
107  EXPECT_EQ(RandomArrayInt[i], *it);
108  }
109 }
110 
111 // String collection - Should result in: max[begin, pivot[ <= pivot <= min]pivot, end]
112 TEST(TestPartition, PartitionString)
113 {
114  std::string randomStr = RandomStr;
115  auto pivot = randomStr.begin() + 5;
116  auto pivotVal = *pivot;
117 
118  auto newPivot = Partition<std::string::iterator>(randomStr.begin(), pivot, randomStr.end());
119  CheckPartition<std::string::iterator>(randomStr.begin(), randomStr.end(), newPivot, pivotVal);
120 }
121 
122 // Extreme Pivot Partition tests
123 TEST(TestPartition, PartitionBoudaryPivots)
124 {
125  // Pivot choose as begin
126  {
127  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
128  auto pivot = randomdArray.begin();
129  const int pivotVal = *pivot;
130 
131  // Run partition
132  auto newPivot = Partition<IT>(randomdArray.begin(), pivot, randomdArray.end());
133  CheckPartition<IT>(randomdArray.begin(), randomdArray.end(), newPivot, pivotVal);
134 
135  }
136 
137  // Pivot choose as last element
138  {
139  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
140  auto pivot = randomdArray.end() - 1;
141  const int pivotVal = *pivot;
142 
143  // Run partition
144  auto newPivot = Partition<IT>(randomdArray.begin(), pivot, randomdArray.end());
145  CheckPartition<IT>(randomdArray.begin(), randomdArray.end(), newPivot, pivotVal);
146  }
147 
148  // Pivot choose as end - cannot process
149  {
150  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
151  auto pivot = randomdArray.end();
152 
153  // Run partition
154  Partition<IT>(randomdArray.begin(), pivot, randomdArray.end());
155 
156  int i = 0;
157  for (auto it = randomdArray.begin(); it < randomdArray.end(); ++it, ++i)
158  EXPECT_EQ(RandomArrayInt[i], *it);
159  }
160 }
161 
162 // Basic Partition tests - Greater element in the left partition
163 TEST(TestPartition, PartitionGreaterComparator)
164 {
165  // Normal Run - Should result in: min[begin, pivot[ >= pivot >= max]pivot, end]
166  {
167  Container randomdArray(RandomArrayInt, RandomArrayInt + sizeof(RandomArrayInt) / sizeof(int));
168  auto pivot = randomdArray.begin() + 5;
169  const auto pivotVal = *pivot;
170 
171  // Run partition
172  auto newPivot = Partition<IT, GE_Compare>(randomdArray.begin(), pivot, randomdArray.end());
173  CheckPartition<IT>(randomdArray.begin(), randomdArray.end(), newPivot, pivotVal, false);
174  }
175 
176  // Already InverseSortedArray - Array should not be affected
177  {
178  Container invSortedArray(InvSortedArrayInt, InvSortedArrayInt + sizeof(InvSortedArrayInt) / sizeof(int));
179  auto pivot = invSortedArray.begin() + 5;
180 
181  Partition<IT, GE_Compare>(invSortedArray.begin(), pivot, invSortedArray.end());
182 
183  int i = 0;
184  for (auto it = invSortedArray.begin(); it < invSortedArray.end(); ++it, ++i)
185  EXPECT_EQ(invSortedArray[i], *it);
186  }
187 
188  // String collection - Should result in: min[begin, pivot[ >= pivot >= max]pivot, end]
189  {
190  std::string randomStr = RandomStr;
191  auto pivot = randomStr.begin() + 5;
192  const auto pivotVal = *pivot;
193 
194  // Run partition
195  auto newPivot = Partition<std::string::iterator, std::greater_equal<char>>(randomStr.begin(), pivot, randomStr.end());
196  CheckPartition<std::string::iterator>(randomStr.begin(), randomStr.end(), newPivot, pivotVal, false);
197  }
198 }
TEST(TestPartition, Partitions)