Zurück zur SP1 Übersicht
halde-test-nudelsalat.c
#define SIZE (1024*1024)
#define MBLOCKSIZE 16
#define DO_SEGFAULT_TESTS 1
#include "halde.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdint.h>
#define DEV 0
#define BUFFER_SIZE 4096
#define FORKS 26
#define MAGICERRNO 242
#define INIT {\
close(fork_pipes[fork_id][0]);\
write(fork_pipes[fork_id][1], "!", 1);\
errno = MAGICERRNO;\
}
#define EXITFORK {\
close(fork_pipes[fork_id][1]);\
exit(0);\
}
#define SETSUCCESS {\
write(fork_pipes[fork_id][1], " ", 1);\
}
#define SUCCESS {\
SETSUCCESS;\
EXITFORK;\
}
#define FAIL(code) {\
write_code_to_pipe(fork_pipes[fork_id][1], code);\
EXITFORK;\
}
static void write_code_to_pipe(int pipe, char code) {
write(pipe, &code, 1);
}
static void buffer_add(char *buffer, int *buffer_position, char *new) {
for (int i = 0; new[i] != '\0' && *buffer_position < BUFFER_SIZE; i++) {
buffer[*buffer_position] = new[i];
(*buffer_position)++;
}
}
static void buffer_add_char(char *buffer, int *buffer_position, char new) {
buffer[*buffer_position] = new;
(*buffer_position)++;
}
#if DEV == 1
static char *int_to_string(int a, char *out) {
int pos = 0;
int stringpos = 0;
char zfill = 0;
for (int div = 1000000000; div > 0; div /= 10) {
if (a / div > 0 || zfill == 1 || div == 1) {
zfill = 1;
out[stringpos] = a / div + 48;
stringpos++;
}
a -= (a / div) * div;
pos++;
}
out[stringpos] = '\0';
return out;
}
#endif
static int fork_id = 0;
static int fork_pipes[FORKS][2];
static void signal_handler(int signal) {
INIT;
SUCCESS;
}
int main(void) {
signal(SIGCHLD, SIG_IGN);
pid_t pid;
for (int i = 0; i < FORKS; i++) {
pipe(fork_pipes[i]);
}
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr = malloc(SIZE);
if (errno != ENOMEM)
FAIL('1');
if (ptr != NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr = malloc(SIZE - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr == NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr = malloc(SIZE - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr == NULL)
FAIL('2');
void *ptr2 = malloc(10);
if (ptr2 != NULL)
FAIL('4');
if (errno != ENOMEM)
FAIL('3');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = malloc(24);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
char *ptr3 = malloc(32);
if (errno != MAGICERRNO)
FAIL('5');
if (ptr3 == NULL)
FAIL('6');
char *ptr4 = malloc(24);
if (errno != MAGICERRNO)
FAIL('7');
if (ptr4 == NULL)
FAIL('8');
if (ptr2 - ptr1 != 32 + MBLOCKSIZE || ptr3 - ptr2 != 24 + MBLOCKSIZE
|| ptr4 - ptr3 != 32 + MBLOCKSIZE)
FAIL('9');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
void *ptr2 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
void *ptr3 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('5');
if (ptr3 == NULL)
FAIL('6');
void *ptr4 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('7');
if (ptr4 == NULL)
FAIL('8');
void *ptr5 = malloc(1);
if (errno != ENOMEM)
FAIL('9');
if (ptr5 != NULL)
FAIL('A');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr = malloc(0);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr != NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr = malloc(SSIZE_MAX);
if (ptr != NULL)
FAIL('2');
if (errno != ENOMEM)
FAIL('1');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(12);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
free(NULL);
if (errno != MAGICERRNO)
FAIL('3');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
#if DO_SEGFAULT_TESTS == 0
FAIL('S');
#endif
INIT;
SETSUCCESS;
void *ptr1 = malloc(16);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
free((void *) 4096);
free((void *) 1048576);
free((void *) 2097152);
free((void *) 4194304);
FAIL('3');
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(128);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
signal(SIGABRT, signal_handler);
free(ptr1 + 1);
FAIL('3');
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
free(ptr1);
if (errno != MAGICERRNO)
FAIL('3');
void *ptr2 = malloc(32);
if (errno != MAGICERRNO)
FAIL('4');
if (ptr2 == NULL)
FAIL('5');
if (ptr1 != ptr2)
FAIL('6');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
void *ptr2 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
void *ptr3 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('5');
if (ptr3 == NULL)
FAIL('6');
void *ptr4 = malloc(SIZE / 4 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('7');
if (ptr4 == NULL)
FAIL('8');
free(ptr1);
if (errno != MAGICERRNO)
FAIL('9');
free(ptr2);
if (errno != MAGICERRNO)
FAIL('A');
free(ptr3);
if (errno != MAGICERRNO)
FAIL('B');
free(ptr4);
if (errno != MAGICERRNO)
FAIL('C');
void *ptr5 = malloc(SIZE / 2 - MBLOCKSIZE);
if (errno != ENOMEM)
FAIL('D');
if (ptr5 != NULL)
FAIL('E');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(128);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('1');
free(ptr1);
if (errno != MAGICERRNO)
FAIL('3');
void *ptr2 = malloc(128 - MBLOCKSIZE);
if (errno != MAGICERRNO)
FAIL('4');
if (ptr2 == NULL)
FAIL('5');
free(ptr2);
if (errno != MAGICERRNO)
FAIL('6');
void *ptr3 = malloc(128);
if (errno != MAGICERRNO)
FAIL('7');
if (ptr3 == NULL)
FAIL('8');
if (ptr3 != ptr1 && (uintptr_t)ptr3 - (uintptr_t)ptr1 != 128 + MBLOCKSIZE)
FAIL('9');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = realloc(NULL, 128);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = malloc(128);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
void *ptr2 = realloc(ptr1, 0);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 != NULL)
FAIL('4');
void *ptr3 = malloc(128);
if (errno != MAGICERRNO)
FAIL('5');
if (ptr3 == NULL)
FAIL('6');
if (ptr3 != ptr1)
FAIL('7');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
void *ptr1 = realloc(NULL, 0);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 != NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
int *ptr1 = malloc(sizeof(int));
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
*ptr1 = 1337;
int *ptr2 = realloc(ptr1, 128);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
if (*ptr2 != 1337)
FAIL('5');
if ((char *) ptr1 + sizeof(int) + MBLOCKSIZE != (char *) ptr2)
FAIL('6');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(64);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = malloc(128);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
char *ptr3 = malloc(256);
if (errno != MAGICERRNO)
FAIL('5');
if (ptr3 == NULL)
FAIL('6');
strcpy(ptr1, "nudelsalat");
free(ptr2);
if (errno != MAGICERRNO)
FAIL('7');
char *ptr4 = realloc(ptr1, 128);
if (errno != MAGICERRNO)
FAIL('8');
if (ptr4 == NULL)
FAIL('9');
if (strcmp(ptr4, "nudelsalat") != 0)
FAIL('A');
if (ptr4 != ptr2)
FAIL('B');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = malloc(100);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
for (int i = 0; i < 32; i++) {
ptr1[i] = '*';
}
free(ptr2);
if (errno != MAGICERRNO)
FAIL('5');
char *ptr5 = realloc(ptr1, 100);
if (errno != MAGICERRNO)
FAIL('6');
if (ptr5 == NULL)
FAIL('7');
for (int i = 0; i < 32; i++) {
if (ptr5[i] != '*')
FAIL('8');
}
char different = 0;
for (int i = 32; i < 32 + MBLOCKSIZE; i++) {
if (ptr5[i] != ptr1[i])
different = 1;
}
if (different == 0)
FAIL('9');
if (ptr5 != ptr2)
FAIL('A');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = malloc(10);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
for (int i = 0; i < 32; i++) {
ptr1[i] = '*';
}
free(ptr2);
if (errno != MAGICERRNO)
FAIL('5');
char *ptr5 = realloc(ptr1, 10);
if (errno != MAGICERRNO)
FAIL('6');
if (ptr2 == NULL)
FAIL('7');
for (int i = 0; i < 10; i++) {
if (ptr5[i] != '*')
FAIL('8');
}
for (int i = 10; i < 32; i++) {
if (ptr5[i] == '*')
FAIL('9');
}
if (ptr5 != ptr2)
FAIL('A');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = calloc(16, 4);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = malloc(1);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
if (ptr2 != ptr1 + 64 + MBLOCKSIZE)
FAIL('5');
for (int i = 0; i < 64; i++) {
if (ptr1[i] != '\0')
FAIL('6');
}
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
signal(SIGABRT, signal_handler);
char *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = realloc((char *) ptr1 + 42, 64);
if (errno != MAGICERRNO)
FAIL('3');
if (ptr2 == NULL)
FAIL('4');
FAIL('5');
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = malloc(32);
if (errno != MAGICERRNO)
FAIL('1');
if (ptr1 == NULL)
FAIL('2');
char *ptr2 = realloc(ptr1, SIZE);
if (errno != ENOMEM)
FAIL('3');
if (ptr2 != NULL)
FAIL('4');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *ptr1 = calloc(SIZE, SIZE);
if (errno != ENOMEM)
FAIL('1');
if (ptr1 != NULL)
FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *p1 = malloc(1024);
char *p2 = malloc(2048);
char *p3 = malloc(SIZE - 3 * MBLOCKSIZE - 1024 - 2048);
if(!p1 || !p2 || !p3) FAIL('1');
free(p3);
free(p2);
free(p1);
p1 = malloc(2048);
p2 = malloc(1024);
p3 = malloc(SIZE - 3 * MBLOCKSIZE - 1024 - 2048);
if(!p1 || !p2 || !p3) FAIL('2');
SUCCESS;
}
fork_id++;
pid = fork();
if (pid < 0)
return -1;
if (pid == 0) {
INIT;
char *p1 = malloc(1024);
if(!p1) FAIL('1');
free(p1);
char *p2 = malloc(SIZE);
if(p2) FAIL('2');
SUCCESS;
}
fork_id++;
printf("\x1B[1;37mhalde-Test von nudelsalat | milan.stephan@fau.de | https://sp.milanstephan.de\x1B[0m\n");
int status = EXIT_SUCCESS;
int buffer_position = 0;
char buffer[BUFFER_SIZE];
for (int i = 0; i < fork_id; i++) {
close(fork_pipes[i][1]);
char pipe_buffer;
char fork_status = 0;
while (read(fork_pipes[i][0], &pipe_buffer, 1) > 0) {
fork_status = pipe_buffer;
}
close(fork_pipes[i][0]);
switch (i) {
case 0:
buffer_add(buffer, &buffer_position,
"\x1B[32m[+]\x1B[0m = OK, \x1B[31m[x]\x1B[0m = Fehler an Marke x, \x1B[31m[\x1B[1;31m!\x1B[0;31m]\x1B[0m = Programmabbruch\n");
buffer_add(buffer, &buffer_position, "Basisfunktionen: malloc\n");
break;
case 7:
buffer_add(buffer, &buffer_position, "Basisfunktionen: free\n");
break;
case 10:
buffer_add(buffer, &buffer_position,
"Kombinierte Tests: malloc + free\n");
break;
case 13:
buffer_add(buffer, &buffer_position, "Abgeleitete Funktionen\n");
break;
case 24:
buffer_add(buffer, &buffer_position, "2015er Tests\n");
break;
default:
break;
}
if (fork_status != ' ')
status = EXIT_FAILURE;
if (fork_status == '!')
buffer_add(buffer, &buffer_position,
"\x1B[31m[\x1B[1;31m!\x1B[0;31m]\x1B[0m - ");
else if (fork_status == ' ')
buffer_add(buffer, &buffer_position, "\x1B[32m[+]\x1B[0m - ");
else {
buffer_add(buffer, &buffer_position, "\x1B[31m[");
buffer_add_char(buffer, &buffer_position, fork_status);
buffer_add(buffer, &buffer_position, "]\x1B[0m - ");
}
switch (i) {
case 0:
buffer_add(buffer, &buffer_position,
"malloc(SIZE) == NULL, errno == ENOMEM");
break;
case 1:
buffer_add(buffer, &buffer_position,
"Maximal grossen Block reservieren");
break;
case 2:
buffer_add(buffer, &buffer_position,
"Pruefen, ob nach maximalem Block voll ist");
break;
case 3:
buffer_add(buffer, &buffer_position,
"Mehrere Bloecke hintereinander reservieren");
break;
case 4:
buffer_add(buffer, &buffer_position,
"Speicher in 4 gleich grosse Bereiche teilen, pruefen ob voll");
break;
case 5:
buffer_add(buffer, &buffer_position,
"malloc(0) == NULL, keine errno gesetzt");
break;
case 6:
buffer_add(buffer, &buffer_position,
"malloc(-1) == NULL, errno == ENOMEM");
break;
case 7:
buffer_add(buffer, &buffer_position,
"free(NULL) geht nicht kaputt");
break;
case 8:
buffer_add(buffer, &buffer_position,
"free(RANDOM ADDRESSES) geht kaputt, S = Test uebersprungen!");
break;
case 9:
buffer_add(buffer, &buffer_position,
"abort() nach free() auf nicht gemalloc'tem Pointer");
break;
case 10:
buffer_add(buffer, &buffer_position,
"malloc(x) nach gefree'tem malloc(x) wieder auf gleicher Adresse");
break;
case 11:
buffer_add(buffer, &buffer_position,
"Speicher in 4 gleich grosse Bereiche teilen, freigeben und versuchen, groesseres Objekt reinzulegen");
break;
case 12:
buffer_add(buffer, &buffer_position,
"Keine unnoetige Fragmentierung durch Verwaltungsbloecke mit size=0");
break;
case 13:
buffer_add(buffer, &buffer_position, "realloc(NULL, x) != NULL");
break;
case 14:
buffer_add(buffer, &buffer_position, "realloc(x, 0) == free(x)");
break;
case 15:
buffer_add(buffer, &buffer_position,
"realloc(NULL, 0) == NULL (malloc(0))");
break;
case 16:
buffer_add(buffer, &buffer_position,
"realloc, neuen Speicherbereich hinten anhaengen");
break;
case 17:
buffer_add(buffer, &buffer_position,
"realloc, neuen Speicherbereich in Luecke einbauen");
break;
case 18:
buffer_add(buffer, &buffer_position,
"realloc Limit Test 1, neue Groesse > alte Groesse");
break;
case 19:
buffer_add(buffer, &buffer_position,
"realloc Limit Test 2, neue Groesse < alte Groesse");
break;
case 20:
buffer_add(buffer, &buffer_position, "calloc Test, 16*4 Byte");
break;
case 21:
buffer_add(buffer, &buffer_position,
"realloc mit nicht gemalloc'tem Pointer -> abort (weil free())");
break;
case 22:
buffer_add(buffer, &buffer_position,
"realloc mit fehlgeschlagenem malloc");
break;
case 23:
buffer_add(buffer, &buffer_position,
"calloc mit fehlgeschlagenem malloc");
break;
case 24:
buffer_add(buffer, &buffer_position,
"Schleppzeiger richtig verwendet / es gehen keine Listenelemente verloren I");
break;
case 25:
buffer_add(buffer, &buffer_position,
"Schleppzeiger richtig verwendet / es gehen keine Listenelemente verloren II");
break;
default:
buffer_add(buffer, &buffer_position, "<Keine Beschreibung>");
break;
}
buffer_add(buffer, &buffer_position, "\n");
}
#if DEV == 1
char intbuffer[11];
int_to_string(buffer_position, intbuffer);
buffer_add(buffer, &buffer_position, "Puffer (vor dieser Zeile): ");
buffer_add(buffer, &buffer_position, intbuffer);
buffer_add(buffer, &buffer_position, " Bytes\n");
#endif
write(STDOUT_FILENO, buffer, buffer_position);
return status;
}