feisty meow concerns codebase  2.140
test_memory_limiter.cpp
Go to the documentation of this file.
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 
24 #include <basis/guards.h>
25 #include <basis/astring.h>
27 #include <mathematics/chaos.h>
29 #include <structures/set.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 
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 
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 
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;
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 
152 
153 HOOPLE_MAIN(test_memory_limiter, );
154 
The application_shell is a base object for console programs.
Represents a sequential, ordered, contiguous collection of objects.
Definition: array.h:54
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A simple object that wraps a templated set of ints.
Definition: set.h:156
Tracks memory currently in use by memory manager objects.
int elements() const
Returns the number of elements in this set.
Definition: set.h:47
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
time_representation value() const
returns the time_stamp in terms of the lower level type.
Definition: time_stamp.h:61
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition: enhance_cpp.h:45
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
Provides macros that implement the 'main' program of an application.
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
const int MEGABYTE
Number of bytes in a megabyte.
Definition: definitions.h:135
const int SECOND_ms
Number of milliseconds in a second.
Definition: definitions.h:120
unsigned int un_int
Abbreviated name for unsigned integers.
Definition: definitions.h:62
const int KILOBYTE
Number of bytes in a kilobyte.
Definition: definitions.h:134
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition: averager.h:21
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
Useful support functions for unit testing, especially within hoople.
Definition: unit_base.cpp:35
#define randomizer()
const int RUN_TIME
const int MAXIMUM_MEM_PER_OWNER
const int MAXIMUM_MEM_OVERALL
HOOPLE_MAIN(test_memory_limiter,)
#define LOG(to_print)
#define ASSERT_EQUAL(a, b, test_name)
Definition: unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition: unit_base.h:46
#define ASSERT_FALSE(a, test_name)
Definition: unit_base.h:50