f0e413d0a16c17a434ed8afd412ab18069c33ba2
[platform/core/system/stability-monitor.git] / tests / test-stability-mem.cpp
1 #include "test-stability.hpp"
2
3 // C
4 #include <cstdlib>
5
6 // C++
7 #include <thread>
8 #include <vector>
9
10 // POSIX
11 #include <sys/sysinfo.h>
12
13 static void * do_mem (size_t to_alloc)
14 {
15         /* Allocate memory and pretend we're using it (so as to make it actually
16          * count to RSS use). The allocated amount stays constant. The memory is
17          * volatile to prevent smart compilers from optimizing stuff out. */
18
19         std::unique_ptr <volatile char []> ptr (new volatile char [to_alloc]);
20         for (size_t i = 0; i < to_alloc; i += 4096) // FIXME: 4096 -> page size
21                 ptr[i] = 'a' + (i % ('z' - 'a'));
22
23         while (!global_stop)
24                 std::this_thread::sleep_for (std::chrono::seconds (1));
25
26         return nullptr;
27 }
28
29 unsigned long long operator "" _MB (unsigned long long n)
30 { return 1024 * 1024 * n; }
31
32 static void * mem_heavy_peak (void * arg)
33 { return do_mem (750_MB); }
34
35 static void * mem_heavy_avg (void * arg)
36 { return do_mem (400_MB); }
37
38 static void * mem_light (void * arg)
39 { return do_mem (25_MB); }
40
41 struct mem_handler : public dbus_signal_handler {
42         const std::string limitType;
43         static constexpr const char * const gtype = "(isdda{sv})";
44
45         mem_handler (const char * lt) : limitType (lt) { }
46
47         bool match (const gchar * objpath, const gchar * iface, GVariant * parameters) const override {
48                 if ("/Org/Tizen/StabilityMonitor/tsm_mem"s != objpath
49                 ||  "org.tizen.abnormality.mem.relative"s  != iface
50                 ||  !g_variant_is_of_type (parameters, G_VARIANT_TYPE(gtype)))
51                         return false;
52
53                 const char * paramType = nullptr;
54                 int pid = -1;
55                 g_variant_get (parameters, gtype, & pid, & paramType, nullptr, nullptr, nullptr);
56                 return pid == getpid() && limitType == paramType;
57         }
58 } handler_avg ("avg"), handler_peak ("peak");
59
60 bool run_mem_test (thread_func_t * func, size_t test_time, dbus_signal_handler * handler)
61 { return run_test (func, 1, handler, test_time); }
62
63 int main (int argc, char ** argv)
64 {
65         const std::vector <std::pair <bool (*) (), std::string>> test_cases
66                 { { []() {
67                         /* Do a reasonable amount of memory (re)allocation.
68                          * Expect no signal. */
69                         return run_mem_test (mem_light, TEST_TIME_PEAK, & handler_peak);
70                 } , "small allocation (25 MB + overhead), expecting no signal"
71                 } , { []() {
72                         /* Allocate and keep lots of memory.
73                          * Expect a signal. */
74                         return ! run_mem_test (mem_heavy_peak, TEST_TIME_PEAK, & handler_peak);
75                 } , "heavy allocation (750 MB + overhead), expecting peak signal"
76                 } , { []() {
77                         /* Allocate an amount of memory not high enough
78                          * to trigger peak, but keep it long enough to
79                          * trigger average. */
80                         return ! run_mem_test (mem_heavy_avg, TEST_TIME_AVG, & handler_avg);
81                 } , "medium allocation (400 MB + overhead), expecting avg signal"
82                 }
83         };
84
85         return standard_main (test_cases, argc, argv);
86 }