OILS / mycpp / gc_mylib_test.cc View on Github | oilshell.org

327 lines, 208 significant
1#include "mycpp/gc_mylib.h"
2
3#include <unistd.h>
4
5#include "mycpp/gc_alloc.h" // gHeap
6#include "mycpp/gc_str.h"
7#include "vendor/greatest.h"
8
9TEST split_once_test() {
10 log("split_once()");
11
12 BigStr* s = nullptr;
13 BigStr* delim = nullptr;
14 StackRoots _roots1({&s, &delim});
15
16 s = StrFromC("foo=bar");
17 delim = StrFromC("=");
18 Tuple2<BigStr*, BigStr*> t = mylib::split_once(s, delim);
19
20 auto t0 = t.at0();
21 auto t1 = t.at1();
22
23 log("t %p %p", t0, t1);
24
25 BigStr* foo = nullptr;
26 StackRoots _roots2({&t0, &t1, &foo});
27 foo = StrFromC("foo");
28
29 // TODO: We lack rooting in the cases below!
30 PASS();
31
32 Tuple2<BigStr*, BigStr*> u =
33 mylib::split_once(StrFromC("foo="), StrFromC("="));
34 ASSERT(str_equals(u.at0(), StrFromC("foo")));
35 ASSERT(str_equals(u.at1(), StrFromC("")));
36
37 Tuple2<BigStr*, BigStr*> v =
38 mylib::split_once(StrFromC("foo="), StrFromC("Z"));
39 ASSERT(str_equals(v.at0(), StrFromC("foo=")));
40 ASSERT(v.at1() == nullptr);
41
42 Tuple2<BigStr*, BigStr*> w = mylib::split_once(StrFromC(""), StrFromC("Z"));
43 ASSERT(str_equals(w.at0(), StrFromC("")));
44 ASSERT(w.at1() == nullptr);
45
46 PASS();
47}
48
49TEST int_to_str_test() {
50 int int_min = INT_MIN;
51 BigStr* int_str;
52
53 int_str = mylib::hex_lower(15);
54 ASSERT(str_equals0("f", int_str));
55 print(int_str);
56 print(mylib::hex_lower(int_min));
57
58 PASS();
59}
60
61TEST funcs_test() {
62 BigStr* int_str = nullptr;
63
64 StackRoots _roots({&int_str});
65
66 BigStr* fooEqualsBar = nullptr;
67 BigStr* foo = nullptr;
68 BigStr* bar = nullptr;
69 BigStr* fooEquals = nullptr;
70
71 BigStr* equals = nullptr;
72 BigStr* Z = nullptr;
73 BigStr* emptyStr = nullptr;
74
75 StackRoots _roots2(
76 {&fooEqualsBar, &foo, &bar, &fooEquals, &equals, &Z, &emptyStr});
77
78 fooEqualsBar = StrFromC("foo=bar");
79 foo = StrFromC("foo");
80 bar = StrFromC("bar");
81 fooEquals = StrFromC("foo=");
82
83 equals = StrFromC("=");
84 Z = StrFromC("Z");
85 emptyStr = StrFromC("");
86
87 log("split_once()");
88 Tuple2<BigStr*, BigStr*> t = mylib::split_once(fooEqualsBar, equals);
89 ASSERT(str_equals(t.at0(), foo));
90 ASSERT(str_equals(t.at1(), bar));
91
92 Tuple2<BigStr*, BigStr*> u = mylib::split_once(fooEquals, equals);
93 ASSERT(str_equals(u.at0(), foo));
94 ASSERT(str_equals(u.at1(), emptyStr));
95
96 Tuple2<BigStr*, BigStr*> v = mylib::split_once(fooEquals, Z);
97 ASSERT(str_equals(v.at0(), fooEquals));
98 ASSERT(v.at1() == nullptr);
99
100 Tuple2<BigStr*, BigStr*> w = mylib::split_once(emptyStr, Z);
101 ASSERT(str_equals(w.at0(), emptyStr));
102 ASSERT(w.at1() == nullptr);
103
104 PASS();
105}
106
107#if 0
108TEST writeln_test() {
109 mylib::writeln(StrFromC("stdout"));
110 mylib::writeln(StrFromC("stderr"), mylib::kStderr);
111
112 PASS();
113}
114#endif
115
116TEST BufWriter_test() {
117 mylib::BufWriter* writer = nullptr;
118 BigStr* s = nullptr;
119 BigStr* foo = nullptr;
120 BigStr* bar = nullptr;
121 StackRoots _roots({&writer, &s, &foo, &bar});
122
123 foo = StrFromC("foo");
124 bar = StrFromC("bar");
125
126 writer = Alloc<mylib::BufWriter>();
127 s = writer->getvalue();
128 ASSERT_EQ(kEmptyString, s);
129
130 // Create a new BufWriter to call getvalue() again
131 writer = Alloc<mylib::BufWriter>();
132 writer->write(foo);
133 s = writer->getvalue();
134 ASSERT(str_equals0("foo", s));
135
136 // Create a new BufWriter to call getvalue() again
137 writer = Alloc<mylib::BufWriter>();
138 writer->write(foo);
139 writer->write_spaces(3);
140 writer->write_spaces(0);
141 writer->write(bar);
142
143 s = writer->getvalue();
144 ASSERT(str_equals0("foo bar", s));
145 log("result = %s", s->data());
146
147 writer->clear();
148 writer->write(bar);
149 s = writer->getvalue();
150 ASSERT(str_equals0("bar", s));
151
152 PASS();
153}
154
155using mylib::BufLineReader;
156
157TEST BufLineReader_test() {
158 BigStr* s = StrFromC("foo\nbar\nleftover");
159 auto reader = Alloc<BufLineReader>(s);
160
161 ASSERT_EQ(false, reader->isatty());
162
163 log("BufLineReader");
164
165 BigStr* line = nullptr;
166 line = reader->readline();
167 log("1 [%s]", line->data_);
168 ASSERT(str_equals0("foo\n", line));
169
170 line = reader->readline();
171 log("2 [%s]", line->data_);
172 ASSERT(str_equals0("bar\n", line));
173
174 line = reader->readline();
175 log("3 [%s]", line->data_);
176 ASSERT(str_equals0("leftover", line));
177
178 line = reader->readline();
179 log("4 [%s]", line->data_);
180 ASSERT(str_equals0("", line));
181
182 // Optimization we want
183 ASSERT_EQ(kEmptyString, line);
184
185 // Read again
186 line = reader->readline();
187 log("5 [%s]", line->data_);
188 // Optimization we want
189 ASSERT_EQ(kEmptyString, line);
190
191 reader->close();
192
193 //
194 // Empty
195 //
196
197 reader = Alloc<BufLineReader>(kEmptyString);
198 line = reader->readline();
199 ASSERT_EQ(kEmptyString, line);
200
201 BigStr* one_line = StrFromC("one line");
202 reader = Alloc<BufLineReader>(one_line);
203 line = reader->readline();
204 ASSERT(str_equals(one_line, line));
205
206 // Optimization: pointers should be equal too!
207 ASSERT_EQ(one_line, line);
208
209 line = reader->readline();
210 ASSERT_EQ(kEmptyString, line);
211
212 PASS();
213}
214
215TEST files_test() {
216 mylib::Writer* stdout_ = mylib::Stdout();
217 log("stdout isatty() = %d", stdout_->isatty());
218
219 mylib::LineReader* stdin_ = mylib::Stdin();
220 log("stdin isatty() = %d", stdin_->isatty());
221
222 FILE* f = fopen("README.md", "r");
223
224 mylib::CFile* r = nullptr;
225 BigStr* filename = nullptr;
226 BigStr* filename2 = nullptr;
227 StackRoots _roots({&r, &filename, &filename2});
228
229 r = Alloc<mylib::CFile>(f);
230 filename = StrFromC("README.md");
231 filename2 = StrFromC("README.md ");
232 // auto r = mylib::Stdin();
233
234 log("files_test");
235 int i = 0;
236 while (true) {
237 BigStr* s = r->readline();
238 if (len(s) == 0) {
239 break;
240 }
241 if (i < 5) {
242 mylib::print_stderr(s);
243 }
244 ++i;
245 }
246 r->close();
247 log("files_test DONE");
248
249 auto f2 = mylib::open(filename);
250 ASSERT(f2 != nullptr);
251
252 // See if we can strip a space and still open it. Underlying fopen() call
253 // works.
254 auto f3 = mylib::open(filename2->strip());
255 ASSERT(f3 != nullptr);
256
257 auto w = Alloc<mylib::CFile>(stdout);
258 w->write(StrFromC("stdout"));
259 w->flush();
260
261 PASS();
262}
263
264TEST for_test_coverage() {
265 mylib::MaybeCollect(); // trivial wrapper for translation
266
267 auto writer = mylib::Stderr();
268 writer->write(kEmptyString);
269
270 // Methods we're not really using? Refactoring types could eliminate these
271 auto w = Alloc<mylib::BufWriter>();
272 ASSERT_EQ(false, w->isatty());
273 w->flush();
274
275 // Initializes the heap
276 mylib::InitCppOnly();
277
278 PASS();
279}
280
281TEST getc_demo() {
282 // CPython fileobject.c appears to use getc? Is it buffered?
283 // Oh yeah I see a syscall read(0, "hi123")
284 // OK maybe I should just use getc instead of getline()?
285 // getline() has different buffering perhaps?
286
287 int fd[2];
288 ::pipe(fd);
289
290 ::dup2(fd[0], 0);
291
292 write(fd[1], "hi", 3);
293
294 int c = getc(stdin);
295 log("c = %c", c);
296
297 c = getc(stdin);
298 log("c = %c", c);
299
300 PASS();
301}
302
303GREATEST_MAIN_DEFS();
304
305int main(int argc, char** argv) {
306 gHeap.Init();
307
308 GREATEST_MAIN_BEGIN();
309
310 RUN_TEST(split_once_test);
311 RUN_TEST(int_to_str_test);
312 RUN_TEST(funcs_test);
313
314 // RUN_TEST(writeln_test);
315 RUN_TEST(BufWriter_test);
316 RUN_TEST(BufLineReader_test);
317 RUN_TEST(files_test);
318 RUN_TEST(for_test_coverage);
319
320 RUN_TEST(getc_demo);
321
322 gHeap.CleanProcessExit();
323
324 GREATEST_MAIN_END(); /* display results */
325
326 return 0;
327}