source: tests/collections/string-istream-manip.cfa@ b771581

stuck-waitfor-destruct
Last change on this file since b771581 was 8a33777, checked in by Michael Brooks <mlbrooks@…>, 2 years ago

Fix analysis error in string-input testing.

Add comments correlating .in file content with line of code that reads it.

This test's correctness expectation is bootstrapped from the actual behaviour of scanf.
A mistake in knowing "which character are we on at this point"
led to an inaccurate understanding of what scanf does on an edge case.
The test was showing that the CFA analogs behave the same as scanf.
But the test was not exercising the case that it suggested it was.
This issue is now fixed.

Old position, mistaken: case 14 begins on line ccccuuuucccc
Old position, corrected: cases 12/13 consume leading cccc; case 14 begins on uuuucccc
New positions: as commented in test .cfa

prior scanf understanding, mistaken: include skips unwanted characters before capturing
wanted characters, while exclude fails on unwanted characters

scanf understanding, corrected: include and exclude fail on unwanted characters

  • Property mode set to 100644
File size: 7.7 KB
Line 
1
2#include <fstream.hfa>
3#include <collections/string.hfa>
4#include <collections/string_res.hfa>
5#include <stdio.h>
6
7// No-op manipulators.
8// Temporary hack while there are two code paths in the string implementation.
9// (One for reading plain strings, the other for reading via a manipulator.)
10// The test cases that use plainjane(-) are exercising the via-manipulator code path,
11// just with trivial manipulation.
12static _Istream_Sstr plainjane( string & s ) { return (_Istream_Sstr)@{ s, {{0p}, -1, {.flags.rwd : false}} }; }
13static _Istream_Rstr plainjane( string_res & s ) { return (_Istream_Rstr)@{ &s, {{0p}, -1, {.flags.rwd : false}} }; }
14
15static void forceStringHeapFreeSpaceTo(int desiredSize) {
16 for (1_000_000) {
17 string x = "a";
18 (void)x;
19 if (desiredSize == DEBUG_string_bytes_avail_until_gc(DEBUG_string_heap())) return;
20 }
21 sout | "Unable to force size" | desiredSize | "in 1,000,000 tries";
22}
23
24int main() {
25 // These "pre" cases deal with issues analogous to the "pre" cases of io/manipulatorsInput.
26 // The acceptance criterion is simpler but driving the cases is harder.
27 // The tests just read strings and echo what they read; acceptance of simple echoing assures
28 // no spurious splitting merging.
29 // The lengths of the strings are chosen to match white-box knowledge of when the string layer
30 // has tor drive the cstring layer through a second iteration:
31 // - for no-manip, lengths are near the room at end of string heap
32 // (chosen target size of 9 showed the original bug on preS2, aligned with the other cases)
33 // - for manip, lengths are near the auxiliary buffer size of 128
34 // Only first case repeats for string_res; rest run only from the passthru string layer.
35 // Similarly, the manipulator breadth isn't checked at the cstring layer either.
36 {
37 // S: string, no manipulator
38 void echoTillX(const char * casename) {
39 string s;
40 // loop assumes behaviour not tested until main-case #15:
41 // on reading nothing, the prior string value is left alone
42 do {
43 s = "";
44 forceStringHeapFreeSpaceTo(9);
45 sin | s;
46 sout | casename | s;
47 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
48 }
49 echoTillX("preS1");
50 echoTillX("preS2");
51 echoTillX("preS3");
52 echoTillX("preS4");
53 }
54 {
55 // SMN: string, manipulator for no-op
56 void echoTillX(const char * casename) {
57 string s;
58 do {
59 s = "";
60 sin | plainjane( s );
61 sout | casename | s;
62 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
63 }
64 echoTillX("preSMN1");
65 echoTillX("preSMN2");
66 echoTillX("preSMN3");
67 echoTillX("preSMN4");
68 }
69 {
70 // RMN: string_res, manipulator for no-op
71 void echoTillX(const char * casename) {
72 string_res s;
73 do {
74 s = "";
75 sin | plainjane( s );
76 sout | casename | s;
77 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
78 }
79 echoTillX("preRMN1");
80 echoTillX("preRMN2");
81 echoTillX("preRMN3");
82 echoTillX("preRMN4");
83 }
84 {
85 // SMI: string, manipulator `incl`
86 void echoTillX(const char * casename) {
87 string s;
88 do {
89 s = "";
90 sin | skip("-\n");
91 sin | incl( ".:|# x", s );
92 sout | casename | " \"" | s | "\"";
93 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
94 }
95 echoTillX("preSMI1");
96 echoTillX("preSMI2");
97 echoTillX("preSMI3");
98 echoTillX("preSMI4");
99 }
100 {
101 // SME: string, manipulator `excl`
102 void echoTillX(const char * casename) {
103 string s;
104 do {
105 s = "";
106 sin | skip("-\n");
107 sin | excl( "-\n", s );
108 sout | casename | " \"" | s | "\"";
109 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
110 }
111 echoTillX("preSME1");
112 echoTillX("preSME2");
113 echoTillX("preSME3");
114 echoTillX("preSME4");
115 }
116 sin | skip("-\n");
117 {
118 // SMG: string, manipulator `getline`
119 void echoTillX(const char * casename) {
120 string s;
121 do {
122 s = "";
123 sin | getline( s );
124 sout | casename | s;
125 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
126 }
127 echoTillX("preSMG1");
128 echoTillX("preSMG2");
129 echoTillX("preSMG3");
130 echoTillX("preSMG4");
131 }
132 {
133 // SMD: string, manipulator (`getline` with custom) delimiter
134 void echoTillX(const char * casename) {
135 string s;
136 do {
137 s = "";
138 sin | getline( s, '@' );
139 sout | casename | s;
140 } while ( size(s) > 0 && s[size(s)-1] != 'x' );
141 sin | skip(" \n");
142 }
143 echoTillX("preSMD1");
144 echoTillX("preSMD2");
145 echoTillX("preSMD3");
146 echoTillX("preSMD4");
147 }
148
149 /* Keep harmonized with io/manipulatorsInput */
150 {
151 string s = "yyyyyyyyyyyyyyyyyyyy";
152 char sk[] = "abc";
153 sin | "abc " | skip( sk ) | skip( 5 ); sout | "1" | s;
154 sin | s; sout | "2" | s;
155 sin | ignore( s ); sout | "3" | s;
156 sin | wdi( 8, s ); sout | "4" | s;
157 sin | ignore( wdi( 8, s ) ); sout | "5" | s;
158
159 sin | incl( "abc", s ); sout | "6" | s;
160 sin | excl( "abc", s ); sout | "7" | s;
161 sin | ignore( incl( "abc", s ) ); sout | "8" | s;
162 sin | ignore( excl( "abc", s ) ); sout | "9" | s;
163 sin | incl( "abc", wdi( 8, s ) ); sout | "10" | s;
164 sin | excl( "abc", wdi( 8, s ) ); sout | "11" | s;
165 sin | ignore( incl( "abc", wdi( 8, s ) ) ); sout | "12" | s;
166 sin | ignore( excl( "abc", wdi( 8, s ) ) ); sout | "13" | s;
167 sin | "\n";
168
169 s = "q";
170 sin | incl( "abc", s ); sout | "14" | s;
171 s = "q";
172 sin | excl( "u", s ); sout | "15" | s;
173 sin | skip( "u" );
174 sin | "\n";
175 }
176 // Full repeat on string_res layer assures the full manipulator vocabulary is supported there.
177 {
178 string_res s = "yyyyyyyyyyyyyyyyyyyy";
179 char sk[] = "abc";
180 sin | "abc " | skip( sk ) | skip( 5 ); sout | "1" | s;
181 sin | s; sout | "2" | s;
182 sin | ignore( s ); sout | "3" | s;
183 sin | wdi( 8, s ); sout | "4" | s;
184 sin | ignore( wdi( 8, s ) ); sout | "5" | s;
185
186 sin | incl( "abc", s ); sout | "6" | s;
187 sin | excl( "abc", s ); sout | "7" | s;
188 sin | ignore( incl( "abc", s ) ); sout | "8" | s;
189 sin | ignore( excl( "abc", s ) ); sout | "9" | s;
190 sin | incl( "abc", wdi( 8, s ) ); sout | "10" | s;
191 sin | excl( "abc", wdi( 8, s ) ); sout | "11" | s;
192 sin | ignore( incl( "abc", wdi( 8, s ) ) ); sout | "12" | s;
193 sin | ignore( excl( "abc", wdi( 8, s ) ) ); sout | "13" | s;
194 sin | "\n";
195
196 s = "q";
197 sin | incl( "abc", s ); sout | "14" | s;
198 s = "q";
199 sin | excl( "u", s ); sout | "15" | s;
200 sin | skip( "u" );
201 sin | "\n";
202 }
203}
Note: See TracBrowser for help on using the repository browser.