]> git.scottworley.com Git - overonion/blob - reverse_test.c
0b82f19af270ad0150a5f51794f0d00ccea0d46d
[overonion] / reverse_test.c
1 #include "reverse_lib.h"
2 #include "temp_file.h"
3
4 #include <err.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sysexits.h>
9 #include <unistd.h>
10
11 static const char test_file[] = "reverse.c";
12
13 /* Reverse input_file. Dump the result in a temporary file. Return the temp
14 * file's name. The caller must free the filename. */
15 char* reverse_to_temp_file(const char* input_file) {
16 char* temp_filename;
17 FILE* f;
18 make_temporary_file(&temp_filename, &f);
19 reverse_file(input_file, f);
20 if (fclose(f) == EOF) err(EX_IOERR, "Couldn't close temporary file");
21 return temp_filename;
22 }
23
24 /* Compare the contents of two files. Terminate with a diagnostic if they
25 * differ. */
26 void compare(const char* filename1, const char* filename2) {
27 FILE* f1 = fopen(filename1, "r");
28 if (f1 == NULL) err(EX_IOERR, "Couldn't open file %s", filename1);
29 FILE* f2 = fopen(filename2, "r");
30 if (f2 == NULL) err(EX_IOERR, "Couldn't open file %s", filename2);
31
32 for (int pos = 0; ; pos++) {
33 int c1 = fgetc(f1);
34 int c2 = fgetc(f2);
35 if (c1 == EOF && ferror(f1)) err(EX_IOERR, "Error reading file %s", filename1);
36 if (c2 == EOF && ferror(f2)) err(EX_IOERR, "Error reading file %s", filename2);
37 if (c1 != c2) {
38 errx(EX_SOFTWARE, "Unexpected difference found at offset %d after reversing twice. "
39 "Expected %d but found %d", pos, c1, c2);
40 }
41 if (c1 == EOF) break;
42 }
43
44 if (fclose(f1) != 0) err(EX_IOERR, "Couldn't close file %s", filename1);
45 if (fclose(f2) != 0) err(EX_IOERR, "Couldn't close file %s", filename2);
46 }
47
48 void test_reverse_twice_from_files_is_the_same() {
49 char* intermediate = reverse_to_temp_file(test_file);
50 char* back_to_normal = reverse_to_temp_file(intermediate);
51
52 compare(test_file, back_to_normal);
53
54 if (unlink(intermediate) == -1) err(EX_IOERR, "Couldn't remove intermediate temp file");
55 if (unlink(back_to_normal) == -1) err(EX_IOERR, "Couldn't remove twice-reversed temp file");
56 free(intermediate);
57 free(back_to_normal);
58 }
59
60 void test_reverse_from_file_then_from_stream_is_the_same() {
61 int pipefd[2];
62 if (pipe(pipefd) == -1) err(EX_OSERR, "Couldn't create pipe");
63
64 pid_t pid = fork();
65 if (pid == -1) err(EX_OSERR, "Couldn't fork");
66 if (pid == 0) {
67 if (close(pipefd[0]) == -1) err(EX_OSERR, "Couldn't close unneeded pipe descriptor");
68 FILE* to_second = fdopen(pipefd[1], "w");
69 if (to_second == NULL) err(EX_IOERR, "Couldn't open pipe for writing");
70 reverse_file(test_file, to_second);
71 exit(0);
72 }
73 if (close(pipefd[1]) == -1) err(EX_OSERR, "Couldn't close unneeded pipe descriptor");
74 FILE* from_first = fdopen(pipefd[0], "r");
75 if (from_first == NULL) err(EX_IOERR, "Couldn't open pipe for reading");
76 char* out_temp_filename;
77 FILE* out_file;
78 make_temporary_file(&out_temp_filename, &out_file);
79 reverse_stream(from_first, out_file);
80 if (fclose(out_file) == EOF) err(EX_IOERR, "Couldn't close temporary file");
81
82 compare(test_file, out_temp_filename);
83
84 if (unlink(out_temp_filename) == -1) err(EX_IOERR, "Couldn't remove temp output file");
85 free(out_temp_filename);
86 }
87
88 int main() {
89 test_reverse_twice_from_files_is_the_same();
90 test_reverse_from_file_then_from_stream_is_the_same();
91 puts("PASS");
92 return 0;
93 }