forked from svarshavchik/vera
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunit_test.H
164 lines (121 loc) · 3.3 KB
/
unit_test.H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#ifndef UNIT_TEST_H
#define UNIT_TEST_H
#include <vector>
#include <string>
#include <unistd.h>
#include <time.h>
#include <sstream>
#include <string>
#include "privrequest.H"
#include "proc_loader.H"
extern std::vector<std::string> logged_state_changes;
extern struct timespec fake_time;
extern std::vector<std::tuple<pid_t, int>> sent_sigs;
extern std::vector<std::string> completed_switchlog;
#define UNIT_TEST
#include "log.C"
#undef UNIT_TEST
extern std::vector<std::string> logged_runners;
extern pid_t next_pid;
extern bool all_forks_fail;
std::string read_stdoutcc(const external_filedesc &stdoutcc);
void populated(const proc_container &container, bool isit);
std::string populated_sh(const proc_container &container, bool isit=false);
#ifndef UNIT_TEST_RUNNER
static pid_t get_next_pid(const proc_container &container,
std::vector<std::vector<char>> &argv)
{
pid_t pid=next_pid++;
if (next_pid == 0)
++next_pid;
if (all_forks_fail)
pid= -1;
std::ostringstream o;
o << container->name << ":";
const char *sep=" ";
for (auto &c:argv)
{
o << sep << c.data();
sep="|";
}
o << " (pid " << pid << ")";
logged_runners.push_back(o.str());
if (pid != -1)
populated(container, true);
return pid;
}
#define UNIT_TEST_RUNNER (get_next_pid(container, argv))
#endif
#define UNIT_TEST() UNIT_TEST_RUNNER
#include "proc_container_runner.C"
#undef UNIT_TEST
extern std::function<void ()> reexec_handler;
void test_reset(bool keep_cgroupfs=false)
{
proc_containers_reset();
for (const auto &[pc, ignore] : get_proc_containers())
proc_container_stopped(pc->name);
logged_state_changes.clear();
logged_runners.clear();
next_pid=1;
all_forks_fail=false;
fake_time.tv_sec=1;
switchlog_stop();
completed_switchlog.clear();
if (!keep_cgroupfs)
{
std::filesystem::remove_all(
proc_container_group_data::get_cgroupfs_base_path()
);
std::filesystem::create_directory(
proc_container_group_data::get_cgroupfs_base_path()
);
}
std::filesystem::remove_all(slashprocslash);
std::filesystem::remove_all(environconfig());
environconfigvars.clear();
sent_sigs.clear();
reexec_handler=[]
{
throw "unexpected call to reexec.";
};
std::filesystem::remove_all(overrideconfigdir());
std::filesystem::create_directory(overrideconfigdir());
}
void test_finished()
{
test_reset();
std::filesystem::remove_all(
proc_container_group_data::get_cgroupfs_base_path()
);
std::filesystem::remove_all(overrideconfigdir());
}
void test_advance(time_t interval)
{
fake_time.tv_sec += interval;
run_timers();
}
///////////////////////////////////////////////////////////////////////////
//
// Simulate requests.
// Attempt to start a container.
std::string proc_container_start(const std::string &s);
//! Attempt to stop a container.
std::string proc_container_stop(const std::string &s);
//! Switch run levels
std::string proc_container_runlevel(const std::string &new_runlevel);
//! Get current runlevels
std::string current_runlevel();
//! Create a fake cgroup.procs file.
void create_fake_cgroup(const proc_container &pc,
const std::vector<pid_t> &pids);
/*! Create a fake /proc/ entry.
For the given pid, with the given parent pid, for the given executable,
and arg args.
*/
void create_fake_proc(
pid_t p,
pid_t ppid,
const std::string &exe,
const std::vector<std::string> &args);
#endif