Merge commit 'release-4-0-0alpha15' into master4-tmp
[kai/samba-autobuild/.git] / lib / util / charset / tests / convert_string.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for the charcnv functions
4
5    Copyright (C) Andrew Bartlett 2011
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "lib/util/charset/charset.h"
24
25 /* The text below is in ancient and a latin charset transliteration of
26  * greek, and an english translation.  It from Apology by Plato and sourced from
27  * http://en.wikipedia.org/w/index.php?title=Ancient_Greek&oldid=421361065#Example_text
28  */
29
30 const char *plato_english_ascii = 
31         "What you, men of Athens, have learned from my accusers, I do not"
32         " know: but I, for my part, nearly forgot who I was thanks to them since"
33         " they spoke so persuasively. And yet, of the truth, they have spoken,"
34         " one might say, nothing at all.";
35
36 const char *plato_english_utf16le_base64 =
37         "VwBoAGEAdAAgAHkAbwB1ACwAIABtAGUAbgAgAG8AZgAgAEEAdABoAGUAbgBzACwAIABoAGEAdgBl"
38         "ACAAbABlAGEAcgBuAGUAZAAgAGYAcgBvAG0AIABtAHkAIABhAGMAYwB1AHMAZQByAHMALAAgAEkA"
39         "IABkAG8AIABuAG8AdAAgAGsAbgBvAHcAOgAgAGIAdQB0ACAASQAsACAAZgBvAHIAIABtAHkAIABw"
40         "AGEAcgB0ACwAIABuAGUAYQByAGwAeQAgAGYAbwByAGcAbwB0ACAAdwBoAG8AIABJACAAdwBhAHMA"
41         "IAB0AGgAYQBuAGsAcwAgAHQAbwAgAHQAaABlAG0AIABzAGkAbgBjAGUAIAB0AGgAZQB5ACAAcwBw"
42         "AG8AawBlACAAcwBvACAAcABlAHIAcwB1AGEAcwBpAHYAZQBsAHkALgAgAEEAbgBkACAAeQBlAHQA"
43         "LAAgAG8AZgAgAHQAaABlACAAdAByAHUAdABoACwAIAB0AGgAZQB5ACAAaABhAHYAZQAgAHMAcABv"
44         "AGsAZQBuACwAIABvAG4AZQAgAG0AaQBnAGgAdAAgAHMAYQB5ACwAIABuAG8AdABoAGkAbgBnACAA"
45         "YQB0ACAAYQBsAGwALgA=";
46
47 static const char *plato_utf8_base64 = 
48         "4b2Nz4TOuSDOvOG9ss69IOG9kc68zrXhv5bPgiwg4b2mIOG8hM69zrTPgc61z4IgzobOuM63zr3O"
49         "seG/ls6/zrksIM+AzrXPgM+Mzr3OuM6xz4TOtSDhvZHPgOG9uCDPhOG/ts69IOG8kM684b+2zr0g"
50         "zrrOsc+EzrfOs8+Mz4HPic69LCDOv+G9kM66IM6/4by2zrTOsTog4byQzrPhvbwgzrQnIM6/4b2W"
51         "zr0gzrrOseG9tiDOseG9kM+E4b24z4Ig4b2Rz4AnIM6x4b2Qz4Thv7bOvSDhvYDOu86vzrPOv8+F"
52         "IOG8kM68zrHPhc+Ezr/hv6Yg4byQz4DOtc67zrHOuM+MzrzOt869LCDOv+G9lc+Ez4kgz4DOuc64"
53         "zrHOveG/ts+CIOG8lM67zrXOs86/zr0uIM6azrHOr8+Ezr/OuSDhvIDOu863zrjOrc+CIM6zzrUg"
54         "4b2hz4Ig4byUz4DOv8+CIM614bywz4DOteG/ls69IM6/4b2QzrThvbLOvSDOteG8sM+Bzq7Ous6x"
55         "z4POuc69Lg==";
56
57 static const char *plato_utf16le_base64 = 
58         "TR/EA7kDIAC8A3IfvQMgAFEfvAO1A9YfwgMsACAAZh8gAAQfvQO0A8EDtQPCAyAAhgO4A7cDvQOx"
59         "A9YfvwO5AywAIADAA7UDwAPMA70DuAOxA8QDtQMgAFEfwAN4HyAAxAP2H70DIAAQH7wD9h+9AyAA"
60         "ugOxA8QDtwOzA8wDwQPJA70DLAAgAL8DUB+6AyAAvwM2H7QDsQM6ACAAEB+zA3wfIAC0AycAIAC/"
61         "A1YfvQMgALoDsQN2HyAAsQNQH8QDeB/CAyAAUR/AAycAIACxA1AfxAP2H70DIABAH7sDrwOzA78D"
62         "xQMgABAfvAOxA8UDxAO/A+YfIAAQH8ADtQO7A7EDuAPMA7wDtwO9AywAIAC/A1UfxAPJAyAAwAO5"
63         "A7gDsQO9A/YfwgMgABQfuwO1A7MDvwO9Ay4AIACaA7EDrwPEA78DuQMgAAAfuwO3A7gDrQPCAyAA"
64         "swO1AyAAYR/CAyAAFB/AA78DwgMgALUDMB/AA7UD1h+9AyAAvwNQH7QDch+9AyAAtQMwH8EDrgO6"
65         "A7EDwwO5A70DLgA=";
66
67 static const char *plato_latin_utf8_base64 = 
68         "SMOzdGkgbcOobiBodW1lw65zLCDDtCDDoW5kcmVzIEF0aMSTbmHDrm9pLCBwZXDDs250aGF0ZSBo"
69         "dXDDsiB0w7RuIGVtw7RuIGthdMSTZ8OzcsWNbiwgb3VrIG/DrmRhOiBlZ+G5kSBkJyBvw7tuIGth"
70         "w6wgYXV0w7JzIGh1cCcgYXV0xY1uIG9sw61nb3UgZW1hdXRvw7sgZXBlbGF0aMOzbcSTbiwgaG/D"
71         "unTFjSBwaXRoYW7DtHMgw6lsZWdvbi4gS2HDrXRvaSBhbMSTdGjDqXMgZ2UgaMWNcyDDqXBvcyBl"
72         "aXBlw65uIG91ZMOobiBlaXLhuJdrYXNpbi4=";
73
74 static const char *plato_latin_utf16le_base64 = 
75         "SADzAHQAaQAgAG0A6ABuACAAaAB1AG0AZQDuAHMALAAgAPQAIADhAG4AZAByAGUAcwAgAEEAdABo"
76         "ABMBbgBhAO4AbwBpACwAIABwAGUAcADzAG4AdABoAGEAdABlACAAaAB1AHAA8gAgAHQA9ABuACAA"
77         "ZQBtAPQAbgAgAGsAYQB0ABMBZwDzAHIATQFuACwAIABvAHUAawAgAG8A7gBkAGEAOgAgAGUAZwBR"
78         "HiAAZAAnACAAbwD7AG4AIABrAGEA7AAgAGEAdQB0APIAcwAgAGgAdQBwACcAIABhAHUAdABNAW4A"
79         "IABvAGwA7QBnAG8AdQAgAGUAbQBhAHUAdABvAPsAIABlAHAAZQBsAGEAdABoAPMAbQATAW4ALAAg"
80         "AGgAbwD6AHQATQEgAHAAaQB0AGgAYQBuAPQAcwAgAOkAbABlAGcAbwBuAC4AIABLAGEA7QB0AG8A"
81         "aQAgAGEAbAATAXQAaADpAHMAIABnAGUAIABoAE0BcwAgAOkAcABvAHMAIABlAGkAcABlAO4AbgAg"
82         "AG8AdQBkAOgAbgAgAGUAaQByABceawBhAHMAaQBuAC4A";
83
84 static const char *gd_utf8_base64 = "R8O8bnRoZXIgRGVzY2huZXI=";
85 static const char *gd_utf8_upper_base64 = "R8OcTlRIRVIgREVTQ0hORVI=";
86 static const char *gd_utf8_lower_base64 = "Z8O8bnRoZXIgZGVzY2huZXI=";
87 static const char *gd_cp850_base64 = "R4FudGhlciBEZXNjaG5lcg==";
88 static const char *gd_cp850_upper_base64 = "R5pOVEhFUiBERVNDSE5FUg==";
89 static const char *gd_cp850_lower_base64 = "Z4FudGhlciBkZXNjaG5lcg==";
90 static const char *gd_iso8859_1_base64 = "R/xudGhlciBEZXNjaG5lcg==";
91 static const char *gd_utf16le_base64 = "RwD8AG4AdABoAGUAcgAgAEQAZQBzAGMAaABuAGUAcgA=";
92
93 static bool test_gd_iso8859_cp850_handle(struct torture_context *tctx)
94 {
95         struct smb_iconv_handle *iconv_handle;
96         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
97         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
98         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
99         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
100         DATA_BLOB gd_output;
101         DATA_BLOB gd_output2;
102         
103         talloc_steal(tctx, gd_utf8.data);
104         talloc_steal(tctx, gd_cp850.data);
105         talloc_steal(tctx, gd_iso8859_1.data);
106         talloc_steal(tctx, gd_utf16le.data);
107
108         iconv_handle = get_iconv_testing_handle(tctx, "ISO8859-1", "CP850");
109         torture_assert(tctx, iconv_handle, "getting iconv handle");
110                 
111         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
112                                                     CH_UTF8, CH_DOS, 
113                                                     gd_utf8.data, gd_utf8.length, 
114                                                     (void *)&gd_output.data, &gd_output.length), 
115                        "conversion from UTF8 to (dos charset) ISO8859-1");
116         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO8859-1 incorrect");
117         
118         torture_assert(tctx, convert_string_error_handle(iconv_handle,
119                                                          CH_UTF8, CH_DOS,
120                                                          gd_utf8.data, gd_utf8.length,
121                                                          (void *)gd_output.data, gd_output.length,
122                                                          &gd_output.length),
123                        "conversion from UTF8 to (dos charset) ISO8859-1");
124         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF8 to (dos charset) ISO8859-1 incorrect");
125
126         /* Short output handling confirmation */
127         gd_output.length = 1;
128         torture_assert(tctx, convert_string_error_handle(iconv_handle,
129                                                          CH_UTF8, CH_DOS,
130                                                          gd_utf8.data, gd_utf8.length,
131                                                          (void *)gd_output.data, gd_output.length,
132                                                          &gd_output.length) == false,
133                        "conversion from UTF8 to (dos charset) ISO8859-1 should fail due to too short");
134         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO8859-1 should fail E2BIG");
135         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
136         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ISO8859-1 incorrect");
137
138         /* Short output handling confirmation */
139         gd_output.length = 2;
140         torture_assert(tctx, convert_string_error_handle(iconv_handle,
141                                                          CH_UTF8, CH_DOS,
142                                                          gd_utf8.data, gd_utf8.length,
143                                                          (void *)gd_output.data, gd_output.length,
144                                                          &gd_output.length) == false,
145                        "conversion from UTF8 to (dos charset) ISO8859-1 should fail due to too short");
146         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ISO8859-1 should fail E2BIG");
147         torture_assert_int_equal(tctx, gd_output.length, 2, "Should only get 2 char of output");
148
149         /* Short input handling confirmation */
150         gd_output.length = gd_iso8859_1.length;
151         torture_assert(tctx, convert_string_error_handle(iconv_handle,
152                                                          CH_UTF8, CH_DOS,
153                                                          gd_utf8.data, 2,
154                                                          (void *)gd_output.data, gd_output.length,
155                                                          &gd_output.length) == false,
156                        "conversion from UTF8 to (dos charset) ISO8859-1 should fail due to too short");
157         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ISO8859-1 should fail EINVAL");
158         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
159
160         /* Short output handling confirmation */
161         gd_output.length = 1;
162         torture_assert(tctx, convert_string_error_handle(iconv_handle,
163                                                          CH_UTF16LE, CH_UTF8,
164                                                          gd_utf16le.data, gd_utf16le.length,
165                                                          (void *)gd_output.data, gd_output.length,
166                                                          &gd_output.length) == false,
167                        "conversion from UTF16 to UTF8 should fail due to too short");
168         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO8859-1 should fail E2BIG");
169         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
170         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect");
171
172         /* Short output handling confirmation */
173         gd_output.length = 3;
174         torture_assert(tctx, convert_string_error_handle(iconv_handle,
175                                                          CH_UTF16LE, CH_UTF8,
176                                                          gd_utf16le.data, gd_utf16le.length,
177                                                          (void *)gd_output.data, gd_output.length,
178                                                          &gd_output.length) == false,
179                        "conversion from UTF16 to UTF8 should fail due to too short");
180         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to (utf8 charset) ISO8859-1 should fail E2BIG");
181         torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8");
182
183         /* Short input handling confirmation */
184         gd_output.length = gd_utf8.length;
185         torture_assert(tctx, convert_string_error_handle(iconv_handle,
186                                                          CH_UTF16LE, CH_UTF8,
187                                                          gd_utf16le.data, 3,
188                                                          (void *)gd_output.data, gd_output.length,
189                                                          &gd_output.length) == false,
190                        "conversion from UTF16 to UTF8 should fail due to too short");
191         torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL");
192         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
193
194         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
195                                                     CH_UTF8, CH_UNIX, 
196                                                     gd_utf8.data, gd_utf8.length, 
197                                                     (void *)&gd_output.data, &gd_output.length), 
198                        "conversion from UTF8 to (unix charset) CP850");
199         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect");
200         
201         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
202                                                     CH_UTF8, CH_UTF8, 
203                                                     gd_utf8.data, gd_utf8.length, 
204                                                     (void *)&gd_output.data, &gd_output.length), 
205                        "conversion from UTF8 to UTF8");
206         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF8 to UTF8 incorrect");
207         
208         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
209                                                     CH_UTF16LE, CH_DOS, 
210                                                     gd_utf16le.data, gd_utf16le.length, 
211                                                     (void *)&gd_output.data, &gd_output.length),
212                        "conversion from UTF16LE to (dos charset) ISO8859-1");
213         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO8859-1 incorrect");
214         
215         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
216                                                     CH_DOS, CH_UTF16LE, 
217                                                     gd_output.data, gd_output.length, 
218                                                     (void *)&gd_output2.data, &gd_output2.length),
219                        "round trip conversion from (dos charset) ISO8859-1 back to UTF16LE");
220         torture_assert_data_blob_equal(tctx, gd_output2, gd_utf16le,  "round trip conversion from (dos charset) ISO8859-1 back to UTF16LE");
221         
222         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
223                                                     CH_UTF16LE, CH_UNIX, 
224                                                     gd_utf16le.data, gd_utf16le.length, 
225                                                     (void *)&gd_output.data, &gd_output.length),
226                        "conversion from UTF16LE to (unix charset) CP850");
227         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
228         
229         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
230                                                     CH_UTF16LE, CH_UTF8, 
231                                                     gd_utf16le.data, gd_utf16le.length, 
232                                                     (void *)&gd_output.data, &gd_output.length), 
233                        "conversion from UTF16LE to UTF8");
234         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect");
235         
236         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
237                                                     CH_DOS, CH_DOS, 
238                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
239                                                     (void *)&gd_output.data, &gd_output.length),
240                        "conversion from (dos charset) ISO8859-1 to (dos charset) ISO8859-1");
241         torture_assert_data_blob_equal(tctx, gd_output, gd_iso8859_1, "conversion from UTF16LE to (dos charset) ISO8859-1 incorrect");
242         
243         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
244                                                     CH_DOS, CH_UNIX, 
245                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
246                                                     (void *)&gd_output.data, &gd_output.length), 
247                        "conversion from (dos charset) ISO8859-1 to (unix charset) CP850");
248         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
249         
250         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
251                                                     CH_DOS, CH_UTF8, 
252                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
253                                                     (void *)&gd_output.data, &gd_output.length), 
254                        "conversion from (dos charset) ISO8859-1 to UTF8");
255         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 incorrect");
256
257         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
258                                                     CH_DOS, CH_UTF16LE, 
259                                                     gd_iso8859_1.data, gd_iso8859_1.length, 
260                                                     (void *)&gd_output.data, &gd_output.length), 
261                        "conversion from (dos charset) ISO8859-1 to UTF16LE");
262         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from (dos charset) ISO8859-1 to UTF16LE");
263         torture_assert_int_equal(tctx,
264                                  strlen_m_ext_handle(iconv_handle,
265                                                      (const char *)gd_iso8859_1.data,
266                                                      CH_DOS, CH_UTF16LE),
267                                  gd_output.length / 2,
268                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
269
270         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
271                                                     CH_DOS, CH_UTF8,
272                                                     gd_iso8859_1.data, gd_iso8859_1.length,
273                                                     (void *)&gd_output.data, &gd_output.length),
274                        "conversion from (dos charset) ISO8859-1 to UTF8");
275         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from (dos charset) ISO8859-1 to UTF8");
276         torture_assert_int_equal(tctx,
277                                  strlen_m_ext_handle(iconv_handle,
278                                                      (const char *)gd_iso8859_1.data,
279                                                      CH_DOS, CH_UTF8),
280                                  gd_output.length,
281                                  "checking strlen_m_ext of conversion from (dos charset) ISO8859-1 to UTF8");
282         return true;
283 }
284
285 static bool test_gd_minus_1_handle(struct torture_context *tctx)
286 {
287         struct smb_iconv_handle *iconv_handle;
288         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
289         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
290         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
291         DATA_BLOB gd_output;
292         DATA_BLOB gd_utf8_terminated;
293         DATA_BLOB gd_cp850_terminated;
294         DATA_BLOB gd_utf16le_terminated;
295         
296         talloc_steal(tctx, gd_utf8.data);
297         talloc_steal(tctx, gd_cp850.data);
298         talloc_steal(tctx, gd_utf16le.data);
299
300         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "CP850");
301         torture_assert(tctx, iconv_handle, "getting iconv handle");
302
303         gd_utf8_terminated = data_blob_talloc(tctx, NULL, gd_utf8.length + 1);
304         memcpy(gd_utf8_terminated.data, gd_utf8.data, gd_utf8.length);
305         gd_utf8_terminated.data[gd_utf8.length] = '\0';
306
307         gd_cp850_terminated = data_blob_talloc(tctx, NULL, gd_cp850.length + 1);
308         memcpy(gd_cp850_terminated.data, gd_cp850.data, gd_cp850.length);
309         gd_cp850_terminated.data[gd_cp850.length] = '\0';
310
311         gd_utf16le_terminated = data_blob_talloc(tctx, NULL, gd_utf16le.length + 2);
312         memcpy(gd_utf16le_terminated.data, gd_utf16le.data, gd_utf16le.length);
313         gd_utf16le_terminated.data[gd_utf16le.length] = '\0';
314         gd_utf16le_terminated.data[gd_utf16le.length + 1] = '\0';
315
316         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
317
318         torture_assert(tctx, convert_string_error_handle(iconv_handle,
319                                                           CH_UTF8, CH_UTF16LE,
320                                                           gd_utf8_terminated.data, -1,
321                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
322                        "conversion from UTF8 to UTF16LE null terminated");
323         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
324
325         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
326         torture_assert(tctx, convert_string_error_handle(iconv_handle,
327                                                           CH_UTF8, CH_UTF16LE,
328                                                           gd_utf8_terminated.data, -1,
329                                                           (void *)gd_output.data, gd_utf16le.length, &gd_output.length) == false,
330                        "conversion from UTF8 to UTF16LE null terminated should fail");
331         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
332         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le, "conversion from UTF8 to UTF16LE null terminated");
333
334         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
335         torture_assert(tctx, convert_string_error_handle(iconv_handle,
336                                                           CH_UTF8, CH_UTF16LE,
337                                                           gd_utf8_terminated.data, -1,
338                                                           (void *)gd_output.data, gd_utf16le.length - 1, &gd_output.length) == false,
339                        "conversion from UTF8 to UTF16LE null terminated should fail");
340         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
341
342         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
343         torture_assert(tctx, convert_string_error_handle(iconv_handle,
344                                                           CH_UTF8, CH_UTF16LE,
345                                                           gd_utf8_terminated.data, -1,
346                                                           (void *)gd_output.data, gd_utf16le.length - 2, &gd_output.length) == false,
347                        "conversion from UTF8 to UTF16LE null terminated should fail");
348         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
349
350         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
351         torture_assert(tctx, convert_string_error_handle(iconv_handle,
352                                                          CH_UTF16LE, CH_UTF8,
353                                                          gd_utf16le_terminated.data, -1,
354                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
355                        "conversion from UTF16LE to UTF8 null terminated");
356         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
357
358         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
359
360         torture_assert(tctx, convert_string_error_handle(iconv_handle,
361                                                          CH_UTF16LE, CH_UTF8,
362                                                          gd_utf16le_terminated.data, -1,
363                                                          (void *)gd_output.data, gd_utf8.length, &gd_output.length) == false,
364                        "conversion from UTF16LE to UTF8 null terminated should fail");
365         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
366         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8, "conversion from UTF16LE to UTF8 null terminated");
367
368         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
369
370         torture_assert(tctx, convert_string_error_handle(iconv_handle,
371                                                          CH_UTF16LE, CH_UTF8,
372                                                          gd_utf16le_terminated.data, -1,
373                                                          (void *)gd_output.data, gd_utf8.length - 1, &gd_output.length) == false,
374                        "conversion from UTF16LE to UTF8 null terminated should fail");
375         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
376
377         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
378
379         torture_assert(tctx, convert_string_error_handle(iconv_handle,
380                                                          CH_UTF16LE, CH_UTF8,
381                                                          gd_utf16le_terminated.data, -1,
382                                                          (void *)gd_output.data, gd_utf8.length - 2, &gd_output.length) == false,
383                        "conversion from UTF16LE to UTF8 null terminated should fail");
384         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
385
386         gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
387
388         torture_assert(tctx, convert_string_error_handle(iconv_handle,
389                                                          CH_UTF16LE, CH_DOS,
390                                                          gd_utf16le_terminated.data, -1,
391                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
392                        "conversion from UTF16LE to CP850 (dos) null terminated");
393         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to CP850 (dos) null terminated");
394
395         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
396         gd_utf8_terminated.data[3] = '\0';
397         gd_utf8_terminated.length = 4; /* used for the comparison only */
398
399         gd_cp850_terminated.data[2] = '\0';
400         gd_cp850_terminated.length = 3; /* used for the comparison only */
401
402         gd_utf16le_terminated.data[4] = '\0';
403         gd_utf16le_terminated.data[5] = '\0';
404         gd_utf16le_terminated.length = 6; /* used for the comparison only */
405
406         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
407
408         torture_assert(tctx, convert_string_error_handle(iconv_handle,
409                                                           CH_UTF8, CH_UTF16LE,
410                                                           gd_utf8_terminated.data, -1,
411                                                           (void *)gd_output.data, gd_output.length, &gd_output.length),
412                        "conversion from UTF8 to UTF16LE null terminated");
413         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
414
415         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
416
417         torture_assert(tctx, convert_string_error_handle(iconv_handle,
418                                                           CH_UTF16LE, CH_UTF8,
419                                                           gd_utf16le_terminated.data, -1,
420                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
421                        "conversion from UTF16LE to UTF8 null terminated");
422         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
423
424         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
425
426         torture_assert(tctx, convert_string_error_handle(iconv_handle,
427                                                           CH_DOS, CH_UTF16LE,
428                                                           gd_cp850_terminated.data, -1,
429                                                           (void *)gd_output.data, gd_output.length, &gd_output.length),
430                        "conversion from CP850 to UTF16LE null terminated");
431         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
432
433         gd_output = data_blob_talloc(tctx, NULL, gd_cp850.length + 10);
434
435         torture_assert(tctx, convert_string_error_handle(iconv_handle,
436                                                           CH_UTF16LE, CH_DOS,
437                                                           gd_utf16le_terminated.data, -1,
438                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
439                        "conversion from UTF16LE to UTF8 null terminated");
440         torture_assert_data_blob_equal(tctx, gd_output, gd_cp850_terminated, "conversion from UTF16LE to UTF8 null terminated early");
441         
442         /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */
443         gd_utf8_terminated.data[1] = '\0';
444         gd_utf8_terminated.length = 2; /* used for the comparison only */
445         
446         gd_utf16le_terminated.data[2] = '\0';
447         gd_utf16le_terminated.data[3] = '\0';
448         gd_utf16le_terminated.length = 4; /* used for the comparison only */
449
450         gd_output = data_blob_talloc(tctx, NULL, gd_utf16le.length + 10);
451
452         torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE,
453                                                           gd_utf8_terminated.data, -1,
454                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
455                        "conversion from UTF8 to UTF16LE null terminated");
456         torture_assert_data_blob_equal(tctx, gd_output, gd_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early");
457
458         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length + 10);
459
460         torture_assert(tctx, convert_string_error_handle(iconv_handle,
461                                                           CH_UTF16LE, CH_UTF8,
462                                                           gd_utf16le_terminated.data, -1,
463                                                          (void *)gd_output.data, gd_output.length, &gd_output.length),
464                        "conversion from UTF16LE to UTF8 null terminated");
465         torture_assert_data_blob_equal(tctx, gd_output, gd_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early");
466
467         return true;
468 }
469
470 static bool test_gd_ascii_handle(struct torture_context *tctx)
471 {
472         struct smb_iconv_handle *iconv_handle;
473         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
474         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
475         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
476         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
477         DATA_BLOB gd_output;
478
479         talloc_steal(tctx, gd_utf8.data);
480         talloc_steal(tctx, gd_cp850.data);
481         talloc_steal(tctx, gd_iso8859_1.data);
482         talloc_steal(tctx, gd_utf16le.data);
483
484         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8");
485         torture_assert(tctx, iconv_handle, "getting iconv handle");
486
487         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
488                                                     CH_UTF8, CH_DOS,
489                                                     gd_utf8.data, gd_utf8.length,
490                                                     (void *)&gd_output.data, &gd_output.length) == false,
491                        "conversion from UTF8 to (dos charset) ASCII should fail");
492
493         gd_output = data_blob_talloc(tctx, NULL, gd_utf8.length);
494
495         torture_assert(tctx, convert_string_error_handle(iconv_handle,
496                                                          CH_UTF8, CH_DOS,
497                                                          gd_utf8.data, gd_utf8.length,
498                                                          (void *)gd_output.data, gd_output.length,
499                                                          &gd_output.length) == false,
500                        "conversion from UTF8 to (dos charset) ASCII should fail");
501         torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO8859-1 should fail E2BIG");
502         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
503         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "partial conversion from UTF8 to (dos charset) ASCII incorrect");
504
505         /* Short output handling confirmation */
506         gd_output.length = 1;
507         torture_assert(tctx, convert_string_error_handle(iconv_handle,
508                                                          CH_UTF8, CH_DOS,
509                                                          gd_utf8.data, gd_utf8.length,
510                                                          (void *)gd_output.data, gd_output.length,
511                                                          &gd_output.length) == false,
512                        "conversion from UTF8 to (dos charset) ASCII should fail due to too short");
513         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to (dos charset) ASCII too short");
514         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
515         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to (dos charset) ASCII incorrect");
516
517         /* Short output handling confirmation */
518         gd_output.length = 2;
519         torture_assert(tctx, convert_string_error_handle(iconv_handle,
520                                                          CH_UTF8, CH_DOS,
521                                                          gd_utf8.data, gd_utf8.length,
522                                                          (void *)gd_output.data, gd_output.length,
523                                                          &gd_output.length) == false,
524                        "conversion from UTF8 to (dos charset) ASCII should fail due to too illigal seqence");
525         torture_assert_errno_equal(tctx, EILSEQ, "conversion from UTF8 to (dos charset) ISO8859-1 should fail EILSEQ");
526         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 2 char of output");
527
528         /* Short input handling confirmation */
529         gd_output.length = gd_utf8.length;
530         torture_assert(tctx, convert_string_error_handle(iconv_handle,
531                                                          CH_UTF8, CH_DOS,
532                                                          gd_utf8.data, 2,
533                                                          (void *)gd_output.data, gd_output.length,
534                                                          &gd_output.length) == false,
535                        "conversion from UTF8 to (dos charset) ASCII should fail due to too short");
536         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to (dos charset) ASCII should fail EILSEQ");
537         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
538         return true;
539 }
540
541 static bool test_plato_english_iso8859_cp850_handle(struct torture_context *tctx)
542 {
543         struct smb_iconv_handle *iconv_handle;
544         DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii);
545         DATA_BLOB plato_english_cp850 = plato_english_utf8;
546         DATA_BLOB plato_english_iso8859_1 = plato_english_utf8;
547         DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64);
548         DATA_BLOB plato_english_output;
549         DATA_BLOB plato_english_output2;
550         
551         talloc_steal(tctx, plato_english_utf16le.data);
552
553         iconv_handle = get_iconv_testing_handle(tctx, "ISO8859-1", "CP850");
554         torture_assert(tctx, iconv_handle, "getting iconv handle");
555                 
556         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
557                                                     CH_UTF8, CH_DOS, 
558                                                     plato_english_utf8.data, plato_english_utf8.length, 
559                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
560                        "conversion from UTF8 to (dos charset) ISO8859-1");
561         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF8 to (dos charset) ISO8859-1 incorrect");
562         
563         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
564                                                     CH_UTF8, CH_UNIX, 
565                                                     plato_english_utf8.data, plato_english_utf8.length, 
566                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
567                        "conversion from UTF8 to (unix charset) CP850");
568         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF8 to (unix charset) CP850 incorrect");
569         
570         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
571                                                     CH_UTF8, CH_UTF8, 
572                                                     plato_english_utf8.data, plato_english_utf8.length, 
573                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
574                        "conversion from UTF8 to UTF8");
575         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF8 to UTF8 incorrect");
576         
577         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
578                                                     CH_UTF16LE, CH_DOS, 
579                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
580                                                     (void *)&plato_english_output.data, &plato_english_output.length),
581                        "conversion from UTF16LE to (dos charset) ISO8859-1");
582         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO8859-1 incorrect");
583         
584         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
585                                                     CH_DOS, CH_UTF16LE, 
586                                                     plato_english_output.data, plato_english_output.length, 
587                                                     (void *)&plato_english_output2.data, &plato_english_output2.length),
588                        "round trip conversion from (dos charset) ISO8859-1 back to UTF16LE");
589         torture_assert_data_blob_equal(tctx, plato_english_output2, plato_english_utf16le,  "round trip conversion from (dos charset) ISO8859-1 back to UTF16LE");
590         
591         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
592                                                     CH_UTF16LE, CH_UTF8,
593                                                     plato_english_utf16le.data, plato_english_utf16le.length,
594                                                     (void *)&plato_english_output.data, &plato_english_output.length),
595                        "conversion from UTF16LE to UTF8");
596         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
597
598         torture_assert(tctx, convert_string_error_handle(iconv_handle,
599                                                          CH_UTF16LE, CH_UTF8,
600                                                          plato_english_utf16le.data, plato_english_utf16le.length,
601                                                          (void *)plato_english_output.data, plato_english_output.length,
602                                                          &plato_english_output.length),
603                        "conversion from UTF16LE to UTF8");
604         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
605
606         plato_english_output.length = 5;
607         torture_assert(tctx, convert_string_error_handle(iconv_handle,
608                                                          CH_UTF16LE, CH_UTF8,
609                                                          plato_english_utf16le.data, plato_english_utf16le.length,
610                                                          (void *)plato_english_output.data, plato_english_output.length,
611                                                          &plato_english_output.length) == false,
612                        "conversion from UTF16LE to UTF8 should fail due to short output");
613         torture_assert_data_blob_equal(tctx, plato_english_output, data_blob_string_const("What "), "conversion from UTF16LE to UTF8 incorrect");
614         torture_assert_int_equal(tctx, plato_english_output.length, 5, "short conversion failed");
615
616         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
617                                                     CH_UTF16LE, CH_UNIX, 
618                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
619                                                     (void *)&plato_english_output.data, &plato_english_output.length),
620                        "conversion from UTF16LE to (unix charset) CP850");
621         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
622         
623         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
624                                                     CH_UTF16LE, CH_UTF8, 
625                                                     plato_english_utf16le.data, plato_english_utf16le.length, 
626                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
627                        "conversion from UTF16LE to UTF8");
628         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
629         
630         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
631                                                     CH_DOS, CH_DOS, 
632                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
633                                                     (void *)&plato_english_output.data, &plato_english_output.length),
634                        "conversion from (dos charset) ISO8859-1 to (dos charset) ISO8859-1");
635         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_iso8859_1, "conversion from UTF16LE to (dos charset) ISO8859-1 incorrect");
636         
637         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
638                                                     CH_DOS, CH_UNIX, 
639                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
640                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
641                        "conversion from (dos charset) ISO8859-1 to (unix charset) CP850");
642         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_cp850, "conversion from UTF16LE to (unix charset) CP850 incorrect");
643         
644         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
645                                                     CH_DOS, CH_UTF8, 
646                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
647                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
648                        "conversion from (dos charset) ISO8859-1 to UTF8");
649         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 incorrect");
650
651         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
652                                                     CH_DOS, CH_UTF16LE, 
653                                                     plato_english_iso8859_1.data, plato_english_iso8859_1.length, 
654                                                     (void *)&plato_english_output.data, &plato_english_output.length), 
655                        "conversion from (dos charset) ISO8859-1 to UTF16LE");
656         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from (dos charset) ISO8859-1 to UTF16LE");
657         return true;
658 }
659
660 static bool test_plato_english_minus_1_handle(struct torture_context *tctx)
661 {
662         struct smb_iconv_handle *iconv_handle;
663         DATA_BLOB plato_english_utf8 = data_blob_string_const(plato_english_ascii);
664         DATA_BLOB plato_english_utf16le = base64_decode_data_blob(plato_english_utf16le_base64);
665         DATA_BLOB plato_english_output;
666         DATA_BLOB plato_english_utf8_terminated;
667         DATA_BLOB plato_english_utf16le_terminated;
668         
669         talloc_steal(tctx, plato_english_utf16le.data);
670
671         iconv_handle = get_iconv_testing_handle(tctx, "ISO8859-1", "CP850");
672         torture_assert(tctx, iconv_handle, "getting iconv handle");
673
674         plato_english_utf8_terminated = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 1);
675         memcpy(plato_english_utf8_terminated.data, plato_english_utf8.data, plato_english_utf8.length);
676         plato_english_utf8_terminated.data[plato_english_utf8.length] = '\0';
677
678         plato_english_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 2);
679         memcpy(plato_english_utf16le_terminated.data, plato_english_utf16le.data, plato_english_utf16le.length);
680         plato_english_utf16le_terminated.data[plato_english_utf16le.length] = '\0';
681         plato_english_utf16le_terminated.data[plato_english_utf16le.length + 1] = '\0';
682                 
683         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
684
685         torture_assert(tctx, convert_string_error_handle(iconv_handle,
686                                                           CH_UTF8, CH_UTF16LE,
687                                                           plato_english_utf8_terminated.data, -1,
688                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
689                        "conversion from UTF8 to UTF16LE null terminated");
690         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
691
692         torture_assert(tctx, convert_string_error_handle(iconv_handle,
693                                                           CH_UTF8, CH_UTF16LE,
694                                                           plato_english_utf8_terminated.data, -1,
695                                                           (void *)plato_english_output.data, plato_english_utf16le.length, &plato_english_output.length) == false,
696                        "conversion from UTF8 to UTF16LE null terminated should fail");
697         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
698         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le, "conversion from UTF8 to UTF16LE null terminated");
699
700         torture_assert(tctx, convert_string_error_handle(iconv_handle,
701                                                           CH_UTF8, CH_UTF16LE,
702                                                           plato_english_utf8_terminated.data, -1,
703                                                           (void *)plato_english_output.data, plato_english_utf16le.length - 1, &plato_english_output.length) == false,
704                        "conversion from UTF8 to UTF16LE null terminated should fail");
705         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
706
707         torture_assert(tctx, convert_string_error_handle(iconv_handle,
708                                                           CH_UTF8, CH_UTF16LE,
709                                                           plato_english_utf8_terminated.data, -1,
710                                                           (void *)plato_english_output.data, plato_english_utf16le.length - 2, &plato_english_output.length) == false,
711                        "conversion from UTF8 to UTF16LE null terminated should fail");
712         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
713
714         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
715
716         torture_assert(tctx, convert_string_error_handle(iconv_handle,
717                                                          CH_UTF16LE, CH_UTF8,
718                                                          plato_english_utf16le_terminated.data, -1,
719                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
720                        "conversion from UTF16LE to UTF8 null terminated");
721         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
722
723         torture_assert(tctx, convert_string_error_handle(iconv_handle,
724                                                          CH_UTF16LE, CH_UTF8,
725                                                          plato_english_utf16le_terminated.data, -1,
726                                                          (void *)plato_english_output.data, plato_english_utf8.length, &plato_english_output.length) == false,
727                        "conversion from UTF16LE to UTF8 null terminated should fail");
728         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
729         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8, "conversion from UTF16LE to UTF8 null terminated");
730
731         torture_assert(tctx, convert_string_error_handle(iconv_handle,
732                                                          CH_UTF16LE, CH_UTF8,
733                                                          plato_english_utf16le_terminated.data, -1,
734                                                          (void *)plato_english_output.data, plato_english_utf8.length - 1, &plato_english_output.length) == false,
735                        "conversion from UTF16LE to UTF8 null terminated should fail");
736         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
737
738         torture_assert(tctx, convert_string_error_handle(iconv_handle,
739                                                          CH_UTF16LE, CH_UTF8,
740                                                          plato_english_utf16le_terminated.data, -1,
741                                                          (void *)plato_english_output.data, plato_english_utf8.length - 2, &plato_english_output.length) == false,
742                        "conversion from UTF16LE to UTF8 null terminated should fail");
743         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
744
745         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
746         plato_english_utf8_terminated.data[3] = '\0';
747         plato_english_utf8_terminated.length = 4; /* used for the comparison only */
748
749         plato_english_utf16le_terminated.data[6] = '\0';
750         plato_english_utf16le_terminated.data[7] = '\0';
751         plato_english_utf16le_terminated.length = 8; /* used for the comparison only */
752
753         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
754
755         torture_assert(tctx, convert_string_error_handle(iconv_handle,
756                                                           CH_UTF8, CH_UTF16LE,
757                                                           plato_english_utf8_terminated.data, -1,
758                                                           (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
759                        "conversion from UTF8 to UTF16LE null terminated");
760         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
761
762         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
763
764         torture_assert(tctx, convert_string_error_handle(iconv_handle,
765                                                           CH_UTF16LE, CH_UTF8,
766                                                           plato_english_utf16le_terminated.data, -1,
767                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
768                        "conversion from UTF16LE to UTF8 null terminated");
769         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
770
771         
772         /* Now null terminate the string particularly early, the confirm we don't skip the NULL and convert any further */
773         plato_english_utf8_terminated.data[1] = '\0';
774         plato_english_utf8_terminated.length = 2; /* used for the comparison only */
775         
776         plato_english_utf16le_terminated.data[2] = '\0';
777         plato_english_utf16le_terminated.data[3] = '\0';
778         plato_english_utf16le_terminated.length = 4; /* used for the comparison only */
779
780         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf16le.length + 10);
781
782         torture_assert(tctx, convert_string_error_handle(iconv_handle, CH_UTF8, CH_UTF16LE,
783                                                           plato_english_utf8_terminated.data, -1,
784                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
785                        "conversion from UTF8 to UTF16LE null terminated");
786         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated very early");
787
788         plato_english_output = data_blob_talloc(tctx, NULL, plato_english_utf8.length + 10);
789
790         torture_assert(tctx, convert_string_error_handle(iconv_handle,
791                                                           CH_UTF16LE, CH_UTF8,
792                                                           plato_english_utf16le_terminated.data, -1,
793                                                          (void *)plato_english_output.data, plato_english_output.length, &plato_english_output.length),
794                        "conversion from UTF16LE to UTF8 null terminated");
795         torture_assert_data_blob_equal(tctx, plato_english_output, plato_english_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated very early");
796
797         return true;
798 }
799
800 static bool test_plato_minus_1_handle(struct torture_context *tctx)
801 {
802         struct smb_iconv_handle *iconv_handle;
803         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
804         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
805         DATA_BLOB plato_output;
806         DATA_BLOB plato_utf8_terminated;
807         DATA_BLOB plato_utf16le_terminated;
808         
809         talloc_steal(tctx, plato_utf8.data);
810         talloc_steal(tctx, plato_utf16le.data);
811
812         iconv_handle = get_iconv_testing_handle(tctx, "ISO8859-1", "CP850");
813         torture_assert(tctx, iconv_handle, "getting iconv handle");
814
815         plato_utf8_terminated = data_blob_talloc(tctx, NULL, plato_utf8.length + 1);
816         memcpy(plato_utf8_terminated.data, plato_utf8.data, plato_utf8.length);
817         plato_utf8_terminated.data[plato_utf8.length] = '\0';
818
819         plato_utf16le_terminated = data_blob_talloc(tctx, NULL, plato_utf16le.length + 2);
820         memcpy(plato_utf16le_terminated.data, plato_utf16le.data, plato_utf16le.length);
821         plato_utf16le_terminated.data[plato_utf16le.length] = '\0';
822         plato_utf16le_terminated.data[plato_utf16le.length + 1] = '\0';
823
824         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10);
825
826         torture_assert(tctx, convert_string_error_handle(iconv_handle,
827                                                           CH_UTF8, CH_UTF16LE,
828                                                           plato_utf8_terminated.data, -1,
829                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
830                        "conversion from UTF8 to UTF16LE null terminated");
831         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated");
832
833         torture_assert(tctx, convert_string_error_handle(iconv_handle,
834                                                           CH_UTF8, CH_UTF16LE,
835                                                           plato_utf8_terminated.data, -1,
836                                                           (void *)plato_output.data, plato_utf16le.length, &plato_output.length) == false,
837                        "conversion from UTF8 to UTF16LE null terminated should fail");
838         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
839         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE null terminated");
840
841         torture_assert(tctx, convert_string_error_handle(iconv_handle,
842                                                           CH_UTF8, CH_UTF16LE,
843                                                           plato_utf8_terminated.data, -1,
844                                                           (void *)plato_output.data, plato_utf16le.length - 1, &plato_output.length) == false,
845                        "conversion from UTF8 to UTF16LE null terminated should fail");
846         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
847
848         torture_assert(tctx, convert_string_error_handle(iconv_handle,
849                                                           CH_UTF8, CH_UTF16LE,
850                                                           plato_utf8_terminated.data, -1,
851                                                           (void *)plato_output.data, plato_utf16le.length - 2, &plato_output.length) == false,
852                        "conversion from UTF8 to UTF16LE null terminated should fail");
853         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to UTF16LE should fail E2BIG");
854
855         plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10);
856
857         torture_assert(tctx, convert_string_error_handle(iconv_handle,
858                                                          CH_UTF16LE, CH_UTF8,
859                                                          plato_utf16le_terminated.data, -1,
860                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
861                        "conversion from UTF16LE to UTF8 null terminated");
862         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated");
863
864         torture_assert(tctx, convert_string_error_handle(iconv_handle,
865                                                          CH_UTF16LE, CH_UTF8,
866                                                          plato_utf16le_terminated.data, -1,
867                                                          (void *)plato_output.data, plato_utf8.length, &plato_output.length) == false,
868                        "conversion from UTF16LE to UTF8 null terminated should fail");
869         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
870         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 null terminated");
871
872         torture_assert(tctx, convert_string_error_handle(iconv_handle,
873                                                          CH_UTF16LE, CH_UTF8,
874                                                          plato_utf16le_terminated.data, -1,
875                                                          (void *)plato_output.data, plato_utf8.length - 1, &plato_output.length) == false,
876                        "conversion from UTF16LE to UTF8 null terminated should fail");
877         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
878
879         torture_assert(tctx, convert_string_error_handle(iconv_handle,
880                                                          CH_UTF16LE, CH_UTF8,
881                                                          plato_utf16le_terminated.data, -1,
882                                                          (void *)plato_output.data, plato_utf8.length - 2, &plato_output.length) == false,
883                        "conversion from UTF16LE to UTF8 null terminated should fail");
884         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16LE to UTF8 should fail E2BIG");
885
886         /* Now null terminate the string early, the confirm we don't skip the NULL and convert any further */
887         plato_utf8_terminated.data[5] = '\0';
888         plato_utf8_terminated.length = 6; /* used for the comparison only */
889
890         plato_utf16le_terminated.data[4] = '\0';
891         plato_utf16le_terminated.data[5] = '\0';
892         plato_utf16le_terminated.length = 6; /* used for the comparison only */
893
894         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length + 10);
895
896         torture_assert(tctx, convert_string_error_handle(iconv_handle,
897                                                           CH_UTF8, CH_UTF16LE,
898                                                           plato_utf8_terminated.data, -1,
899                                                           (void *)plato_output.data, plato_output.length, &plato_output.length),
900                        "conversion from UTF8 to UTF16LE null terminated");
901         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le_terminated, "conversion from UTF8 to UTF16LE null terminated early");
902
903         plato_output = data_blob_talloc(tctx, NULL, plato_utf8.length + 10);
904
905         torture_assert(tctx, convert_string_error_handle(iconv_handle,
906                                                           CH_UTF16LE, CH_UTF8,
907                                                           plato_utf16le_terminated.data, -1,
908                                                          (void *)plato_output.data, plato_output.length, &plato_output.length),
909                        "conversion from UTF16LE to UTF8 null terminated");
910         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8_terminated, "conversion from UTF16LE to UTF8 null terminated early");
911         
912         return true;
913 }
914
915 static bool test_plato_cp850_utf8_handle(struct torture_context *tctx)
916 {
917         struct smb_iconv_handle *iconv_handle;
918         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
919         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
920         DATA_BLOB plato_output;
921         DATA_BLOB plato_output2;
922         
923         talloc_steal(tctx, plato_utf8.data);
924         talloc_steal(tctx, plato_utf16le.data);
925
926         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8");
927         torture_assert(tctx, iconv_handle, "creating iconv handle");
928                 
929         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
930                                                     CH_UTF8, CH_UTF16LE,
931                                                     plato_utf8.data, plato_utf8.length,
932                                                     (void *)&plato_output.data, &plato_output.length),
933                        "conversion of UTF8 ancient greek to UTF16 failed");
934         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
935
936         torture_assert_int_equal(tctx,
937                                  strlen_m_ext_handle(iconv_handle,
938                                                      (const char *)plato_utf8.data,
939                                                      CH_UTF8, CH_UTF16LE),
940                                  plato_output.length / 2,
941                                  "checking strlen_m_ext of conversion of UTF8 to UTF16LE");
942
943         memset(plato_output.data, '\0', plato_output.length);
944         torture_assert(tctx, convert_string_error_handle(iconv_handle,
945                                                          CH_UTF8, CH_UTF16LE,
946                                                          plato_utf8.data, plato_utf8.length,
947                                                          (void *)plato_output.data, plato_output.length,
948                                                          &plato_output.length),
949                        "conversion of UTF8 ancient greek to UTF16 failed");
950         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
951
952         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
953                                                     CH_UTF16LE, CH_UTF8,
954                                                     plato_output.data, plato_output.length,
955                                                     (void *)&plato_output2.data, &plato_output2.length),
956                        "conversion of UTF8 ancient greek to UTF16 failed");
957         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
958
959         memset(plato_output2.data, '\0', plato_output2.length);
960         torture_assert(tctx, convert_string_error_handle(iconv_handle,
961                                                    CH_UTF16LE, CH_UTF8,
962                                                    plato_output.data, plato_output.length,
963                                                    (void *)plato_output2.data, plato_output2.length, &plato_output2.length),
964                        "conversion of UTF8 ancient greek to UTF16 failed");
965         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
966
967         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
968                                                           CH_UTF8, CH_UTF8,
969                                                           plato_utf8.data, plato_utf8.length,
970                                                           (void *)&plato_output.data, &plato_output.length),
971                        "conversion of UTF8 to UTF8");
972         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
973                                        "conversion of UTF8 to UTF8");
974         torture_assert_int_equal(tctx,
975                                  strlen_m_ext_handle(iconv_handle,
976                                                      (const char *)plato_utf8.data,
977                                                      CH_UTF8, CH_UTF8),
978                                  plato_output.length,
979                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
980         memset(plato_output.data, '\0', plato_output.length);
981         torture_assert(tctx, convert_string_error_handle(iconv_handle,
982                                                          CH_UTF8, CH_UTF8,
983                                                          plato_utf8.data, plato_utf8.length,
984                                                          (void *)plato_output.data, plato_output.length,
985                                                          &plato_output.length),
986                        "conversion of UTF8 to UTF8");
987
988         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
989                                                     CH_UTF8, CH_DOS, 
990                                                     plato_utf8.data, plato_utf8.length, 
991                                                     (void *)&plato_output.data, &plato_output.length) == false, 
992                        "conversion of UTF8 ancient greek to DOS charset CP850 should fail");
993         
994         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
995                                                     CH_UTF8, CH_UNIX, 
996                                                     plato_utf8.data, plato_utf8.length, 
997                                                     (void *)&plato_output.data, &plato_output.length),
998                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
999         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
1000         
1001         memset(plato_output.data, '\0', plato_output.length);
1002         torture_assert(tctx, convert_string_error_handle(iconv_handle,
1003                                                          CH_UTF8, CH_UNIX,
1004                                                          plato_utf8.data, plato_utf8.length,
1005                                                          (void *)plato_output.data, plato_output.length,
1006                                                          &plato_output.length),
1007                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
1008         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
1009
1010         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1011                                                     CH_UTF8, CH_UTF8, 
1012                                                     plato_utf8.data, plato_utf8.length, 
1013                                                     (void *)&plato_output.data, &plato_output.length),
1014                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
1015         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF8 to UTF8 incorrect");
1016         
1017         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1018                                                     CH_UTF16LE, CH_DOS, 
1019                                                     plato_utf16le.data, plato_utf16le.length, 
1020                                                     (void *)&plato_output.data, &plato_output.length) == false,         
1021                        "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
1022
1023         /* Allocate enough space, if it were possible do do the conversion */
1024         plato_output = data_blob_talloc(tctx, NULL, plato_utf16le.length);
1025         torture_assert(tctx, convert_string_error_handle(iconv_handle,
1026                                                          CH_UTF16LE, CH_DOS,
1027                                                          plato_utf16le.data, plato_utf16le.length,
1028                                                          (void *)plato_output.data, plato_output.length,
1029                                                          &plato_output.length) == false,
1030                        "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
1031         torture_assert_errno_equal(tctx,  EILSEQ, "conversion of UTF16 ancient greek to DOS charset CP850 should fail");
1032
1033         /* Allocate only enough space for a partial conversion */
1034         plato_output = data_blob_talloc(tctx, NULL, 9);
1035         torture_assert(tctx, convert_string_error_handle(iconv_handle,
1036                                                          CH_UTF16LE, CH_UTF8,
1037                                                          plato_utf16le.data, plato_utf16le.length,
1038                                                          (void *)plato_output.data, plato_output.length,
1039                                                          &plato_output.length) == false,
1040                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1041         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1042         torture_assert_int_equal(tctx, plato_output.length, 8,
1043                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
1044
1045         plato_output = data_blob_talloc(tctx, NULL, 2);
1046         torture_assert(tctx, convert_string_error_handle(iconv_handle,
1047                                                          CH_UTF16LE, CH_UTF8,
1048                                                          plato_utf16le.data, plato_utf16le.length,
1049                                                          (void *)plato_output.data, plato_output.length,
1050                                                          &plato_output.length) == false,
1051                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1052         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1053         torture_assert_int_equal(tctx, plato_output.length, 0,
1054                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
1055
1056
1057         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1058                                                     CH_UTF16LE, CH_UNIX, 
1059                                                     plato_utf16le.data, plato_utf16le.length, 
1060                                                     (void *)&plato_output.data, &plato_output.length),  
1061                        "conversion of UTF16 ancient greek to unix charset UTF8 failed");
1062         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to (unix charset) UTF8 incorrect");
1063         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
1064                                                     CH_UTF16LE, CH_UTF8,
1065                                                     plato_utf16le.data, plato_utf16le.length,
1066                                                     (void *)&plato_output.data, &plato_output.length),
1067                        "conversion of UTF16 ancient greek to UTF8 failed");
1068         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect");
1069         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1070                                                           CH_UTF16LE, CH_UTF8, 
1071                                                           plato_utf16le.data, plato_utf16le.length, 
1072                                                           (void *)&plato_output.data, &plato_output.length),
1073                        "conversion of UTF16 ancient greek to UTF8 failed");
1074         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8, "conversion from UTF16LE to UTF8 incorrect");
1075         
1076         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1077                                                           CH_UTF8, CH_UTF16LE, 
1078                                                           plato_output.data, plato_output.length, 
1079                                                           (void *)&plato_output2.data, &plato_output2.length),
1080                        "round trip conversion of UTF16 ancient greek to UTF8 and back again failed");
1081         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf16le,
1082                                        "round trip conversion of UTF16 ancient greek to UTF8 and back again failed");
1083         torture_assert_int_equal(tctx,
1084                                  strlen_m_ext_handle(iconv_handle,
1085                                                      (const char *)plato_output.data,
1086                                                      CH_UTF8, CH_UTF16LE),
1087                                  plato_output2.length / 2,
1088                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
1089
1090         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle,
1091                                                           CH_UTF8, CH_UTF8,
1092                                                           plato_output.data, plato_output.length,
1093                                                           (void *)&plato_output2.data, &plato_output2.length),
1094                        "conversion of UTF8 to UTF8");
1095         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8,
1096                                        "conversion of UTF8 to UTF8");
1097         torture_assert_int_equal(tctx,
1098                                  strlen_m_ext_handle(iconv_handle,
1099                                                      (const char *)plato_output.data,
1100                                                      CH_UTF8, CH_UTF8),
1101                                  plato_output2.length,
1102                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
1103         return true;
1104 }
1105
1106 static bool test_plato_latin_cp850_utf8_handle(struct torture_context *tctx)
1107 {
1108         struct smb_iconv_handle *iconv_handle;
1109         DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64);
1110         DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64);
1111         DATA_BLOB plato_latin_output;
1112         DATA_BLOB plato_latin_output2;
1113         
1114         talloc_steal(tctx, plato_latin_utf8.data);
1115         talloc_steal(tctx, plato_latin_utf16le.data);
1116
1117         iconv_handle = get_iconv_testing_handle(tctx, "CP850", "UTF8");
1118         torture_assert(tctx, iconv_handle, "creating iconv handle");
1119                 
1120         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1121                                                     CH_UTF8, CH_DOS, 
1122                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
1123                                                     (void *)&plato_latin_output.data, &plato_latin_output.length) == false, 
1124                        "conversion of UTF8  latin charset greek to DOS charset CP850 should fail");
1125         
1126         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1127                                                     CH_UTF8, CH_UNIX, 
1128                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
1129                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
1130                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
1131         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to (unix charset) UTF8 incorrect");
1132         
1133         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1134                                                     CH_UTF8, CH_UTF8, 
1135                                                     plato_latin_utf8.data, plato_latin_utf8.length, 
1136                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
1137                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
1138         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF8 to UTF8 incorrect");
1139         
1140         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1141                                                     CH_UTF16LE, CH_DOS, 
1142                                                     plato_latin_utf16le.data, plato_latin_utf16le.length, 
1143                                                     (void *)&plato_latin_output.data, &plato_latin_output.length) == false,     
1144                        "conversion of UTF16 latin charset greek to DOS charset CP850 should fail");
1145         
1146         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1147                                                     CH_UTF16LE, CH_UNIX, 
1148                                                     plato_latin_utf16le.data, plato_latin_utf16le.length, 
1149                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),      
1150                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
1151         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to (unix charset) CP850 incorrect");
1152         
1153         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1154                                                           CH_UTF16LE, CH_UTF8, 
1155                                                           plato_latin_utf16le.data, plato_latin_utf16le.length, 
1156                                                           (void *)&plato_latin_output.data, &plato_latin_output.length),
1157                        "conversion of UTF16 latin charset greek to UTF8 failed");
1158         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16LE to UTF8 incorrect");
1159         
1160         torture_assert(tctx, convert_string_talloc_handle(tctx, iconv_handle, 
1161                                                           CH_UTF8, CH_UTF16LE, 
1162                                                           plato_latin_output.data, plato_latin_output.length, 
1163                                                           (void *)&plato_latin_output2.data, &plato_latin_output2.length),
1164                        "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed");
1165         torture_assert_data_blob_equal(tctx, plato_latin_output2, plato_latin_utf16le,
1166                                        "round trip conversion of UTF16 latin charset greek to UTF8 and back again failed");
1167         torture_assert_int_equal(tctx,
1168                                  strlen_m_ext_handle(iconv_handle,
1169                                                      (const char *)plato_latin_output.data,
1170                                                      CH_UTF8, CH_UTF16LE),
1171                                  plato_latin_output2.length / 2,
1172                                  "checking strlen_m_ext of round trip conversion of UTF16 latin charset greek to UTF8 and back again");
1173         return true;
1174 }
1175
1176 static bool test_gd_case_utf8_handle(struct torture_context *tctx)
1177 {
1178         struct smb_iconv_handle *iconv_handle;
1179         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
1180         DATA_BLOB gd_utf8_upper = base64_decode_data_blob(gd_utf8_upper_base64);
1181         DATA_BLOB gd_utf8_lower = base64_decode_data_blob(gd_utf8_lower_base64);
1182         char *gd_lower, *gd_upper;
1183         talloc_steal(tctx, gd_utf8.data);
1184
1185         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8");
1186         torture_assert(tctx, iconv_handle, "getting utf8 iconv handle");
1187
1188         torture_assert(tctx,
1189                        strhasupper_handle(iconv_handle, (const char *)gd_utf8.data),
1190                        "GD's name has an upper case character");
1191         torture_assert(tctx,
1192                        strhaslower_handle(iconv_handle, (const char *)gd_utf8.data),
1193                        "GD's name has an lower case character");
1194         gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_utf8.data);
1195         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
1196         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_utf8_lower,
1197                                        "convert GD's name into lower case");
1198         gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_utf8.data, gd_utf8.length);
1199         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
1200         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_utf8_upper,
1201                                        "convert GD's name into upper case");
1202
1203         torture_assert(tctx,
1204                        strhasupper_handle(iconv_handle, gd_upper),
1205                        "upper case name has an upper case character");
1206         torture_assert(tctx,
1207                        strhaslower_handle(iconv_handle, gd_lower),
1208                        "lower case name has an lower case character");
1209         torture_assert(tctx,
1210                        strhasupper_handle(iconv_handle, gd_lower) == false,
1211                        "lower case name has no upper case character");
1212         torture_assert(tctx,
1213                        strhaslower_handle(iconv_handle, gd_upper) == false,
1214                        "upper case name has no lower case character");
1215
1216         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
1217                                                  gd_upper) == 0,
1218                        "case insensitive comparison orig/upper");
1219         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
1220                                                  gd_lower) == 0,
1221                        "case insensitive comparison orig/lower");
1222         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper,
1223                                                  gd_lower) == 0,
1224                        "case insensitive comparison upper/lower");
1225
1226         /* This string isn't different in length upper/lower */
1227         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
1228                                                   gd_upper, gd_utf8.length) == 0,
1229                        "case insensitive comparison orig/upper");
1230         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data,
1231                                                  gd_lower, gd_utf8.length) == 0,
1232                        "case insensitive comparison orig/lower");
1233         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper,
1234                                                  gd_lower, gd_utf8.length) == 0,
1235                        "case insensitive comparison upper/lower");
1236         return true;
1237 }
1238
1239 static bool test_gd_case_cp850_handle(struct torture_context *tctx)
1240 {
1241         struct smb_iconv_handle *iconv_handle;
1242         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
1243         DATA_BLOB gd_cp850_upper = base64_decode_data_blob(gd_cp850_upper_base64);
1244         DATA_BLOB gd_cp850_lower = base64_decode_data_blob(gd_cp850_lower_base64);
1245         char *gd_lower, *gd_upper;
1246         talloc_steal(tctx, gd_cp850.data);
1247
1248         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "CP850");
1249         torture_assert(tctx, iconv_handle, "getting cp850 iconv handle");
1250
1251         torture_assert(tctx,
1252                        strhasupper_handle(iconv_handle, (const char *)gd_cp850.data),
1253                        "GD's name has an upper case character");
1254         torture_assert(tctx,
1255                        strhaslower_handle(iconv_handle, (const char *)gd_cp850.data),
1256                        "GD's name has an lower case character");
1257         gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_cp850.data);
1258         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
1259         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_lower), gd_cp850_lower,
1260                                        "convert GD's name into lower case");
1261         gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_cp850.data, gd_cp850.length);
1262         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
1263         torture_assert_data_blob_equal(tctx, data_blob_string_const(gd_upper), gd_cp850_upper,
1264                                        "convert GD's name into upper case");
1265
1266         torture_assert(tctx,
1267                        strhasupper_handle(iconv_handle, gd_upper),
1268                        "upper case name has an upper case character");
1269         torture_assert(tctx,
1270                        strhaslower_handle(iconv_handle, gd_lower),
1271                        "lower case name has an lower case character");
1272         torture_assert(tctx,
1273                        strhasupper_handle(iconv_handle, gd_lower) == false,
1274                        "lower case name has no upper case character");
1275         torture_assert(tctx,
1276                        strhaslower_handle(iconv_handle, gd_upper) == false,
1277                        "upper case name has no lower case character");
1278
1279         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
1280                                                  gd_upper) == 0,
1281                        "case insensitive comparison orig/upper");
1282         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
1283                                                  gd_lower) == 0,
1284                        "case insensitive comparison orig/lower");
1285         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper,
1286                                                  gd_lower) == 0,
1287                        "case insensitive comparison upper/lower");
1288
1289         /* This string isn't different in length upper/lower */
1290         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
1291                                                  gd_upper, gd_cp850.length) == 0,
1292                        "case insensitive comparison orig/upper");
1293         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data,
1294                                                  gd_lower, gd_cp850.length) == 0,
1295                        "case insensitive comparison orig/lower");
1296         torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper,
1297                                                  gd_lower, gd_cp850.length) == 0,
1298                        "case insensitive comparison upper/lower");
1299         return true;
1300 }
1301
1302 static bool test_plato_case_utf8_handle(struct torture_context *tctx)
1303 {
1304         struct smb_iconv_handle *iconv_handle;
1305         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
1306         char *plato_lower, *plato_upper;
1307         talloc_steal(tctx, plato_utf8.data);
1308
1309         iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8");
1310         torture_assert(tctx, iconv_handle, "getting utf8 iconv handle");
1311
1312         torture_assert(tctx,
1313                        strhasupper_handle(iconv_handle, (const char *)plato_utf8.data),
1314                        "PLATO's apology has an upper case character");
1315         torture_assert(tctx,
1316                        strhaslower_handle(iconv_handle, (const char *)plato_utf8.data),
1317                        "PLATO's apology has an lower case character");
1318         plato_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)plato_utf8.data);
1319         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case");
1320         plato_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)plato_utf8.data, plato_utf8.length);
1321         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case");
1322
1323         torture_assert(tctx,
1324                        strhasupper_handle(iconv_handle, plato_upper),
1325                        "upper case string has an upper case character");
1326         torture_assert(tctx,
1327                        strhaslower_handle(iconv_handle, plato_lower),
1328                        "lower case string has an lower case character");
1329         torture_assert(tctx,
1330                        strhasupper_handle(iconv_handle, plato_lower) == false,
1331                        "lower case string has no upper case character");
1332         torture_assert(tctx,
1333                        strhaslower_handle(iconv_handle, plato_upper) == false,
1334                        "upper case string has no lower case character");
1335
1336         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data,
1337                                                  plato_upper) == 0,
1338                        "case insensitive comparison orig/upper");
1339         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data,
1340                                                  plato_lower) == 0,
1341                        "case insensitive comparison orig/lower");
1342         torture_assert(tctx, strcasecmp_m_handle(iconv_handle, plato_upper,
1343                                                  plato_lower) == 0,
1344                        "case insensitive comparison upper/lower");
1345         return true;
1346 }
1347
1348 static bool test_gd(struct torture_context *tctx)
1349 {
1350         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
1351         DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64);
1352         DATA_BLOB gd_iso8859_1 = base64_decode_data_blob(gd_iso8859_1_base64);
1353         DATA_BLOB gd_utf16le = base64_decode_data_blob(gd_utf16le_base64);
1354         DATA_BLOB gd_output;
1355         size_t saved_len;
1356
1357         talloc_steal(tctx, gd_utf8.data);
1358         talloc_steal(tctx, gd_cp850.data);
1359         talloc_steal(tctx, gd_iso8859_1.data);
1360         talloc_steal(tctx, gd_utf16le.data);
1361
1362         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UTF8,
1363                                                    gd_utf8.data, gd_utf8.length,
1364                                                    (void *)&gd_output.data, &gd_output.length),
1365                        "conversion from UTF8 to utf8 charset");
1366         saved_len = gd_output.length;
1367
1368         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
1369                                                          gd_utf8.data, gd_utf8.length,
1370                                                          (void *)gd_output.data, gd_output.length,
1371                                                          &gd_output.length),
1372                        "conversion from UTF8 to utf8 charset");
1373
1374         /* Short output handling confirmation */
1375         gd_output.length = 1;
1376         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
1377                                                          gd_utf8.data, gd_utf8.length,
1378                                                          (void *)gd_output.data, gd_output.length,
1379                                                          &gd_output.length) == false,
1380                        "conversion from UTF8 to any utf8 charset should fail due to too short");
1381         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG");
1382         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
1383         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF8 to utf8 charset incorrect");
1384
1385 #if 0 /* This currently fails as we just copy like-for-like character conversions */
1386         /* Short output handling confirmation */
1387         gd_output.length = 2;
1388         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
1389                                                   gd_utf8.data, gd_utf8.length,
1390                                                   (void *)gd_output.data, gd_output.length,
1391                                                   &gd_output.length) == false,
1392                        "conversion from UTF8 to utf8 charset should fail due to too short");
1393         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF8 to utf8 charset should fail E2BIG");
1394         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
1395
1396         /* Short input handling confirmation */
1397         gd_output.length = saved_len;
1398         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
1399                                                   gd_utf8.data, 2,
1400                                                   (void *)gd_output.data, gd_output.length,
1401                                                   &gd_output.length) == false,
1402                        "conversion from UTF8 to UTF8 should fail due to too short");
1403         torture_assert_errno_equal(tctx, EILSEQ, "conversion from short UTF8 to UTF8 should fail EINVAL");
1404         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
1405 #endif
1406
1407         /* Short output handling confirmation */
1408         gd_output.length = 1;
1409         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1410                                                   gd_utf16le.data, gd_utf16le.length,
1411                                                   (void *)gd_output.data, gd_output.length,
1412                                                   &gd_output.length) == false,
1413                        "conversion from UTF16 to UTF8 should fail due to too short");
1414         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG");
1415         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
1416         torture_assert_data_blob_equal(tctx, gd_output, data_blob_string_const("G"), "conversion from UTF16 to UTF8 incorrect");
1417
1418         /* Short output handling confirmation */
1419         gd_output.length = 3;
1420         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1421                                                   gd_utf16le.data, gd_utf16le.length,
1422                                                   (void *)gd_output.data, gd_output.length,
1423                                                   &gd_output.length) == false,
1424                        "conversion from UTF16 to UTF8 should fail due to too short");
1425         torture_assert_errno_equal(tctx, E2BIG, "conversion from UTF16 to UTF8 should fail E2BIG");
1426         torture_assert_int_equal(tctx, gd_output.length, 3, "Should get 3 bytes output for UTF8");
1427
1428         /* Short input handling confirmation */
1429         gd_output.length = saved_len;
1430         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1431                                                   gd_utf16le.data, 3,
1432                                                   (void *)gd_output.data, gd_output.length,
1433                                                   &gd_output.length) == false,
1434                        "conversion from UTF16 to UTF8 should fail due to too short");
1435         torture_assert_errno_equal(tctx, EINVAL, "conversion from short UTF16 to UTF8 should fail EINVAL");
1436         torture_assert_int_equal(tctx, gd_output.length, 1, "Should only get 1 char of output");
1437
1438         return true;
1439 }
1440
1441 static bool test_plato(struct torture_context *tctx)
1442 {
1443         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
1444         DATA_BLOB plato_utf16le = base64_decode_data_blob(plato_utf16le_base64);
1445         DATA_BLOB plato_output;
1446         DATA_BLOB plato_output2;
1447
1448         talloc_steal(tctx, plato_utf8.data);
1449         talloc_steal(tctx, plato_utf16le.data);
1450
1451         torture_assert(tctx, convert_string_talloc(tctx,
1452                                                    CH_UTF8, CH_UTF16LE,
1453                                                    plato_utf8.data, plato_utf8.length,
1454                                                    (void *)&plato_output.data, &plato_output.length),
1455                        "conversion of UTF8 ancient greek to UTF16 failed");
1456         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
1457
1458         torture_assert_int_equal(tctx,
1459                                  strlen_m_ext((const char *)plato_utf8.data,
1460                                               CH_UTF8, CH_UTF16LE),
1461                                  plato_output.length / 2,
1462                                  "checking strlen_m_ext of conversion of UTF8 to UTF16LE");
1463
1464         memset(plato_output.data, '\0', plato_output.length);
1465         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF16LE,
1466                                                   plato_utf8.data, plato_utf8.length,
1467                                                   (void *)plato_output.data, plato_output.length,
1468                                                   &plato_output.length),
1469                        "conversion of UTF8 ancient greek to UTF16 failed");
1470         torture_assert_data_blob_equal(tctx, plato_output, plato_utf16le, "conversion from UTF8 to UTF16LE incorrect");
1471
1472         torture_assert(tctx, convert_string_talloc(tctx,
1473                                                    CH_UTF16LE, CH_UTF8,
1474                                                    plato_output.data, plato_output.length,
1475                                                    (void *)&plato_output2.data, &plato_output2.length),
1476                        "conversion of UTF8 ancient greek to UTF16 failed");
1477         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
1478
1479         memset(plato_output2.data, '\0', plato_output2.length);
1480         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1481                                                   plato_output.data, plato_output.length,
1482                                                   (void *)plato_output2.data, plato_output2.length, &plato_output2.length),
1483                        "conversion of UTF8 ancient greek to UTF16 failed");
1484         torture_assert_data_blob_equal(tctx, plato_output2, plato_utf8, "conversion from UTF8 to UTF16LE incorrect");
1485
1486         torture_assert(tctx, convert_string_talloc(tctx,
1487                                                    CH_UTF8, CH_UTF8,
1488                                                    plato_utf8.data, plato_utf8.length,
1489                                                    (void *)&plato_output.data, &plato_output.length),
1490                        "conversion of UTF8 to UTF8");
1491         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
1492                                        "conversion of UTF8 to UTF8");
1493         torture_assert_int_equal(tctx,
1494                                  strlen_m_ext((const char *)plato_utf8.data,
1495                                               CH_UTF8, CH_UTF8),
1496                                  plato_output.length,
1497                                  "checking strlen_m_ext of conversion of UTF8 to UTF8");
1498         memset(plato_output.data, '\0', plato_output.length);
1499         torture_assert(tctx, convert_string_error(CH_UTF8, CH_UTF8,
1500                                                   plato_utf8.data, plato_utf8.length,
1501                                                   (void *)plato_output.data, plato_output.length,
1502                                                   &plato_output.length),
1503                        "conversion of UTF8 to UTF8");
1504         torture_assert_data_blob_equal(tctx, plato_output, plato_utf8,
1505                                        "conversion of UTF8 to UTF8");
1506
1507         memset(plato_output.data, '\0', plato_output.length);
1508         torture_assert(tctx, convert_string_error(CH_UTF8, CH_DOS,
1509                                                   plato_utf8.data, plato_utf8.length,
1510                                                   (void *)plato_output.data, plato_output.length,
1511                                                   &plato_output.length) == false,
1512                        "conversion of UTF8 to any dos charset should fail");
1513         torture_assert_errno_equal(tctx,  EILSEQ, "conversion of UTF16 ancient greek to any DOS charset should fail EILSEQ");
1514
1515         torture_assert(tctx, convert_string_talloc(tctx,
1516                                                    CH_UTF8, CH_DOS,
1517                                                    plato_utf8.data, plato_utf8.length,
1518                                                    (void *)&plato_output.data, &plato_output.length) == false,
1519                        "conversion of UTF8 ancient greek to any DOS charset should fail");
1520
1521         /* Allocate only enough space for a partial conversion */
1522         plato_output = data_blob_talloc(tctx, NULL, 9);
1523         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1524                                                   plato_utf16le.data, plato_utf16le.length,
1525                                                   (void *)plato_output.data, plato_output.length,
1526                                                   &plato_output.length) == false,
1527                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1528         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1529         torture_assert_int_equal(tctx, plato_output.length, 8,
1530                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
1531
1532         plato_output = data_blob_talloc(tctx, NULL, 2);
1533         torture_assert(tctx, convert_string_error(CH_UTF16LE, CH_UTF8,
1534                                                   plato_utf16le.data, plato_utf16le.length,
1535                                                   (void *)plato_output.data, plato_output.length,
1536                                                   &plato_output.length) == false,
1537                        "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1538         torture_assert_errno_equal(tctx,  E2BIG, "conversion of UTF16 ancient greek to UTF8 should fail, not enough space");
1539         torture_assert_int_equal(tctx, plato_output.length, 0,
1540                                  "conversion of UTF16 ancient greek to UTF8 should stop on multibyte boundary");
1541
1542
1543         return true;
1544 }
1545
1546 static bool test_plato_latin(struct torture_context *tctx)
1547 {
1548         DATA_BLOB plato_latin_utf8 = base64_decode_data_blob(plato_latin_utf8_base64);
1549         DATA_BLOB plato_latin_utf16le = base64_decode_data_blob(plato_latin_utf16le_base64);
1550         DATA_BLOB plato_latin_output;
1551
1552         talloc_steal(tctx, plato_latin_utf8.data);
1553         talloc_steal(tctx, plato_latin_utf16le.data);
1554
1555         torture_assert(tctx, convert_string_talloc(tctx,
1556                                                     CH_UTF16LE, CH_UTF8,
1557                                                     plato_latin_utf16le.data, plato_latin_utf16le.length,
1558                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
1559                        "conversion of UTF16 latin charset greek to unix charset UTF8 failed");
1560         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf8, "conversion from UTF16 to UTF8 incorrect");
1561
1562         torture_assert_int_equal(tctx,
1563                                  strlen_m_ext((const char *)plato_latin_output.data,
1564                                               CH_UTF8, CH_UTF16LE),
1565                                  plato_latin_utf16le.length / 2,
1566                                  "checking strlen_m_ext UTF16 latin charset greek to UTF8");
1567         torture_assert(tctx, convert_string_talloc(tctx,
1568                                                     CH_UTF8, CH_UTF16LE,
1569                                                     plato_latin_utf8.data, plato_latin_utf8.length,
1570                                                     (void *)&plato_latin_output.data, &plato_latin_output.length),
1571                        "conversion of UTF16 latin charset greek to UTF16LE failed");
1572         torture_assert_data_blob_equal(tctx, plato_latin_output, plato_latin_utf16le, "conversion from UTF8 to UTF16LE incorrect");
1573
1574         return true;
1575 }
1576
1577 static bool test_gd_case(struct torture_context *tctx)
1578 {
1579         DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64);
1580         char *gd_unix;
1581         size_t gd_size;
1582         char *gd_lower, *gd_upper;
1583         talloc_steal(tctx, gd_utf8.data);
1584
1585         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
1586                                                    gd_utf8.data, gd_utf8.length,
1587                                                    (void *)&gd_unix, &gd_size),
1588                        "conversion of unix charset to UTF8");
1589
1590         gd_lower = strlower_talloc(tctx, gd_unix);
1591         torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case");
1592         gd_upper = strupper_talloc_n(tctx, gd_unix, gd_size);
1593         torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case");
1594
1595         torture_assert(tctx,
1596                        strhasupper(gd_unix),
1597                        "GD's name has an upper case character");
1598         torture_assert(tctx,
1599                        strhaslower(gd_unix),
1600                        "GD's name has an lower case character");
1601         torture_assert(tctx,
1602                        strhasupper(gd_upper),
1603                        "upper case name has an upper case character");
1604         torture_assert(tctx,
1605                        strhaslower(gd_lower),
1606                        "lower case name has an lower case character");
1607         torture_assert(tctx,
1608                        strhasupper(gd_lower) == false,
1609                        "lower case name has no upper case character");
1610         torture_assert(tctx,
1611                        strhaslower(gd_upper) == false,
1612                        "upper case name has no lower case character");
1613
1614         torture_assert(tctx, strcasecmp_m(gd_unix,
1615                                                  gd_upper) == 0,
1616                        "case insensitive comparison orig/upper");
1617         torture_assert(tctx, strcasecmp_m(gd_unix,
1618                                                  gd_lower) == 0,
1619                        "case insensitive comparison orig/lower");
1620         torture_assert(tctx, strcasecmp_m(gd_upper,
1621                                                  gd_lower) == 0,
1622                        "case insensitive comparison upper/lower");
1623
1624         /* This string isn't different in length upper/lower, but just check the first 5 chars */
1625         torture_assert(tctx, strncasecmp_m(gd_unix,
1626                                                   gd_upper, 5) == 0,
1627                        "case insensitive comparison orig/upper");
1628         torture_assert(tctx, strncasecmp_m(gd_unix,
1629                                                  gd_lower, 5) == 0,
1630                        "case insensitive comparison orig/lower");
1631         torture_assert(tctx, strncasecmp_m(gd_upper,
1632                                                  gd_lower, 5) == 0,
1633                        "case insensitive comparison upper/lower");
1634         return true;
1635 }
1636
1637 static bool test_plato_case(struct torture_context *tctx)
1638 {
1639         DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64);
1640         char *plato_unix;
1641         size_t plato_length;
1642         char *plato_lower, *plato_upper;
1643         talloc_steal(tctx, plato_utf8.data);
1644
1645         torture_assert(tctx, convert_string_talloc(tctx, CH_UTF8, CH_UNIX,
1646                                                    plato_utf8.data, plato_utf8.length,
1647                                                    (void *)&plato_unix, &plato_length),
1648                        "conversion of unix charset to UTF8");
1649
1650         torture_assert(tctx,
1651                        strhasupper(plato_unix),
1652                        "PLATO's apology has an upper case character");
1653         torture_assert(tctx,
1654                        strhaslower(plato_unix),
1655                        "PLATO's apology has an lower case character");
1656         plato_lower = strlower_talloc(tctx, plato_unix);
1657         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case");
1658         plato_upper = strupper_talloc_n(tctx, plato_unix, plato_utf8.length);
1659         torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case");
1660
1661         torture_assert(tctx,
1662                        strhasupper(plato_upper),
1663                        "upper case string has an upper case character");
1664         torture_assert(tctx,
1665                        strhaslower(plato_lower),
1666                        "lower case string has an lower case character");
1667         torture_assert(tctx,
1668                        strhasupper(plato_lower) == false,
1669                        "lower case string has no upper case character");
1670         torture_assert(tctx,
1671                        strhaslower(plato_upper) == false,
1672                        "upper case string has no lower case character");
1673
1674         torture_assert(tctx, strcasecmp_m(plato_unix,
1675                                                  plato_upper) == 0,
1676                        "case insensitive comparison orig/upper");
1677         torture_assert(tctx, strcasecmp_m(plato_unix,
1678                                                  plato_lower) == 0,
1679                        "case insensitive comparison orig/lower");
1680         torture_assert(tctx, strcasecmp_m(plato_upper,
1681                                                  plato_lower) == 0,
1682                        "case insensitive comparison upper/lower");
1683         return true;
1684 }
1685
1686 struct torture_suite *torture_local_convert_string_handle(TALLOC_CTX *mem_ctx)
1687 {
1688         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string_handle");
1689
1690         torture_suite_add_simple_test(suite, "gd_ascii", test_gd_ascii_handle);
1691         torture_suite_add_simple_test(suite, "gd_minus_1", test_gd_minus_1_handle);
1692         torture_suite_add_simple_test(suite, "gd_iso8859_cp850", test_gd_iso8859_cp850_handle);
1693         torture_suite_add_simple_test(suite, "plato_english_iso8859_cp850", test_plato_english_iso8859_cp850_handle);
1694         torture_suite_add_simple_test(suite, "plato_english_minus_1", test_plato_english_minus_1_handle);
1695         torture_suite_add_simple_test(suite, "plato_cp850_utf8", test_plato_cp850_utf8_handle);
1696         torture_suite_add_simple_test(suite, "plato_minus_1", test_plato_minus_1_handle);
1697         torture_suite_add_simple_test(suite, "plato_latin_cp850_utf8", test_plato_latin_cp850_utf8_handle);
1698         return suite;
1699 }
1700
1701 struct torture_suite *torture_local_string_case_handle(TALLOC_CTX *mem_ctx)
1702 {
1703         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
1704
1705         torture_suite_add_simple_test(suite, "gd_case_utf8", test_gd_case_utf8_handle);
1706         torture_suite_add_simple_test(suite, "gd_case_cp850", test_gd_case_cp850_handle);
1707         torture_suite_add_simple_test(suite, "plato_case_utf8", test_plato_case_utf8_handle);
1708         return suite;
1709 }
1710
1711 struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx)
1712 {
1713         struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string");
1714
1715         torture_suite_add_simple_test(suite, "gd", test_gd);
1716         torture_suite_add_simple_test(suite, "plato", test_plato);
1717         torture_suite_add_simple_test(suite, "plato_latin", test_plato_latin);
1718         return suite;
1719 }
1720
1721 struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx)
1722 {
1723         struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case_handle");
1724
1725         torture_suite_add_simple_test(suite, "gd_case", test_gd_case);
1726         torture_suite_add_simple_test(suite, "plato_case", test_plato_case);
1727         return suite;
1728 }