TestAlgorithm.cpp (5429B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 9 #include "mozilla/Algorithm.h" 10 #include "mozilla/Maybe.h" 11 #include "mozilla/ResultVariant.h" 12 13 #include <iterator> 14 #include <vector> 15 16 using namespace mozilla; 17 using std::begin; 18 using std::end; 19 20 namespace { 21 struct MoveOnly { 22 explicit MoveOnly(int32_t aValue) : mValue{Some(aValue)} {} 23 24 MoveOnly(MoveOnly&&) = default; 25 MoveOnly& operator=(MoveOnly&&) = default; 26 27 Maybe<int32_t> mValue; 28 }; 29 30 struct TestError {}; 31 32 constexpr static int32_t arr1[3] = {1, 2, 3}; 33 } // namespace 34 35 TEST(MFBT_Algorithm_TransformAbortOnErr, NoError) 36 { 37 std::vector<int64_t> out; 38 auto res = TransformAbortOnErr( 39 begin(arr1), end(arr1), std::back_inserter(out), 40 [](const int32_t value) -> Result<int64_t, TestError> { 41 return value * 10; 42 }); 43 ASSERT_TRUE(res.isOk()); 44 45 const std::vector<int64_t> expected = {10, 20, 30}; 46 ASSERT_EQ(expected, out); 47 } 48 49 TEST(MFBT_Algorithm_TransformAbortOnErr, NoError_Range) 50 { 51 std::vector<int64_t> out; 52 auto res = TransformAbortOnErr( 53 arr1, std::back_inserter(out), 54 [](const int32_t value) -> Result<int64_t, TestError> { 55 return value * 10; 56 }); 57 ASSERT_TRUE(res.isOk()); 58 59 const std::vector<int64_t> expected = {10, 20, 30}; 60 ASSERT_EQ(expected, out); 61 } 62 63 TEST(MFBT_Algorithm_TransformAbortOnErr, ErrorOnFirst) 64 { 65 std::vector<int64_t> out; 66 auto res = TransformAbortOnErr( 67 begin(arr1), end(arr1), std::back_inserter(out), 68 [](const int32_t value) -> Result<int64_t, TestError> { 69 return Err(TestError{}); 70 }); 71 ASSERT_TRUE(res.isErr()); 72 ASSERT_TRUE(out.empty()); 73 } 74 75 TEST(MFBT_Algorithm_TransformAbortOnErr, ErrorOnOther) 76 { 77 std::vector<int64_t> out; 78 auto res = TransformAbortOnErr( 79 begin(arr1), end(arr1), std::back_inserter(out), 80 [](const int32_t value) -> Result<int64_t, TestError> { 81 if (value > 2) { 82 return Err(TestError{}); 83 } 84 return value * 10; 85 }); 86 ASSERT_TRUE(res.isErr()); 87 88 // XXX Should we assert on this, or is the content of out an implementation 89 // detail? 90 const std::vector<int64_t> expected = {10, 20}; 91 ASSERT_EQ(expected, out); 92 } 93 94 TEST(MFBT_Algorithm_TransformAbortOnErr, ErrorOnOther_Move) 95 { 96 MoveOnly in[3] = {MoveOnly{1}, MoveOnly{2}, MoveOnly{3}}; 97 std::vector<int64_t> out; 98 auto res = TransformAbortOnErr( 99 std::make_move_iterator(begin(in)), std::make_move_iterator(end(in)), 100 std::back_inserter(out), 101 [](MoveOnly value) -> Result<int64_t, TestError> { 102 if (*value.mValue > 1) { 103 return Err(TestError{}); 104 } 105 return *value.mValue * 10; 106 }); 107 ASSERT_TRUE(res.isErr()); 108 109 ASSERT_FALSE(in[0].mValue); 110 ASSERT_FALSE(in[1].mValue); 111 ASSERT_TRUE(in[2].mValue); 112 113 // XXX Should we assert on this, or is the content of out an implementation 114 // detail? 115 const std::vector<int64_t> expected = {10}; 116 ASSERT_EQ(expected, out); 117 } 118 119 TEST(MFBT_Algorithm_TransformIfAbortOnErr, NoError) 120 { 121 std::vector<int64_t> out; 122 auto res = TransformIfAbortOnErr( 123 begin(arr1), end(arr1), std::back_inserter(out), 124 [](const int32_t value) { return value % 2 == 1; }, 125 [](const int32_t value) -> Result<int64_t, TestError> { 126 return value * 10; 127 }); 128 ASSERT_TRUE(res.isOk()); 129 130 const std::vector<int64_t> expected = {10, 30}; 131 ASSERT_EQ(expected, out); 132 } 133 134 TEST(MFBT_Algorithm_TransformIfAbortOnErr, NoError_Range) 135 { 136 std::vector<int64_t> out; 137 auto res = TransformIfAbortOnErr( 138 arr1, std::back_inserter(out), 139 [](const int32_t value) { return value % 2 == 1; }, 140 [](const int32_t value) -> Result<int64_t, TestError> { 141 return value * 10; 142 }); 143 ASSERT_TRUE(res.isOk()); 144 145 const std::vector<int64_t> expected = {10, 30}; 146 ASSERT_EQ(expected, out); 147 } 148 149 TEST(MFBT_Algorithm_TransformIfAbortOnErr, ErrorOnOther) 150 { 151 std::vector<int64_t> out; 152 auto res = TransformIfAbortOnErr( 153 begin(arr1), end(arr1), std::back_inserter(out), 154 [](const int32_t value) { return value % 2 == 1; }, 155 [](const int32_t value) -> Result<int64_t, TestError> { 156 if (value > 2) { 157 return Err(TestError{}); 158 } 159 return value * 10; 160 }); 161 ASSERT_TRUE(res.isErr()); 162 163 const std::vector<int64_t> expected = {10}; 164 ASSERT_EQ(expected, out); 165 } 166 167 TEST(MFBT_Algorithm_TransformIfAbortOnErr, ErrorOnOther_Move) 168 { 169 MoveOnly in[3] = {MoveOnly{1}, MoveOnly{2}, MoveOnly{3}}; 170 std::vector<int64_t> out; 171 auto res = TransformIfAbortOnErr( 172 std::make_move_iterator(begin(in)), std::make_move_iterator(end(in)), 173 std::back_inserter(out), 174 [](const MoveOnly& value) { return *value.mValue % 2 == 1; }, 175 [](MoveOnly value) -> Result<int64_t, TestError> { 176 if (*value.mValue > 1) { 177 return Err(TestError{}); 178 } 179 return *value.mValue * 10; 180 }); 181 ASSERT_TRUE(res.isErr()); 182 183 ASSERT_FALSE(in[0].mValue); 184 ASSERT_TRUE(in[1].mValue); 185 ASSERT_FALSE(in[2].mValue); 186 187 // XXX Should we assert on this, or is the content of out an implementation 188 // detail? 189 const std::vector<int64_t> expected = {10}; 190 ASSERT_EQ(expected, out); 191 }