c1886b295f73048921fe50e8c345d3699d32cb61
[ardour.git] / tools / sanity_check / main.cpp
1 /*
2  * 
3  *   program:  sanityCheck 
4  *   file:     main.c
5  *   author:   Todd Naugle
6  *   date:     11/17/2010
7  * 
8  *   Desc:  Command line version of the sanity check functions found in jack
9 */ 
10
11 #include <algorithm>
12 #include <stdio.h>
13 #include <string>
14 #include <vector>
15
16 #include "systemtest.h"
17
18
19 using namespace std;
20
21 typedef int (*testfuncPtr) ();
22 typedef int (*testfuncOpPtr) (string);
23
24 typedef struct
25 {
26         string                  switchText;                     // ie -option
27         string                  swOptionText;       // option arguments for just this swtich.
28         string                  descriptionText;        // Help Text on what this does
29         string                  failureText;            // What to say when this test fails
30         bool                    hasOption;                      // Set true if this switch has option paramters
31         testfuncPtr             functionPtr;            // Function to call
32         testfuncOpPtr   opFunctionPtr;          // Function with option string to call
33         string                  optionArg;                      // Storage used to hold any options passed in by the user
34 } testRecord;
35
36 static vector<testRecord>       gTestSet;
37         
38 static vector<string>           gValidSwitchList;
39 static vector<string>           gSwitchDescriptionList;
40
41 static vector<string>           gSwitchesReceived;
42
43 int
44 ExecuteAll()
45 {
46         bool OK = true;
47
48         OK &= system_user_can_rtprio();
49
50         if (system_has_frequencyscaling()) {
51                 OK &= !system_uses_frequencyscaling();
52         }
53
54         OK &= !(system_memlock_amount() == 0);
55         
56         return OK;
57 }
58
59 int
60 HasGroup(string name)
61 {
62         return system_has_group(name.c_str());
63 }
64
65 int
66 IsMemberOfGroup(string name)
67 {
68         return system_user_in_group(name.c_str());
69 }
70
71 int
72 CheckFreqScaling()
73 {
74         bool OK = true;
75
76         if (system_has_frequencyscaling()) {
77                 OK &= !system_uses_frequencyscaling();
78         }
79
80         return OK;
81 }
82
83 int
84 CheckMemoryLocking()
85 {
86         return !(system_memlock_amount() == 0);
87 }
88
89 int
90 PrintUsage()
91 {
92         printf("\n");
93         printf("  sanityCheck - A program to verify proper system settings for use with audio applications (Ardour/Jack/Mixbus).\n");
94         printf("\n");
95         printf("  Usage:  sanityCheck [OPTIONS]\n");
96         printf("\n");
97         printf("  Options are as follows:\n");
98         printf("\n");
99         printf("\n");
100         
101         vector<testRecord>::iterator            itr;
102         
103         for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
104                 printf("%20s %s :\t%s\n", (*itr).switchText.c_str(), (*itr).swOptionText.c_str(), (*itr).descriptionText.c_str());
105         }
106
107         printf("\n");
108         
109         return true;
110 }
111
112 void
113 DefineSwitches()
114 {
115         testRecord rec;
116         
117         // Global switches
118         rec.switchText = "-a";
119         rec.swOptionText = "";
120         rec.descriptionText = "Checks for a working RT system. Same as -rt -freqscaling -memlock";
121         rec.failureText = "";
122         rec.hasOption = false;
123         rec.functionPtr = &ExecuteAll;
124         rec.optionArg = "";
125         gTestSet.push_back(rec);
126
127         rec.switchText = "-h";
128         rec.swOptionText = "";
129         rec.descriptionText = "Print usage";
130         rec.failureText = "";
131         rec.hasOption = false;
132         rec.functionPtr = &PrintUsage;
133         rec.optionArg = "";
134         gTestSet.push_back(rec);
135
136         // Switches for various tests that can be performed.
137         rec.switchText = "-rt";
138         rec.swOptionText = "";
139         rec.descriptionText = "Verfiy that the user can run tasks with realtime priority";
140         rec.failureText = "";
141         rec.hasOption = false;
142         rec.functionPtr = &system_user_can_rtprio;
143         rec.optionArg = "";
144         gTestSet.push_back(rec);
145
146         rec.switchText = "-hasrtlimits";
147         rec.swOptionText = "";
148         rec.descriptionText = "Verfiy the system has a limits.conf and the audio group can use realtime";
149         rec.failureText = "";
150         rec.hasOption = false;
151         rec.functionPtr = &system_has_rtprio_limits_conf;
152         rec.optionArg = "";
153         gTestSet.push_back(rec);
154
155         rec.switchText = "-hasgroup";
156         rec.swOptionText = "<groupname>";
157         rec.descriptionText = "Verfiy that the system has a group named <groupname>";
158         rec.failureText = "";
159         rec.hasOption = true;
160         rec.opFunctionPtr = &HasGroup;
161         rec.optionArg = "";
162         gTestSet.push_back(rec);
163
164         rec.switchText = "-hasaudiogroup";
165         rec.swOptionText = "";
166         rec.descriptionText = "Verfiy that the system has an audio group (audio or jackuser) defined";
167         rec.failureText = "";
168         rec.hasOption = false;
169         rec.functionPtr = &system_has_audiogroup;
170         rec.optionArg = "";
171         gTestSet.push_back(rec);
172
173         rec.switchText = "-memberofgroup";
174         rec.swOptionText = "<groupname>";
175         rec.descriptionText = "Verfiy that the user is a member of the group named <groupname>";
176         rec.failureText = "";
177         rec.hasOption = true;
178         rec.opFunctionPtr = &IsMemberOfGroup;
179         rec.optionArg = "";
180         gTestSet.push_back(rec);
181
182         rec.switchText = "-memberaudiogroup";
183         rec.swOptionText = "";
184         rec.descriptionText = "Verfiy that the user is a member of the audio group (audio or jackuser)";
185         rec.failureText = "";
186         rec.hasOption = false;
187         rec.functionPtr = &system_user_in_audiogroup;
188         rec.optionArg = "";
189         gTestSet.push_back(rec);
190
191         rec.switchText = "-freqscaling";
192         rec.swOptionText = "";
193         rec.descriptionText = "Check to see if frequency scaling is being used by the CPU";
194         rec.failureText = "";
195         rec.hasOption = false;
196         rec.functionPtr = &CheckFreqScaling;
197         rec.optionArg = "";
198         gTestSet.push_back(rec);
199
200         rec.switchText = "-memlock";
201         rec.swOptionText = "";
202         rec.descriptionText = "Check to see if the user is able to lock memory";
203         rec.failureText = "";
204         rec.hasOption = false;
205         rec.functionPtr = &CheckMemoryLocking;
206         rec.optionArg = "";
207         gTestSet.push_back(rec);
208
209 }
210
211 bool
212 ParseSwitches(
213         int             argc,
214         char    **argv)
215 {
216         string  tmp;
217         vector<testRecord>::iterator    itr;
218         bool    OK = true;
219         int     i;
220         
221         if (argc == 1) {
222                 gSwitchesReceived.push_back("-a");
223         }
224         else {
225                 for (i = 1; i < argc && OK == true; i++) {
226                         tmp = argv[i];
227
228                         for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
229                                 if (tmp == (*itr).switchText) {
230                                         if ((*itr).hasOption == true) {
231                                                 if (++i < argc) {
232                                                         string  op = argv[i];
233                                                         if (op[0] == '-') {
234                                                                 // reqiured option for this switch is missing
235                                                                 --i;
236                                                                 OK = false;
237                                                                 break;
238                                                         }
239                                                         (*itr).optionArg = op;
240                                                         break;
241                                                 }
242                                                 else {
243                                                         // reqiured option for this switch is missing
244                                                         --i;
245                                                         OK = false;
246                                                         break;
247                                                 }
248                                         }
249                                         break;
250                                 }
251                         }
252                         
253                         if (OK && itr != gTestSet.end()) {
254                                 // Known option switch found
255                                 gSwitchesReceived.push_back(tmp);
256                         }
257                         else {
258                                 // Unknown option
259                                 OK = false;
260                         }
261                 }
262         }
263
264         if (OK) {
265                 // All switches are at least valid, now check to make sure they are all valid to 
266                 // be used together.
267                 
268                 if (gSwitchesReceived.size() > 1) {
269                         // make sure help is not mixed with other options
270                         vector<string>::iterator        swItr;
271                         tmp = "-h";
272
273                         swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
274
275                         if (swItr != gSwitchesReceived.end()) {
276                                 gSwitchesReceived.clear();
277                                 gSwitchesReceived.push_back("-h");
278                         }
279
280                         // make sure -a is only used by itself
281                         tmp = "-a";
282                         swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
283
284                         if (swItr != gSwitchesReceived.end()) {
285                                 gSwitchesReceived.clear();
286                                 gSwitchesReceived.push_back("-a");
287                         }
288                 }
289
290                 return true;
291         }
292         else {
293                 fprintf(stderr, "\n");
294                 fprintf(stderr, "ERROR - Invalid Option: %s\n", (const char *) argv[--i]); 
295                 fprintf(stderr, "Check syntax\n");
296                 PrintUsage();
297                 return false;
298         }
299 }
300
301 bool
302 Execute()
303 {
304         bool OK = true;
305         vector<string>::iterator        itr;
306         vector<testRecord>::iterator    testItr;
307         
308         for (itr = gSwitchesReceived.begin(); itr != gSwitchesReceived.end(); ++itr) {
309                 for (testItr = gTestSet.begin(); testItr != gTestSet.end(); ++testItr) {
310                         if ((*itr) == (*testItr).switchText) {
311                                 break;
312                         }
313                 }
314                 
315                 bool result;
316                 if ((*testItr).hasOption) {
317                         result = ((*testItr).opFunctionPtr((*testItr).optionArg) != 0);
318                 }
319                 else {
320                         result = ((*testItr).functionPtr() != 0);
321                 }
322
323                 if (result == 0) {
324                         // Check for a Failure message and print it if found.
325                         if (!(*testItr).failureText.empty()) {
326                                 printf("\n%s\n", (*testItr).failureText.c_str());
327                         }
328                 }
329
330                 OK &= result;
331         }
332         
333         return OK;
334 }
335
336 int
337 main(
338         int              argc,
339         char    **argv)
340 {
341         int status = 0;
342         
343         DefineSwitches();
344
345         if (ParseSwitches(argc, argv)) {
346                 if (Execute() == false) {
347                         printf("\nSanity Check Failed!\n\n");
348                         status = -1;
349                 }
350                 else {
351                         printf("\nSanity Check OK!\n\n");
352                 }
353         }
354         else {
355                 status = -1;
356         }
357
358         return status;
359 }