11 vmsg (const char *format, va_list args, const char *suffix)
13 /* We go to some trouble to stuff the entire message into a
14 single buffer and output it in a single system call, because
15 that'll (typically) ensure that it gets sent to the console
16 atomically. Otherwise kernel messages like "foo: exit(0)"
17 can end up being interleaved if we're unlucky. */
18 static char buf[1024];
20 snprintf (buf, sizeof buf, "(%s) ", test_name);
21 vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args);
22 strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf));
23 write (STDOUT_FILENO, buf, strlen (buf));
27 msg (const char *format, ...)
33 va_start (args, format);
34 vmsg (format, args, "\n");
39 fail (const char *format, ...)
43 va_start (args, format);
44 vmsg (format, args, ": FAILED\n");
51 seq_test (const char *filename, void *buf, size_t size, size_t initial_size,
52 size_t (*block_size_func) (void),
53 void (*check_func) (int fd, long ofs))
58 random_bytes (buf, size);
59 CHECK (create (filename, initial_size), "create \"%s\"", filename);
60 CHECK ((fd = open (filename)) > 1, "open \"%s\"", filename);
63 msg ("writing \"%s\"", filename);
66 size_t block_size = block_size_func ();
67 if (block_size > size - ofs)
68 block_size = size - ofs;
70 if (write (fd, buf + ofs, block_size) <= 0)
71 fail ("write %zu bytes at offset %zu in \"%s\" failed",
72 block_size, ofs, filename);
75 if (check_func != NULL)
78 msg ("close \"%s\"", filename);
80 check_file (filename, buf, size);
84 swap (void *a_, void *b_, size_t size)
90 for (i = 0; i < size; i++)
99 shuffle (void *buf_, size_t cnt, size_t size)
104 for (i = 0; i < cnt; i++)
106 size_t j = i + random_ulong () % (cnt - i);
107 swap (buf + i * size, buf + j * size, size);
112 check_file (const char *filename, const void *buf_, size_t size)
114 const char *buf = buf_;
119 CHECK ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
124 size_t block_size = size - ofs;
125 if (block_size > sizeof block)
126 block_size = sizeof block;
128 if (read (fd, block, block_size) <= 0)
129 fail ("read %zu bytes at offset %zu in \"%s\" failed",
130 block_size, ofs, filename);
132 compare_bytes (block, buf + ofs, block_size, ofs, filename);
136 msg ("close \"%s\"", filename);
141 compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
142 size_t ofs, const char *filename)
144 const uint8_t *read_data = read_data_;
145 const uint8_t *expected_data = expected_data_;
149 if (!memcmp (read_data, expected_data, size))
152 for (i = 0; i < size; i++)
153 if (read_data[i] != expected_data[i])
155 for (j = i + 1; j < size; j++)
156 if (read_data[j] == expected_data[j])
160 msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
161 "from expected.", j - i, ofs + i, filename);
166 msg ("Showing first differing %zu bytes.", show_cnt);
168 msg ("Data actually read:");
169 hex_dump (ofs + i, read_data + i, show_cnt, true);
170 msg ("Expected data:");
171 hex_dump (ofs + i, expected_data + i, show_cnt, true);
172 fail ("%zu bytes read starting at offset %zu in \"%s\" differ "
173 "from expected", j - i, ofs, filename);
177 exec_children (const char *child_name, pid_t pids[], size_t child_cnt)
181 for (i = 0; i < child_cnt; i++)
184 snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i);
185 CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR,
186 "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line);
191 wait_children (pid_t pids[], size_t child_cnt)
195 for (i = 0; i < child_cnt; i++)
197 int status = wait (pids[i]);
198 CHECK (status == (int) i,
199 "wait for child %zu of %zu returned %d (expected %zu)",
200 i + 1, child_cnt, status, i);