#include <stdio.h>
#include <string.h>
#include <syscall.h>
-#include "../lib/arc4.h"
bool quiet = false;
static void
-vmsg (const char *format, va_list args, bool failure)
+vmsg (const char *format, va_list args, const char *suffix)
{
- if (quiet && !failure)
- return;
-
- printf ("(%s) ", test_name);
- vprintf (format, args);
- if (failure)
- printf (": FAILED");
- printf ("\n");
+ /* We go to some trouble to stuff the entire message into a
+ single buffer and output it in a single system call, because
+ that'll (typically) ensure that it gets sent to the console
+ atomically. Otherwise kernel messages like "foo: exit(0)"
+ can end up being interleaved if we're unlucky. */
+ static char buf[1024];
+
+ snprintf (buf, sizeof buf, "(%s) ", test_name);
+ vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args);
+ strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf));
+ write (STDOUT_FILENO, buf, strlen (buf));
}
void
{
va_list args;
+ if (quiet)
+ return;
va_start (args, format);
- vmsg (format, args, false);
+ vmsg (format, args, "\n");
va_end (args);
}
{
va_list args;
- quiet = false;
-
va_start (args, format);
- vmsg (format, args, true);
+ vmsg (format, args, ": FAILED\n");
va_end (args);
exit (1);
}
-void
-check (bool success, const char *format, ...)
-{
- va_list args;
-
- va_start (args, format);
- if (success)
- {
- if (!quiet)
- vmsg (format, args, false);
- }
- else
- {
- vmsg (format, args, true);
- exit (1);
- }
- va_end (args);
-}
-
void
-seq_test (const char *filename, void *buf, size_t size,
- size_t initial_size, int seed,
+seq_test (const char *filename, void *buf, size_t size, size_t initial_size,
size_t (*block_size_func) (void),
void (*check_func) (int fd, long ofs))
{
- static struct arc4 arc4;
size_t ofs;
int fd;
- arc4_init (&arc4, &seed, sizeof seed);
- arc4_crypt (&arc4, buf, size);
-
- check (create (filename, initial_size), "create \"%s\"", filename);
- check ((fd = open (filename)) > 1, "open \"%s\"", filename);
+ random_bytes (buf, size);
+ CHECK (create (filename, initial_size), "create \"%s\"", filename);
+ CHECK ((fd = open (filename)) > 1, "open \"%s\"", filename);
ofs = 0;
msg ("writing \"%s\"", filename);
char block[512];
int fd;
- check ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
+ CHECK ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
ofs = 0;
while (ofs < size)
fail ("read %zu bytes at offset %zu in \"%s\" failed",
block_size, ofs, filename);
- if (memcmp (buf + ofs, block, block_size))
- {
- if (block_size <= 512)
- {
- printf ("Expected data:\n");
- hex_dump (ofs, buf + ofs, block_size, false);
- printf ("Actually read data:\n");
- hex_dump (ofs, block, block_size, false);
- }
- fail ("%zu bytes at offset %zu differed from expected",
- block_size, ofs);
- }
-
+ compare_bytes (block, buf + ofs, block_size, ofs, filename);
ofs += block_size;
}
msg ("close \"%s\"", filename);
close (fd);
}
+
+void
+compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
+ size_t ofs, const char *filename)
+{
+ const uint8_t *read_data = read_data_;
+ const uint8_t *expected_data = expected_data_;
+ size_t i, j;
+ size_t show_cnt;
+
+ if (!memcmp (read_data, expected_data, size))
+ return;
+
+ for (i = 0; i < size; i++)
+ if (read_data[i] != expected_data[i])
+ break;
+ for (j = i + 1; j < size; j++)
+ if (read_data[j] == expected_data[j])
+ break;
+
+ quiet = false;
+ msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
+ "from expected.", j - i, ofs + i, filename);
+ show_cnt = j - i;
+ if (j - i > 64)
+ {
+ show_cnt = 64;
+ msg ("Showing first differing %zu bytes.", show_cnt);
+ }
+ msg ("Data actually read:");
+ hex_dump (ofs + i, read_data + i, show_cnt, true);
+ msg ("Expected data:");
+ hex_dump (ofs + i, expected_data + i, show_cnt, true);
+ fail ("%zu bytes read starting at offset %zu in \"%s\" differ "
+ "from expected", j - i, ofs, filename);
+}
+
+void
+exec_children (const char *child_name, pid_t pids[], size_t child_cnt)
+{
+ size_t i;
+
+ for (i = 0; i < child_cnt; i++)
+ {
+ char cmd_line[128];
+ snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i);
+ CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR,
+ "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line);
+ }
+}
+
+void
+join_children (pid_t pids[], size_t child_cnt)
+{
+ size_t i;
+
+ for (i = 0; i < child_cnt; i++)
+ {
+ int status = join (pids[i]);
+ CHECK (status == (int) i,
+ "join child %zu of %zu returned %d (expected %d)",
+ i + 1, child_cnt, status, i);
+ }
+}