3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "TestRetransmit.h"
20 #include <support/UnitTestRegistration.h>
21 #include <transport/retransmit/Cache.h>
24 #include <nlunit-test.h>
26 // Helpers for simple payload management
28 constexpr int kMaxPayloadValue = 100;
31 * Derived cache class containing some test helper methods.
33 template <typename KeyType, typename PayloadType, size_t N>
34 class TestableCache : public chip::Retransmit::Cache<KeyType, PayloadType, N>
38 * Convenience add when types are trivially copyable, so no actual
39 * reference needs to be created.
41 template <typename = std::enable_if<std::is_trivially_copyable<PayloadType>::value, int>>
42 CHIP_ERROR AddValue(const KeyType & key, PayloadType payload)
44 return chip::Retransmit::Cache<KeyType, PayloadType, N>::Add(key, payload);
48 class IntPayloadTracker
51 void Init(nlTestSuite * suite) { mSuite = suite; }
53 void Acquire(int value)
55 NL_TEST_ASSERT(mSuite, (value > 0) && value < kMaxPayloadValue);
56 mAquired.set(static_cast<size_t>(value));
59 void Release(int value)
61 NL_TEST_ASSERT(mSuite, (value > 0) && value < kMaxPayloadValue);
62 NL_TEST_ASSERT(mSuite, mAquired.test(static_cast<size_t>(value)));
63 mAquired.reset(static_cast<size_t>(value));
66 size_t Count() const { return mAquired.count(); }
68 bool IsAquired(int value) const { return mAquired.test(static_cast<size_t>(value)); }
72 std::bitset<kMaxPayloadValue> mAquired;
75 IntPayloadTracker gPayloadTracker;
78 * Helper class defining a matches method for things divisible by a
84 DivisibleBy(int value) : mValue(value) {}
86 bool Matches(int x) const { return (x % mValue) == 0; }
95 int chip::Retransmit::Lifetime<int>::Acquire(int & value)
97 gPayloadTracker.Acquire(value);
102 void chip::Retransmit::Lifetime<int>::Release(int & value)
104 gPayloadTracker.Release(value);
105 value = 0; // make sure it is not used anymore
110 void TestNoOp(nlTestSuite * inSuite, void * inContext)
112 // unused address cache should not do any aquire/release at any time
113 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
115 TestableCache<int, int, 20> test;
116 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
118 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
121 void TestDestructorFree(nlTestSuite * inSuite, void * inContext)
124 TestableCache<int, int, 20> test;
126 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
128 NL_TEST_ASSERT(inSuite, test.AddValue(1, 1) == CHIP_NO_ERROR);
129 NL_TEST_ASSERT(inSuite, test.AddValue(2, 2) == CHIP_NO_ERROR);
131 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 2);
134 // destructor should release the items
135 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
138 void OutOfSpace(nlTestSuite * inSuite, void * inContext)
141 TestableCache<int, int, 4> test;
143 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
145 NL_TEST_ASSERT(inSuite, test.AddValue(1, 1) == CHIP_NO_ERROR);
146 NL_TEST_ASSERT(inSuite, test.AddValue(2, 2) == CHIP_NO_ERROR);
147 NL_TEST_ASSERT(inSuite, test.AddValue(3, 4) == CHIP_NO_ERROR);
148 NL_TEST_ASSERT(inSuite, test.AddValue(4, 6) == CHIP_NO_ERROR);
149 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 4);
151 NL_TEST_ASSERT(inSuite, test.AddValue(5, 8) == CHIP_ERROR_NO_MEMORY);
152 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 4);
154 NL_TEST_ASSERT(inSuite, test.AddValue(6, 10) == CHIP_ERROR_NO_MEMORY);
155 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 4);
157 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
160 void AddRemove(nlTestSuite * inSuite, void * inContext)
162 TestableCache<int, int, 3> test;
164 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
166 NL_TEST_ASSERT(inSuite, test.AddValue(1, 1) == CHIP_NO_ERROR);
167 NL_TEST_ASSERT(inSuite, test.AddValue(2, 2) == CHIP_NO_ERROR);
168 NL_TEST_ASSERT(inSuite, test.AddValue(3, 4) == CHIP_NO_ERROR);
169 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 3);
171 NL_TEST_ASSERT(inSuite, test.AddValue(10, 8) == CHIP_ERROR_NO_MEMORY);
172 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 3);
174 NL_TEST_ASSERT(inSuite, test.Remove(2) == CHIP_NO_ERROR);
175 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 2);
177 NL_TEST_ASSERT(inSuite, test.AddValue(10, 8) == CHIP_NO_ERROR);
178 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 3);
180 NL_TEST_ASSERT(inSuite, test.Remove(14) == CHIP_ERROR_KEY_NOT_FOUND);
181 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 3);
183 NL_TEST_ASSERT(inSuite, test.Remove(1) == CHIP_NO_ERROR);
184 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 2);
186 NL_TEST_ASSERT(inSuite, test.Remove(3) == CHIP_NO_ERROR);
187 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 1);
189 NL_TEST_ASSERT(inSuite, test.Remove(3) == CHIP_ERROR_KEY_NOT_FOUND);
190 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 1);
192 NL_TEST_ASSERT(inSuite, test.Remove(10) == CHIP_NO_ERROR);
193 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
195 NL_TEST_ASSERT(inSuite, test.Remove(10) == CHIP_ERROR_KEY_NOT_FOUND);
196 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
199 void RemoveMatching(nlTestSuite * inSuite, void * inContext)
201 TestableCache<int, int, 4> test;
203 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
205 NL_TEST_ASSERT(inSuite, test.AddValue(1, 1) == CHIP_NO_ERROR);
206 NL_TEST_ASSERT(inSuite, test.AddValue(2, 2) == CHIP_NO_ERROR);
207 NL_TEST_ASSERT(inSuite, test.AddValue(3, 4) == CHIP_NO_ERROR);
208 NL_TEST_ASSERT(inSuite, test.AddValue(4, 8) == CHIP_NO_ERROR);
209 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 4);
211 test.RemoveMatching(DivisibleBy(2));
212 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 2);
214 // keys 1 and 3 remain
215 NL_TEST_ASSERT(inSuite, gPayloadTracker.IsAquired(1));
216 NL_TEST_ASSERT(inSuite, gPayloadTracker.IsAquired(4));
218 NL_TEST_ASSERT(inSuite, test.Remove(3) == CHIP_NO_ERROR);
219 NL_TEST_ASSERT(inSuite, gPayloadTracker.IsAquired(1));
220 NL_TEST_ASSERT(inSuite, !gPayloadTracker.IsAquired(4));
223 void FindMatching(nlTestSuite * inSuite, void * inContext)
225 TestableCache<int, int, 4> test;
227 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 0);
229 NL_TEST_ASSERT(inSuite, test.AddValue(1, 1) == CHIP_NO_ERROR);
230 NL_TEST_ASSERT(inSuite, test.AddValue(2, 2) == CHIP_NO_ERROR);
231 NL_TEST_ASSERT(inSuite, test.AddValue(3, 4) == CHIP_NO_ERROR);
232 NL_TEST_ASSERT(inSuite, test.AddValue(4, 8) == CHIP_NO_ERROR);
233 NL_TEST_ASSERT(inSuite, gPayloadTracker.Count() == 4);
238 NL_TEST_ASSERT(inSuite, test.Find(DivisibleBy(20), &key, &value) == false);
239 NL_TEST_ASSERT(inSuite, key == nullptr);
240 NL_TEST_ASSERT(inSuite, value == nullptr);
242 // This relies on linear add. May need changing if implementation changes
243 NL_TEST_ASSERT(inSuite, test.Find(DivisibleBy(2), &key, &value) == true);
244 NL_TEST_ASSERT(inSuite, *key == 2);
245 NL_TEST_ASSERT(inSuite, *value == 2);
247 NL_TEST_ASSERT(inSuite, test.Remove(*key) == CHIP_NO_ERROR);
249 NL_TEST_ASSERT(inSuite, test.Find(DivisibleBy(2), &key, &value) == true);
250 NL_TEST_ASSERT(inSuite, *key == 4);
251 NL_TEST_ASSERT(inSuite, *value == 8);
253 NL_TEST_ASSERT(inSuite, test.Remove(*key) == CHIP_NO_ERROR);
254 NL_TEST_ASSERT(inSuite, test.Find(DivisibleBy(2), &key, &value) == false);
255 NL_TEST_ASSERT(inSuite, key == nullptr);
256 NL_TEST_ASSERT(inSuite, value == nullptr);
262 static const nlTest sTests[] =
264 NL_TEST_DEF("NoOp", TestNoOp),
265 NL_TEST_DEF("DestructorFree", TestDestructorFree),
266 NL_TEST_DEF("OutOfSpace", OutOfSpace),
267 NL_TEST_DEF("AddRemove", AddRemove),
268 NL_TEST_DEF("RemoveMatching", RemoveMatching),
269 NL_TEST_DEF("FindMatching", FindMatching),
276 nlTestSuite theSuite = { "Retransmit-Cache", &sTests[0], nullptr, nullptr };
277 gPayloadTracker.Init(&theSuite);
278 nlTestRunner(&theSuite, nullptr);
279 return nlTestRunnerStats(&theSuite);
282 CHIP_REGISTER_TEST_SUITE(TestCache)