1 //--------------------------------------------------------------------------
2 // Copyright (C) 2020-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // memcap_allocator_test.cc author davis mcpherson <davmcphe@cisco.com>
20 // unit tests for MemCapAllocator class
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "../memcap_allocator.h"
27 
28 #include <CppUTest/CommandLineTestRunner.h>
29 #include <CppUTest/TestHarness.h>
30 
31 const unsigned long ALLOCATION_SIZE = 250;
32 const unsigned long NO_MEM_CAP_LIMIT = 0;
33 const unsigned NO_MEMCAP_LIMIT_ALLOCATIONS = 10000;
34 
35 const unsigned long MEM_CAP_5000 = 5000;
36 const unsigned MAX_ALLOCATIONS_5000 = MEM_CAP_5000 / ALLOCATION_SIZE;
37 
38 const unsigned long MEM_CAP_10000 = 10000;
39 const unsigned MAX_ALLOCATIONS_10000 = MEM_CAP_10000 / ALLOCATION_SIZE;
40 
41 const unsigned long MEM_CAP_20000 = 20000;
42 const unsigned MAX_ALLOCATIONS_20000 = MEM_CAP_20000 / ALLOCATION_SIZE;
43 
TEST_GROUP(memcap_allocator)44 TEST_GROUP(memcap_allocator)
45 { };
46 
TEST(memcap_allocator,no_memcap_limit_allocator_test)47 TEST(memcap_allocator, no_memcap_limit_allocator_test)
48 {
49     MemCapAllocator* mca = new MemCapAllocator(NO_MEM_CAP_LIMIT, ALLOCATION_SIZE);
50     CHECK(mca);
51     CHECK(mca->get_allocation_size() == ALLOCATION_SIZE);
52     CHECK(mca->get_mem_capacity() == NO_MEM_CAP_LIMIT);
53     CHECK(mca->is_space_available());
54     CHECK(!mca->is_over_capacity());
55     CHECK(mca->get_mem_allocated() == 0);
56     CHECK(mca->get_allocation_requests() == 0);
57     CHECK(mca->get_free_requests() == 0);
58     CHECK(mca->get_no_memory_available() == 0);
59     delete mca;
60 }
61 
TEST(memcap_allocator,no_memcap_limit_allocations_test)62 TEST(memcap_allocator, no_memcap_limit_allocations_test)
63 {
64     MemCapAllocator* mca = new MemCapAllocator(NO_MEM_CAP_LIMIT, ALLOCATION_SIZE);
65     CHECK(mca);
66 
67     unsigned bytes_allocated;
68     uint8_t** mem_blocks = (uint8_t**)snort_alloc(sizeof(uint8_t*) * NO_MEMCAP_LIMIT_ALLOCATIONS);
69     for ( unsigned i = 0; i < NO_MEMCAP_LIMIT_ALLOCATIONS; i++)
70     {
71         mem_blocks[i] = (uint8_t*)mca->allocate();
72         bytes_allocated = (i + 1) * ALLOCATION_SIZE;
73         CHECK(mem_blocks[i]);
74         CHECK(mca->get_mem_allocated() == bytes_allocated);
75         CHECK(mca->is_space_available());
76         CHECK(!mca->is_over_capacity());
77     }
78 
79     CHECK(mca->get_allocation_requests() == NO_MEMCAP_LIMIT_ALLOCATIONS);
80     CHECK(mca->get_free_requests() == 0);
81     CHECK(mca->get_no_memory_available() == 0);
82 
83     for ( unsigned i = 0; i < NO_MEMCAP_LIMIT_ALLOCATIONS; i++)
84     {
85         mca->free(mem_blocks[i]);
86         bytes_allocated = (NO_MEMCAP_LIMIT_ALLOCATIONS - (i + 1)) * ALLOCATION_SIZE;
87         CHECK(mca->get_mem_allocated() == bytes_allocated);
88     }
89 
90     CHECK(mca->is_space_available());
91     CHECK(!mca->is_over_capacity());
92     CHECK(mca->get_mem_allocated() == 0);
93     CHECK(mca->get_free_requests() == NO_MEMCAP_LIMIT_ALLOCATIONS);
94     CHECK(mca->get_no_memory_available() == 0);
95 
96     snort_free(mem_blocks);
97     delete mca;
98 }
99 
TEST(memcap_allocator,create_memcap_allocator_test)100 TEST(memcap_allocator, create_memcap_allocator_test)
101 {
102     MemCapAllocator* mca = new MemCapAllocator(MEM_CAP_10000, ALLOCATION_SIZE);
103     CHECK(mca);
104     CHECK(mca->get_allocation_size() == ALLOCATION_SIZE);
105     CHECK(mca->get_mem_capacity() == MEM_CAP_10000);
106     mca->set_mem_capacity(MEM_CAP_20000);
107     CHECK(mca->get_mem_capacity() == MEM_CAP_20000);
108     CHECK(mca->get_mem_allocated() == 0);
109     CHECK(mca->get_allocation_requests() == 0);
110     CHECK(mca->get_free_requests() == 0);
111     CHECK(mca->get_no_memory_available() == 0);
112     delete mca;
113 }
114 
TEST(memcap_allocator,allocate_and_free_memory_test)115 TEST(memcap_allocator, allocate_and_free_memory_test)
116 {
117     MemCapAllocator* mca = new MemCapAllocator(MEM_CAP_10000, ALLOCATION_SIZE);
118     CHECK(mca);
119     CHECK(mca->is_space_available());
120     CHECK(!mca->is_over_capacity());
121 
122     uint8_t* mem = (uint8_t*)mca->allocate();
123     CHECK(mem);
124     CHECK(mca->get_mem_allocated() == ALLOCATION_SIZE);
125     CHECK(mca->is_space_available());
126     CHECK(!mca->is_over_capacity());
127     CHECK(mca->get_allocation_requests() == 1);
128     CHECK(mca->get_free_requests() == 0);
129     CHECK(mca->get_no_memory_available() == 0);
130 
131     mca->free(mem);
132     CHECK(mca->get_mem_allocated() == 0);
133     CHECK(mca->is_space_available());
134     CHECK(!mca->is_over_capacity());
135     CHECK(mca->get_allocation_requests() == 1);
136     CHECK(mca->get_free_requests() == 1);
137     CHECK(mca->get_no_memory_available() == 0);
138 
139     delete mca;
140 }
141 
TEST(memcap_allocator,max_allocations_test)142 TEST(memcap_allocator, max_allocations_test)
143 {
144     MemCapAllocator* mca = new MemCapAllocator(MEM_CAP_10000, ALLOCATION_SIZE);
145     CHECK(mca);
146 
147     unsigned bytes_allocated;
148     uint8_t* mem_blocks[MAX_ALLOCATIONS_10000];
149     for ( unsigned i = 0; i < MAX_ALLOCATIONS_10000; i++)
150     {
151         mem_blocks[i] = (uint8_t*)mca->allocate();
152         bytes_allocated = (i + 1) * ALLOCATION_SIZE;
153         CHECK(mem_blocks[i]);
154         CHECK(mca->get_mem_allocated() == bytes_allocated);
155         if ( i < MAX_ALLOCATIONS_10000 - 1 )
156         {
157             CHECK(mca->is_space_available());
158         }
159         else
160         {
161             CHECK(!mca->is_space_available());
162         }
163         CHECK(!mca->is_over_capacity());
164     }
165     CHECK(mca->get_allocation_requests() == MAX_ALLOCATIONS_10000);
166     CHECK(mca->get_free_requests() == 0);
167     CHECK(mca->get_no_memory_available() == 0);
168 
169     uint8_t* mem = (uint8_t*)mca->allocate();
170     CHECK(!mem);
171     CHECK(mca->get_no_memory_available() == 1);
172     mem = (uint8_t*)mca->allocate();
173     CHECK(!mem);
174     mem = (uint8_t*)mca->allocate();
175     CHECK(!mem);
176     CHECK(mca->get_no_memory_available() == 3);
177     mca->free(mem_blocks[0]);
178     mem_blocks[0] = (uint8_t*)mca->allocate();
179     CHECK(mem_blocks[0]);
180     CHECK(mca->get_free_requests() == 1);
181     CHECK(mca->get_no_memory_available() == 3);
182 
183     mca->set_mem_capacity(MEM_CAP_20000);
184     mem = (uint8_t*)mca->allocate();
185     CHECK(mem);
186     mca->set_mem_capacity(MEM_CAP_5000);
187     CHECK(mca->is_over_capacity());
188     mca->free(mem);
189     CHECK(mca->get_free_requests() == 2);
190 
191     for ( unsigned i = 0; i < MAX_ALLOCATIONS_5000; i++)
192     {
193         CHECK(!mca->is_space_available());
194         mca->free(mem_blocks[i]);
195         bytes_allocated = (MAX_ALLOCATIONS_10000 - (i + 1)) * ALLOCATION_SIZE;
196         CHECK(mca->get_mem_allocated() == bytes_allocated);
197     }
198 
199     CHECK(!mca->is_space_available());
200     CHECK(!mca->is_over_capacity());
201 
202     for ( unsigned i = MAX_ALLOCATIONS_5000; i < MAX_ALLOCATIONS_10000; i++)
203     {
204         mca->free(mem_blocks[i]);
205         bytes_allocated = (MAX_ALLOCATIONS_10000 - (i + 1)) * ALLOCATION_SIZE;
206         CHECK(mca->get_mem_allocated() == bytes_allocated);
207         CHECK(mca->is_space_available());
208         CHECK(!mca->is_over_capacity());
209     }
210 
211     CHECK(mca->get_mem_allocated() == 0);
212     CHECK(mca->get_free_requests() == MAX_ALLOCATIONS_10000 + 2);
213     CHECK(mca->get_no_memory_available() == 3);
214 
215     delete mca;
216 }
217 
main(int argc,char ** argv)218 int main(int argc, char** argv)
219 {
220     return CommandLineTestRunner::RunAllTests(argc, argv);
221 }
222