1 /**xpand
2    Tests "inspired" by the ones in dstep's UnitTests.d module
3  */
4 module it.c.dstep.ut;
5 
6 import it;
7 
8 
9 @("2 functions and a global variable")
10 @safe unittest {
11     shouldCompile(
12         C(q{
13                 float foo(int x);
14                 float bar(int x);
15                 int a;
16             }
17         ),
18         D(
19 
20             q{
21                 float f = foo(42);
22                 float b = bar(77);
23                 a = 33;
24             }
25         ),
26     );
27 
28 }
29 
30 @("extern int declared several times")
31 @safe unittest {
32     shouldCompile(
33         C(
34             q{
35                 extern int foo;
36                 extern int bar;
37                 extern int foo;
38                 extern int foo;
39             }
40         ),
41         D(
42 
43             q{
44                 foo = 5;
45                 bar = 3;
46             }
47         ),
48     );
49 }
50 
51 @("array with #defined length")
52 @safe unittest {
53     shouldCompile(
54         C(
55             `
56               #define FOO 4
57               char var[FOO];
58           `
59         ),
60         D(
61             q{
62                 static assert(var.sizeof == 4);
63                 var[0] = cast(byte)3;
64             }
65         ),
66     );
67 }
68 
69 @("struct with array with #defined length")
70 @safe unittest {
71     shouldCompile(
72         C(
73             `
74                 #define BAR 128
75 
76                 struct Foo {
77                     char var[BAR];
78                 };
79             `
80         ),
81         D(
82             q{
83                 auto f = Foo();
84                 static assert(f.var.sizeof == 128);
85                 f.var[127] = cast(byte)3;
86             }
87         ),
88     );
89 }
90 
91 
92 @("struct with 3d arrays of #defined length")
93 @safe unittest {
94     shouldCompile(
95         C(
96             `
97                 #define FOO 2
98                 #define BAR 4
99                 #define BAZ 8
100 
101                 struct Foo {
102                     char var[FOO][BAR][BAZ];
103                 };
104             `
105         ),
106         D(
107             q{
108                 auto f = Foo();
109                 // opposite order than in C
110                 static assert(f.var.length == 2);
111                 static assert(f.var[0].length == 4);
112                 static assert(f.var[0][0].length == 8);
113                 auto v = f.var[0][0][7];
114             }
115         ),
116     );
117 }
118 
119 @("nested anonymous structures")
120 @safe unittest {
121     shouldCompile(
122         C(
123             q{
124                 struct C {
125                     struct {
126                         int x;
127                         int y;
128 
129                         struct {
130                             int z;
131                             int w;
132                         } nested;
133                     } point;
134                 };
135             }
136         ),
137         D(
138 
139             q{
140                 auto c = C();
141                 c.point.x = 42;
142                 c.point.y = 77;
143                 c.point.nested.z = 2;
144                 c.point.nested.w = 3;
145             }
146         ),
147     );
148 
149 }
150 
151 @("interleaved enum-based array size consts and macro based array size counts")
152 @safe unittest {
153     shouldCompile(
154         C(
155             `
156                 struct qux {
157                     char scale;
158                 };
159 
160                 #define FOO 2
161                 #define BAZ 8
162 
163                 struct stats_t {
164                     enum
165                     {
166                         BAR = 4,
167                     };
168 
169                     struct qux stat[FOO][BAR][FOO][BAZ];
170                 };
171             `
172         ),
173         D(
174             q{
175                 auto s = stats_t();
176                 // opposite order than in C
177                 static assert(stats_t.BAR == 4);
178                 // accessing at the limits of each dimension
179                 auto q = s.stat[1][3][1][7];
180             }
181         ),
182     );
183 }
184 
185 @("function pointer with unnamed parameter")
186 @safe unittest {
187     shouldCompile(
188         C(
189             q{
190                 typedef int (*read_char)(void *);
191             }
192         ),
193         D(
194 
195             q{
196                 read_char func;
197                 int val;
198                 int ret = func(&val);
199             }
200         ),
201     );
202 
203 }
204 
205 @("array typedef")
206 @safe unittest {
207     shouldCompile(
208         C(
209             q{
210                 typedef double foo[2];
211             }
212         ),
213         D(
214 
215             q{
216                 foo doubles;
217                 static assert(doubles.length == 2);
218                 doubles[0] = 33.3;
219                 doubles[1] = 77.7;
220             }
221         ),
222     );
223 
224 }
225 
226 @("array of structs declared immediately")
227 @safe unittest {
228     shouldCompile(
229         C(
230             q{
231                 struct Foo {
232                     struct Bar {
233                     } bar[64];
234                 };
235             }
236         ),
237         D(
238 
239             q{
240                 auto f = Foo();
241                 static assert(f.bar.length == 64);
242                 f.bar[63] = Foo.Bar();
243             }
244         ),
245     );
246 
247 }
248 
249 @("variadic function without ...")
250 @safe unittest {
251 
252     shouldCompile(
253         C(
254             q{
255                 // Since fully variadic C functions aren't allowed in D,
256                 // we assume the header means `void foo(void);`
257                 // The reason being that void foo(...) wouldn't compile
258                 // anyway and it's possible they meant foo(void).
259                 void foo();
260             }
261         ),
262         D(
263             q{
264                 foo();
265                 static assert(!__traits(compiles, foo(2, 3)));
266             }
267         ),
268     );
269 }
270 
271 
272 @("function pointers")
273 @safe unittest {
274     shouldCompile(
275         C(
276             q{
277                 typedef void* ClientData;
278                 typedef struct { int dummy; } EntityInfo;
279                 void (*fun)(ClientData client_data, const EntityInfo*, unsigned last);
280             }
281         ),
282         D(
283 
284             q{
285                 auto eInfo = EntityInfo(77);
286                 struct Data { int value; }
287                 auto data = Data(42);
288                 uint last = 33;
289                 fun(&data, &eInfo, last);
290             }
291         ),
292     );
293 
294 }
295 
296 
297 @("array function parameters")
298 @safe unittest {
299     shouldCompile(
300         C(
301             q{
302                 int foo (int data[]);             // int*
303                 int bar (const int data[]);       // const int*
304                 int baz (const int data[32]);     // const int*
305                 int qux (const int data[32][64]); // const int(*)[64]
306             }
307         ),
308         D(
309 
310             q{
311                 int* data;
312                 foo(data);
313                 bar(data);
314                 baz(data);
315 
316                 const(int)* cdata;
317                 static assert(!__traits(compiles, foo(cdata)));
318                 bar(cdata);
319                 baz(cdata);
320 
321                 static assert(!__traits(compiles, qux(data)));
322                 static assert(!__traits(compiles, qux(cdata)));
323                 const(int)[64] arr;
324                 qux(&arr);
325             }
326         ),
327     );
328 
329 }
330 
331 @("name collision between struct and function")
332 @safe unittest {
333     shouldCompile(
334         C(
335             q{
336                 struct foo;
337                 struct foo { int i; };
338                 void foo(void);
339             }
340         ),
341         D(
342 
343             q{
344                 foo f;
345                 f.i = 42;
346                 foo_();
347             }
348         ),
349     );
350 
351 }
352 
353 @("name collision between struct and enum")
354 @safe unittest {
355     shouldCompile(
356         C(
357             q{
358                 enum foo { FOO };
359                 void foo(void);
360             }
361         ),
362         D(
363 
364             q{
365                 foo_();
366                 auto f1 = FOO;
367                 foo f2 = foo.FOO;
368             }
369         ),
370     );
371 
372 }
373 
374 @("function parameter of elaborate type")
375 @safe unittest {
376     shouldCompile(
377         C(
378             q{
379                 struct foo_t { int i; };
380                 void bar(const struct foo_t *foo);
381             }
382         ),
383         D(
384 
385             q{
386                 auto f = foo_t(42);
387                 bar(&f);
388                 const cf = const foo_t(33);
389                 bar(&cf);
390             }
391         ),
392     );
393 
394 }
395 
396 @("packed struct")
397 @safe unittest {
398     shouldCompile(
399         C(
400             q{
401                 struct Foo {
402                     char x;
403                     short y;
404                     int z;
405                 } __attribute__((__packed__));
406             }
407         ),
408         D(
409             q{
410                 static assert(Foo.sizeof == 7, "Foo should be 7 bytes");
411             }
412         ),
413     );
414 }