1 module tanya.tests.format;
2 
3 import tanya.format;
4 import tanya.range;
5 
6 // Converting an integer to string.
7 @nogc nothrow pure @system unittest
8 {
9     char[21] buf;
10 
11     assert(integral2String(80, buf) == "80");
12     assert(integral2String(-80, buf) == "-80");
13     assert(integral2String(0, buf) == "0");
14     assert(integral2String(uint.max, buf) == "4294967295");
15     assert(integral2String(int.min, buf) == "-2147483648");
16 }
17 
18 // Doesn't print the first argument repeatedly
19 @nogc nothrow pure @safe unittest
20 {
21     assert(format!"{}{}"(1, 2) == "12");
22 }
23 
24 @nogc nothrow pure @safe unittest
25 {
26     assert(format!"Without arguments"() == "Without arguments");
27     assert(format!""().length == 0);
28 
29     static assert(!is(typeof(format!"{}"())));
30     static assert(!is(typeof(format!"{j}"(5))));
31 }
32 
33 // Enum
34 @nogc nothrow pure @safe unittest
35 {
36     enum E1 : int
37     {
38         one,
39         two,
40     }
41     assert(format!"{}"(E1.one) == "one");
42 
43     const E1 e1;
44     assert(format!"{}"(e1) == "one");
45 }
46 
47 // Modifiers
48 @nogc pure @safe unittest
49 {
50     assert(format!"{}"(8.5) == "8.5");
51     assert(format!"{}"(8.6) == "8.6");
52     assert(format!"{}"(1000) == "1000");
53     assert(format!"{}"(1) == "1");
54     assert(format!"{}"(10.25) == "10.25");
55     assert(format!"{}"(1) == "1");
56     assert(format!"{}"(0.01) == "0.01");
57 }
58 
59 // String printing
60 @nogc pure @safe unittest
61 {
62     assert(format!"{}"("Some weired string") == "Some weired string");
63     assert(format!"{}"(cast(string) null) == "");
64     assert(format!"{}"('c') == "c");
65 }
66 
67 // Integer
68 @nogc pure @safe unittest
69 {
70     assert(format!"{}"(8) == "8");
71     assert(format!"{}"(8) == "8");
72     assert(format!"{}"(-8) == "-8");
73     assert(format!"{}"(-8L) == "-8");
74     assert(format!"{}"(8) == "8");
75     assert(format!"{}"(100000001) == "100000001");
76     assert(format!"{}"(99999999L) == "99999999");
77     assert(format!"{}"(10) == "10");
78     assert(format!"{}"(10L) == "10");
79 }
80 
81 // Floating point
82 @nogc pure @safe unittest
83 {
84     assert(format!"{}"(0.1234) == "0.1234");
85     assert(format!"{}"(0.3) == "0.3");
86     assert(format!"{}"(0.333333333333) == "0.333333");
87     assert(format!"{}"(38234.1234) == "38234.1");
88     assert(format!"{}"(-0.3) == "-0.3");
89     assert(format!"{}"(0.000000000000000006) == "6e-18");
90     assert(format!"{}"(0.0) == "0");
91     assert(format!"{}"(double.init) == "NaN");
92     assert(format!"{}"(-double.init) == "-NaN");
93     assert(format!"{}"(double.infinity) == "Inf");
94     assert(format!"{}"(-double.infinity) == "-Inf");
95     assert(format!"{}"(0.000000000000000000000000003) == "3e-27");
96     assert(format!"{}"(0.23432e304) == "2.3432e+303");
97     assert(format!"{}"(-0.23432e8) == "-2.3432e+07");
98     assert(format!"{}"(1e-307) == "1e-307");
99     assert(format!"{}"(1e+8) == "1e+08");
100     assert(format!"{}"(111234.1) == "111234");
101     assert(format!"{}"(0.999) == "0.999");
102     assert(format!"{}"(0x1p-16382L) == "0");
103     assert(format!"{}"(1e+3) == "1000");
104     assert(format!"{}"(38234.1234) == "38234.1");
105     assert(format!"{}"(double.max) == "1.79769e+308");
106 }
107 
108 // typeof(null)
109 @nogc pure @safe unittest
110 {
111     assert(format!"{}"(null) == "null");
112 }
113 
114 // Boolean
115 @nogc pure @safe unittest
116 {
117     assert(format!"{}"(true) == "true");
118     assert(format!"{}"(false) == "false");
119 }
120 
121 // Unsafe tests with pointers
122 @nogc pure @system unittest
123 {
124     // Pointer convesions
125     assert(format!"{}"(cast(void*) 1) == "0x1");
126     assert(format!"{}"(cast(void*) 20) == "0x14");
127     assert(format!"{}"(cast(void*) null) == "0x0");
128 }
129 
130 // Structs
131 @nogc pure @safe unittest
132 {
133     static struct WithoutStringify1
134     {
135         int a;
136         void func()
137         {
138         }
139     }
140     assert(format!"{}"(WithoutStringify1(6)) == "WithoutStringify1(6)");
141 
142     static struct WithoutStringify2
143     {
144     }
145     assert(format!"{}"(WithoutStringify2()) == "WithoutStringify2()");
146 
147     static struct WithoutStringify3
148     {
149         int a = -2;
150         int b = 8;
151     }
152     assert(format!"{}"(WithoutStringify3()) == "WithoutStringify3(-2, 8)");
153 
154     struct Nested
155     {
156         int i;
157 
158         void func()
159         {
160         }
161     }
162     assert(format!"{}"(Nested()) == "Nested(0)");
163 
164     static struct WithToString
165     {
166         OR toString(OR)(OR range) const
167         {
168             put(range, "toString method");
169             return range;
170         }
171     }
172     assert(format!"{}"(WithToString()) == "toString method");
173 }
174 
175 // Aggregate types
176 @system unittest // Object.toString has no attributes.
177 {
178     import tanya.memory.allocator;
179     import tanya.memory.smartref;
180 
181     interface I
182     {
183     }
184     class A : I
185     {
186     }
187     auto instance = defaultAllocator.unique!A();
188     assert(format!"{}"(instance.get()) == instance.get().toString());
189     assert(format!"{}"(cast(I) instance.get()) == I.classinfo.name);
190     assert(format!"{}"(cast(A) null) == "null");
191 
192     class B
193     {
194         OR toString(OR)(OR range) const
195         {
196             put(range, "Class B");
197             return range;
198         }
199     }
200     assert(format!"{}"(cast(B) null) == "null");
201 }
202 
203 // Unions
204 unittest
205 {
206     union U
207     {
208         int i;
209         char c;
210     }
211     assert(format!"{}"(U(2)) == "U");
212 }
213 
214 // Ranges
215 @nogc pure @safe unittest
216 {
217     static struct Stringish
218     {
219         private string content = "Some content";
220 
221         immutable(char) front() const @nogc nothrow pure @safe
222         {
223             return this.content[0];
224         }
225 
226         void popFront() @nogc nothrow pure @safe
227         {
228             this.content = this.content[1 .. $];
229         }
230 
231         bool empty() const @nogc nothrow pure @safe
232         {
233             return this.content.length == 0;
234         }
235     }
236     assert(format!"{}"(Stringish()) == "Some content");
237 
238     static struct Intish
239     {
240         private int front_ = 3;
241 
242         int front() const @nogc nothrow pure @safe
243         {
244             return this.front_;
245         }
246 
247         void popFront() @nogc nothrow pure @safe
248         {
249             --this.front_;
250         }
251 
252         bool empty() const @nogc nothrow pure @safe
253         {
254             return this.front == 0;
255         }
256     }
257     assert(format!"{}"(Intish()) == "[3, 2, 1]");
258 }
259 
260 // Typeid
261 nothrow @safe unittest
262 {
263     assert(format!"{}"(typeid(int[])) == "int[]");
264 
265     class C
266     {
267     }
268     assert(format!"{}"(typeid(C)) == typeid(C).toString());
269 }