qual_fault.c revision d35df493b4e7684c50d2d2fa032ee3a7ac228009
1/*
2 * Check that fault injection works properly.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 *    derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "tests.h"
31
32#include <assert.h>
33#include <errno.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38#include <sys/stat.h>
39#include <sys/uio.h>
40
41static const int expfd = 4;
42static const int gotfd = 5;
43
44#define DEFAULT_ERRNO ENOSYS
45
46static const char *errstr;
47static int is_raw, err, first, step, iter, try;
48
49static void
50invoke(int fail)
51{
52	static char buf[sizeof(int) * 3 + 3];
53	const struct iovec io = {
54		.iov_base = buf,
55		.iov_len = sprintf(buf, "%d.", ++try)
56	};
57	int rc;
58
59	if (!fail) {
60		rc = write(expfd, io.iov_base, io.iov_len);
61		if (rc != (int) io.iov_len)
62			perror_msg_and_fail("write");
63	}
64
65	errno = 0;
66	rc = writev(gotfd, &io, 1);
67
68	if (fail) {
69		if (!(rc == -1 && errno == err))
70			perror_msg_and_fail("expected errno %d"
71					    ", got rc == %d, errno == %d",
72					    err, rc, errno);
73
74		if (is_raw)
75			tprintf("writev(%#x, %p, 0x1) = -1 (errno %d)"
76				" (INJECTED)\n", gotfd, &io, err);
77		else
78			tprintf("writev(%d, [{iov_base=\"%s\", iov_len=%d}], 1)"
79				" = -1 %s (%m) (INJECTED)\n",
80				gotfd, buf, (int) io.iov_len, errstr);
81	} else {
82		if (rc != (int) io.iov_len)
83			perror_msg_and_fail("expected %d"
84					    ", got rc == %d, errno == %d",
85					    (int) io.iov_len, rc, errno);
86
87		if (is_raw)
88			tprintf("writev(%#x, %p, 0x1) = %#x\n", gotfd, &io, rc);
89		else
90			tprintf("writev(%d, [{iov_base=\"%s\", iov_len=%d}], 1)"
91				" = %d\n",
92				gotfd, buf, (int) io.iov_len, (int) io.iov_len);
93	}
94}
95
96int
97main(int argc, char *argv[])
98{
99	struct stat st;
100
101	assert(fstat(expfd, &st) == 0);
102	assert(fstat(gotfd, &st) == 0);
103
104	assert(argc == 6);
105
106	is_raw = !strcmp("raw", argv[1]);
107
108	errstr = argv[2];
109	err = atoi(errstr);
110	assert(err >= 0);
111
112	if (!err) {
113		if (!*errstr)
114			err = DEFAULT_ERRNO;
115		else if (!strcasecmp(errstr, "EINVAL"))
116			err = EINVAL;
117		else
118			err = ENOSYS;
119	}
120
121	errno = err;
122	errstr = errno2name();
123
124	first = atoi(argv[3]);
125	step = atoi(argv[4]);
126	iter = atoi(argv[5]);
127
128	assert(first > 0);
129	assert(step >= 0);
130
131	tprintf("%s", "");
132
133	int i;
134	for (i = 1; i <= iter; ++i) {
135		int fail = 0;
136		if (first > 0) {
137			--first;
138			if (first == 0) {
139				fail = 1;
140				first = step;
141			}
142		}
143		invoke(fail);
144	}
145
146	tprintf("%s\n", "+++ exited with 0 +++");
147	return 0;
148}
149