Edit

kc3-lang/libxkbcommon/test/stringcomp.c

Branch :

  • Show log

    Commit

  • Author : Pierre Le Marre
    Date : 2024-10-09 08:34:27
    Hash : 948f7a59
    Message : symbols: Skip interprets only for groups with explicit actions Previously setting explicit actions for a group in symbols files made the parser skip compatibility interpretations for the corresponding *whole* key, so the other groups with *no* explicit actions could result broken on some levels. In the following example, `<RALT>` would have an action on group 2, because it is explicit, but none on group 1 because interpretation are also skipped there as a side effect: ```c key <RALT> { symbols[1]= [ ISO_Level3_Shift ], symbols[2]= [ ISO_Level3_Shift ], actions[2]= [ SetMods(modifiers=LevelThree) ] }; ``` Fixed by skipping interpretations *only* for groups with explicit actions. We still set `key->explicit |= EXPLICIT_INTERP` if at least one group has explicit actions. In such case, when dumping a keymap, we will write explicit actions for *all* groups, in order to ensure that X11 and previous versions of libxkbcommon can parse the keymap as intended. One side effect is that no interpretation will be run on this key anymore, so we may have to set some extra fields explicitly: repeat, virtualMods. Thus the previous example would be bumped as: ```c key <RALT> { repeat= No, symbols[1]= [ ISO_Level3_Shift ], actions[1]= [ SetMods(modifiers=LevelThree,clearLocks) ], symbols[2]= [ ISO_Level3_Shift ], actions[2]= [ SetMods(modifiers=LevelThree) ] }; ```

  • test/stringcomp.c
  • /*
     * Copyright © 2009 Dan Nicholson
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice (including the next
     * paragraph) shall be included in all copies or substantial portions of the
     * Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     * DEALINGS IN THE SOFTWARE.
     */
    
    #include "config.h"
    
    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "test.h"
    #include "test/utils-text.h"
    
    #define DATA_PATH "keymaps/stringcomp.data"
    
    static void
    test_explicit_actions(struct xkb_context *ctx)
    {
        struct xkb_keymap *keymap;
    
        char *original = test_read_file("keymaps/explicit-actions.xkb");
        assert(original);
        char *tmp = uncomment(original, strlen(original), "//");
        assert(tmp);
        char *expected = strip_lines(tmp, strlen(tmp), "//");
        free(tmp);
        assert(expected);
        char *got = NULL;
    
        /* Try original */
        keymap = test_compile_string(ctx, original);
        free(original);
        assert(keymap);
        got = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
        xkb_keymap_unref(keymap);
        assert_streq_not_null("Check output from original", expected, got);
        free(got);
    
        /* Try round-trip */
        keymap = test_compile_string(ctx, expected);
        assert(keymap);
        got = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
        xkb_keymap_unref(keymap);
        assert_streq_not_null("Check roundtrip", expected, got);
        free(got);
    
        free(expected);
    }
    
    int
    main(int argc, char *argv[])
    {
        test_init();
    
        struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG);
        struct xkb_keymap *keymap;
        char *original, *dump, *dump2;
    
        assert(ctx);
    
        /* Load in a prebuilt keymap, make sure we can compile it from a string,
         * then compare it to make sure we get the same result when dumping it
         * to a string. */
        original = test_read_file(DATA_PATH);
        assert(original);
    
        keymap = test_compile_string(ctx, original);
        assert(keymap);
    
        dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
        assert(dump);
    
        if (!streq(original, dump)) {
            fprintf(stderr,
                    "round-trip test failed: dumped map differs from original\n");
            fprintf(stderr, "path to original file: %s\n",
                    test_get_path(DATA_PATH));
            fprintf(stderr, "length: dumped %lu, original %lu\n",
                    (unsigned long) strlen(dump),
                    (unsigned long) strlen(original));
            fprintf(stderr, "dumped map:\n");
            fprintf(stderr, "%s\n", dump);
            fflush(stderr);
            assert(0);
        }
    
        free(original);
        free(dump);
        xkb_keymap_unref(keymap);
    
        /* Make sure we can't (falsely claim to) compile an empty string. */
        keymap = test_compile_string(ctx, "");
        assert(!keymap);
    
        /* Make sure we can recompile our output for a normal keymap from rules. */
        keymap = test_compile_rules(ctx, NULL, NULL,
                                    "ru,ca,de,us", ",multix,neo,intl", NULL);
        assert(keymap);
        dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
        assert(dump);
        xkb_keymap_unref(keymap);
        keymap = test_compile_string(ctx, dump);
        assert(keymap);
        /* Now test that the dump of the dump is equal to the dump! */
        dump2 = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
        assert(dump2);
        assert(streq(dump, dump2));
    
        /* Test response to invalid formats and flags. */
        assert(!xkb_keymap_new_from_string(ctx, dump, 0, 0));
        assert(!xkb_keymap_new_from_string(ctx, dump, -1, 0));
        assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1+1, 0));
        assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, -1));
        assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, 1414));
        assert(!xkb_keymap_get_as_string(keymap, 0));
        assert(!xkb_keymap_get_as_string(keymap, 4893));
    
        xkb_keymap_unref(keymap);
        free(dump);
        free(dump2);
    
        test_explicit_actions(ctx);
    
        xkb_context_unref(ctx);
    
        return EXIT_SUCCESS;
    }