1 /*
2 * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12 #include "iamf/common/utils/map_utils.h"
13
14 #include <array>
15 #include <utility>
16
17 #include "absl/container/flat_hash_map.h"
18 #include "absl/functional/function_ref.h"
19 #include "absl/status/status.h"
20 #include "absl/status/status_matchers.h"
21 #include "absl/strings/string_view.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24
25 namespace iamf_tools {
26 namespace {
27
28 using ::absl_testing::IsOk;
29 using ::absl_testing::IsOkAndHolds;
30 using ::absl_testing::StatusIs;
31 using ::testing::HasSubstr;
32 using ::testing::MockFunction;
33 using ::testing::Return;
34
35 constexpr absl::string_view kOmitContext = "";
36 constexpr absl::string_view kCustomUserContext = "Custom User Context";
37
DoNothing(bool)38 void DoNothing(bool /*ignored_value*/) {}
39
TEST(CopyFromMap,ReturnsOkWhenLookupSucceeds)40 TEST(CopyFromMap, ReturnsOkWhenLookupSucceeds) {
41 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
42 {1, false}, {2, true}, {3, true}, {4, false}};
43
44 bool result;
45 EXPECT_THAT(CopyFromMap(kIntegerToIsPrime, 3, kOmitContext, result), IsOk());
46
47 EXPECT_TRUE(result);
48 }
49
TEST(CopyFromMap,ReturnsStatusNotFoundWhenLookupFails)50 TEST(CopyFromMap, ReturnsStatusNotFoundWhenLookupFails) {
51 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
52 {1, false}, {2, true}, {3, true}, {4, false}};
53
54 bool undefined_result;
55 EXPECT_THAT(
56 CopyFromMap(kIntegerToIsPrime, -1, kOmitContext, undefined_result),
57 StatusIs(absl::StatusCode::kNotFound));
58 }
59
TEST(CopyFromMap,MessageContainsEmptyWhenMapIsEmpty)60 TEST(CopyFromMap, MessageContainsEmptyWhenMapIsEmpty) {
61 const absl::flat_hash_map<int, bool> kEmptyMap = {};
62
63 bool undefined_result;
64 EXPECT_THAT(
65 CopyFromMap(kEmptyMap, 3, kOmitContext, undefined_result).message(),
66 HasSubstr("empty"));
67 }
68
TEST(CopyFromMap,MessageContainsContextOnError)69 TEST(CopyFromMap, MessageContainsContextOnError) {
70 const absl::flat_hash_map<int, bool> kEmptyMap = {};
71
72 bool undefined_result;
73 EXPECT_THAT(
74 CopyFromMap(kEmptyMap, 3, kCustomUserContext, undefined_result).message(),
75 HasSubstr(kCustomUserContext));
76 }
77
TEST(LookupInMapStatusOr,OkIfLookupSucceeds)78 TEST(LookupInMapStatusOr, OkIfLookupSucceeds) {
79 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
80 {1, false}, {2, true}, {3, true}, {4, false}};
81
82 EXPECT_THAT(LookupInMap(kIntegerToIsPrime, 3, kOmitContext),
83 IsOkAndHolds(true));
84 }
85
TEST(LookupInMapStatusOr,ReturnsStatusNotFoundWhenLookupFails)86 TEST(LookupInMapStatusOr, ReturnsStatusNotFoundWhenLookupFails) {
87 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
88 {1, false}, {2, true}, {3, true}, {4, false}};
89
90 EXPECT_THAT(LookupInMap(kIntegerToIsPrime, -1, kOmitContext),
91 StatusIs(absl::StatusCode::kNotFound));
92 }
93
TEST(LookupInMapStatusOr,MessageContainsContextOnError)94 TEST(LookupInMapStatusOr, MessageContainsContextOnError) {
95 const absl::flat_hash_map<int, bool> kEmptyMap = {};
96
97 EXPECT_THAT(LookupInMap(kEmptyMap, 3, kCustomUserContext).status().message(),
98 HasSubstr(kCustomUserContext));
99 }
100
TEST(LookupInMapStatusOr,MessageContainsEmptyWhenMapIsEmpty)101 TEST(LookupInMapStatusOr, MessageContainsEmptyWhenMapIsEmpty) {
102 const absl::flat_hash_map<int, bool> kEmptyMap = {};
103
104 EXPECT_THAT(LookupInMap(kEmptyMap, 3, kOmitContext).status().message(),
105 HasSubstr("empty"));
106 }
107
TEST(SetFromMap,CallsSetterWithValueWhenLookupSucceeds)108 TEST(SetFromMap, CallsSetterWithValueWhenLookupSucceeds) {
109 constexpr int kKey = 3;
110 constexpr bool kExpectedValue = true;
111 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
112 {1, false}, {2, true}, {3, true}, {4, false}};
113 testing::MockFunction<void(bool)> mock_setter;
114
115 EXPECT_CALL(mock_setter, Call(kExpectedValue));
116
117 EXPECT_THAT(
118 SetFromMap(kIntegerToIsPrime, kKey, kOmitContext,
119 absl::FunctionRef<void(bool)>(mock_setter.AsStdFunction())),
120 IsOk());
121 }
122
TEST(SetFromMap,DoesNotCallSetterAndReturnsStatusNotFoundWhenLookupFails)123 TEST(SetFromMap, DoesNotCallSetterAndReturnsStatusNotFoundWhenLookupFails) {
124 constexpr int kAbsentKey = 99;
125 const absl::flat_hash_map<int, bool> kIntegerToIsPrime = {
126 {1, false}, {2, true}, {3, true}, {4, false}};
127
128 testing::MockFunction<void(bool)> setter;
129 EXPECT_CALL(setter, Call).Times(0);
130
131 EXPECT_THAT(SetFromMap(kIntegerToIsPrime, kAbsentKey, kOmitContext,
132 absl::FunctionRef<void(bool)>(setter.AsStdFunction())),
133 StatusIs(absl::StatusCode::kNotFound));
134 }
135
TEST(SetFromMap,MessageContainsContextOnError)136 TEST(SetFromMap, MessageContainsContextOnError) {
137 constexpr int kAbsentKey = -1;
138 const absl::flat_hash_map<int, bool> kEmptyMap = {};
139
140 EXPECT_THAT(SetFromMap(kEmptyMap, kAbsentKey, kCustomUserContext,
141 absl::FunctionRef<void(bool)>(DoNothing))
142 .message(),
143 HasSubstr(kCustomUserContext));
144 }
145
TEST(SetFromMap,MessageContainsEmptyWhenMapIsEmpty)146 TEST(SetFromMap, MessageContainsEmptyWhenMapIsEmpty) {
147 constexpr int kAbsentKey = -1;
148 const absl::flat_hash_map<int, bool> kEmptyMap = {};
149
150 EXPECT_THAT(SetFromMap(kEmptyMap, kAbsentKey, kOmitContext,
151 absl::FunctionRef<void(bool)>(DoNothing))
152 .message(),
153 HasSubstr("empty"));
154 }
155
TEST(BuildStaticMapFromPairs,SucceedsOnEmptyContainer)156 TEST(BuildStaticMapFromPairs, SucceedsOnEmptyContainer) {
157 constexpr std::array<std::pair<int, float>, 0> kPairs{};
158 static const auto kMap = BuildStaticMapFromPairs(kPairs);
159
160 EXPECT_TRUE(kMap->empty());
161 }
162
TEST(BuildStaticMapFromPairs,BuildsMap)163 TEST(BuildStaticMapFromPairs, BuildsMap) {
164 constexpr std::array<std::pair<int, float>, 3> kPairs{
165 {{1, 2.0f}, {3, 6.0f}, {5, 10.f}}};
166 const absl::flat_hash_map<int, float> kExpectedMap = {
167 {1, 2.0f}, {3, 6.0f}, {5, 10.f}};
168
169 static const auto kMap = BuildStaticMapFromPairs(kPairs);
170
171 EXPECT_EQ(*kMap, kExpectedMap);
172 }
173
TEST(BuildStaticMapFromPairs,BuildsMapWithDuplicateValues)174 TEST(BuildStaticMapFromPairs, BuildsMapWithDuplicateValues) {
175 constexpr float kDuplicateValue = 2.0;
176 constexpr std::array<std::pair<int, float>, 3> kPairsWithDuplicateSecond{
177 {{1, kDuplicateValue}, {3, kDuplicateValue}, {5, 10.f}}};
178 const absl::flat_hash_map<int, float> kExpectedMap = {
179 {1, kDuplicateValue}, {3, kDuplicateValue}, {5, 10.f}};
180
181 static const auto kMap = BuildStaticMapFromPairs(kPairsWithDuplicateSecond);
182
183 EXPECT_EQ(*kMap, kExpectedMap);
184 }
185
TEST(BuildStaticMapFromPairs,ReturnsEmptyMapOnDuplicateKey)186 TEST(BuildStaticMapFromPairs, ReturnsEmptyMapOnDuplicateKey) {
187 constexpr int kDuplicateKey = 1;
188 constexpr std::array<std::pair<int, float>, 3> kPairsWithDuplicateFirst{
189 {{kDuplicateKey, 2.0f}, {kDuplicateKey, 6.0f}, {5, 10.f}}};
190
191 static const auto kMap = BuildStaticMapFromPairs(kPairsWithDuplicateFirst);
192
193 EXPECT_TRUE(kMap->empty());
194 }
195
TEST(BuildStaticMapFromInvertedPairs,SucceedsOnEmptyContainer)196 TEST(BuildStaticMapFromInvertedPairs, SucceedsOnEmptyContainer) {
197 constexpr std::array<std::pair<int, float>, 0> kEmptyPairs{};
198 static const auto kMap = BuildStaticMapFromInvertedPairs(kEmptyPairs);
199
200 EXPECT_TRUE(kMap->empty());
201 }
202
TEST(BuildStaticMapFromInvertedPairs,BuildsInvertedMap)203 TEST(BuildStaticMapFromInvertedPairs, BuildsInvertedMap) {
204 constexpr std::array<std::pair<int, float>, 3> kPairs{
205 {{1, 2.0f}, {3, 6.0f}, {5, 10.f}}};
206 const absl::flat_hash_map<float, int> kExpectedInvertedMap = {
207 {2.0f, 1}, {6.0f, 3}, {10.f, 5}};
208
209 static const auto kMap = BuildStaticMapFromInvertedPairs(kPairs);
210
211 EXPECT_EQ(*kMap, kExpectedInvertedMap);
212 }
213
TEST(BuildStaticMapFromInvertedPairs,BuildsInvertedMapWithDuplicateValues)214 TEST(BuildStaticMapFromInvertedPairs, BuildsInvertedMapWithDuplicateValues) {
215 constexpr int kDuplicateValue = 1;
216 constexpr std::array<std::pair<int, float>, 3> kPairsWithDuplicateFirst{
217 {{kDuplicateValue, 2.0f}, {kDuplicateValue, 6.0f}, {5, 10.f}}};
218 const absl::flat_hash_map<float, int> kExpectedInvertedMap = {
219 {2.0f, kDuplicateValue}, {6.0f, kDuplicateValue}, {10.f, 5}};
220
221 static const auto kMap =
222 BuildStaticMapFromInvertedPairs(kPairsWithDuplicateFirst);
223
224 EXPECT_EQ(*kMap, kExpectedInvertedMap);
225 }
226
TEST(BuildStaticMapFromInvertedPairs,ReturnsEmptyMapOnDuplicateKey)227 TEST(BuildStaticMapFromInvertedPairs, ReturnsEmptyMapOnDuplicateKey) {
228 constexpr int kDuplicateKey = 1.0f;
229 constexpr std::array<std::pair<int, float>, 3> kPairsWithDuplicateSecond{
230 {{1, kDuplicateKey}, {3, kDuplicateKey}, {5, 10.f}}};
231
232 static const auto kMap =
233 BuildStaticMapFromInvertedPairs(kPairsWithDuplicateSecond);
234
235 EXPECT_TRUE(kMap->empty());
236 }
237
238 } // namespace
239 } // namespace iamf_tools
240