1 
2 module dquery.tests.regression;
3 
4 import dquery.d;
5 
6 version(unittest)
7 {
8 	struct Coord
9 	{
10 
11 		private
12 		{
13 			struct Attr
14 			{
15 			}
16 
17 			struct Limit
18 			{
19 				int value;
20 			}
21 
22 			struct None
23 			{
24 			}
25 		}
26 
27 		@Attr
28 		@Limit(10)
29 		int x;
30 
31 		@Attr
32 		@Limit(10)
33 		int y;
34 
35 		@Attr
36 		@Limit(10)
37 		int z;
38 
39 		int tmp;
40 
41 		@disable this();
42 
43 		this(int x, int y, int z)
44 		{
45 			this.x = x;
46 			this.y = y;
47 			this.z = z;
48 		}
49 
50 		void reset()
51 		{
52 			x = y = z = 0;
53 		}
54 
55 		int[3] getCoords()
56 		{
57 			return [x, y, z];
58 		}
59 	}
60 }
61 
62 unittest
63 {
64 	alias Attr = Coord.Attr;
65 	alias Limit = Coord.Limit;
66 	alias None = Coord.None;
67 
68 	Coord coord = Coord(1, 2, 3);
69 	auto query = coord.query;
70 
71 	// Should not be empty.
72 	static assert(!query.empty);
73 
74 	// Should have 11 elements.
75 	static assert(query.length == 11);
76 
77 	auto fields = query.fields;
78 
79 	// Should match parent type.
80 	static assert(is(fields.type == query.type));
81 
82 	// Should not be empty.
83 	static assert(!fields.empty);
84 
85 	// Should have 4 elements.
86 	static assert(fields.length == 4);
87 
88 	foreach(element; fields)
89 	{
90 		// Should match parent type.
91 		static assert(is(element.type == fields.type));
92 
93 		static if(!element.isName!"tmp")
94 		{
95 			// Should have attribute Attr.
96 			static assert(element.hasAttribute!Attr);
97 
98 			// Should have attribute Limit.
99 			static assert(element.hasAttribute!Limit);
100 
101 			// Should not have attribute None.
102 			static assert(!element.hasAttribute!None);
103 
104 			// Should not have nonexistent elements.
105 			static assert(element.attributes.anyOf!None.empty);
106 
107 			// Should not have noneOfden elements.
108 			static assert(element.attributes.noneOf!(Attr, Limit).empty);
109 
110 			foreach(attribute; element.attributes.anyOf!Attr)
111 			{
112 				// Should be a type attribute.
113 				static assert(attribute.isType);
114 
115 				// Should not be an expression attribute.
116 				static assert(!attribute.isExpression);
117 
118 				// Should be type Attr.
119 				static assert(attribute.isTypeOf!Attr);
120 
121 				// Should not be type None.
122 				static assert(!attribute.isTypeOf!None);
123 
124 				// Should be assignable to Attr.
125 				static assert(attribute.isTypeAssignableTo!Attr);
126 
127 				// Should not be assignable to None.
128 				static assert(!attribute.isTypeAssignableTo!None);
129 
130 				// Should be assignable from Attr.
131 				static assert(attribute.isTypeAssignableFrom!Attr);
132 
133 				// Should not be assignable from None.
134 				static assert(!attribute.isTypeAssignableFrom!None);
135 			}
136 
137 			foreach(attribute; element.attributes.anyOf!Limit)
138 			{
139 				// Should be a type attribute.
140 				static assert(!attribute.isType);
141 
142 				// Should not be an expression attribute.
143 				static assert(attribute.isExpression);
144 
145 				// Should be type Limit.
146 				static assert(attribute.isTypeOf!Limit);
147 
148 				// Should not be type None.
149 				static assert(!attribute.isTypeOf!None);
150 
151 				// Should be assignable to Limit.
152 				static assert(attribute.isTypeAssignableTo!Limit);
153 
154 				// Should not be assignable to None.
155 				static assert(!attribute.isTypeAssignableTo!None);
156 
157 				// Should be assignable from Limit.
158 				static assert(attribute.isTypeAssignableFrom!Limit);
159 
160 				// Should not be assignable from None.
161 				static assert(!attribute.isTypeAssignableFrom!None);
162 			}
163 		}
164 		else
165 		{
166 			// Should not have attribute Attr.
167 			static assert(!element.hasAttribute!Attr);
168 
169 			// Should not have attribute Limit.
170 			static assert(!element.hasAttribute!Limit);
171 
172 			// Should not have attribute None.
173 			static assert(!element.hasAttribute!None);
174 
175 			// Should not have nonexistent elements.
176 			static assert(element.attributes.anyOf!None.empty);
177 
178 			// Should not have anyOfed but nonexistent elements.
179 			static assert(element.attributes.anyOf!(Attr, Limit).empty);
180 
181 			// Should not have noneOfden elements.
182 			static assert(element.attributes.noneOf!(Attr, Limit).empty);
183 		}
184 
185 		// Should have public protection.
186 		static assert(element.protection == "public");
187 
188 		// Should be a field.
189 		static assert(element.isField);
190 
191 		// Should be an int.
192 		static assert(element.isTypeOf!int);
193 
194 		// Should be not a ulong.
195 		static assert(!element.isTypeOf!ulong);
196 
197 		// Should be assignable to int.
198 		static assert(element.isTypeAssignableTo!int);
199 
200 		// Should be assignable to ulong.
201 		static assert(element.isTypeAssignableTo!ulong);
202 
203 		// Should be assignable from int.
204 		static assert(element.isTypeAssignableFrom!int);
205 
206 		// Should not be assignable from ulong.
207 		static assert(!element.isTypeAssignableFrom!ulong);
208 
209 		// Should not be a function.
210 		static assert(!element.isFunction);
211 
212 		// Should not have arity 0.
213 		static assert(!element.isArity!0);
214 
215 		// Should not return an int.
216 		static assert(!element.isReturnTypeOf!int);
217 
218 		// Should not be an aggregate.
219 		static assert(!element.isAggregate);
220 
221 		// Should not be a class.
222 		static assert(!element.isClass);
223 
224 		// Should not be a struct.
225 		static assert(!element.isStruct);
226 	}
227 
228 	auto namedFields = fields.names!("x", "z");
229 
230 	// Should match parent type.
231 	static assert(is(namedFields.type == fields.type));
232 
233 	// Should not be empty.
234 	static assert(!namedFields.empty);
235 
236 	// Should have 2 elements.
237 	static assert(namedFields.length == 2);
238 
239 	foreach(element; namedFields)
240 	{
241 		// Should match parent type.
242 		static assert(is(element.type == namedFields.type));
243 
244 		// Should not be field y.
245 		static assert(!element.isName!"y");
246 
247 		// Should be one of fields x or z.
248 		static assert(
249 			element.isName!"x" ||
250 			element.isName!"z"
251 		);
252 	}
253 
254 	auto anyOfedFields = fields.anyOf!Attr;
255 
256 	// Should match parent type.
257 	static assert(is(anyOfedFields.type == fields.type));
258 
259 	// Should not be empty.
260 	static assert(!anyOfedFields.empty);
261 
262 	// Should have 3 elements.
263 	static assert(anyOfedFields.length == 3);
264 
265 	foreach(element; anyOfedFields)
266 	{
267 		// Should match parent type.
268 		static assert(is(element.type == anyOfedFields.type));
269 
270 		// Should not be field tmp.
271 		static assert(!element.isName!"tmp");
272 
273 		// Should have attribute Attr.
274 		static assert(element.hasAttribute!Attr);
275 	}
276 
277 	auto noneOfdenFields = fields.noneOf!Limit;
278 
279 	// Should match parent type.
280 	static assert(is(noneOfdenFields.type == fields.type));
281 
282 	// Should not be empty.
283 	static assert(!noneOfdenFields.empty);
284 
285 	// Should have 1 element.
286 	static assert(noneOfdenFields.length == 1);
287 
288 	foreach(element; noneOfdenFields)
289 	{
290 		// Should match parent type.
291 		static assert(is(element.type == noneOfdenFields.type));
292 
293 		// Should be field tmp.
294 		static assert(element.isName!"tmp");
295 
296 		// Should have attribute Other.
297 		static assert(!element.hasAttribute!Limit);
298 
299 		// Should have no attributes.
300 		static assert(element.attributes.empty);
301 	}
302 
303 	auto functions = query.functions;
304 
305 	// Should not be empty.
306 	static assert(!functions.empty);
307 
308 	// Should have 4 elements.
309 	static assert(functions.length == 4);
310 
311 	foreach(element; functions)
312 	{
313 		// Should match parent type.
314 		static assert(is(element.type == fields.type));
315 
316 		// Should not have attribute Attr.
317 		static assert(!element.hasAttribute!Attr);
318 
319 		// Should not have attribute Limit.
320 		static assert(!element.hasAttribute!Limit);
321 
322 		// Should not have attribute None.
323 		static assert(!element.hasAttribute!None);
324 
325 		// Should not have nonexistent elements.
326 		static assert(element.attributes.anyOf!None.empty);
327 
328 		// Should not have noneOfden elements.
329 		static assert(element.attributes.noneOf!(Attr, Limit).empty);
330 
331 		// Should have public protection.
332 		static assert(element.protection == "public");
333 
334 		// Should not be a field.
335 		static assert(!element.isField);
336 
337 		// Should be an int.
338 		static assert(!element.isTypeOf!int);
339 
340 		// Should be not a ulong.
341 		static assert(!element.isTypeOf!ulong);
342 
343 		// Should be assignable to int.
344 		static assert(!element.isTypeAssignableTo!int);
345 
346 		// Should be assignable to ulong.
347 		static assert(!element.isTypeAssignableTo!ulong);
348 
349 		// Should be assignable from int.
350 		static assert(!element.isTypeAssignableFrom!int);
351 
352 		// Should not be assignable from ulong.
353 		static assert(!element.isTypeAssignableFrom!ulong);
354 
355 		// Should be a function.
356 		static assert(element.isFunction);
357 
358 		static if(element.isName!"__ctor")
359 		{
360 			static if(element.isArity!0)
361 			{
362 				// Should have parameters ().
363 				static assert(element.isParameterTypesOf!());
364 
365 				// Should not have parameters (int).
366 				static assert(!element.isParameterTypesOf!(int));
367 
368 				// Should not have parameters (int, int, int).
369 				static assert(!element.isParameterTypesOf!(int, int, int));
370 
371 				// Should not return an int.
372 				static assert(!element.isReturnTypeOf!int);
373 
374 				// Should return a Coord.
375 				static assert(element.isReturnTypeOf!Coord);
376 			}
377 			else static if(element.isArity!3)
378 			{
379 				// Should not have parameters ().
380 				static assert(!element.isParameterTypesOf!());
381 
382 				// Should not have parameters (int).
383 				static assert(!element.isParameterTypesOf!(int));
384 
385 				// Should have parameters (int, int, int).
386 				static assert(element.isParameterTypesOf!(int, int, int));
387 
388 				// Should not return an int.
389 				static assert(!element.isReturnTypeOf!int);
390 
391 				// Should return a Coord.
392 				static assert(element.isReturnTypeOf!Coord);
393 			}
394 			else
395 			{
396 				static assert(0);
397 			}
398 		}
399 		else static if(element.isName!"reset")
400 		{
401 			// Should have arity 0.
402 			static assert(element.isArity!0);
403 			
404 			// Should not have arity 3.
405 			static assert(!element.isArity!3);
406 
407 			// Should have parameters ().
408 			static assert(element.isParameterTypesOf!());
409 
410 			// Should not have parameters (int).
411 			static assert(!element.isParameterTypesOf!(int));
412 
413 			// Should not have parameters (int, int, int).
414 			static assert(!element.isParameterTypesOf!(int, int, int));
415 
416 			// Should not return an int.
417 			static assert(!element.isReturnTypeOf!int);
418 
419 			// Should not return an int array.
420 			static assert(!element.isReturnTypeOf!(int[3]));
421 
422 			// Should return void.
423 			static assert(element.isReturnTypeOf!void);
424 		}
425 		else static if(element.isName!"getCoords")
426 		{
427 			// Should have arity 0.
428 			static assert(element.isArity!0);
429 			
430 			// Should not have arity 3.
431 			static assert(!element.isArity!3);
432 
433 			// Should have parameters ().
434 			static assert(element.isParameterTypesOf!());
435 
436 			// Should not have parameters (int).
437 			static assert(!element.isParameterTypesOf!(int));
438 
439 			// Should not have parameters (int, int, int).
440 			static assert(!element.isParameterTypesOf!(int, int, int));
441 
442 			// Should not return an int.
443 			static assert(!element.isReturnTypeOf!int);
444 
445 			// Should return an int array.
446 			static assert(element.isReturnTypeOf!(int[3]));
447 		}
448 		else
449 		{
450 			// Should not have any other elements.
451 			static assert(0, "Unexpected element " ~ element.name);
452 		}
453 
454 		// Should not be an aggregate.
455 		static assert(!element.isAggregate);
456 
457 		// Should not be a class.
458 		static assert(!element.isClass);
459 
460 		// Should not be a struct.
461 		static assert(!element.isStruct);
462 	}
463 
464 	auto aggregates = query.aggregates;
465 
466 	// Should not be empty.
467 	static assert(!aggregates.empty);
468 
469 	// Should have 3 elements.
470 	static assert(aggregates.length == 3);
471 
472 	foreach(element; aggregates)
473 	{
474 		// Should match parent type.
475 		static assert(is(element.type == aggregates.type));
476 
477 		// Should not have attribute Attr.
478 		static assert(!element.hasAttribute!Attr);
479 
480 		// Should not have attribute Limit.
481 		static assert(!element.hasAttribute!Limit);
482 
483 		// Should not have attribute None.
484 		static assert(!element.hasAttribute!None);
485 
486 		// Should not have nonexistent elements.
487 		static assert(element.attributes.anyOf!None.empty);
488 
489 		// Should not have noneOfden elements.
490 		static assert(element.attributes.noneOf!(Attr, Limit).empty);
491 
492 		// Should have private protection.
493 		static assert(element.protection == "private");
494 
495 		// Should not be a field.
496 		static assert(!element.isField);
497 
498 		// Should be an int.
499 		static assert(!element.isTypeOf!int);
500 
501 		// Should be not a ulong.
502 		static assert(!element.isTypeOf!ulong);
503 
504 		// Should be assignable to int.
505 		static assert(!element.isTypeAssignableTo!int);
506 
507 		// Should be assignable to ulong.
508 		static assert(!element.isTypeAssignableTo!ulong);
509 
510 		// Should be assignable from int.
511 		static assert(!element.isTypeAssignableFrom!int);
512 
513 		// Should not be assignable from ulong.
514 		static assert(!element.isTypeAssignableFrom!ulong);
515 
516 		// Should not be a function.
517 		static assert(!element.isFunction);
518 
519 		// Should not have arity 0.
520 		static assert(!element.isArity!0);
521 
522 		// Should not return an int.
523 		static assert(!element.isReturnTypeOf!int);
524 
525 		// Should not return void.
526 		static assert(!element.isReturnTypeOf!void);
527 
528 		// Should be an aggregate.
529 		static assert(element.isAggregate);
530 
531 		// Should not be a class.
532 		static assert(!element.isClass);
533 
534 		// Should be a struct.
535 		static assert(element.isStruct);
536 
537 		auto subQuery = element.query;
538 
539 		// Should not match parent type.
540 		static assert(!is(subQuery.type == element.type));
541 
542 		static if(is(subQuery.type == Limit))
543 		{
544 			// Should not be empty.
545 			static assert(!subQuery.empty);
546 
547 			// Should have 1 element.
548 			static assert(subQuery.length == 1);
549 		}
550 		else
551 		{
552 			// Should be empty.
553 			static assert(subQuery.empty);
554 		}
555 	}
556 }