PKUOS - Pintos
Pintos source browser for PKU Operating System 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
8const char *test_name;
9bool quiet = false;
10
11static void
12vmsg (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
27void
28msg (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);
38
39void
40fail (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
51static void
52swap (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
66void
67shuffle (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
79void
80exec_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
93void
94wait_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
107void
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
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
150void
151check_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
162void
163compare_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}
block_sector_t block_size(struct block *block)
Returns the number of sectors in BLOCK.
Definition: block.c:144
static char buf[BUF_SIZE]
static void wait(struct intq *q, struct thread **waiter)
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
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
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
int filesize(int fd)
Definition: syscall.c:109
void exit(int status)
Definition: syscall.c:72
void close(int fd)
Definition: syscall.c:139
int open(const char *file)
Definition: syscall.c:103
int write(int fd, const void *buffer, unsigned size)
Definition: syscall.c:121
pid_t exec(const char *file)
Definition: syscall.c:79
int read(int fd, void *buffer, unsigned size)
Definition: syscall.c:115
int pid_t
Process identifier.
Definition: syscall.h:8
#define PID_ERROR
Definition: syscall.h:9
static void vmsg(const char *format, va_list args, const char *suffix)
Definition: lib.c:12
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
void fail(const char *format,...)
Definition: lib.c:40
void check_file(const char *file_name, const void *buf, size_t size)
Definition: lib.c:151
void msg(const char *format,...)
Definition: lib.c:28
static void swap(void *a_, void *b_, size_t size)
Definition: lib.c:52
const char * test_name
Child process for syn-read test.
Definition: lib.c:8
void shuffle(void *buf_, size_t cnt, size_t size)
Definition: lib.c:67
void check_file_handle(int fd, const char *file_name, const void *buf_, size_t size)
Definition: lib.c:108
void wait_children(pid_t pids[], size_t child_cnt)
Definition: lib.c:94
bool quiet
Definition: lib.c:9
void exec_children(const char *child_name, pid_t pids[], size_t child_cnt)
Definition: lib.c:80
#define CHECK(SUCCESS,...)
Takes an expression to test for SUCCESS and a message, which may include printf-style arguments.
Definition: lib.h:29
unsigned long random_ulong(void)
Returns a pseudo-random unsigned long.
Definition: random.c:78
#define va_end(LIST)
Definition: stdarg.h:10
#define va_start(LIST, ARG)
Definition: stdarg.h:9
__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
unsigned char uint8_t
Definition: stdint.h:20
#define STDOUT_FILENO
Definition: stdio.h:16
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
size_t strlen(const char *string)
Returns the length of STRING.
Definition: string.c:293
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
A block device.
Definition: block.c:10
static const char file_name[]
tests/filesys/base/syn-read.h
Definition: syn-read.h:5