|
@@ -1064,6 +1064,130 @@ stdlib_overflow(void *arg)
|
|
|
return TEST_COMPLETED;
|
|
|
}
|
|
|
|
|
|
+static void format_for_description(char *buffer, size_t buflen, const char *text) {
|
|
|
+ if (text == NULL) {
|
|
|
+ SDL_strlcpy(buffer, "NULL", buflen);
|
|
|
+ } else {
|
|
|
+ SDL_snprintf(buffer, buflen, "\"%s\"", text);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+stdlib_iconv(void *arg)
|
|
|
+{
|
|
|
+ struct {
|
|
|
+ SDL_bool expect_success;
|
|
|
+ const char *from_encoding;
|
|
|
+ const char *text;
|
|
|
+ const char *to_encoding;
|
|
|
+ const char *expected;
|
|
|
+ } inputs[] = {
|
|
|
+ { SDL_FALSE, "bogus-from-encoding", NULL, "bogus-to-encoding", NULL },
|
|
|
+ { SDL_FALSE, "bogus-from-encoding", "hello world", "bogus-to-encoding", NULL },
|
|
|
+ { SDL_FALSE, "bogus-from-encoding", "hello world", "ascii", NULL },
|
|
|
+ { SDL_TRUE, "utf-8", NULL, "ascii", "" },
|
|
|
+ { SDL_TRUE, "utf-8", "hello world", "ascii", "hello world" },
|
|
|
+ { SDL_TRUE, "utf-8", "\xe2\x8c\xa8\xf0\x9f\x92\xbb", "utf-16le", "\x28\x23\x3d\xd8\xbb\xdc\x00" },
|
|
|
+ };
|
|
|
+ SDL_iconv_t cd;
|
|
|
+ size_t i;
|
|
|
+
|
|
|
+ for (i = 0; i < SDL_arraysize(inputs); i++) {
|
|
|
+ char to_encoding_str[32];
|
|
|
+ char from_encoding_str[32];
|
|
|
+ char text_str[32];
|
|
|
+ size_t len_text = 0;
|
|
|
+ int r;
|
|
|
+ char out_buffer[6];
|
|
|
+ const char *in_ptr;
|
|
|
+ size_t in_pos;
|
|
|
+ char *out_ptr;
|
|
|
+ char *output;
|
|
|
+ size_t iconv_result;
|
|
|
+ size_t out_len;
|
|
|
+ SDL_bool is_error;
|
|
|
+ size_t out_pos;
|
|
|
+
|
|
|
+ SDLTest_AssertPass("case %d", (int)i);
|
|
|
+ format_for_description(to_encoding_str, SDL_arraysize(to_encoding_str), inputs[i].to_encoding);
|
|
|
+ format_for_description(from_encoding_str, SDL_arraysize(from_encoding_str), inputs[i].from_encoding);
|
|
|
+ format_for_description(text_str, SDL_arraysize(text_str), inputs[i].text);
|
|
|
+
|
|
|
+ if (inputs[i].text) {
|
|
|
+ len_text = SDL_strlen(inputs[i].text) + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ SDLTest_AssertPass("About to call SDL_iconv_open(%s, %s)", to_encoding_str, from_encoding_str);
|
|
|
+ cd = SDL_iconv_open(inputs[i].to_encoding, inputs[i].from_encoding);
|
|
|
+ if (inputs[i].expect_success) {
|
|
|
+ SDLTest_AssertCheck(cd != (SDL_iconv_t)SDL_ICONV_ERROR, "result must NOT be SDL_ICONV_ERROR");
|
|
|
+ } else {
|
|
|
+ SDLTest_AssertCheck(cd == (SDL_iconv_t)SDL_ICONV_ERROR, "result must be SDL_ICONV_ERROR");
|
|
|
+ }
|
|
|
+
|
|
|
+ in_ptr = inputs[i].text;
|
|
|
+ in_pos = 0;
|
|
|
+ out_pos = 0;
|
|
|
+ do {
|
|
|
+ size_t in_left;
|
|
|
+ size_t count_written;
|
|
|
+ size_t count_read;
|
|
|
+
|
|
|
+ in_left = len_text - in_pos;
|
|
|
+ out_ptr = out_buffer;
|
|
|
+ out_len = SDL_arraysize(out_buffer);
|
|
|
+ SDLTest_AssertPass("About to call SDL_iconv(cd, %s+%d, .., dest, ..)", text_str, (int)in_pos);
|
|
|
+ iconv_result = SDL_iconv(cd, &in_ptr, &in_left, &out_ptr, &out_len);
|
|
|
+ count_written = SDL_arraysize(out_buffer) - out_len;
|
|
|
+ count_read = in_ptr - inputs[i].text - in_pos;
|
|
|
+ in_pos += count_read;
|
|
|
+
|
|
|
+ is_error = iconv_result == SDL_ICONV_ERROR
|
|
|
+ || iconv_result == SDL_ICONV_EILSEQ
|
|
|
+ || iconv_result == SDL_ICONV_EINVAL;
|
|
|
+ if (inputs[i].expect_success) {
|
|
|
+ SDLTest_AssertCheck(!is_error, "result must NOT be an error code");
|
|
|
+ SDLTest_AssertCheck(count_written > 0 || inputs[i].expected[out_pos] == '\0', "%" SDL_PRIu64 " bytes have been written", (Uint64)count_written);
|
|
|
+ SDLTest_AssertCheck(out_pos <= SDL_strlen(inputs[i].expected), "Data written by SDL_iconv cannot be longer then reference output");
|
|
|
+ SDLTest_CompareMemory(out_buffer, count_written, inputs[i].expected + out_pos, count_written);
|
|
|
+ } else {
|
|
|
+ SDLTest_AssertCheck(is_error, "result must be an error code");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ out_pos += count_written;
|
|
|
+ if (count_written == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (count_read == 0) {
|
|
|
+ SDLTest_AssertCheck(SDL_FALSE, "SDL_iconv wrote data, but read no data");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (!is_error && in_pos < len_text);
|
|
|
+
|
|
|
+ SDLTest_AssertPass("About to call SDL_iconv_close(cd)");
|
|
|
+ r = SDL_iconv_close(cd);
|
|
|
+ if (inputs[i].expect_success) {
|
|
|
+ SDLTest_AssertCheck(r == 0, "result must be 0");
|
|
|
+ } else {
|
|
|
+ SDLTest_AssertCheck(r == -1, "result must be -1");
|
|
|
+ }
|
|
|
+
|
|
|
+ SDLTest_AssertPass("About to call SDL_iconv_string(%s, %s, %s, %" SDL_PRIu64 ")",
|
|
|
+ to_encoding_str, from_encoding_str, text_str, (Uint64)len_text);
|
|
|
+ output = SDL_iconv_string(inputs[i].to_encoding, inputs[i].from_encoding, inputs[i].text, len_text);
|
|
|
+ if (inputs[i].expect_success) {
|
|
|
+ SDLTest_AssertCheck(output != NULL, "result must NOT be NULL");
|
|
|
+ SDLTest_AssertCheck(SDL_strncmp(inputs[i].expected, output, SDL_strlen(inputs[i].expected)) == 0,
|
|
|
+ "converted string should be correct");
|
|
|
+ } else {
|
|
|
+ SDLTest_AssertCheck(output == NULL, "result must be NULL");
|
|
|
+ }
|
|
|
+ SDL_free(output);
|
|
|
+ }
|
|
|
+
|
|
|
+ return TEST_COMPLETED;
|
|
|
+}
|
|
|
+
|
|
|
/* ================= Test References ================== */
|
|
|
|
|
|
/* Standard C routine test cases */
|
|
@@ -1103,6 +1227,10 @@ static const SDLTest_TestCaseReference stdlibTestOverflow = {
|
|
|
stdlib_overflow, "stdlib_overflow", "Overflow detection", TEST_ENABLED
|
|
|
};
|
|
|
|
|
|
+static const SDLTest_TestCaseReference stdlibIconv = {
|
|
|
+ stdlib_iconv, "stdlib_iconv", "Calls to iconv", TEST_ENABLED
|
|
|
+};
|
|
|
+
|
|
|
/* Sequence of Standard C routine test cases */
|
|
|
static const SDLTest_TestCaseReference *stdlibTests[] = {
|
|
|
&stdlibTest_strnlen,
|
|
@@ -1114,6 +1242,7 @@ static const SDLTest_TestCaseReference *stdlibTests[] = {
|
|
|
&stdlibTest_sscanf,
|
|
|
&stdlibTest_aligned_alloc,
|
|
|
&stdlibTestOverflow,
|
|
|
+ &stdlibIconv,
|
|
|
NULL
|
|
|
};
|
|
|
|