1 #include "test.h"
2 #include "systype.h"
3 #include "generic_agent.h"
4 #include "item_lib.h"
5 #include "mon.h"
6 #include <logging.h> /* LogSetGlobalLevel */
7 #include <misc_lib.h> /* xsnprintf */
8 #include <known_dirs.h>
9
10 char CFWORKDIR[CF_BUFSIZE];
11
tests_setup(void)12 static void tests_setup(void)
13 {
14 xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/mon_processes_test.XXXXXX");
15 mkdtemp(CFWORKDIR);
16
17 char buf[CF_BUFSIZE];
18 xsnprintf(buf, CF_BUFSIZE, "%s", GetStateDir());
19 mkdir(buf, 0755);
20 }
21
tests_teardown(void)22 static void tests_teardown(void)
23 {
24 char cmd[CF_BUFSIZE];
25 xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR);
26 system(cmd);
27 }
28
GetSysUsers(int * userListSz,int * numRootProcs,int * numOtherProcs)29 static bool GetSysUsers( int *userListSz, int *numRootProcs, int *numOtherProcs)
30 {
31 FILE *fp;
32 char user[CF_BUFSIZE];
33 char vbuff[CF_BUFSIZE];
34 char cbuff[CF_BUFSIZE];
35
36 /*
37 * The best would be to ask only "user" field from ps, but we are asking
38 * for "user,pid". The reason is that we try to mimic cf-monitord's
39 * behaviour, else a different number of users might be detected by the
40 * test, as printing "user,pid" truncates the user column. TODO fix the
41 * ps command to use only "-o user" in both mon_processes.c and this test.
42 */
43 #if defined(__sun)
44 xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user,pid > %s/users.txt", CFWORKDIR);
45 #elif defined(_AIX)
46 xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -N -eo user,pid > %s/users.txt", CFWORKDIR);
47 #elif defined(__hpux)
48 xsnprintf(cbuff, CF_BUFSIZE, "UNIX95=1 /bin/ps -eo user,pid > %s/users.txt", CFWORKDIR);
49 /* SKIP on HP-UX since cf-monitord doesn't count processes correctly! */
50 return false;
51 #else
52 xsnprintf(cbuff, CF_BUFSIZE, "ps -eo user:30,pid > %s/users.txt", CFWORKDIR);
53 #endif
54
55 Item *userList = NULL;
56 system(cbuff);
57 xsnprintf(cbuff, CF_BUFSIZE, "%s/users.txt", CFWORKDIR);
58 if ((fp = fopen(cbuff, "r")) == NULL)
59 {
60 return false;
61 }
62 while (fgets(vbuff, CF_BUFSIZE, fp) != NULL)
63 {
64 int ret = sscanf(vbuff, " %s ", user);
65
66 if (ret != 1 ||
67 strcmp(user, "") == 0 ||
68 strcmp(user, "USER") == 0 ||
69 isdigit(user[0]))
70 {
71 continue;
72 }
73
74 if (!IsItemIn(userList, user))
75 {
76 PrependItem(&userList, user, NULL);
77 (*userListSz)++;
78 }
79
80 if (strcmp(user, "root") == 0)
81 {
82 (*numRootProcs)++;
83 }
84 else
85 {
86 (*numOtherProcs)++;
87 }
88 }
89 fclose(fp);
90
91 if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
92 {
93 char *s = ItemList2CSV(userList);
94 Log(LOG_LEVEL_DEBUG, "Users in the process table detected from the test: (%s)", s);
95 free(s);
96 }
97 DeleteItemList(userList);
98 return true;
99 }
100
test_processes_monitor(void)101 void test_processes_monitor(void)
102 {
103 double cf_this[100] = { 0.0 };
104 MonProcessesGatherData(cf_this);
105 MonProcessesGatherData(cf_this);
106 MonProcessesGatherData(cf_this);
107
108 int usr, rusr, ousr;
109 usr = rusr = ousr = 0;
110
111 bool res = GetSysUsers(&usr, &rusr, &ousr);
112 if (!res)
113 {
114 Log(LOG_LEVEL_NOTICE, "TEST SKIPPED!");
115 return;
116 }
117
118 usr = 3*usr;
119 rusr = 3*rusr;
120 ousr = 3*ousr;
121
122 Log(LOG_LEVEL_NOTICE, "Counted %d/3 different users on the process table,"
123 " while CFEngine counted %f/3", usr, cf_this[ob_users]);
124 Log(LOG_LEVEL_NOTICE, "This is a non-deterministic test,"
125 " the two numbers should be *about* the same since the 'ps'"
126 " commands run very close to each other");
127
128 int upper = (int) ((double) usr*1.20);
129 int lower = (int) ((double) usr*0.80);
130 assert_in_range((long long) cf_this[ob_users], lower, upper);
131 }
132
main()133 int main()
134 {
135 LogSetGlobalLevel(LOG_LEVEL_DEBUG);
136 strcpy(CFWORKDIR, "data");
137
138 #if defined(__sun)
139 VSYSTEMHARDCLASS = PLATFORM_CONTEXT_SOLARIS;
140 VPSHARDCLASS = PLATFORM_CONTEXT_SOLARIS;
141 #elif defined(_AIX)
142 VSYSTEMHARDCLASS = PLATFORM_CONTEXT_AIX;
143 VPSHARDCLASS = PLATFORM_CONTEXT_AIX;
144 #elif defined(__linux__)
145 VSYSTEMHARDCLASS = PLATFORM_CONTEXT_LINUX;
146 VPSHARDCLASS = PLATFORM_CONTEXT_LINUX;
147 #endif
148
149 PRINT_TEST_BANNER();
150 tests_setup();
151 const UnitTest tests[] =
152 {
153 unit_test(test_processes_monitor),
154 };
155
156 int ret = run_tests(tests);
157 tests_teardown();
158 return ret;
159 }
160