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