/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "test-config.h" #include #include "context.h" #include "darray.h" #include "log.h" #include "messages-codes.h" #include "test.h" #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wmissing-format-attribute" #endif static void test_basic(void) { int ret; ret = setenv("XKB_LOG_LEVEL", "warn", 1); assert(ret == 0); ret = setenv("XKB_LOG_VERBOSITY", "5", 1); assert(ret == 0); struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "first warning: %d\n", 87); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "first info\n"); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "first debug: %s\n", "hello"); log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "first error: %lu\n", 115415UL); log_vrb(ctx, 5, XKB_LOG_MESSAGE_NO_ID, "first verbose 5\n"); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_DEBUG); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "second warning: %d\n", 87); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "second debug: %s %s\n", "hello", "world"); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "second info\n"); log_err(ctx, XKB_ERROR_MALFORMED_NUMBER_LITERAL, "second error: %lu\n", 115415UL); log_vrb(ctx, 6, XKB_LOG_MESSAGE_NO_ID, "second verbose 6\n"); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_MINIMAL); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "third warning: %d\n", 87); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "third debug: %s %s\n", "hello", "world"); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "third info\n"); log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "third error: %lu\n", 115415UL); log_vrb(ctx, 0, XKB_LOG_MESSAGE_NO_ID, "third verbose 0\n"); printf("%s", darray_items(log_string)); assert(streq(darray_items(log_string), "warning: first warning: 87\n" "error: first error: 115415\n" "warning: first verbose 5\n" "warning: second warning: 87\n" "debug: second debug: hello world\n" "info: second info\n" "error: [XKB-034] second error: 115415\n")); xkb_context_unref(ctx); darray_free(log_string); } struct test_data { const char * const input; const char * const log; bool error; }; static void test_keymaps(void) { struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_WARNING); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_COMPREHENSIVE); const struct test_data keymaps[] = { { .input = "", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = " ", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "\n", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap {\n", .log = "error: [XKB-769] (input string):1:12: syntax error, unexpected end of file\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap \"\\j\"\n" " { xkb_symbols = {};\n" "};", .log = "warning: [XKB-645] (input string):1:12: unknown escape sequence \"\\j\" in string literal\n" "error: [XKB-769] (input string):2:16: syntax error, unexpected =, expecting {\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { [\"\xC3\xBC\xff\"] }; };\n" "};", .log = "error: [XKB-542] (input string):3:26: Cannot convert string to keysyms: Invalid UTF-8 encoding starting at byte position 3 (code point position: 2).\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, /* Extra lines & spaces intented to check the file positions */ { .input = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 1;\n" "\n" " alias <1> = <>;\n" " alias <1> =\n" " <>;\n" " };\n" " xkb_types \"\\400x\\j\" { };\n" " xkb_compat {\n" " interpret invalidKeysym +\n" " Any { repeat = true; };\n" " };\n" " xkb_symbols { key <> {[0x30, leftshoe]}; };\n" "};", .log = "warning: [XKB-193] (input string):9:13: invalid octal escape sequence \"\\400\" in string literal\n" "warning: [XKB-645] (input string):9:13: unknown escape sequence \"\\j\" in string literal\n" "warning: [XKB-107] (input string):11:15: unrecognized keysym \"invalidKeysym\"\n" "warning: [XKB-489] (input string):14:26: numeric keysym \"0x0030\" (48)\n" "warning: [XKB-301] (input string):14:32: deprecated keysym \"leftshoe\".\n" "warning: [XKB-523] Alias of <1> for <> declared more than once; First definition ignored\n" "warning: [XKB-286] The type \"TWO_LEVEL\" for key '<>' group 1 was not previously defined; Using the default type\n" "warning: [XKB-516] Type \"ONE_LEVEL\" has 1 levels, but <> has 2 levels; Ignoring extra symbols\n", .error = false }, /* Deprecated */ { .input = "default deprecated xkb_keymap {\n" " xkb_symbols {};\n" " deprecated xkb_types {};\n" "};", .log = "warning: [XKB-021] (input string):3:26: deprecated section: \"(unnamed map)\"\n", .error = false }, /* Invalid action fields */ { .input = "default xkb_keymap {\n" " xkb_compat {\n" " NoAction.data = 1;\n" " interpret VoidSymbol { action= VoidAction(data=); };\n" " };\n" "};", .log = "error: [XKB-563] The \"NoAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-563] The \"VoidAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: Failed to compile xkb_compatibility\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, /* Invalid action fields */ { .input = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols {\n" " NoAction.data = 1;\n" " key <> { [TerminateServer(data=)] };\n" " };\n" "};", .log = "error: [XKB-563] The \"NoAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-563] The \"Terminate\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-796] Illegal action definition for <>; Action for group 1/level 1 ignored\n" "error: Failed to compile xkb_symbols\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, /* Unsupported legacy X11 actions */ { .input = "default xkb_keymap {\n" " xkb_compat {\n" /* This is a valid entry */ " interpret ISO_Lock+AnyOf(all) {\n" " action= ISOLock(modifiers=modMapMods,affect=all);\n" " };\n" /* This uses invalid field, but we do not check fields of * legacy actions */ " interpret VoidSymbol+AnyOf(all) {\n" " action= DeviceButton(data=);\n" " };\n" " };\n" "};", .log = "warning: [XKB-362] Unsupported legacy action type \"ISOLock\".\n" "warning: [XKB-362] Unsupported legacy action type \"DeviceButton\".\n", .error = false }, /* Invalid global var */ { .input = "default xkb_keymap {\n" " xkb_keycodes { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_keycodes\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_types { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_types\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_compat { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_compatibility\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_symbols { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_symbols\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k].input, strlen(keymaps[k].input)); assert_printf(keymaps[k].error ^ !!keymap, "%s\n", darray_items(log_string)); xkb_keymap_unref(keymap); assert_printf(streq_not_null(darray_items(log_string), keymaps[k].log), "Expected:\n%s\nGot:\n%s\n", keymaps[k].log, darray_items(log_string)); darray_size(log_string) = 0; } xkb_context_unref(ctx); darray_free(log_string); } static void test_compose(void) { struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_WARNING); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_VERBOSE); const struct test_data composes[] = { { .input = "", .log = NULL, .error = false }, { .input = "\n", .log = NULL, .error = false }, { .input = "\xff\n", .log = "error: [XKB-542] (input string):1:1: unexpected non-ASCII character.\n" "error: [XKB-542] (input string):1:1: This could be a file encoding issue. Supported file encodings are ASCII and UTF-8.\n" "error: (input string):1:1: failed to parse file\n", .error = true }, { .input = " : x\n" "include \"x\"\n", .log = "warning: [XKB-301] (input string):1:1: deprecated keysym \"leftshoe\".\n" "error: (input string):2:9: failed to open included Compose file \"x\": No such file or directory\n" "error: (input string):2:9: failed to parse file\n", .error = true }, { .input = " : \"a\"\n" "\n" " : \"i\\j\\xk\n" "<0x30> : \"\\400\" invalidKeysym\n" "<0> <1> <2> <3> <4> <5> <6> <7> <8> <9> : \"\"\n", .log = "warning: [XKB-645] (input string):3:7: unknown escape sequence \"\\j\" in string literal\n" "warning: [XKB-193] (input string):3:7: illegal hexadecimal escape sequence \"\\x\" in string literal\n" "error: [XKB-685] (input string):3:7: unterminated string literal\n" "warning: [XKB-193] (input string):4:10: illegal octal escape sequence \"\\400\" in string literal\n" "error: (input string):4:17: unrecognized keysym \"invalidKeysym\" on right-hand side\n" "warning: [XKB-301] (input string):5:41: deprecated keysym \"leftshoe\".\n" "warning: [XKB-685] (input string):5:41: too many keysyms (11) on left-hand side; skipping line\n", .error = false }, { .input = ":\n" " :\n" "#\n" " : \"a\" \"b\"\n" " : a b\n", .log = "warning: (input string):1:1: expected at least one keysym on left-hand side; skipping line\n" "warning: [XKB-685] (input string):2:5: right-hand side must have at least one of string or keysym; skipping line\n" "warning: (input string):4:11: right-hand side can have at most one string; skipping line\n" "error: [XKB-685] (input string):5:9: unrecognized modifier \"b\"\n", .error = false }, { .input = " : a\n" " : a\n" " : b\n" " : x\n" " : y\n" " : c\n", .log = "warning: (input string):2:7: this compose sequence is a duplicate of another; skipping line\n" "warning: (input string):4:11: a sequence already exists which is a prefix of this sequence; overriding\n" "warning: (input string):6:11: this compose sequence is a prefix of another; overriding\n", .error = false } }; for (unsigned int k = 0; k < ARRAY_SIZE(composes); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_compose_table *table = xkb_compose_table_new_from_buffer( ctx, composes[k].input, strlen(composes[k].input), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS ); assert(composes[k].error ^ !!table); xkb_compose_table_unref(table); assert_printf(streq_null(darray_items(log_string), composes[k].log), "Expected:\n%s\nGot:\n%s\n", darray_items(log_string), composes[k].log); darray_size(log_string) = 0; } xkb_context_unref(ctx); darray_free(log_string); } int main(void) { test_init(); /* We really need to be locale-independent here */ setlocale(LC_ALL, "C"); test_basic(); test_keymaps(); test_compose(); return EXIT_SUCCESS; }