OILS / mycpp / gc_mylib_test.cc View on Github | oils.pub

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