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

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