/* * Helper application to test internal library error reporting. * Copyright © 2023 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "cdecl-internal.h" #include "cdecl.h" #include "errmsg.h" #include "tap.h" #if ENABLE_NLS void cdecl__init_i18n(void) { } #endif static char *fmt_char(int c, char *buf) { int escape = 0; switch (c) { case '\a': escape = 'a'; break; case '\b': escape = 'b'; break; case '\t': escape = 't'; break; case '\n': escape = 'n'; break; case '\v': escape = 'v'; break; case '\f': escape = 'f'; break; case '\r': escape = 'r'; break; case '\\': escape = '\\'; break; case '\'': escape = '\''; break; } if (escape) sprintf(buf, "'\\%c'", escape); else if (isprint((unsigned char)c)) sprintf(buf, "'%c'", c); else sprintf(buf, "'\\%.3o'", c & 0777u); return buf; } static void check_fixed_string(size_t len) { const struct cdecl_error *err; char *work1, *work2; size_t errlen; assert(len > 0); work1 = calloc(2, len); if (!work1) abort(); work2 = work1 + len; memset(work1, 'X', len - 1); memset(work2, 'X', len - 1); tap_diag("cdecl__err w/ %lu-byte string", (unsigned long)len); cdecl__err(1234, work1); memset(work1, 0, len); err = cdecl_get_error(); if (!tap_result(err->code == 1234, "returned error code")) { tap_diag("Failed, unexpected result"); tap_diag(" Received: %u", err->code); tap_diag(" Expected: 1234"); } errlen = strlen(err->str); if (!tap_result(errlen == len-1, "returned string length")) { tap_diag("Failed, unexpected result"); tap_diag(" Received: %lu", (unsigned long)errlen); tap_diag(" Expected: %lu", (unsigned long)len); } if (!tap_result(!memcmp(err->str, work2, len), "returned string")) { char buf[8]; size_t n; n = strspn(err->str, "X"); if (n >= len) n = len; tap_diag("Failed, first incorrect character at offset %lu", (unsigned long)n); tap_diag(" Received: %s", fmt_char(err->str[n], buf)); tap_diag(" Expected: %s", fmt_char(work2[n], buf)); } free(work1); } static void check_enomem() { const char expmsg[] = "failed to allocate memory"; const struct cdecl_error *err; tap_diag("cdecl__errmsg(CDECL__ENOMEM)"); cdecl__errmsg(CDECL__ENOMEM); err = cdecl_get_error(); if (!tap_result(err->code == CDECL_ENOMEM, "returned error code")) { tap_diag("Failed, unexpected result"); tap_diag(" Received: %u", err->code); tap_diag(" Expected: %d", CDECL_ENOMEM); } if (!tap_result(!strcmp(err->str, "failed to allocate memory"), "returned string")) { unsigned i; for (i = 0; i < sizeof expmsg; i++) { if (err->str[i] != expmsg[i]) break; } tap_diag("Failed, first incorrect character at offset %u", i); tap_diag(" Received: %.*s", (int)sizeof expmsg, err->str); tap_diag(" Expected: %s", expmsg); } } int main(void) { tap_plan(3*3 + 2); check_fixed_string(50); check_fixed_string(500); check_fixed_string(5000); check_enomem(); tap_done(); }