diff options
author | Peng Wu <pwu@redhat.com> | 2019-11-28 17:38:00 +0800 |
---|---|---|
committer | Peng Wu <pwu@redhat.com> | 2020-02-19 16:26:45 +0800 |
commit | fe036d04c3c56904ceb020eb3793434170eb3d2b (patch) | |
tree | 44a5d3893afc8fb6e537d615caa48972487b6f7d | |
parent | 0c7769929c46e8e81c2fabaae638c73604e5042e (diff) | |
download | ibus-hangul-fe036d04c3c56904ceb020eb3793434170eb3d2b.tar.gz |
Write ibus-hangul.c test case
-rw-r--r-- | tests/ibus-hangul.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/tests/ibus-hangul.c b/tests/ibus-hangul.c new file mode 100644 index 0000000..4375f90 --- /dev/null +++ b/tests/ibus-hangul.c @@ -0,0 +1,322 @@ +#include <unistd.h> +#include <gtk/gtk.h> +#include "ibus.h" +#include "engine.h" + +#define GREEN "\033[0;32m" +#define RED "\033[0;31m" +#define NC "\033[0m" + +typedef struct { + const gchar * input; + const gchar * output; +}TestCase; + +IBusBus *m_bus; +IBusEngine *m_engine; +gchar *m_srcdir; + +IBusKeymap *keymap = NULL; + +const guint m_switch_hangul[3] = {IBUS_Hangul, 122, 0}; + +const TestCase m_test_cases[] = +{ + {"rk ", "가"} +}; + +static gboolean window_focus_in_event_cb (GtkWidget *entry, + GdkEventFocus *event, + gpointer data); + +static guint16 guess_keycode (IBusKeymap *keymap, + guint keyval, + guint32 modifiers) +{ + /* The IBusKeymap only have 256 entries here, + Use Brute Force method to get keycode from keyval. */ + guint16 keycode = 0; + for (; keycode < 256; ++keycode) { + if (keyval == ibus_keymap_lookup_keysym (keymap, keycode, modifiers)) + return keycode; + } + return 0; +} + +static IBusEngine * +create_engine_cb (IBusFactory *factory, + const gchar *name, + gpointer data) +{ + static int i = 1; + gchar *engine_path = + g_strdup_printf ("/org/freedesktop/IBus/engine/hangultest/%d", + i++); + + m_engine = ibus_engine_new_with_type (IBUS_TYPE_HANGUL_ENGINE, + name, + engine_path, + ibus_bus_get_connection (m_bus)); + g_free (engine_path); + + return m_engine; +} + +static gboolean +register_ibus_engine () +{ + IBusFactory *factory; + IBusComponent *component; + IBusEngineDesc *desc; + + m_bus = ibus_bus_new (); + if (!ibus_bus_is_connected (m_bus)) { + g_critical ("ibus-daemon is not running."); + return FALSE; + } + factory = ibus_factory_new (ibus_bus_get_connection (m_bus)); + g_signal_connect (factory, "create-engine", + G_CALLBACK (create_engine_cb), NULL); + + component = ibus_component_new ( + "org.freedesktop.IBus.HangulTest", + "Hangul Engine Test", + "1.5.1", + "GPL", + "Peng Huang <shawn.p.huang@gmail.com>", + "https://github.com/ibus/ibus/wiki", + "", + "ibus-hangul"); + desc = ibus_engine_desc_new ( + "hangultest", + "Hangul Test", + "Hangul Test", + "en", + "GPL", + "Peng Huang <shawn.p.huang@gmail.com>", + "ibus-hangul", + "us"); + ibus_component_add_engine (component, desc); + ibus_bus_register_component (m_bus, component); + + return TRUE; +} + +static gboolean +finit (gpointer data) +{ + g_test_incomplete ("time out"); + gtk_main_quit (); + return FALSE; +} + +static void +set_engine_cb (GObject *object, GAsyncResult *res, gpointer data) +{ + IBusBus *bus = IBUS_BUS (object); + GtkWidget *entry = GTK_WIDGET (data); + GError *error = NULL; + gint i; + const gchar *p = NULL; + + if (!ibus_bus_set_global_engine_async_finish (bus, res, &error)) { + gchar *msg = g_strdup_printf ("set engine failed: %s", error->message); + g_test_incomplete (msg); + g_free (msg); + g_error_free (error); + return; + } + + { + /* Switch hangul mode. */ + guint keyval = m_switch_hangul[0]; + guint keycode = m_switch_hangul[1]; + guint modifiers = m_switch_hangul[2]; + gboolean retval; + + if (keyval == 0) { + g_test_incomplete ("ibus-hangul switch key is not set correctly."); + return; + } + g_signal_emit_by_name (m_engine, "process-key-event", + keyval, keycode, modifiers, &retval); + modifiers |= IBUS_RELEASE_MASK; + sleep(1); + g_signal_emit_by_name (m_engine, "process-key-event", + keyval, keycode, modifiers, &retval); + } + + { + /* Run test cases */ + for (i = 0; + i < G_N_ELEMENTS(m_test_cases); + i++) { + for (p = m_test_cases[i].input; *p; p++) { + gboolean retval; + guint keyval = *p; + guint modifiers = 0; + guint keycode = guess_keycode (keymap, keyval, modifiers); + + if (keyval == 0) + break; + g_signal_emit_by_name (m_engine, "process-key-event", + keyval, keycode, modifiers, &retval); + modifiers |= IBUS_RELEASE_MASK; + sleep(1); + g_signal_emit_by_name (m_engine, "process-key-event", + keyval, keycode, modifiers, &retval); + } + } + } + + g_signal_handlers_disconnect_by_func (entry, + G_CALLBACK (window_focus_in_event_cb), + NULL); + g_timeout_add_seconds (10, finit, NULL); +} + +static gboolean +window_focus_in_event_cb (GtkWidget *entry, GdkEventFocus *event, gpointer data) +{ + g_assert (m_bus != NULL); + ibus_bus_set_global_engine_async (m_bus, + "hangultest", + -1, + NULL, + set_engine_cb, + entry); + return FALSE; +} + +static void +window_inserted_text_cb (GtkEntryBuffer *buffer, + guint position, + const gchar *chars, + guint nchars, + gpointer data) +{ +/* https://gitlab.gnome.org/GNOME/gtk/commit/9981f46e0b + * The latest GTK does not emit "inserted-text" when the text is "". + */ +#if !GTK_CHECK_VERSION (3, 22, 16) + static int n_loop = 0; +#endif + static guint index = 0; + gunichar code = g_utf8_get_char (chars); + const gchar *test; + GtkEntry *entry = GTK_ENTRY (data); + +#if !GTK_CHECK_VERSION (3, 22, 16) + if (n_loop % 2 == 1) { + n_loop = 0; + return; + } +#endif + + { + /* Run test case */ + const gchar *p = chars; + const gchar *output = m_test_cases[index].output; + guint j = 0; + gboolean valid_output = TRUE; + + if (0 != g_strcmp0 (p, output)) + valid_output = FALSE; + index++; + + if (valid_output) { + test = GREEN "PASS" NC; + } else { + test = RED "FAIL" NC; + g_test_fail (); + } + g_print ("%05d %s expected: %s typed: %s\n", + index, test, output, p); + } + + if (index == G_N_ELEMENTS(m_test_cases)) { + gtk_main_quit (); + return; + } + +#if !GTK_CHECK_VERSION (3, 22, 16) + n_loop++; +#endif + gtk_entry_set_text (entry, ""); +} + +static void +create_window () +{ + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + GtkWidget *entry = gtk_entry_new (); + GtkEntryBuffer *buffer; + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + g_signal_connect (entry, "focus-in-event", + G_CALLBACK (window_focus_in_event_cb), NULL); + buffer = gtk_entry_get_buffer (GTK_ENTRY (entry)); + g_signal_connect (buffer, "inserted-text", + G_CALLBACK (window_inserted_text_cb), entry); + gtk_container_add (GTK_CONTAINER (window), entry); + gtk_widget_show_all (window); +} + +static void +test_hangul (void) +{ + GLogLevelFlags flags; + if (!register_ibus_engine ()) { + g_test_fail (); + return; + } + + ibus_hangul_init (m_bus); + + create_window (); + /* FIXME: + * IBusIMContext opens GtkIMContextSimple as the slave and + * GtkIMContextSimple opens the compose table on el_GR.UTF-8, and the + * multiple outputs in el_GR's compose causes a warning in gtkcomposetable + * and the warning always causes a fatal in GTest: + " "GTK+ supports to output one char only: " + */ + flags = g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); + gtk_main (); + g_log_set_always_fatal (flags); +} + +int +main (int argc, char *argv[]) +{ + const gchar *test_name; + gchar *test_path; + + /* Run test cases with X Window. */ + g_setenv ("GDK_BACKEND", "x11", TRUE); + + ibus_init (); + /* Avoid a warning of "AT-SPI: Could not obtain desktop path or name" + * with gtk_main(). + */ + g_setenv ("NO_AT_BRIDGE", "1", TRUE); + g_test_init (&argc, &argv, NULL); + gtk_init (&argc, &argv); + + m_srcdir = argc > 1 ? g_strdup (argv[1]) : g_strdup ("."); + +#if GLIB_CHECK_VERSION (2, 58, 0) + test_name = g_get_language_names_with_category ("LC_CTYPE")[0]; +#else + test_name = g_getenv ("LANG"); +#endif + + test_path = g_build_filename ("/ibus-hangul", test_name, NULL); + g_test_add_func (test_path, test_hangul); + g_free (test_path); + + keymap = ibus_keymap_get("us"); + + return g_test_run (); +} |