source: tests/io/manipulatorsInput-uchunk.cfa

Last change on this file was 406c806, checked in by Michael Brooks <mlbrooks@…>, 2 months ago

Attempt to fix Promote build by naming recently added test data files in a more typical way.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2uchunk - user-visible chunking: how a user's input-consuming loop experiences a presence/absence of qualifying input
3         slight generalization of "eof handling"; we called many of these cases the "eof tests" while first devising them
4
5Coverage criteria include when an input-provided chunk exactly fills a user-provided buffer,
6because the double-boundary case of "this happens just before eof" is (white-box) uchunk-relevant.
7But cases of input-provided chunks exceeding the user's buffer live under
8manipulatorsInput#pre* and ../collections/string-io-istream-manip#pre*.
9
10Test design with subprocesses and auxiliary inputs is cargo-culted from
11configs/parseconfig, configs/usage and io/many_read.
12If you're here to cargo-cult, start there.
13
14*/
15
16#ifdef __cplusplus
17  #include <iostream>
18  #include <iomanip>
19  #include <cstring>
20  using namespace std;
21  #define TRYREAD(str)      tryread(sizeof(str)-1, str);
22  #define DETECT_EOF( ... ) __VA_ARGS__
23  #define POLL_EOF          if ( cin.fail() ) break;
24  #define ECHO(stg, str)    cout << #stg << " \"" << str << "\"" << str[sizeof(str)-1] << endl
25#elif defined __cforall
26  #include <fstream.hfa>
27  extern "C" {
28    char* strcpy(char*, const char*);
29  }
30  #define DETECT_EOF( ... ) \
31    try { \
32      __VA_ARGS__ \
33    } catch ( end_of_file * ) {}
34  #define TRYREAD(str)      try {                                             \
35                                  tryread(sizeof(str)-1, str);                \
36                            }                                                 \
37                            catch ( cstring_length* ) {                       \
38                                /* never expected; just harness robustness */ \
39                                sout | "cstring_length and " | nonl;          \
40                            }
41  #define POLL_EOF
42  #define ECHO(stg, str)    sout | #stg | " \"" | str | "\"" | str[sizeof(str)-1]
43#else
44  #error no
45#endif
46
47
48
49//
50// BEGIN: functions only used in child process
51//
52// Parent process does not use test.py-provided stdin.
53// Parent process uses test.py-provided IN_DIR, from which it explicitly opens files.
54// Each child process sees content from one such file on its stdin.
55// The functions in this section echo, from this distinct child stdin, to parent-bridged stdout.
56//
57
58void subcaseHarness( void (*tryread)(size_t, char*) ) {
59    char s[10];
60    DETECT_EOF (
61      for (bool first = true ;; ) {
62          strcpy(s, "---");  // every time: restore "---"x
63          s[9] = 'x';
64          if (first) {
65            ECHO(BGN, s);    // first time: show it
66            first = false;
67          }
68
69          TRYREAD(s)
70          POLL_EOF
71          ECHO(GOT, s);
72      }
73    )
74    ECHO(END, s);
75}
76
77void tryread_default(size_t sizeof_s, char *s) {
78  #ifdef __cplusplus
79    cin >> setw( sizeof_s ) >> s;
80  #else
81    sin | wdi( sizeof_s, s );
82  #endif
83}
84
85void tryread_getline(size_t sizeof_s, char *s) {
86  #ifdef __cplusplus
87    cin.getline(s, sizeof_s);
88  #else
89    sin | getline( wdi( sizeof_s, s ) );
90  #endif
91}
92
93//
94// END: functions only used in child process
95//
96
97
98extern "C" {
99        #include <sys/types.h>
100        #include <sys/stat.h>
101        #include <fcntl.h>
102        #include <unistd.h>
103}
104
105#ifdef SUBCASE_ISOLATION
106
107    #define x(s) s
108    #define TRYREAD_FUNCTION x(tryread_ ## x(SUBCASE_ISOLATION))
109
110    #define MK_TRYREAD_FUNCTION(x) tryread_ ## x
111
112    #define _MAKEDATA(n) tryread_ ## n
113    #define MAKEDATA(n) _MAKEDATA(n)
114
115    int main() {
116        subcaseHarness( MAKEDATA(SUBCASE_ISOLATION) );
117    }
118
119#else
120    #define xstr(s) str(s)
121    #define str(s) #s
122
123    #include "../meta/fork+exec.hfa"
124
125    void forkJoinSubcase( void (*tryread)(size_t, char*), const char* subcase_name, const char* aux_in_fname ) {
126        printf("--- %s ---\n", subcase_name);
127        int aux_in_fd = open(aux_in_fname, 0);
128        if( aux_in_fd < 0 ) {
129            printf("Failed to open file: %s\n", aux_in_fname);
130            exit(1);
131        }
132        if ( pid_t child_pid = strict_fork() ) {
133            // in parent
134            do_wait(child_pid);
135        } else {
136            // in child
137            dup2(aux_in_fd, 0);  // make stdin pull from aux
138            subcaseHarness( tryread );
139            exit(0);
140        }
141    }
142
143    #define SUBCASE_( TRYREAD_FUNCTION, IN_FILE_SLUG ) forkJoinSubcase( TRYREAD_FUNCTION, (IN_FILE_SLUG), (xstr(IN_DIR) "manipulatorsInput-uchunk." IN_FILE_SLUG ".txt") )
144    #define SUBCASE( MANIP, IN_FILE_SUFFIX ) SUBCASE_( tryread_ ## MANIP, #MANIP "." #IN_FILE_SUFFIX )
145
146    int main() {
147
148        SUBCASE( default, 1 );
149        SUBCASE( default, 2 );
150        SUBCASE( default, 3 );
151        SUBCASE( default, 4 );
152        SUBCASE( default, 5 );
153        SUBCASE( default, 6 );
154        SUBCASE( default, 7 );
155        SUBCASE( default, 8 );
156        SUBCASE( default, 9 );
157        SUBCASE( default, 10 );
158        SUBCASE( default, 11 );
159        SUBCASE( default, 12 );
160        SUBCASE( default, 13 );
161        SUBCASE( default, 14 );
162
163        SUBCASE( getline, 1 );
164        SUBCASE( getline, 2 );
165        SUBCASE( getline, 3 );
166        SUBCASE( getline, 4 );
167        SUBCASE( getline, 5 );
168        SUBCASE( getline, 6 );
169        SUBCASE( getline, 7 );
170        SUBCASE( getline, 8 );
171        SUBCASE( getline, 9 );
172        SUBCASE( getline, 10 );
173        SUBCASE( getline, 11 );
174        SUBCASE( getline, 12 );
175        SUBCASE( getline, 13 );
176        SUBCASE( getline, 14 );
177
178        return 0;
179    }
180
181    // not used
182    static int true_main(const char * path, const char * env[]) { return 0; }
183
184
185#endif
Note: See TracBrowser for help on using the repository browser.