• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  *
4  * This program is free software;  you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program;  if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  */
19 
20 /*
21  * File:        ltpapicmd.c
22  *
23  * Description: This program impliments a command line version of some of the
24  *              LTP harness API's. This will enable tests written in shell and
25  *              other scripts to report problems and log results in the LTP
26  *              harness format. The intent is to have a common format in which
27  *              the C tests and tests written in scripts report results in
28  *              a common format.
29  *
30  *              The following LTP API's are available currently in command line
31  *              form:
32  *              tst_brk   - Print result message and break remaining test cases
33  *              tst_brkm  - Print result message, including file contents, and
34  *                          break remaining test cases
35  *              tst_res   - Print result message, including file contents
36  *              tst_resm  - Print result message
37  *              tst_exit  - Exit test with a meaningful exit value
38  *
39  *              These are the minimum set of functions or commands required to
40  *              report results.
41  *
42  * Exit:        All commands exit with
43  *               0   - on success
44  *              -1  - on failure
45  *
46  * History
47  * Dec 10 2002 - Created - Manoj Iyer manjo@mail.utexas.edu
48  * Dec 12 2002 - Modified - Code that checked if the environment variables
49  *               TCID and TST_TOTAL were set did not print usage message.
50  *               Modified code to print usage message in each case.
51  * Dec 16 2002 - Modified - Code to get the test number, gets environment
52  *               variable TST_COUNT and initializes tst_count.
53  * Dec 16 2002 - Documentation and comment changes.
54  * Feb 11 2003 - tst_count was set to -1 during init or setup in the script.
55  *               this was causing tst_resm to issue a warning message.
56  *               This bug is now fixed.
57  *
58  */
59 
60 #include <sys/socket.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <stdlib.h>
64 #include <stdint.h>
65 #include "test.h"
66 #include "usctest.h"
67 #include "safe_macros.h"
68 
69 char *TCID;			/* Name of the testcase */
70 int TST_TOTAL;			/* Total number of testcases */
71 
72 static char cmd_name[1024];	/* name by which this program is invoked tst_brk etc */
73 static char *tst_total;		/* total number of tests in the file. */
74 static char *tst_cntstr;	/* sets the value of tst_count with this value */
75 
76 
77 /*
78  * Function:    ident_ttype - Return test result type.
79  *
80  * Description: This function will return the test result type, it actually
81  *              the string that is entered by the user to an integer value that
82  *              is understood by the API's.
83  *
84  * Return:      test type TPASS, TFAIL, TBROK, TCONF, TWARN, or TINFO
85  *              on success
86  *              -1 on failure
87  */
ident_ttype(char * tstype)88 int ident_ttype(char *tstype)
89 {
90 	/* test result type one of TPASS, TFAIL, etc */
91 	if (strcmp(tstype, "TBROK") == 0)
92 		return TBROK;
93 	else if (strcmp(tstype, "TFAIL") == 0)
94 		return TFAIL;
95 	else if (strcmp(tstype, "TPASS") == 0)
96 		return TPASS;
97 	else if (strcmp(tstype, "TCONF") == 0)
98 		return TCONF;
99 	else if (strcmp(tstype, "TWARN") == 0)
100 		return TWARN;
101 	else if (strcmp(tstype, "TINFO") == 0)
102 		return TINFO;
103 	else
104 		return -1;
105 }
106 
tst_cat_file(const char * filename)107 void tst_cat_file(const char *filename)
108 {
109 	const char *cmd[] = {"cat", filename, NULL};
110 
111 	tst_run_cmd(NULL, cmd, NULL, NULL, 0);
112 }
113 
apicmd_brk(int argc,char * argv[])114 void apicmd_brk(int argc, char *argv[])
115 {
116 	int trestype;
117 	char *file_name;
118 
119 	if (argc < 5) {
120 		fprintf(stderr, "Usage: %s TTYPE FNAME FUNC STRING\n"
121 			"\tTTYPE  - Test Result Type; one of TFAIL, TBROK "
122 			"and TCONF.\n"
123 			"\tFNAME  - Print contents of this file after the message\n"
124 			"\tFUNC   - Cleanup function (ignored), but MUST be provided\n"
125 			"\tSTRING - Message explaining the test result\n",
126 			cmd_name);
127 		exit(1);
128 	}
129 	trestype = ident_ttype((argv++)[0]);
130 	file_name = (argv++)[0];
131 	tst_cat_file(file_name);
132 	argv++;
133 	tst_brkm(trestype, NULL, "%s", *argv);
134 
135 }
136 
apicmd_res(int argc,char * argv[])137 void apicmd_res(int argc, char *argv[])
138 {
139 	int trestype;
140 	char *file_name;
141 
142 	if (argc < 4) {
143 		fprintf(stderr, "Usage: %s TTYPE FNAME STRING\n"
144 			"\tTTYPE  - Test Result Type; one of TFAIL, TBROK "
145 			"and  TCONF.\n"
146 			"\tFNAME  - Print contents of this file after the message\n"
147 			"\tSTRING - Message explaining the test result\n",
148 			cmd_name);
149 		exit(1);
150 	}
151 	trestype = ident_ttype((argv++)[0]);
152 	file_name = (argv++)[0];
153 	tst_cat_file(file_name);
154 	tst_resm(trestype, "%s", *argv);
155 }
156 
apicmd_brkm(int argc,char * argv[])157 void apicmd_brkm(int argc, char *argv[])
158 {
159 	int trestype;
160 
161 	if (argc < 4) {
162 		fprintf(stderr, "Usage: %s TTYPE FUNC STRING\n"
163 			"\tTTYPE  - Test Result Type; one of TFAIL, TBROK "
164 			"and TCONF.\n"
165 			"\tFUNC   - Cleanup function (ignored), but MUST be provided\n"
166 			"\tSTRING - Message explaining the test result\n",
167 			cmd_name);
168 		exit(1);
169 	}
170 	trestype = ident_ttype((argv++)[0]);
171 	argv++;
172 	tst_brkm(trestype, NULL, "%s", *argv);
173 }
174 
apicmd_resm(int argc,char * argv[])175 void apicmd_resm(int argc, char *argv[])
176 {
177 	int trestype;
178 
179 	if (argc < 3) {
180 		fprintf(stderr, "Usage: %s TTYPE STRING\n"
181 			"\tTTYPE  - Test Result Type; one of TFAIL, TBROK"
182 			"and TCONF.\n"
183 			"\tSTRING - Message explaining the test result\n",
184 			cmd_name);
185 		exit(1);
186 	}
187 	trestype = ident_ttype((argv++)[0]);
188 	tst_resm(trestype, "%s", *argv);
189 }
190 
191 struct param_pair {
192 	char *cmd;
193 	int value;
194 };
195 
apicmd_get_unused_port(int argc,char * argv[])196 unsigned short apicmd_get_unused_port(int argc, char *argv[])
197 {
198 	if (argc != 3)
199 		goto err;
200 
201 	const struct param_pair params[][3] = {
202 		{{"ipv4", AF_INET}, {"ipv6", AF_INET6}, {NULL, 0}},
203 		{{"stream", SOCK_STREAM}, {"dgram", SOCK_DGRAM}, {NULL, 0}}
204 	};
205 
206 	int i;
207 	const struct param_pair *p[2];
208 	for (i = 0; i < 2; ++i) {
209 		for (p[i] = params[i]; p[i]->cmd; ++p[i]) {
210 			if (!strcmp(p[i]->cmd, argv[i]))
211 				break;
212 		}
213 		if (!p[i]->cmd)
214 			goto err;
215 	}
216 	return  tst_get_unused_port(NULL, p[0]->value, p[1]->value);
217 
218 err:
219 	fprintf(stderr, "Usage: tst_get_unused_port FAMILY TYPE\n"
220 		"where FAMILY := { ipv4 | ipv6 }\n"
221 		"      TYPE := { stream | dgram }\n");
222 	exit(1);
223 }
224 
apicmd_fs_has_free(int argc,char * argv[])225 int apicmd_fs_has_free(int argc, char *argv[])
226 {
227 	if (argc != 3) {
228 		fprintf(stderr, "Usage: tst_fs_has_free path required_bytes\n"
229 			"path: the pathname of the mounted filesystem\n"
230 			"required_bytes: the required free space"
231 			" (supports kB, MB and GB suffixes)\n");
232 		exit(2);
233 	}
234 
235 	char *endptr;
236 	unsigned int required_kib = strtoull(argv[1], &endptr, 0);
237 	unsigned int mul = TST_BYTES;
238 
239 	if (*argv[1] == '\0')
240 		goto fs_has_free_err;
241 
242 	if (*endptr != '\0') {
243 		if (!strcasecmp(endptr, "kB")) {
244 			mul = TST_KB;
245 		} else if (!strcasecmp(endptr, "MB")) {
246 			mul = TST_MB;
247 		} else if (!strcasecmp(endptr, "GB")) {
248 			mul = TST_GB;
249 		} else {
250 			goto fs_has_free_err;
251 		}
252 	}
253 
254 	exit(!tst_fs_has_free(NULL, argv[0], required_kib, mul));
255 
256 fs_has_free_err:
257 	fprintf(stderr, "%s is not a valid size\n", argv[1]);
258 	exit(2);
259 }
260 
261 /*
262  * Function:    main - entry point of this program
263  *
264  * Description: Parses the arguments to each command. Most commands have in
265  *              common atlest 2 arguments, type of test result, which is one of
266  *              TPASS, TFAIL, TBROK, TCONF, etc, and a message that describes
267  *              the result. Other arguments are a file, the contents of which
268  *              are printed after the type of test result and associated message
269  *              is printed, also a cleanup function that will be executed.
270  *              Currently this function name is ignored but MUST be provided
271  *              for compatability reasons.
272  *
273  *              The different commands are actually a hard link to this program
274  *              the program invokes the appropriate function based on the
275  *              command name with which it was invoked.
276  *
277  *              Set the values for TCID to the name of the test case.
278  *              set the value for TST_TOTAL for total number of tests this is
279  *              required in case one test breaks and all following tests also
280  *              should be reported as broken.
281  *              Set tst_count before every individual test.
282  *
283  * Exit:        0 on success
284  *              -1 on failure
285  */
main(int argc,char * argv[])286 int main(int argc, char *argv[])
287 {
288 	strcpy(cmd_name, SAFE_BASENAME(NULL, (argv++)[0]));
289 
290 	TCID = getenv("TCID");
291 	tst_total = getenv("TST_TOTAL");
292 	tst_cntstr = getenv("TST_COUNT");
293 	if (TCID == NULL || tst_total == NULL || tst_cntstr == NULL) {
294 		 if(!strcmp(cmd_name, "tst_fs_has_free") &&
295 		    !strcmp(cmd_name, "tst_get_unused_port")) {
296 			fprintf(stderr,
297 				"\nSet variables TCID, TST_TOTAL, and TST_COUNT before each test:\n"
298 				"export TCID=<test name>\n"
299 				"export TST_TOTAL=<Total Number of Tests >\n"
300 				"export TST_COUNT=<Test case number>\n\n");
301 			/* Make sure the user knows there's an error. */
302 			abort();
303 		}
304 	} else {
305 		TST_TOTAL = atoi(tst_total);
306 		tst_count = atoi(tst_cntstr);
307 		if (tst_count > 0)
308 			tst_count--;
309 
310 		if (strcmp(TCID, " ") == 0) {
311 			fprintf(stderr,
312 				"Variable TCID not set, use: TCID=<test name>\n");
313 			exit(1);
314 		}
315 		if (TST_TOTAL <= 0) {
316 			fprintf(stderr,
317 				"Variable TST_TOTAL is set to 0, must be "
318 				"greater than zero\n");
319 			exit(1);
320 		}
321 	}
322 
323 	if (strcmp(cmd_name, "tst_brk") == 0) {
324 		apicmd_brk(argc, argv);
325 	} else if (strcmp(cmd_name, "tst_res") == 0) {
326 		apicmd_res(argc, argv);
327 	} else if (strcmp(cmd_name, "tst_brkm") == 0) {
328 		apicmd_brkm(argc, argv);
329 	} else if (strcmp(cmd_name, "tst_resm") == 0) {
330 		apicmd_resm(argc, argv);
331 	} else if (strcmp(cmd_name, "tst_exit") == 0) {
332 		tst_exit();
333 	} else if (strcmp(cmd_name, "tst_ncpus") == 0) {
334 		printf("%li\n", tst_ncpus());
335 	} else if (strcmp(cmd_name, "tst_ncpus_conf") == 0) {
336 		printf("%li\n", tst_ncpus_conf());
337 	} else if (strcmp(cmd_name, "tst_ncpus_max") == 0) {
338 		printf("%li\n", tst_ncpus_max());
339 	} else if (strcmp(cmd_name, "tst_get_unused_port") == 0) {
340 		printf("%u\n", apicmd_get_unused_port(argc, argv));
341 	} else if (strcmp(cmd_name, "tst_fs_has_free") == 0) {
342 		apicmd_fs_has_free(argc, argv);
343 	}
344 
345 	exit(0);
346 }
347