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