From: Michael Orlitzky Date: Sat, 4 Jul 2026 20:07:57 +0000 (-0400) Subject: main.c: begin adding real tests X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=650cb40491a4a95bb610bb0a933be53cd4f0e635;p=iconv-quirks.git main.c: begin adding real tests --- diff --git a/main.c b/main.c index fb4f9bd..38df478 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ -#include #include #include +#include +#include /* The various invalid sequences can be inferred from the table of * valid ones, @@ -27,15 +28,15 @@ * (d) 0xC0, 0xC1, 0xF5-0xFF are never valid */ -#define ICONV_OPEN_FAILED 1 -#define ICONV_CLOSE_FAILED 2 +#define SUCCESS 0 +#define FAILURE 1 -int main(int argc, char** argv) { - const char* tocode = "UTF-8"; - const char* fromcode = "UTF-8"; - - iconv_t cd = iconv_open(tocode, fromcode); - if (cd == (iconv_t)(-1)) { +/* Open a conversion descriptor by reference. Wraps the boilerplate + * error reporting when iconv_open() fails. + */ +int _my_iconv_open(iconv_t* cd, const char *tocode, const char *fromcode) { + *cd = iconv_open(tocode, fromcode); + if (*cd == (iconv_t)(-1)) { /* The errno values are standard, but we have no way of knowing * if the implementation follows the standard! */ fprintf(stderr, @@ -56,15 +57,20 @@ int main(int argc, char** argv) { fprintf(stderr, "EINVAL"); break; default: - fprintf(stderr, "UNKNOWN"); + fprintf(stderr, "UNKNOWN (%d)", errno); } fprintf(stderr, "\n"); - return ICONV_OPEN_FAILED; + return FAILURE; } - /* actual conversion takes place here */ + return SUCCESS; +} - if (iconv_close(cd) == -1) { +/* Close a conversion descriptor by reference. Wraps the boilerplate + * error reporting when iconv_close() fails. + */ +int _my_iconv_close(iconv_t* cd) { + if (iconv_close(*cd) == -1) { /* The underlying type of iconv_t is unspecified, so we can't * easily print the argument here. */ fprintf(stderr, "ERROR: iconv_close() returned "); @@ -73,11 +79,156 @@ int main(int argc, char** argv) { fprintf(stderr, "EBADF"); break; default: - fprintf(stderr, "UNKNOWN"); + fprintf(stderr, "UNKNOWN (%d)", errno); } fprintf(stderr, "\n"); - return ICONV_CLOSE_FAILED; + return FAILURE; + } + + return SUCCESS; +} + +/* + * Open and close a conversion descriptor (basic sanity test). + */ +int test_open_close() { + iconv_t cd; + const char* tocode = "ASCII"; + const char* fromcode = "ASCII"; + + printf("can iconv_open() and iconv_close() a conversion descriptor..."); + if (_my_iconv_open(&cd, tocode, fromcode) == FAILURE) { + printf("FAIL\n"); + return FAILURE; + } + + if (_my_iconv_close(&cd) == SUCCESS) { + printf("OK\n"); + } + else { + printf("FAIL\n"); + return FAILURE; + } + + + return SUCCESS; +} + + +/* + * Ensure that iconv_open() supports the given indicator suffix. + */ +int test_iconv_open_supports_suffix(const char* suffix) { + const char* fromcode = "ASCII"; + char tocode[64] = "ASCII"; + strcat(tocode, suffix); + + printf("iconv_open() supports %s suffix...", suffix); + iconv_t cd = iconv_open(tocode, fromcode); + if (cd == (iconv_t)(-1)) { + switch (errno) { + case EINVAL: + printf("OK (EINVAL, not supported)\n"); + return SUCCESS; + default: + printf("FAIL (errno=%d, unexpected error)\n", errno); + return FAILURE; + } + } + printf("yes\n"); + iconv_close(cd); + return SUCCESS; +} + + +/* + * Check that iconv_open() fails with EINVAL when given a bogus + * indicator suffix. + */ +int test_iconv_open_does_not_support_invalid_suffix() { + const char* fromcode = "ASCII"; + const char* tocode = "ASCII//INVALID"; + + printf("iconv_open() does not support //INVALID..."); + iconv_t cd = iconv_open(tocode, fromcode); + if (cd == (iconv_t)(-1)) { + switch (errno) { + case EINVAL: + printf("OK (EINVAL, expected)\n"); + return SUCCESS; + default: + printf("FAIL (errno=%d, unexpected)\n", errno); + return FAILURE; + } } + printf("FAIL (invalid suffix was accepted)\n"); + iconv_close(cd); + return FAILURE; +} + + +int test_iconv_open_does_not_support_invalid_to_codeset() { + const char* fromcode = "ASCII"; + const char* tocode = "ASDJFI$@#%t234tWER"; + + printf("iconv_open() does not support invalid \"to\" codeset..."); + iconv_t cd = iconv_open(tocode, fromcode); + if (cd == (iconv_t)(-1)) { + switch (errno) { + case EINVAL: + printf("OK (EINVAL, expected)\n"); + return SUCCESS; + default: + printf("FAIL (errno=%d, unexpected)\n", errno); + return FAILURE; + } + } + printf("FAIL (invalid codeset was accepted)\n"); + iconv_close(cd); + return FAILURE; +} + +int test_iconv_open_does_not_support_invalid_from_codeset() { + const char* fromcode = "ASDJFI$@#%t234tWER"; + const char* tocode = "ASCII"; + + printf("iconv_open() does not support invalid \"from\" codeset..."); + iconv_t cd = iconv_open(tocode, fromcode); + if (cd == (iconv_t)(-1)) { + switch (errno) { + case EINVAL: + printf("OK (EINVAL, expected)\n"); + return SUCCESS; + default: + printf("FAIL (errno=%d, unexpected)\n", errno); + return FAILURE; + } + } + printf("FAIL (invalid codeset was accepted)\n"); + iconv_close(cd); + return FAILURE; +} + +int main(int argc, char** argv) { + int result = test_open_close(); + + /* These three are named explicitly by POSIX which says that you are + * free to append them to the destination codeset, but support is + * not guaranteed; iconv_open() is allowed to fail with an EINVAL + * to indicate an unsupported suffix. */ + result |= test_iconv_open_supports_suffix("//IGNORE"); + result |= test_iconv_open_supports_suffix("//NON_IDENTICAL_DISCARD"); + result |= test_iconv_open_supports_suffix("//TRANSLIT"); + + /* The supported codeset names and suffixes are implementation- + * defined, making this a bit ambiguous, but POSIX declares EINVAL + * to be the error code associated with unrecognized or unsupported + * values. (This doesn't stop an implementation from "supporting" + * invalid values by ignoring them, but for now let's assume no one + * is doing that.) */ + result |= test_iconv_open_does_not_support_invalid_suffix(); + result |= test_iconv_open_does_not_support_invalid_to_codeset(); + result |= test_iconv_open_does_not_support_invalid_from_codeset(); - return 0; + return result; }