|
|
@@ -1,18 +1,21 @@
|
|
|
|
/* randomread - tests if the read functions of a file system work correctly
|
|
|
|
/*
|
|
|
|
** by reading arbitrary bytes at arbitrary positions of a file previously
|
|
|
|
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
|
|
|
|
** created.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
** The idea is to be able to calculate the contents on each position
|
|
|
|
*/
|
|
|
|
** of the file. It currently only counts numbers, beginning from zero,
|
|
|
|
|
|
|
|
** which is probably not a really good test.
|
|
|
|
/*! Tests if the read functions of a file system work correctly by reading
|
|
|
|
** But if there is a bug, it would be very likely to show up after some
|
|
|
|
arbitrary bytes at arbitrary positions of a file previously created.
|
|
|
|
** thousand (or even million) runs.
|
|
|
|
|
|
|
|
** Works only on little-endian processors, such as x86 (or else the partial
|
|
|
|
The idea is to be able to calculate the contents on each position
|
|
|
|
** read numbers wouldn't be correctly compared).
|
|
|
|
of the file. It currently only counts numbers, beginning from zero,
|
|
|
|
**
|
|
|
|
which is probably not a really good test.
|
|
|
|
** Use the --help option to see how it's used.
|
|
|
|
But if there is a bug, it would be very likely to show up after some
|
|
|
|
**
|
|
|
|
thousand (or even million) runs.
|
|
|
|
** Initial version by Axel Dörfler, axeld@pinc-software.de
|
|
|
|
|
|
|
|
** This file may be used under the terms of the OpenBeOS License.
|
|
|
|
Works only on little-endian processors, such as x86 (or else the partial
|
|
|
|
|
|
|
|
read numbers wouldn't be correctly compared).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Use the --help option to see how it's used.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <File.h>
|
|
|
|
#include <File.h>
|
|
|
@@ -23,7 +26,7 @@
|
|
|
|
#include <string.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define FILE_NAME "RANDOMREAD_TEST_FILE"
|
|
|
|
#define FILE_NAME "RANDOM_READ_TEST_FILE"
|
|
|
|
#define FILE_SIZE (1024 * 1024)
|
|
|
|
#define FILE_SIZE (1024 * 1024)
|
|
|
|
#define BUFFER_SIZE (64 * 1024)
|
|
|
|
#define BUFFER_SIZE (64 * 1024)
|
|
|
|
#define NUMBER_OF_LOOPS 1000
|
|
|
|
#define NUMBER_OF_LOOPS 1000
|
|
|
@@ -33,18 +36,20 @@
|
|
|
|
typedef uint32 test_t;
|
|
|
|
typedef uint32 test_t;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void createFile(const char *name,size_t size)
|
|
|
|
void
|
|
|
|
|
|
|
|
createFile(const char *name, size_t size)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
BFile file;
|
|
|
|
BFile file;
|
|
|
|
status_t status = file.SetTo(name,B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
|
|
|
status_t status = file.SetTo(name,
|
|
|
|
|
|
|
|
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
|
|
|
if (status < B_OK) {
|
|
|
|
if (status < B_OK) {
|
|
|
|
fprintf(stderr,"Could not create test file: %s!\n",strerror(status));
|
|
|
|
fprintf(stderr, "Could not create test file: %s!\n", strerror(status));
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
test_t max = size / sizeof(test_t);
|
|
|
|
test_t max = size / sizeof(test_t);
|
|
|
|
for (uint32 i = 0;i < max;i++) {
|
|
|
|
for (uint32 i = 0; i < max; i++) {
|
|
|
|
if (file.Write(&i,sizeof(test_t)) != sizeof(test_t)) {
|
|
|
|
if (file.Write(&i, sizeof(test_t)) != sizeof(test_t)) {
|
|
|
|
fprintf(stderr,"Could not create the whole test file!\n");
|
|
|
|
fprintf(stderr,"Could not create the whole test file!\n");
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -52,31 +57,34 @@ void createFile(const char *name,size_t size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void readTest(const char *name,int32 loops)
|
|
|
|
void
|
|
|
|
|
|
|
|
readTest(const char *name, int32 loops)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
BFile file;
|
|
|
|
BFile file;
|
|
|
|
status_t status = file.SetTo(name,B_READ_ONLY);
|
|
|
|
status_t status = file.SetTo(name, B_READ_ONLY);
|
|
|
|
if (status < B_OK) {
|
|
|
|
if (status < B_OK) {
|
|
|
|
fprintf(stderr,"Could not open test file! Run \"randomread create [size]\" first.\n"
|
|
|
|
fprintf(stderr, "Could not open test file! Run \"randomread create "
|
|
|
|
"This will create a file named \"%s\" in the current directory.\n",name);
|
|
|
|
"[size]\" first.\n"
|
|
|
|
|
|
|
|
"This will create a file named \"%s\" in the current directory.\n",
|
|
|
|
|
|
|
|
name);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
off_t size;
|
|
|
|
off_t size;
|
|
|
|
if ((status = file.GetSize(&size)) < B_OK) {
|
|
|
|
if ((status = file.GetSize(&size)) < B_OK) {
|
|
|
|
fprintf(stderr,"Could not get file size: %s!\n",strerror(status));
|
|
|
|
fprintf(stderr, "Could not get file size: %s!\n", strerror(status));
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *buffer = (char *)malloc(BUFFER_SIZE);
|
|
|
|
char *buffer = (char *)malloc(BUFFER_SIZE);
|
|
|
|
if (buffer == NULL) {
|
|
|
|
if (buffer == NULL) {
|
|
|
|
fprintf(stderr,"no memory to create read buffer.\n");
|
|
|
|
fprintf(stderr, "no memory to create read buffer.\n");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
srand(time(NULL));
|
|
|
|
srand(time(NULL));
|
|
|
|
int32 faults = 0;
|
|
|
|
int32 faults = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (int32 i = 0;i < loops;i++) {
|
|
|
|
for (int32 i = 0; i < loops; i++) {
|
|
|
|
off_t pos = rand() % size;
|
|
|
|
off_t pos = rand() % size;
|
|
|
|
// we are lazy tester, minimum read size is 4 bytes
|
|
|
|
// we are lazy tester, minimum read size is 4 bytes
|
|
|
|
int32 bytes = (rand() % BUFFER_SIZE) + 4;
|
|
|
|
int32 bytes = (rand() % BUFFER_SIZE) + 4;
|
|
|
@@ -86,11 +94,14 @@ void readTest(const char *name,int32 loops)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
bytes = max;
|
|
|
|
bytes = max;
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t bytesRead = file.ReadAt(pos,buffer,bytes);
|
|
|
|
ssize_t bytesRead = file.ReadAt(pos, buffer, bytes);
|
|
|
|
if (bytesRead < B_OK)
|
|
|
|
if (bytesRead < B_OK) {
|
|
|
|
printf(" Could not read %ld bytes at offset %Ld: %s\n",bytes,pos,strerror(bytesRead));
|
|
|
|
printf(" Could not read %ld bytes at offset %Ld: %s\n",
|
|
|
|
else if (bytesRead != max)
|
|
|
|
bytes, pos, strerror(bytesRead));
|
|
|
|
printf(" Could only read %ld bytes instead of %ld at offset %Ld\n",bytesRead,bytes,pos);
|
|
|
|
} else if (bytesRead != max) {
|
|
|
|
|
|
|
|
printf(" Could only read %ld bytes instead of %ld at offset %Ld\n",
|
|
|
|
|
|
|
|
bytesRead, bytes, pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// test contents
|
|
|
|
// test contents
|
|
|
|
|
|
|
|
|
|
|
@@ -115,7 +126,9 @@ void readTest(const char *name,int32 loops)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!correct) {
|
|
|
|
if (!correct) {
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (partial begin = %ld, should be %08lx, is %08lx)!\n",pos,bytes,bufferPos,partial,num,read);
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (partial begin = "
|
|
|
|
|
|
|
|
"%ld, should be %08lx, is %08lx)!\n", pos, bytes,
|
|
|
|
|
|
|
|
bufferPos, partial, num, read);
|
|
|
|
faults++;
|
|
|
|
faults++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bufferPos += sizeof(test_t) - partial;
|
|
|
|
bufferPos += sizeof(test_t) - partial;
|
|
|
@@ -124,13 +137,15 @@ void readTest(const char *name,int32 loops)
|
|
|
|
test_t *numBuffer = (test_t *)(buffer + sizeof(test_t) - partial);
|
|
|
|
test_t *numBuffer = (test_t *)(buffer + sizeof(test_t) - partial);
|
|
|
|
|
|
|
|
|
|
|
|
// test full numbers
|
|
|
|
// test full numbers
|
|
|
|
for (;bufferPos < bytesRead - sizeof(test_t);bufferPos += sizeof(test_t)) {
|
|
|
|
for (; bufferPos < bytesRead - sizeof(test_t);
|
|
|
|
|
|
|
|
bufferPos += sizeof(test_t)) {
|
|
|
|
if (faults > MAX_FAULTS) {
|
|
|
|
if (faults > MAX_FAULTS) {
|
|
|
|
printf("maximum number of faults reached, bail out.\n");
|
|
|
|
printf("maximum number of faults reached, bail out.\n");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (num != *numBuffer) {
|
|
|
|
if (num != *numBuffer) {
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (should be %08lx, is %08lx)!\n",pos,bytes,bufferPos,num,*numBuffer);
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (should be %08lx, "
|
|
|
|
|
|
|
|
"is %08lx)!\n", pos, bytes, bufferPos, num, *numBuffer);
|
|
|
|
faults++;
|
|
|
|
faults++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
num++;
|
|
|
|
num++;
|
|
|
@@ -155,7 +170,9 @@ void readTest(const char *name,int32 loops)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!correct) {
|
|
|
|
if (!correct) {
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (partial end = %ld, should be %08lx, is %08lx)!\n",pos,bytes,bufferPos,partial,num,read);
|
|
|
|
printf("[%Ld,%ld] Bytes at %Ld don't match (partial end = "
|
|
|
|
|
|
|
|
"%ld, should be %08lx, is %08lx)!\n", pos, bytes,
|
|
|
|
|
|
|
|
bufferPos, partial, num, read);
|
|
|
|
faults++;
|
|
|
|
faults++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -163,14 +180,15 @@ void readTest(const char *name,int32 loops)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc,char **argv)
|
|
|
|
int
|
|
|
|
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
size_t size = FILE_SIZE;
|
|
|
|
size_t size = FILE_SIZE;
|
|
|
|
int32 loops = NUMBER_OF_LOOPS;
|
|
|
|
int32 loops = NUMBER_OF_LOOPS;
|
|
|
|
bool create = false;
|
|
|
|
bool create = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (argv[1]) {
|
|
|
|
if (argv[1]) {
|
|
|
|
if (!strcmp(argv[1],"create")) {
|
|
|
|
if (!strcmp(argv[1], "create")) {
|
|
|
|
create = true;
|
|
|
|
create = true;
|
|
|
|
if (argv[2])
|
|
|
|
if (argv[2])
|
|
|
|
size = atol(argv[2]);
|
|
|
|
size = atol(argv[2]);
|
|
|
@@ -179,7 +197,8 @@ int main(int argc,char **argv)
|
|
|
|
loops = atol(argv[1]);
|
|
|
|
loops = atol(argv[1]);
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
// get a nice filename of the program
|
|
|
|
// get a nice filename of the program
|
|
|
|
char *filename = strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0];
|
|
|
|
char *filename = strrchr(argv[0], '/')
|
|
|
|
|
|
|
|
? strrchr(argv[0] , '/') + 1 : argv[0];
|
|
|
|
|
|
|
|
|
|
|
|
printf("You can either create a test file or perform the test.\n"
|
|
|
|
printf("You can either create a test file or perform the test.\n"
|
|
|
|
" Create:\t%s create [filesize]\n"
|
|
|
|
" Create:\t%s create [filesize]\n"
|
|
|
@@ -192,14 +211,15 @@ int main(int argc,char **argv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
if (size == 0) {
|
|
|
|
fprintf(stderr,"%s: given file size too small, set to 1 MB.\n",argv[0]);
|
|
|
|
fprintf(stderr, "%s: given file size too small, set to 1 MB.\n",
|
|
|
|
|
|
|
|
argv[0]);
|
|
|
|
size = FILE_SIZE;
|
|
|
|
size = FILE_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (create)
|
|
|
|
if (create)
|
|
|
|
createFile(FILE_NAME,size);
|
|
|
|
createFile(FILE_NAME, size);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
readTest(FILE_NAME,loops);
|
|
|
|
readTest(FILE_NAME, loops);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|