Move problem 1-2 (join) into project 2 as the "wait" system call.
[pintos-anon] / grading / filesys / fslib.c
index 36f67f8efcaee0ed06d6ada5dcb3bb1ac82b12a8..2087d074b379949a18ff3a60030c7fe018875e34 100644 (file)
@@ -4,21 +4,23 @@
 #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
@@ -26,8 +28,10 @@ msg (const char *format, ...)
 {
   va_list args;
 
+  if (quiet)
+    return;
   va_start (args, format);
-  vmsg (format, args, false);
+  vmsg (format, args, "\n");
   va_end (args);
 }
 
@@ -36,49 +40,24 @@ fail (const char *format, ...)
 {
   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);
@@ -137,7 +116,7 @@ check_file (const char *filename, const void *buf_, size_t size)
   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)
@@ -150,22 +129,74 @@ check_file (const char *filename, const void *buf_, size_t 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
+wait_children (pid_t pids[], size_t child_cnt) 
+{
+  size_t i;
+  
+  for (i = 0; i < child_cnt; i++) 
+    {
+      int status = wait (pids[i]);
+      CHECK (status == (int) i,
+             "wait for child %zu of %zu returned %d (expected %zu)",
+             i + 1, child_cnt, status, i);
+    }
+}