gtk2/testsuite/gtk/composetable.c
Martin Kühl a9d7282f00 gtkcomposetable: Accept long replacement strings
This change removes the assertions limiting replacement strings in the compose table to be less than 20 characters.
The limit seems arbitrary, is not required, will break some users' setups, and problems with it result in applications not launching.

Fixes #4273
2021-09-21 17:03:20 +02:00

449 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <gtk/gtk.h>
#include <locale.h>
#include <glib/gstdio.h>
#include "../gtk/gtkcomposetable.h"
#include "../gtk/gtkimcontextsimpleseqs.h"
#include "testsuite/testutils.h"
static void
append_escaped (GString *str,
const char *s)
{
for (const char *p = s; *p; p = g_utf8_next_char (p))
{
gunichar ch = g_utf8_get_char (p);
if (ch == '"')
g_string_append (str, "\\\"");
else if (ch == '\\')
g_string_append (str, "\\\\");
else if (g_unichar_isprint (ch))
g_string_append_unichar (str, ch);
else
{
guint n[8] = { 0, };
int i = 0;
while (ch != 0)
{
n[i++] = ch & 7;
ch = ch >> 3;
}
for (; i >= 0; i--)
g_string_append_printf (str, "\\%o", n[i]);
}
}
}
static void
print_sequence (gunichar *sequence,
int len,
const char *value,
gpointer data)
{
GString *str = data;
for (int j = 0; j < len; j++)
g_string_append_printf (str, "<U%x> ", sequence[j]);
g_string_append (str, ": \"");
append_escaped (str, value);
g_string_append (str, "\"");
if (g_utf8_strlen (value, -1) == 1)
{
gunichar ch = g_utf8_get_char (value);
g_string_append_printf (str, " # U%x", ch);
}
g_string_append_c (str, '\n');
}
static char *
gtk_compose_table_print (GtkComposeTable *table)
{
GString *str;
str = g_string_new ("");
g_string_append_printf (str, "# n_sequences: %d\n# max_seq_len: %d\n# n_index_size: %d\n# data_size: %d\n# n_chars: %d\n",
table->n_sequences,
table->max_seq_len,
table->n_index_size,
table->data_size,
table->n_chars);
gtk_compose_table_foreach (table, print_sequence, str);
return g_string_free (str, FALSE);
}
static void
generate_output (const char *file)
{
GtkComposeTable *table;
char *output;
table = gtk_compose_table_parse (file, NULL);
output = gtk_compose_table_print (table);
g_print ("%s", output);
}
static void
compose_table_compare (gconstpointer data)
{
const char *basename = data;
GtkComposeTable *table;
char *file;
char *expected;
char *output;
char *diff;
GError *error = NULL;
file = g_test_build_filename (G_TEST_DIST, "compose", basename, NULL);
expected = g_strconcat (file, ".expected", NULL);
table = gtk_compose_table_parse (file, NULL);
output = gtk_compose_table_print (table);
diff = diff_with_file (expected, output, -1, &error);
g_assert_no_error (error);
if (diff && diff[0])
{
g_print ("Resulting output doesn't match reference:\n%s", diff);
g_test_fail ();
}
g_free (output);
g_free (file);
g_free (expected);
}
static void
compose_table_cycle (void)
{
if (g_test_subprocess ())
{
char *file;
GtkComposeTable *table;
file = g_test_build_filename (G_TEST_DIST, "compose", "cycle", NULL);
table = gtk_compose_table_parse (file, NULL);
g_assert_nonnull (table);
g_free (file);
return;
}
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_stderr ("*include cycle detected*");
g_test_trap_assert_failed ();
}
static void
compose_table_nofile (void)
{
if (g_test_subprocess ())
{
char *file;
GtkComposeTable *table;
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "nofile", NULL);
table = gtk_compose_table_parse (file, NULL);
g_assert_nonnull (table);
g_free (file);
return;
}
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_stderr ("*No such file or directory*");
g_test_trap_assert_failed ();
}
/* Check matching against a small table */
static void
compose_table_match (void)
{
GtkComposeTable *table;
char *file;
guint buffer[8] = { 0, };
gboolean finish, match, ret;
GString *output;
output = g_string_new ("");
file = g_build_filename (g_test_get_dir (G_TEST_DIST), "compose", "match", NULL);
table = gtk_compose_table_parse (file, NULL);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = 0;
ret = gtk_compose_table_check (table, buffer, 1, &finish, &match, output);
g_assert_true (ret);
g_assert_false (finish);
g_assert_false (match);
g_assert_true (output->len == 0);
buffer[0] = GDK_KEY_a;
buffer[1] = 0;
ret = gtk_compose_table_check (table, buffer, 1, &finish, &match, output);
g_assert_false (ret);
g_assert_false (finish);
g_assert_false (match);
g_assert_true (output->len == 0);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = GDK_KEY_s;
buffer[2] = GDK_KEY_e;
ret = gtk_compose_table_check (table, buffer, 3, &finish, &match, output);
g_assert_true (ret);
g_assert_false (finish);
g_assert_false (match);
g_assert_true (output->len == 0);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = GDK_KEY_s;
buffer[2] = GDK_KEY_e;
buffer[3] = GDK_KEY_q;
ret = gtk_compose_table_check (table, buffer, 4, &finish, &match, output);
g_assert_true (ret);
g_assert_false (finish);
g_assert_true (match);
g_assert_cmpstr (output->str, ==, "!");
g_string_set_size (output, 0);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = GDK_KEY_s;
buffer[2] = GDK_KEY_e;
buffer[3] = GDK_KEY_q;
buffer[4] = GDK_KEY_u;
ret = gtk_compose_table_check (table, buffer, 5, &finish, &match, output);
g_assert_true (ret);
g_assert_true (finish);
g_assert_true (match);
g_assert_cmpstr (output->str, ==, "?");
g_string_set_size (output, 0);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = GDK_KEY_l;
buffer[2] = GDK_KEY_o;
buffer[3] = GDK_KEY_n;
buffer[4] = GDK_KEY_g;
ret = gtk_compose_table_check (table, buffer, 5, &finish, &match, output);
g_assert_true (ret);
g_assert_true (finish);
g_assert_true (match);
g_assert_cmpstr (output->str, ==, "this is a long replacement string");
g_string_free (output, TRUE);
g_free (file);
}
extern const GtkComposeTable builtin_compose_table;
/* just check some random sequences */
static void
compose_table_match_builtin (void)
{
const GtkComposeTable *table = &builtin_compose_table;
guint buffer[8] = { 0, };
gboolean finish, match, ret;
GString *s;
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = 0;
s = g_string_new ("");
ret = gtk_compose_table_check (table, buffer, 1, &finish, &match, s);
g_assert_true (ret);
g_assert_false (finish);
g_assert_false (match);
g_assert_true (s->len == 0);
buffer[0] = GDK_KEY_a;
buffer[1] = GDK_KEY_b;
buffer[2] = GDK_KEY_c;
buffer[3] = 0;
ret = gtk_compose_table_check (table, buffer, 3, &finish, &match, s);
g_assert_false (ret);
g_assert_false (finish);
g_assert_false (match);
g_assert_true (s->len == 0);
buffer[0] = GDK_KEY_Multi_key;
buffer[1] = GDK_KEY_parenleft;
buffer[2] = GDK_KEY_j;
buffer[3] = GDK_KEY_parenright;
buffer[4] = 0;
ret = gtk_compose_table_check (table, buffer, 4, &finish, &match, s);
g_assert_true (ret);
g_assert_true (finish);
g_assert_true (match);
g_assert_cmpstr (s->str, ==, ""); /* CIRCLED LATIN SMALL LETTER J */
buffer[0] = GDK_KEY_dead_acute;
buffer[1] = GDK_KEY_space;
buffer[2] = 0;
g_string_set_size (s, 0);
ret = gtk_compose_table_check (table, buffer, 2, &finish, &match, s);
g_assert_true (ret);
g_assert_true (finish);
g_assert_true (match);
g_assert_cmpstr (s->str, ==, "'");
buffer[0] = GDK_KEY_dead_acute;
buffer[1] = GDK_KEY_dead_acute;
buffer[2] = 0;
g_string_set_size (s, 0);
ret = gtk_compose_table_check (table, buffer, 2, &finish, &match, s);
g_assert_true (ret);
g_assert_true (finish);
g_assert_true (match);
g_assert_cmpstr (s->str, ==, "´");
g_string_free (s, TRUE);
}
static void
match_algorithmic (void)
{
guint buffer[8] = { 0, };
gboolean ret;
GString *output;
output = g_string_new ("");
buffer[0] = GDK_KEY_a;
buffer[1] = GDK_KEY_b;
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_false (ret);
g_assert_cmpstr (output->str, ==, "");
buffer[0] = GDK_KEY_dead_abovering;
buffer[1] = GDK_KEY_A;
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "Å");
buffer[0] = GDK_KEY_A;
buffer[1] = GDK_KEY_dead_abovering;
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_false (ret);
g_assert_cmpstr (output->str, ==, "");
buffer[0] = GDK_KEY_dead_dasia;
buffer[1] = GDK_KEY_dead_perispomeni;
buffer[2] = GDK_KEY_Greek_alpha;
ret = gtk_check_algorithmically (buffer, 3, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "\xcc\x94");
buffer[0] = GDK_KEY_dead_perispomeni;
buffer[1] = GDK_KEY_dead_dasia;
buffer[2] = GDK_KEY_Greek_alpha;
ret = gtk_check_algorithmically (buffer, 3, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "");
buffer[0] = GDK_KEY_dead_acute;
buffer[1] = GDK_KEY_dead_cedilla;
buffer[2] = GDK_KEY_c;
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "");
ret = gtk_check_algorithmically (buffer, 3, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "");
buffer[0] = GDK_KEY_dead_cedilla;
buffer[1] = GDK_KEY_dead_acute;
buffer[2] = GDK_KEY_c;
ret = gtk_check_algorithmically (buffer, 3, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "");
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_true (ret);
buffer[0] = GDK_KEY_dead_acute;
buffer[1] = GDK_KEY_dead_cedilla;
buffer[2] = GDK_KEY_dead_grave;
ret = gtk_check_algorithmically (buffer, 3, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "");
buffer[0] = GDK_KEY_dead_diaeresis;
buffer[1] = GDK_KEY_a;
ret = gtk_check_algorithmically (buffer, 2, output);
g_assert_true (ret);
g_assert_cmpstr (output->str, ==, "ä");
g_string_free (output, TRUE);
}
int
main (int argc, char *argv[])
{
if (argc == 3 && strcmp (argv[1], "--generate") == 0)
{
gtk_disable_setlocale();
setlocale (LC_ALL, "en_US.UTF-8");
gtk_init ();
/* Ensure that the builtin table is initialized */
GtkIMContext *ctx = gtk_im_context_simple_new ();
g_object_unref (ctx);
generate_output (argv[2]);
return 0;
}
gtk_test_init (&argc, &argv, NULL);
/* Ensure that the builtin table is initialized */
GtkIMContext *ctx = gtk_im_context_simple_new ();
g_object_unref (ctx);
g_test_add_data_func ("/compose-table/basic", "basic", compose_table_compare);
g_test_add_data_func ("/compose-table/long", "long", compose_table_compare);
g_test_add_data_func ("/compose-table/octal", "octal", compose_table_compare);
g_test_add_data_func ("/compose-table/hex", "hex", compose_table_compare);
g_test_add_data_func ("/compose-table/codepoint", "codepoint", compose_table_compare);
g_test_add_data_func ("/compose-table/multi", "multi", compose_table_compare);
g_test_add_data_func ("/compose-table/strings", "strings", compose_table_compare);
g_test_add_data_func ("/compose-table/include", "include", compose_table_compare);
g_test_add_data_func ("/compose-table/system", "system", compose_table_compare);
g_test_add_func ("/compose-table/include-cycle", compose_table_cycle);
g_test_add_func ("/compose-table/include-nofile", compose_table_nofile);
g_test_add_func ("/compose-table/match", compose_table_match);
g_test_add_func ("/compose-table/match-builtin", compose_table_match_builtin);
g_test_add_func ("/compose-table/match-algorithmic", match_algorithmic);
return g_test_run ();
}