CS318 - Pintos
Pintos source browser for JHU CS318 course
lib.c
Go to the documentation of this file.
1 #include "tests/lib.h"
2 #include <random.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <syscall.h>
7 
8 const char *test_name;
9 bool quiet = false;
10 
11 static void
12 vmsg (const char *format, va_list args, const char *suffix)
13 {
14  /* We go to some trouble to stuff the entire message into a
15  single buffer and output it in a single system call, because
16  that'll (typically) ensure that it gets sent to the console
17  atomically. Otherwise kernel messages like "foo: exit(0)"
18  can end up being interleaved if we're unlucky. */
19  static char buf[1024];
20 
21  snprintf (buf, sizeof buf, "(%s) ", test_name);
22  vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args);
23  strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf));
25 }
26 
27 void
28 msg (const char *format, ...)
29 {
30  va_list args;
31 
32  if (quiet)
33  return;
34  va_start (args, format);
35  vmsg (format, args, "\n");
36  va_end (args);
37 }
38 
39 void
40 fail (const char *format, ...)
41 {
42  va_list args;
43 
44  va_start (args, format);
45  vmsg (format, args, ": FAILED\n");
46  va_end (args);
47 
48  exit (1);
49 }
50 
51 static void
52 swap (void *a_, void *b_, size_t size)
53 {
54  uint8_t *a = a_;
55  uint8_t *b = b_;
56  size_t i;
57 
58  for (i = 0; i < size; i++)
59  {
60  uint8_t t = a[i];
61  a[i] = b[i];
62  b[i] = t;
63  }
64 }
65 
66 void
67 shuffle (void *buf_, size_t cnt, size_t size)
68 {
69  char *buf = buf_;
70  size_t i;
71 
72  for (i = 0; i < cnt; i++)
73  {
74  size_t j = i + random_ulong () % (cnt - i);
75  swap (buf + i * size, buf + j * size, size);
76  }
77 }
78 
79 void
80 exec_children (const char *child_name, pid_t pids[], size_t child_cnt)
81 {
82  size_t i;
83 
84  for (i = 0; i < child_cnt; i++)
85  {
86  char cmd_line[128];
87  snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i);
88  CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR,
89  "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line);
90  }
91 }
92 
93 void
94 wait_children (pid_t pids[], size_t child_cnt)
95 {
96  size_t i;
97 
98  for (i = 0; i < child_cnt; i++)
99  {
100  int status = wait (pids[i]);
101  CHECK (status == (int) i,
102  "wait for child %zu of %zu returned %d (expected %zu)",
103  i + 1, child_cnt, status, i);
104  }
105 }
106 
107 void
109  const char *file_name, const void *buf_, size_t size)
110 {
111  const char *buf = buf_;
112  size_t ofs = 0;
113  size_t file_size;
114 
115  /* Warn about file of wrong size. Don't fail yet because we
116  may still be able to get more information by reading the
117  file. */
118  file_size = filesize (fd);
119  if (file_size != size)
120  msg ("size of %s (%zu) differs from expected (%zu)",
121  file_name, file_size, size);
122 
123  /* Read the file block-by-block, comparing data as we go. */
124  while (ofs < size)
125  {
126  char block[512];
127  size_t block_size, ret_val;
128 
129  block_size = size - ofs;
130  if (block_size > sizeof block)
131  block_size = sizeof block;
132 
133  ret_val = read (fd, block, block_size);
134  if (ret_val != block_size)
135  fail ("read of %zu bytes at offset %zu in \"%s\" returned %zu",
136  block_size, ofs, file_name, ret_val);
137 
138  compare_bytes (block, buf + ofs, block_size, ofs, file_name);
139  ofs += block_size;
140  }
141 
142  /* Now fail due to wrong file size. */
143  if (file_size != size)
144  fail ("size of %s (%zu) differs from expected (%zu)",
145  file_name, file_size, size);
146 
147  msg ("verified contents of \"%s\"", file_name);
148 }
149 
150 void
151 check_file (const char *file_name, const void *buf, size_t size)
152 {
153  int fd;
154 
155  CHECK ((fd = open (file_name)) > 1, "open \"%s\" for verification",
156  file_name);
157  check_file_handle (fd, file_name, buf, size);
158  msg ("close \"%s\"", file_name);
159  close (fd);
160 }
161 
162 void
163 compare_bytes (const void *read_data_, const void *expected_data_, size_t size,
164  size_t ofs, const char *file_name)
165 {
166  const uint8_t *read_data = read_data_;
167  const uint8_t *expected_data = expected_data_;
168  size_t i, j;
169  size_t show_cnt;
170 
171  if (!memcmp (read_data, expected_data, size))
172  return;
173 
174  for (i = 0; i < size; i++)
175  if (read_data[i] != expected_data[i])
176  break;
177  for (j = i + 1; j < size; j++)
178  if (read_data[j] == expected_data[j])
179  break;
180 
181  quiet = false;
182  msg ("%zu bytes read starting at offset %zu in \"%s\" differ "
183  "from expected.", j - i, ofs + i, file_name);
184  show_cnt = j - i;
185  if (j - i > 64)
186  {
187  show_cnt = 64;
188  msg ("Showing first differing %zu bytes.", show_cnt);
189  }
190  msg ("Data actually read:");
191  hex_dump (ofs + i, read_data + i, show_cnt, true);
192  msg ("Expected data:");
193  hex_dump (ofs + i, expected_data + i, show_cnt, true);
194  fail ("%zu bytes read starting at offset %zu in \"%s\" differ "
195  "from expected", j - i, ofs + i, file_name);
196 }
lib.h
snprintf
int snprintf(char *buffer, size_t buf_size, const char *format,...)
Like printf(), except that output is stored into BUFFER, which must have space for BUF_SIZE character...
Definition: stdio.c:62
uint8_t
unsigned char uint8_t
Definition: stdint.h:20
va_end
#define va_end(LIST)
Definition: stdarg.h:10
shuffle
void shuffle(void *buf_, size_t cnt, size_t size)
Definition: lib.c:67
STDOUT_FILENO
#define STDOUT_FILENO
Definition: stdio.h:16
va_start
#define va_start(LIST, ARG)
Definition: stdarg.h:9
string.h
buf
static char buf[BUF_SIZE]
Definition: child-syn-read.c:16
write
int write(int fd, const void *buffer, unsigned size)
Definition: syscall.c:121
CHECK
#define CHECK(SUCCESS,...)
Takes an expression to test for SUCCESS and a message, which may include printf-style arguments.
Definition: lib.h:29
random_ulong
unsigned long random_ulong(void)
Returns a pseudo-random unsigned long.
Definition: random.c:78
exec
pid_t exec(const char *file)
Definition: syscall.c:79
swap
static void swap(void *a_, void *b_, size_t size)
Definition: lib.c:52
compare_bytes
void compare_bytes(const void *read_data_, const void *expected_data_, size_t size, size_t ofs, const char *file_name)
test/lib.h
Definition: lib.c:163
random.h
hex_dump
void hex_dump(uintptr_t ofs, const void *buf_, size_t size, bool ascii)
Dumps the SIZE bytes in BUF to the console as hex bytes arranged 16 per line.
Definition: stdio.c:593
stdarg.h
open
int open(const char *file)
Definition: syscall.c:103
vmsg
static void vmsg(const char *format, va_list args, const char *suffix)
Definition: lib.c:12
memcmp
int memcmp(const void *a_, const void *b_, size_t size)
Find the first differing byte in the two blocks of SIZE bytes at A and B.
Definition: string.c:53
wait_children
void wait_children(pid_t pids[], size_t child_cnt)
Definition: lib.c:94
va_list
__builtin_va_list va_list
GCC has <stdarg.h> functionality as built-ins, so all we need is to use it.
Definition: stdarg.h:7
fail
void fail(const char *format,...)
Definition: lib.c:40
block
A block device.
Definition: block.c:9
filesize
int filesize(int fd)
Definition: syscall.c:109
file_name
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5
strlen
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
wait
static void wait(struct intq *q, struct thread **waiter)
vsnprintf
int vsnprintf(char *buffer, size_t buf_size, const char *format, va_list args)
Like vprintf(), except that output is stored into BUFFER, which must have space for BUF_SIZE characte...
Definition: stdio.c:26
pid_t
int pid_t
Process identifier.
Definition: syscall.h:8
close
void close(int fd)
Definition: syscall.c:139
exec_children
void exec_children(const char *child_name, pid_t pids[], size_t child_cnt)
Definition: lib.c:80
msg
void msg(const char *format,...)
Definition: lib.c:28
block_size
block_sector_t block_size(struct block *block)
Returns the number of sectors in BLOCK.
Definition: block.c:144
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
check_file_handle
void check_file_handle(int fd, const char *file_name, const void *buf_, size_t size)
Definition: lib.c:108
exit
void exit(int status)
Definition: syscall.c:72
check_file
void check_file(const char *file_name, const void *buf, size_t size)
Definition: lib.c:151
test_name
const char * test_name
Child process for syn-read test.
Definition: lib.c:8
PID_ERROR
#define PID_ERROR
Definition: syscall.h:9
read
int read(int fd, void *buffer, unsigned size)
Definition: syscall.c:115
quiet
bool quiet
Definition: lib.c:9