first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / tests_structures / test_memory_limiter.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : test_memory_limiter                                               *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *  Purpose:                                                                   *
7 *                                                                             *
8 *    Tests that the memory_limiter is keeping track of the memory users       *
9 *  accurately.                                                                *
10 *                                                                             *
11 *******************************************************************************
12 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
13 * redistribute it and/or modify it under the terms of the GNU General Public  *
14 * License as published by the Free Software Foundation; either version 2 of   *
15 * the License or (at your option) any later version.  This is online at:      *
16 *     http://www.fsf.org/copyleft/gpl.html                                    *
17 * Please send any updates to: fred@gruntose.com                               *
18 \*****************************************************************************/
19
20 //#define DEBUG_MEMORY_LIMITER
21   // uncomment for debugging version.
22
23 #include <application/hoople_main.h>
24 #include <basis/guards.h>
25 #include <basis/astring.h>
26 #include <configuration/ini_configurator.h>
27 #include <mathematics/chaos.h>
28 #include <structures/memory_limiter.h>
29 #include <structures/set.h>
30 #include <structures/static_memory_gremlin.h>
31 #include <timely/time_stamp.h>
32 #include <unit_test/unit_base.h>
33
34 #ifdef DEBUG_MEMORY_LIMITER
35   #include <stdio.h>
36 #endif
37
38 using namespace application;
39 using namespace basis;
40 using namespace filesystem;
41 using namespace loggers;
42 using namespace mathematics;
43 using namespace structures;
44 using namespace textual;
45 using namespace timely;
46 using namespace unit_test;
47
48 #define LOG(to_print) EMERGENCY_LOG(program_wide_logger().get(), astring(to_print))
49
50 const int MAXIMUM_MEM_OVERALL = 1 * MEGABYTE;
51 const int MAXIMUM_MEM_PER_OWNER = 100 * KILOBYTE;
52
53 const int RUN_TIME = .8 * SECOND_ms;
54
55 //////////////
56
57 class test_memory_limiter : virtual public unit_base, virtual public application_shell
58 {
59 public:
60   test_memory_limiter() {}
61   DEFINE_CLASS_NAME("test_memory_limiter");
62   virtual int execute();
63 };
64
65 //////////////
66
67 struct mem_record {
68   int parent;
69   int allocated;
70
71   mem_record(int parent_in = 0, int allocated_in = 0)
72       : parent(parent_in), allocated(allocated_in) {}
73 };
74
75 struct memorial : array<mem_record> {};
76
77 //////////////
78
79 int test_memory_limiter::execute()
80 {
81   FUNCDEF("execute");
82   time_stamp when_to_leave(RUN_TIME);
83   time_stamp start;
84   memorial wtc;
85   memory_limiter to_test(MAXIMUM_MEM_OVERALL, MAXIMUM_MEM_PER_OWNER);
86   int allocations = 0;
87   int deletions = 0;
88   basis::un_int total_allocated = 0;
89   basis::un_int total_deleted = 0;
90   while (time_stamp() < when_to_leave) {
91     int to_do = randomizer().inclusive(1, 100);
92     if (to_do < 50) {
93       // add a new record.
94       int alloc = randomizer().inclusive(1, 1 * MEGABYTE);
95 //isolate min max alloc
96       int parent = randomizer().inclusive(1, 120);
97 //isolate min max parents
98
99       if (!to_test.okay_allocation(parent, alloc))
100         continue;  // no space right now.
101       wtc += mem_record(parent, alloc);
102       allocations++;
103       total_allocated += alloc;
104     } else if (to_do < 88) {
105       // remove an existing record.
106       if (!wtc.length()) continue;  // nothing to remove.
107       int indy = randomizer().inclusive(0, wtc.length() - 1);
108       mem_record to_gone = wtc[indy];
109       wtc.zap(indy, indy);
110       ASSERT_TRUE(to_test.record_deletion(to_gone.parent, to_gone.allocated),
111           "first case failed to record deletion!");
112       deletions++;
113       total_deleted += to_gone.allocated;
114     } else {
115 //do something funky, like allocate part of one into another...
116     }
117   }
118
119   // now clear everything left in our list.
120   for (int i = 0; i < wtc.length(); i++) {
121     mem_record to_gone = wtc[i];
122     ASSERT_TRUE(to_test.record_deletion(to_gone.parent, to_gone.allocated),
123         "second case failed to record deletion!");
124     deletions++;
125     total_deleted += to_gone.allocated;
126   }
127
128   // now check that the memory limiter has returned to camber.
129
130   ASSERT_FALSE(to_test.overall_usage(), "final checks: there is still memory in use!");
131
132   ASSERT_EQUAL(to_test.overall_space_left(), MAXIMUM_MEM_OVERALL,
133       "final checks: the free space is not correct!");
134
135   int_set remaining = to_test.individuals_listed();
136   ASSERT_FALSE(remaining.elements(), "final checks: there were still uncleared individuals!");
137
138   time_stamp end;
139
140   LOG("stats for this run:");
141   LOG(astring(astring::SPRINTF, "\trun time %f ms",
142       end.value() - start.value()));
143   LOG(astring(astring::SPRINTF, "\tallocations %d, total memory allocated %d",
144       allocations, total_allocated));
145   LOG(astring(astring::SPRINTF, "\tdeletions %d, total memory deleted %d",
146       deletions, total_deleted));
147
148   return final_report();
149 }
150
151 //////////////
152
153 HOOPLE_MAIN(test_memory_limiter, );
154