]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/arrow/cpp/src/arrow/stl_iterator_test.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / stl_iterator_test.cc
diff --git a/ceph/src/arrow/cpp/src/arrow/stl_iterator_test.cc b/ceph/src/arrow/cpp/src/arrow/stl_iterator_test.cc
new file mode 100644 (file)
index 0000000..864011d
--- /dev/null
@@ -0,0 +1,252 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <algorithm>
+#include <cstdint>
+
+#include <gtest/gtest.h>
+
+#include "arrow/stl.h"
+#include "arrow/stl_iterator.h"
+#include "arrow/testing/gtest_util.h"
+#include "arrow/type.h"
+#include "arrow/util/checked_cast.h"
+
+namespace arrow {
+
+using internal::checked_cast;
+using internal::checked_pointer_cast;
+using util::nullopt;
+using util::optional;
+
+namespace stl {
+
+TEST(ArrayIterator, Basics) {
+  auto array =
+      checked_pointer_cast<Int32Array>(ArrayFromJSON(int32(), "[4, 5, null, 6]"));
+
+  ArrayIterator<Int32Array> it(*array);
+  optional<int32_t> v = *it;
+  ASSERT_EQ(v, 4);
+  ASSERT_EQ(it[0], 4);
+  ++it;
+  ASSERT_EQ(it[0], 5);
+  ASSERT_EQ(*it, 5);
+  ASSERT_EQ(it[1], nullopt);
+  ASSERT_EQ(it[2], 6);
+}
+
+TEST(ArrayIterator, Arithmetic) {
+  auto array = checked_pointer_cast<Int32Array>(
+      ArrayFromJSON(int32(), "[4, 5, null, 6, null, 7]"));
+
+  ArrayIterator<Int32Array> it(*array);
+  auto it2 = it + 2;
+  ASSERT_EQ(*it, 4);
+  ASSERT_EQ(*it2, nullopt);
+  ASSERT_EQ(it2 - it, 2);
+  ASSERT_EQ(it - it2, -2);
+  auto it3 = it++;
+  ASSERT_EQ(it2 - it, 1);
+  ASSERT_EQ(it2 - it3, 2);
+  ASSERT_EQ(*it3, 4);
+  ASSERT_EQ(*it, 5);
+  auto it4 = ++it;
+  ASSERT_EQ(*it, nullopt);
+  ASSERT_EQ(*it4, nullopt);
+  ASSERT_EQ(it2 - it, 0);
+  ASSERT_EQ(it2 - it4, 0);
+  auto it5 = it + 3;
+  ASSERT_EQ(*it5, 7);
+  ASSERT_EQ(*(it5 - 2), 6);
+  ASSERT_EQ(*(it5 + (-2)), 6);
+  auto it6 = (--it5)--;
+  ASSERT_EQ(*it6, nullopt);
+  ASSERT_EQ(*it5, 6);
+  ASSERT_EQ(it6 - it5, 1);
+}
+
+TEST(ArrayIterator, Comparison) {
+  auto array = checked_pointer_cast<Int32Array>(
+      ArrayFromJSON(int32(), "[4, 5, null, 6, null, 7]"));
+
+  auto it = ArrayIterator<Int32Array>(*array) + 2;
+  auto it2 = ArrayIterator<Int32Array>(*array) + 2;
+  auto it3 = ArrayIterator<Int32Array>(*array) + 4;
+
+  ASSERT_TRUE(it == it2);
+  ASSERT_TRUE(it <= it2);
+  ASSERT_TRUE(it >= it2);
+  ASSERT_FALSE(it != it2);
+  ASSERT_FALSE(it < it2);
+  ASSERT_FALSE(it > it2);
+
+  ASSERT_FALSE(it == it3);
+  ASSERT_TRUE(it <= it3);
+  ASSERT_FALSE(it >= it3);
+  ASSERT_TRUE(it != it3);
+  ASSERT_TRUE(it < it3);
+  ASSERT_FALSE(it > it3);
+}
+
+TEST(ArrayIterator, BeginEnd) {
+  auto array =
+      checked_pointer_cast<Int32Array>(ArrayFromJSON(int32(), "[4, 5, null, 6]"));
+  std::vector<optional<int32_t>> values;
+  for (auto it = array->begin(); it != array->end(); ++it) {
+    values.push_back(*it);
+  }
+  std::vector<optional<int32_t>> expected{4, 5, {}, 6};
+  ASSERT_EQ(values, expected);
+}
+
+TEST(ArrayIterator, RangeFor) {
+  auto array =
+      checked_pointer_cast<Int32Array>(ArrayFromJSON(int32(), "[4, 5, null, 6]"));
+  std::vector<optional<int32_t>> values;
+  for (const auto v : *array) {
+    values.push_back(v);
+  }
+  std::vector<optional<int32_t>> expected{4, 5, {}, 6};
+  ASSERT_EQ(values, expected);
+}
+
+TEST(ArrayIterator, String) {
+  auto array = checked_pointer_cast<StringArray>(
+      ArrayFromJSON(utf8(), R"(["foo", "bar", null, "quux"])"));
+  std::vector<optional<util::string_view>> values;
+  for (const auto v : *array) {
+    values.push_back(v);
+  }
+  std::vector<optional<util::string_view>> expected{"foo", "bar", {}, "quux"};
+  ASSERT_EQ(values, expected);
+}
+
+TEST(ArrayIterator, Boolean) {
+  auto array = checked_pointer_cast<BooleanArray>(
+      ArrayFromJSON(boolean(), "[true, null, null, false]"));
+  std::vector<optional<bool>> values;
+  for (const auto v : *array) {
+    values.push_back(v);
+  }
+  std::vector<optional<bool>> expected{true, {}, {}, false};
+  ASSERT_EQ(values, expected);
+}
+
+TEST(ArrayIterator, FixedSizeBinary) {
+  auto array = checked_pointer_cast<FixedSizeBinaryArray>(
+      ArrayFromJSON(fixed_size_binary(3), R"(["foo", "bar", null, "quu"])"));
+  std::vector<optional<util::string_view>> values;
+  for (const auto v : *array) {
+    values.push_back(v);
+  }
+  std::vector<optional<util::string_view>> expected{"foo", "bar", {}, "quu"};
+  ASSERT_EQ(values, expected);
+}
+
+// Test compatibility with various STL algorithms
+
+TEST(ArrayIterator, StdFind) {
+  auto array = checked_pointer_cast<StringArray>(
+      ArrayFromJSON(utf8(), R"(["foo", "bar", null, "quux"])"));
+
+  auto it = std::find(array->begin(), array->end(), "bar");
+  ASSERT_EQ(it.index(), 1);
+  it = std::find(array->begin(), array->end(), nullopt);
+  ASSERT_EQ(it.index(), 2);
+  it = std::find(array->begin(), array->end(), "zzz");
+  ASSERT_EQ(it, array->end());
+}
+
+TEST(ArrayIterator, StdCountIf) {
+  auto array = checked_pointer_cast<BooleanArray>(
+      ArrayFromJSON(boolean(), "[true, null, null, false]"));
+
+  auto n = std::count_if(array->begin(), array->end(),
+                         [](optional<bool> v) { return !v.has_value(); });
+  ASSERT_EQ(n, 2);
+}
+
+TEST(ArrayIterator, StdCopy) {
+  auto array = checked_pointer_cast<BooleanArray>(
+      ArrayFromJSON(boolean(), "[true, null, null, false]"));
+  std::vector<optional<bool>> values;
+  std::copy(array->begin() + 1, array->end(), std::back_inserter(values));
+  std::vector<optional<bool>> expected{{}, {}, false};
+  ASSERT_EQ(values, expected);
+}
+
+TEST(ArrayIterator, StdPartitionPoint) {
+  auto array = checked_pointer_cast<DoubleArray>(
+      ArrayFromJSON(float64(), "[4.5, 2.5, 1e100, 3, null, null, null, null, null]"));
+  auto it = std::partition_point(array->begin(), array->end(),
+                                 [](optional<double> v) { return v.has_value(); });
+  ASSERT_EQ(it.index(), 4);
+  ASSERT_EQ(*it, nullopt);
+
+  array =
+      checked_pointer_cast<DoubleArray>(ArrayFromJSON(float64(), "[null, null, null]"));
+  it = std::partition_point(array->begin(), array->end(),
+                            [](optional<double> v) { return v.has_value(); });
+  ASSERT_EQ(it, array->begin());
+  it = std::partition_point(array->begin(), array->end(),
+                            [](optional<double> v) { return !v.has_value(); });
+  ASSERT_EQ(it, array->end());
+}
+
+TEST(ArrayIterator, StdEqualRange) {
+  auto array = checked_pointer_cast<Int8Array>(
+      ArrayFromJSON(int8(), "[1, 4, 5, 5, 5, 7, 8, null, null, null]"));
+  auto cmp_lt = [](optional<int8_t> u, optional<int8_t> v) {
+    return u.has_value() && (!v.has_value() || *u < *v);
+  };
+
+  auto pair = std::equal_range(array->begin(), array->end(), nullopt, cmp_lt);
+  ASSERT_EQ(pair.first, array->end() - 3);
+  ASSERT_EQ(pair.second, array->end());
+  pair = std::equal_range(array->begin(), array->end(), 6, cmp_lt);
+  ASSERT_EQ(pair.first, array->begin() + 5);
+  ASSERT_EQ(pair.second, pair.first);
+  pair = std::equal_range(array->begin(), array->end(), 5, cmp_lt);
+  ASSERT_EQ(pair.first, array->begin() + 2);
+  ASSERT_EQ(pair.second, array->begin() + 5);
+  pair = std::equal_range(array->begin(), array->end(), 1, cmp_lt);
+  ASSERT_EQ(pair.first, array->begin());
+  ASSERT_EQ(pair.second, array->begin() + 1);
+  pair = std::equal_range(array->begin(), array->end(), 0, cmp_lt);
+  ASSERT_EQ(pair.first, array->begin());
+  ASSERT_EQ(pair.second, pair.first);
+}
+
+TEST(ArrayIterator, StdMerge) {
+  auto array1 = checked_pointer_cast<Int8Array>(
+      ArrayFromJSON(int8(), "[1, 4, 5, 5, 7, null, null, null]"));
+  auto array2 =
+      checked_pointer_cast<Int8Array>(ArrayFromJSON(int8(), "[-1, 3, 3, 6, 42]"));
+  auto cmp_lt = [](optional<int8_t> u, optional<int8_t> v) {
+    return u.has_value() && (!v.has_value() || *u < *v);
+  };
+
+  std::vector<optional<int8_t>> values;
+  std::merge(array1->begin(), array1->end(), array2->begin(), array2->end(),
+             std::back_inserter(values), cmp_lt);
+  std::vector<optional<int8_t>> expected{-1, 1, 3, 3, 4, 5, 5, 6, 7, 42, {}, {}, {}};
+  ASSERT_EQ(values, expected);
+}
+
+}  // namespace stl
+}  // namespace arrow