Get rid of unnecessary barrier. Improve comment.
[pintos-anon] / grading / filesys / fslib.c
1 #include "fslib.h"
2 #include <random.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <syscall.h>
7
8 bool quiet = false;
9
10 static void
11 vmsg (const char *format, va_list args, const char *suffix) 
12 {
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];
19
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));
24 }
25
26 void
27 msg (const char *format, ...) 
28 {
29   va_list args;
30
31   if (quiet)
32     return;
33   va_start (args, format);
34   vmsg (format, args, "\n");
35   va_end (args);
36 }
37
38 void
39 fail (const char *format, ...) 
40 {
41   va_list args;
42
43   va_start (args, format);
44   vmsg (format, args, ": FAILED\n");
45   va_end (args);
46
47   exit (1);
48 }
49
50 void 
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)) 
54 {
55   size_t ofs;
56   int fd;
57   
58   random_bytes (buf, size);
59   CHECK (create (filename, initial_size), "create \"%s\"", filename);
60   CHECK ((fd = open (filename)) > 1, "open \"%s\"", filename);
61
62   ofs = 0;
63   msg ("writing \"%s\"", filename);
64   while (ofs < size) 
65     {
66       size_t block_size = block_size_func ();
67       if (block_size > size - ofs)
68         block_size = size - ofs;
69
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);
73
74       ofs += block_size;
75       if (check_func != NULL)
76         check_func (fd, ofs);
77     }
78   msg ("close \"%s\"", filename);
79   close (fd);
80   check_file (filename, buf, size);
81 }
82
83 static void
84 swap (void *a_, void *b_, size_t size) 
85 {
86   uint8_t *a = a_;
87   uint8_t *b = b_;
88   size_t i;
89
90   for (i = 0; i < size; i++) 
91     {
92       uint8_t t = a[i];
93       a[i] = b[i];
94       b[i] = t;
95     }
96 }
97
98 void
99 shuffle (void *buf_, size_t cnt, size_t size) 
100 {
101   char *buf = buf_;
102   size_t i;
103
104   for (i = 0; i < cnt; i++)
105     {
106       size_t j = i + random_ulong () % (cnt - i);
107       swap (buf + i * size, buf + j * size, size);
108     }
109 }
110
111 void
112 check_file (const char *filename, const void *buf_, size_t size) 
113 {
114   const char *buf = buf_;
115   size_t ofs;
116   char block[512];
117   int fd;
118
119   CHECK ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
120
121   ofs = 0;
122   while (ofs < size)
123     {
124       size_t block_size = size - ofs;
125       if (block_size > sizeof block)
126         block_size = sizeof block;
127
128       if (read (fd, block, block_size) <= 0)
129         fail ("read %zu bytes at offset %zu in \"%s\" failed",
130               block_size, ofs, filename);
131
132       compare_bytes (block, buf + ofs, block_size, ofs, filename);
133       ofs += block_size;
134     }
135
136   msg ("close \"%s\"", filename);
137   close (fd);
138 }
139
140 void
141 compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
142                size_t ofs, const char *filename) 
143 {
144   const uint8_t *read_data = read_data_;
145   const uint8_t *expected_data = expected_data_;
146   size_t i, j;
147   size_t show_cnt;
148
149   if (!memcmp (read_data, expected_data, size))
150     return;
151   
152   for (i = 0; i < size; i++)
153     if (read_data[i] != expected_data[i])
154       break;
155   for (j = i + 1; j < size; j++)
156     if (read_data[j] == expected_data[j])
157       break;
158
159   quiet = false;
160   msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
161        "from expected.", j - i, ofs + i, filename);
162   show_cnt = j - i;
163   if (j - i > 64) 
164     {
165       show_cnt = 64;
166       msg ("Showing first differing %zu bytes.", show_cnt);
167     }
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);
174 }
175
176 void
177 exec_children (const char *child_name, pid_t pids[], size_t child_cnt) 
178 {
179   size_t i;
180
181   for (i = 0; i < child_cnt; i++) 
182     {
183       char cmd_line[128];
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);
187     }
188 }
189
190 void
191 wait_children (pid_t pids[], size_t child_cnt) 
192 {
193   size_t i;
194   
195   for (i = 0; i < child_cnt; i++) 
196     {
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);
201     }
202 }