1 /*
2  *  Copyright (c) 2020, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "test_platform.h"
30 
31 #include <openthread/config.h>
32 
33 #include "common/instance.hpp"
34 #include "common/pool.hpp"
35 
36 #include "test_util.h"
37 
38 struct EntryBase
39 {
40     EntryBase *mNext;
41 };
42 
43 struct Entry : public EntryBase, ot::LinkedListEntry<Entry>
44 {
45 public:
EntryEntry46     Entry(void)
47         : mInitWithInstance(false)
48     {
49     }
50 
InitEntry51     void Init(ot::Instance &) { mInitWithInstance = true; }
52 
IsInitializedWithInstanceEntry53     bool IsInitializedWithInstance(void) const { return mInitWithInstance; }
54 
55 private:
56     bool mInitWithInstance;
57 };
58 
59 enum : uint16_t
60 {
61     kPoolSize = 11,
62 };
63 
64 typedef ot::Pool<Entry, kPoolSize> EntryPool;
65 
66 static Entry sNonPoolEntry;
67 
VerifyEntry(EntryPool & aPool,const Entry & aEntry,bool aInitWithInstance)68 void VerifyEntry(EntryPool &aPool, const Entry &aEntry, bool aInitWithInstance)
69 {
70     uint16_t         index;
71     const EntryPool &constPool = const_cast<const EntryPool &>(aPool);
72 
73     VerifyOrQuit(aPool.IsPoolEntry(aEntry));
74     VerifyOrQuit(!aPool.IsPoolEntry(sNonPoolEntry), "Pool::IsPoolEntry() succeeded for non-pool entry");
75 
76     index = aPool.GetIndexOf(aEntry);
77     VerifyOrQuit(&aPool.GetEntryAt(index) == &aEntry);
78     VerifyOrQuit(&constPool.GetEntryAt(index) == &aEntry);
79 
80     VerifyOrQuit(aEntry.IsInitializedWithInstance() == aInitWithInstance, "Pool did not correctly Init() entry");
81 }
82 
TestPool(EntryPool & aPool,bool aInitWithInstance)83 void TestPool(EntryPool &aPool, bool aInitWithInstance)
84 {
85     Entry *entries[kPoolSize];
86 
87     VerifyOrQuit(aPool.GetSize() == kPoolSize);
88 
89     for (Entry *&entry : entries)
90     {
91         entry = aPool.Allocate();
92         VerifyOrQuit(entry != nullptr, "Pool::Allocate() failed");
93 
94         VerifyEntry(aPool, *entry, aInitWithInstance);
95     }
96 
97     for (uint16_t numEntriesToFree = 1; numEntriesToFree <= kPoolSize; numEntriesToFree++)
98     {
99         VerifyOrQuit(aPool.Allocate() == nullptr, "Pool::Allocate() did not fail when all pool entries were allocated");
100 
101         for (uint16_t i = 0; i < numEntriesToFree; i++)
102         {
103             VerifyEntry(aPool, *entries[i], aInitWithInstance);
104             aPool.Free(*entries[i]);
105         }
106 
107         for (uint16_t i = 0; i < numEntriesToFree; i++)
108         {
109             entries[i] = aPool.Allocate();
110             VerifyOrQuit(entries[i] != nullptr, "Pool::Allocate() failed");
111 
112             VerifyEntry(aPool, *entries[i], aInitWithInstance);
113         }
114     }
115 
116     VerifyOrQuit(aPool.Allocate() == nullptr, "Pool::Allocate() did not fail when all pool entries were allocated");
117 }
118 
TestPool(void)119 void TestPool(void)
120 {
121     ot::Instance *instance = testInitInstance();
122     EntryPool     pool1;
123     EntryPool     pool2(*instance);
124 
125     TestPool(pool1, /* aInitWithInstance */ false);
126     TestPool(pool2, /* aInitWithInstance */ true);
127 
128     testFreeInstance(instance);
129 }
130 
main(void)131 int main(void)
132 {
133     TestPool();
134     printf("All tests passed\n");
135     return 0;
136 }
137