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