12 vmsg (const char *format, va_list args, const char *suffix)
14 /* We go to some trouble to stuff the entire message into a
15 single buffer and output it in a single system call, because
16 that'll (typically) ensure that it gets sent to the console
17 atomically. Otherwise kernel messages like "foo: exit(0)"
18 can end up being interleaved if we're unlucky. */
19 static char buf[1024];
21 snprintf (buf, sizeof buf, "(%s) ", test_name);
22 vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args);
23 strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf));
24 write (STDOUT_FILENO, buf, strlen (buf));
28 msg (const char *format, ...)
34 va_start (args, format);
35 vmsg (format, args, "\n");
40 fail (const char *format, ...)
44 va_start (args, format);
45 vmsg (format, args, ": FAILED\n");
52 swap (void *a_, void *b_, size_t size)
58 for (i = 0; i < size; i++)
67 shuffle (void *buf_, size_t cnt, size_t size)
72 for (i = 0; i < cnt; i++)
74 size_t j = i + random_ulong () % (cnt - i);
75 swap (buf + i * size, buf + j * size, size);
80 exec_children (const char *child_name, pid_t pids[], size_t child_cnt)
84 for (i = 0; i < child_cnt; i++)
87 snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i);
88 CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR,
89 "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line);
94 wait_children (pid_t pids[], size_t child_cnt)
98 for (i = 0; i < child_cnt; i++)
100 int status = wait (pids[i]);
101 CHECK (status == (int) i,
102 "wait for child %zu of %zu returned %d (expected %zu)",
103 i + 1, child_cnt, status, i);
108 check_file_handle (int fd,
109 const char *file_name, const void *buf_, size_t size)
111 const char *buf = buf_;
115 /* Warn about file of wrong size. Don't fail yet because we
116 may still be able to get more information by reading the
118 file_size = filesize (fd);
119 if (file_size != size)
120 msg ("size of %s (%zu) differs from expected (%zu)",
121 file_name, file_size, size);
123 /* Read the file block-by-block, comparing data as we go. */
127 size_t block_size, ret_val;
129 block_size = size - ofs;
130 if (block_size > sizeof block)
131 block_size = sizeof block;
133 ret_val = read (fd, block, block_size);
134 if (ret_val != block_size)
135 fail ("read of %zu bytes at offset %zu in \"%s\" returned %zu",
136 block_size, ofs, file_name, ret_val);
138 compare_bytes (block, buf + ofs, block_size, ofs, file_name);
142 /* Now fail due to wrong file size. */
143 if (file_size != size)
144 fail ("size of %s (%zu) differs from expected (%zu)",
145 file_name, file_size, size);
147 msg ("verified contents of \"%s\"", file_name);
151 check_file (const char *file_name, const void *buf, size_t size)
155 CHECK ((fd = open (file_name)) > 1, "open \"%s\" for verification",
157 check_file_handle (fd, file_name, buf, size);
158 msg ("close \"%s\"", file_name);
163 compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
164 size_t ofs, const char *file_name)
166 const uint8_t *read_data = read_data_;
167 const uint8_t *expected_data = expected_data_;
171 if (!memcmp (read_data, expected_data, size))
174 for (i = 0; i < size; i++)
175 if (read_data[i] != expected_data[i])
177 for (j = i + 1; j < size; j++)
178 if (read_data[j] == expected_data[j])
182 msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
183 "from expected.", j - i, ofs + i, file_name);
188 msg ("Showing first differing %zu bytes.", show_cnt);
190 msg ("Data actually read:");
191 hex_dump (ofs + i, read_data + i, show_cnt, true);
192 msg ("Expected data:");
193 hex_dump (ofs + i, expected_data + i, show_cnt, true);
194 fail ("%zu bytes read starting at offset %zu in \"%s\" differ "
195 "from expected", j - i, ofs + i, file_name);