Initial file system tests.
[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 #include "../lib/arc4.h"
8
9 bool quiet = false;
10
11 static void
12 vmsg (const char *format, va_list args, bool failure) 
13 {
14   if (quiet && !failure)
15     return;
16   
17   printf ("(%s) ", test_name);
18   vprintf (format, args);
19   if (failure)
20     printf (": FAILED");
21   printf ("\n");
22 }
23
24 void
25 msg (const char *format, ...) 
26 {
27   va_list args;
28
29   va_start (args, format);
30   vmsg (format, args, false);
31   va_end (args);
32 }
33
34 void
35 fail (const char *format, ...) 
36 {
37   va_list args;
38
39   quiet = false;
40   
41   va_start (args, format);
42   vmsg (format, args, true);
43   va_end (args);
44
45   exit (1);
46 }
47
48 void
49 check (bool success, const char *format, ...) 
50 {
51   va_list args;
52
53   va_start (args, format);
54   if (success) 
55     {
56       if (!quiet)
57         vmsg (format, args, false); 
58     }
59   else 
60     {
61       vmsg (format, args, true);
62       exit (1);
63     }
64   va_end (args);
65 }
66
67 void 
68 seq_test (const char *filename, void *buf, size_t size,
69           size_t initial_size, int seed,
70           size_t (*block_size_func) (void),
71           void (*check_func) (int fd, long ofs)) 
72 {
73   static struct arc4 arc4;
74   size_t ofs;
75   int fd;
76   
77   arc4_init (&arc4, &seed, sizeof seed);
78   arc4_crypt (&arc4, buf, size);
79
80   check (create (filename, initial_size), "create \"%s\"", filename);
81   check ((fd = open (filename)) > 1, "open \"%s\"", filename);
82
83   ofs = 0;
84   msg ("writing \"%s\"", filename);
85   while (ofs < size) 
86     {
87       size_t block_size = block_size_func ();
88       if (block_size > size - ofs)
89         block_size = size - ofs;
90
91       if (write (fd, buf + ofs, block_size) <= 0)
92         fail ("write %zu bytes at offset %zu in \"%s\" failed",
93               block_size, ofs, filename);
94
95       ofs += block_size;
96       if (check_func != NULL)
97         check_func (fd, ofs);
98     }
99   msg ("close \"%s\"", filename);
100   close (fd);
101   check_file (filename, buf, size);
102 }
103
104 static void
105 swap (void *a_, void *b_, size_t size) 
106 {
107   uint8_t *a = a_;
108   uint8_t *b = b_;
109   size_t i;
110
111   for (i = 0; i < size; i++) 
112     {
113       uint8_t t = a[i];
114       a[i] = b[i];
115       b[i] = t;
116     }
117 }
118
119 void
120 shuffle (void *buf_, size_t cnt, size_t size) 
121 {
122   char *buf = buf_;
123   size_t i;
124
125   for (i = 0; i < cnt; i++)
126     {
127       size_t j = i + random_ulong () % (cnt - i);
128       swap (buf + i * size, buf + j * size, size);
129     }
130 }
131
132 void
133 check_file (const char *filename, const void *buf_, size_t size) 
134 {
135   const char *buf = buf_;
136   size_t ofs;
137   char block[512];
138   int fd;
139
140   check ((fd = open (filename)) > 1, "open \"%s\" for verification", filename);
141
142   ofs = 0;
143   while (ofs < size)
144     {
145       size_t block_size = size - ofs;
146       if (block_size > sizeof block)
147         block_size = sizeof block;
148
149       if (read (fd, block, block_size) <= 0)
150         fail ("read %zu bytes at offset %zu in \"%s\" failed",
151               block_size, ofs, filename);
152
153       if (memcmp (buf + ofs, block, block_size))
154         {
155           if (block_size <= 512) 
156             {
157               printf ("Expected data:\n");
158               hex_dump (ofs, buf + ofs, block_size, false);
159               printf ("Actually read data:\n");
160               hex_dump (ofs, block, block_size, false); 
161             }
162           fail ("%zu bytes at offset %zu differed from expected",
163                 block_size, ofs);
164         }
165
166       ofs += block_size;
167     }
168
169   msg ("close \"%s\"", filename);
170   close (fd);
171 }