197 lines
4.6 KiB
C
197 lines
4.6 KiB
C
|
/*
|
||
|
textprint: Test filtering of text before terminal printout.
|
||
|
|
||
|
copyright 2019-2020 by the mpg123 project
|
||
|
free software under the terms of the LGPL 2.1
|
||
|
|
||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||
|
initially written by Thomas Orgis
|
||
|
*/
|
||
|
|
||
|
#include "../mpg123app.h"
|
||
|
#include "../local.h"
|
||
|
|
||
|
// A number of UTF-8 strings to test.
|
||
|
|
||
|
struct test_string
|
||
|
{
|
||
|
const char* in; // UTF-8 input including control chars etc.
|
||
|
const char* ascii; // output reduced to ASCII
|
||
|
const char* utf8hack; // output in UTF-8 without controls, hacked
|
||
|
const char* utf8full; // output in UTF-8 only including printing chars
|
||
|
size_t chars; // number of apparent characters (for utf8hack)
|
||
|
size_t width; // proper printing width
|
||
|
};
|
||
|
|
||
|
// const char *bla = "..." is not constant enoug to server as initializer.
|
||
|
#define simple_string "Just a plain string without trouble."
|
||
|
#define simple_width 36
|
||
|
// o-Umlaut and a random Chinese character
|
||
|
#define utf_string "St\xc3\xb6rt mein \xe7\x8c\x95?"
|
||
|
#define utf_string_ascii "St?rt mein ??"
|
||
|
#define utf_width 14
|
||
|
#define utf_chars 13
|
||
|
|
||
|
const struct test_string test_input[] =
|
||
|
{
|
||
|
{
|
||
|
.in=simple_string
|
||
|
, .ascii=simple_string
|
||
|
, .utf8hack=simple_string
|
||
|
, .utf8full=simple_string
|
||
|
, .chars=simple_width
|
||
|
, .width=simple_width
|
||
|
}
|
||
|
, {
|
||
|
.in="U\xcc\x88""bel\nist mir."
|
||
|
, .ascii="U?bel ist mir."
|
||
|
, .utf8hack="U\xcc\x88""bel ist mir."
|
||
|
, .utf8full="U\xcc\x88""bel ist mir."
|
||
|
, .chars=14
|
||
|
, .width=13
|
||
|
}
|
||
|
, {
|
||
|
.in=utf_string
|
||
|
, .ascii=utf_string_ascii
|
||
|
, .utf8hack=utf_string
|
||
|
, .utf8full=utf_string
|
||
|
, .chars=utf_chars
|
||
|
, .width=utf_width
|
||
|
}
|
||
|
, {
|
||
|
.in="Gimme\x0a some\x0a\x0d""con\302\237tr\xc3\xb6l!\x7f\x7f""b \033]0;xtermed\x07"
|
||
|
, .ascii="Gimme some contr?l!b ]0;xtermed"
|
||
|
, .utf8hack="Gimme some contr\xc3\xb6l!b ]0;xtermed"
|
||
|
, .utf8full="Gimme some contr\xc3\xb6l!b ]0;xtermed"
|
||
|
, .chars=33
|
||
|
, .width=33
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
char *dst = NULL;
|
||
|
const size_t test_count = sizeof(test_input)/sizeof(*test_input);
|
||
|
int err = 0;
|
||
|
|
||
|
// First, without any locale check, we should work like in C locale.
|
||
|
// Only ASCII is safe.
|
||
|
fprintf(stderr, "Testing plain ASCII world.\n");
|
||
|
for(size_t t=0; t<test_count; ++t)
|
||
|
{
|
||
|
int lerr = 0;
|
||
|
fprintf(stderr, "string %zu: ", t);
|
||
|
size_t w = utf8outstr(&dst, test_input[t].in, 1);
|
||
|
size_t l = strlen(test_input[t].ascii);
|
||
|
if(!dst)
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(conversion failed) ");
|
||
|
}
|
||
|
else if(w == l)
|
||
|
{
|
||
|
if(strcmp(test_input[t].ascii, dst))
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(mismatch) ");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(bad length %zu != %zu) ", w, l);
|
||
|
}
|
||
|
err += lerr;
|
||
|
fprintf(stderr, "%s\n", lerr ? "FAIL" : "PASS");
|
||
|
}
|
||
|
|
||
|
// Now, the internal UTF-8 sanitation is employed, assuming no working
|
||
|
// locale to help us.
|
||
|
utf8env = 1;
|
||
|
utf8loc = 0;
|
||
|
fprintf(stderr, "Testing hacked UTF-8 world.\n");
|
||
|
for(size_t t=0; t<test_count; ++t)
|
||
|
{
|
||
|
int lerr = 0;
|
||
|
fprintf(stderr, "string %zu: ", t);
|
||
|
size_t w = utf8outstr(&dst, test_input[t].in, 1);
|
||
|
size_t l = test_input[t].chars;
|
||
|
if(!dst)
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(conversion failed) ");
|
||
|
}
|
||
|
else if(w == l)
|
||
|
{
|
||
|
if(strcmp(test_input[t].utf8hack, dst))
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(mismatch) ");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(bad length %zu != %zu) ", w, l);
|
||
|
}
|
||
|
err += lerr;
|
||
|
fprintf(stderr, "%s\n", lerr ? "FAIL" : "PASS");
|
||
|
}
|
||
|
|
||
|
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCSWIDTH) && \
|
||
|
defined(HAVE_ISWPRINT) && defined(HAVE_WCSTOMBS)
|
||
|
// Finally, proper UTF-8 handling including iswprint() shall be undertaken.
|
||
|
// The test is skipped if there is no UTF-8 locale to work with.
|
||
|
utf8env = 0;
|
||
|
utf8loc = 0;
|
||
|
utf8force = 1;
|
||
|
check_locale();
|
||
|
if(utf8env && utf8loc)
|
||
|
{
|
||
|
fprintf(stderr, "Got locale, testing proper workings.\n");
|
||
|
for(size_t t=0; t<test_count; ++t)
|
||
|
{
|
||
|
int lerr = 0;
|
||
|
fprintf(stderr, "string %zu: ", t);
|
||
|
size_t w = utf8outstr(&dst, test_input[t].in, 1);
|
||
|
size_t l = test_input[t].width;
|
||
|
if(!dst)
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(conversion failed) ");
|
||
|
}
|
||
|
else if(w == l)
|
||
|
{
|
||
|
if(strcmp(test_input[t].utf8full, dst))
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(mismatch) ");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
++lerr;
|
||
|
fprintf(stderr, "(bad length %zu != %zu) ", w, l);
|
||
|
}
|
||
|
err += lerr;
|
||
|
fprintf(stderr, "%s\n", lerr ? "FAIL" : "PASS");
|
||
|
fprintf(stderr, "non-terminal non-filtering: ");
|
||
|
lerr = 0;
|
||
|
w = utf8outstr(&dst, test_input[t].in, 0);
|
||
|
if(!dst || strcmp(test_input[t].in, dst))
|
||
|
++lerr;
|
||
|
err += lerr;
|
||
|
fprintf(stderr, "%s\n", lerr ? "FAIL" : "PASS");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
fprintf(stderr, "Skipped locale-based conversion\n");
|
||
|
|
||
|
free(dst);
|
||
|
|
||
|
printf("%s\n", err ? "FAIL" : "PASS");
|
||
|
return err ? 1 : 0;
|
||
|
}
|