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