Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / tests / testcache.c
blobe589250674f7b0198bc13af8f64346c147e0e67f
1 /* A general i/o consistency test library. It performs i/o
2 * using functions provided by the client (readblock, dowriteblock)
3 * with a working set size specified by the client. It checks that
4 * blocks that were written have the same contents when later read,
5 * using different access patterns. The assumption is the various
6 * cache layers so exercised are forced into many different states
7 * (reordering, eviction, etc), hopefully triggering bugs if present.
9 * Entry point: dotest()
12 #include <sys/types.h>
13 #include <sys/ioc_memory.h>
14 #include <stdio.h>
15 #include <assert.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <fcntl.h>
21 #include "testcache.h"
22 #include "common.h"
24 extern int quietflag;
26 int fds[MAXFILES];
28 static void
29 genblock(int b, char *blockdata, int blocksize, u32_t seed)
31 u32_t *p = (u32_t *) blockdata,
32 *plimit = (u32_t *) (blockdata + blocksize),
33 i = 0;
35 srandom(seed ^ b);
37 for(p = (u32_t *) blockdata; p < plimit; p++) {
38 i++;
39 *p = random();
43 static int
44 checkblock(int b, int blocksize, u32_t seed)
46 static char data[MAXBLOCKSIZE], expected_data[MAXBLOCKSIZE];
47 int r;
49 genblock(b, expected_data, blocksize, seed);
51 r = readblock(b, blocksize, seed, data);
53 if(r == OK_BLOCK_GONE) { return 0; }
55 if(r != blocksize) {
56 fprintf(stderr, "readblock failed\n");
57 return 1;
60 if(memcmp(expected_data, data, blocksize)) {
61 fprintf(stderr, "comparison of %d failed\n", b);
62 return 1;
65 return 0;
68 static int
69 writeblock(int b, int blocksize, u32_t seed)
71 static char data[MAXBLOCKSIZE];
73 genblock(b, data, blocksize, seed);
75 if(dowriteblock(b, blocksize, seed, data) != blocksize) {
76 fprintf(stderr, "writeblock of %d failed\n", b);
77 return 0;
80 return blocksize;
83 static int *
84 makepermutation(int nblocks, int *permutation)
86 int b;
88 assert(nblocks > 0 && nblocks <= MAXBLOCKS);
90 for(b = 0; b < nblocks; b++) permutation[b] = b;
92 for(b = 0; b < nblocks-1; b++) {
93 int s, other = b + random() % (nblocks - b - 1);
94 assert(other >= b && other < nblocks);
95 s = permutation[other];
96 permutation[other] = permutation[b];
97 permutation[b] = s;
100 return permutation;
103 static int
104 checkblocks(int nblocks, int blocksize, u32_t seed)
106 int b;
107 int nrandom = nblocks * 3;
108 static int perm1[MAXBLOCKS];
110 if(!quietflag) { fprintf(stderr, "\nverifying "); fflush(stderr); }
112 makepermutation(nblocks, perm1);
114 assert(nblocks > 0 && nblocks <= MAXBLOCKS);
115 assert(blocksize > 0 && blocksize <= MAXBLOCKSIZE);
117 for(b = 0; b < nblocks; b++) {
118 if(checkblock(b, blocksize, seed)) { return 1; }
121 for(b = 0; b < nrandom; b++) {
122 if(checkblock(random() % nblocks, blocksize, seed)) { return 1; }
125 for(b = 0; b < nblocks; b++) {
126 if(checkblock(b, blocksize, seed)) { return 1; }
129 for(b = 0; b < nblocks; b++) {
130 if(checkblock(perm1[b], blocksize, seed)) { return 1; }
133 if(!quietflag) { fprintf(stderr, "done\n"); }
135 return 0;
139 dotest(int blocksize, int nblocks, int iterations)
141 int b, i;
142 int nrandom = nblocks * iterations;
143 static int perm1[MAXBLOCKS], perm2[MAXBLOCKS];
144 static int newblock[MAXBLOCKS];
145 u32_t seed = random(), newseed;
146 int mb;
148 assert(nblocks > 0 && nblocks <= MAXBLOCKS);
150 mb = (int) ((u64_t) blocksize * nblocks / 1024 / 1024);
152 if(!quietflag) { fprintf(stderr, "test: %d * %d = %dMB\n", blocksize, nblocks, mb); }
154 for(b = 0; b < nblocks; b++) {
155 if(writeblock(b, blocksize, seed) < blocksize) { return 1; }
156 if(checkblock(b, blocksize, seed)) { return 1; }
157 printprogress("writing sequential", b, nblocks);
160 if(checkblocks(nblocks, blocksize, seed)) { return 1; }
162 makepermutation(nblocks, perm1);
164 for(b = 0; b < nblocks; b++) {
165 if(writeblock(perm1[b], blocksize, seed) < blocksize) { return 1; }
166 if(checkblock(perm1[b], blocksize, seed)) { return 1; }
167 printprogress("writing permutation", b, nblocks);
170 if(checkblocks(nblocks, blocksize, seed)) { return 1; }
172 for(i = 0; i < iterations; i++) {
173 makepermutation(nblocks, perm1);
174 makepermutation(nblocks, perm2);
175 memset(newblock, 0, sizeof(newblock));
177 newseed = random();
179 if(!quietflag) { fprintf(stderr, "iteration %d/%d\n", i, iterations); }
181 for(b = 0; b < nblocks; b++) {
182 int wr = perm1[b], check = perm2[b];
183 if(writeblock(wr, blocksize, newseed) < blocksize) { return 1; }
184 newblock[wr] = 1;
185 if(checkblock(check, blocksize, newblock[check] ? newseed : seed)) { return 1; }
186 printprogress("interleaved permutation read, write", b, nblocks);
189 seed = newseed;
191 if(checkblocks(nblocks, blocksize, seed)) { return 1; }
194 newseed = random();
196 memset(newblock, 0, sizeof(newblock));
198 for(b = 0; b < nrandom; b++) {
199 int wr = random() % nblocks, check = random() % nblocks;
200 if(writeblock(wr, blocksize, newseed) < blocksize) { return 1; }
201 newblock[wr] = 1;
202 if(checkblock(check, blocksize,
203 newblock[check] ? newseed : seed)) { return 1; }
204 printprogress("1 random verify, 1 random write", b, nrandom);
207 seed = newseed;
209 if(!quietflag) { fprintf(stderr, "\n"); }
210 testend();
212 return 0;
215 void
216 get_fd_offset(int b, int blocksize, u64_t *file_offset, int *fd)
218 u64_t offset = (u64_t) b * blocksize;
219 int filenumber;
221 filenumber = offset / MB / MBPERFILE;
223 assert(filenumber >= 0 && filenumber < MAXFILES);
224 assert(fds[filenumber] > 0);
226 *fd = fds[filenumber];
227 *file_offset = offset - (filenumber * MBPERFILE * MB);
230 void
231 makefiles(int n)
233 int f;
234 for(f = 0; f < n; f++) {
235 char tempfilename[] = "cachetest.XXXXXXXX";
236 fds[f] = mkstemp(tempfilename);
237 if(fds[f] < 0) {
238 perror("mkstemp");
239 fprintf(stderr, "mkstemp %d/%d failed\n", f, n);
240 exit(1);
242 assert(fds[f] > 0);
246 void cachequiet(int quiet)
248 quietflag = quiet;