-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compose: Add quickcheck test for traversal
Test against the `foreach` implementation: - Suffle compose file lines randomly; - Compare traversal entry by entry.
- Loading branch information
Showing
6 changed files
with
286 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#include "config.h" | ||
|
||
#include "src/darray.h" | ||
#include <stdio.h> | ||
#include <stdbool.h> | ||
#include <string.h> | ||
|
||
#include "xkbcommon/xkbcommon-compose.h" | ||
#include "src/compose/dump.h" | ||
#include "src/compose/parser.h" | ||
#include "src/keysym.h" | ||
#include "src/utils.h" | ||
#include "test/compose-iter.h" | ||
|
||
static void | ||
for_each_helper(struct xkb_compose_table *table, | ||
xkb_compose_table_iter_t iter, | ||
void *data, | ||
xkb_keysym_t *syms, | ||
size_t nsyms, | ||
uint16_t p) | ||
{ | ||
if (!p) { | ||
return; | ||
} | ||
const struct compose_node *node = &darray_item(table->nodes, p); | ||
for_each_helper(table, iter, data, syms, nsyms, node->lokid); | ||
syms[nsyms++] = node->keysym; | ||
if (node->is_leaf) { | ||
struct xkb_compose_table_entry entry = { | ||
.sequence = syms, | ||
.sequence_length = nsyms, | ||
.keysym = node->leaf.keysym, | ||
.utf8 = &darray_item(table->utf8, node->leaf.utf8), | ||
}; | ||
iter(&entry, data); | ||
} else { | ||
for_each_helper(table, iter, data, syms, nsyms, node->internal.eqkid); | ||
} | ||
nsyms--; | ||
for_each_helper(table, iter, data, syms, nsyms, node->hikid); | ||
} | ||
|
||
XKB_EXPORT void | ||
xkb_compose_table_for_each(struct xkb_compose_table *table, | ||
xkb_compose_table_iter_t iter, | ||
void *data) | ||
{ | ||
if (darray_size(table->nodes) <= 1) { | ||
return; | ||
} | ||
xkb_keysym_t syms[MAX_LHS_LEN]; | ||
for_each_helper(table, iter, data, syms, 0, 1); | ||
} | ||
|
||
bool | ||
print_compose_table_entry(FILE *file, struct xkb_compose_table_entry *entry) | ||
{ | ||
size_t nsyms; | ||
const xkb_keysym_t *syms = xkb_compose_table_entry_sequence(entry, &nsyms); | ||
char buf[XKB_KEYSYM_NAME_MAX_SIZE]; | ||
for (size_t i = 0; i < nsyms; i++) { | ||
xkb_keysym_get_name(syms[i], buf, sizeof(buf)); | ||
fprintf(file, "<%s>", buf); | ||
if (i + 1 < nsyms) { | ||
fprintf(file, " "); | ||
} | ||
} | ||
fprintf(file, " : "); | ||
const char *utf8 = xkb_compose_table_entry_utf8(entry); | ||
if (*utf8 != '\0') { | ||
char *escaped = escape_utf8_string_literal(utf8); | ||
if (!escaped) { | ||
fprintf(file, "ERROR: Cannot escape the string: allocation error\n"); | ||
return false; | ||
} else { | ||
fprintf(file, " \"%s\"", escaped); | ||
free(escaped); | ||
} | ||
} | ||
const xkb_keysym_t keysym = xkb_compose_table_entry_keysym(entry); | ||
if (keysym != XKB_KEY_NoSymbol) { | ||
xkb_keysym_get_name(keysym, buf, sizeof(buf)); | ||
fprintf(file, " %s", buf); | ||
} | ||
fprintf(file, "\n"); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef COMPOSE_LEGACY_ITER_H | ||
#define COMPOSE_LEGACY_ITER_H | ||
|
||
#include "config.h" | ||
#include "src/compose/table.h" | ||
|
||
/** | ||
* The iterator function type used by xkb_compose_table_for_each(). | ||
* | ||
* @sa xkb_compose_table_for_each | ||
* @memberof xkb_compose | ||
* @since 1.6.0 | ||
*/ | ||
typedef void | ||
(*xkb_compose_table_iter_t)(struct xkb_compose_table_entry *entry, | ||
void *data); | ||
|
||
/** | ||
* Run a specified function for every valid entry in the table. | ||
* | ||
* The entries are returned in lexicographic order of the left-hand | ||
* side of entries. This does not correspond to the order in which | ||
* the entries appear in the Compose file. | ||
* | ||
* @memberof xkb_compose_table | ||
* @since 1.6.0 | ||
*/ | ||
void | ||
xkb_compose_table_for_each(struct xkb_compose_table *table, | ||
xkb_compose_table_iter_t iter, | ||
void *data); | ||
|
||
bool | ||
print_compose_table_entry(FILE *file, struct xkb_compose_table_entry *entry); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include "config.h" | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include "src/utils.h" | ||
#include "test/shuffle-lines.h" | ||
|
||
/* Split string into lines */ | ||
size_t | ||
split_lines(const char *input, size_t input_length, | ||
struct text_line *output, size_t output_length) | ||
{ | ||
const char *start = input; | ||
char *next; | ||
size_t l; | ||
size_t i = 0; | ||
|
||
for (l = 0; i < input_length && l < output_length && *start != '\0'; l++) { | ||
/* Look for newline character */ | ||
next = strchr(start, 0x0a); | ||
output[l].start = start; | ||
if (next == NULL) { | ||
/* Not found: add the rest of the string */ | ||
output[l++].length = strlen(start); | ||
break; | ||
} | ||
output[l].length = (size_t)(next - start) + 1; | ||
start = next + 1; | ||
i += output[l].length; | ||
} | ||
return l; | ||
} | ||
|
||
size_t | ||
shuffle_lines(struct text_line *lines, size_t length, char *output) | ||
{ | ||
/* Shuffle in-place using Fisher–Yates algorithm, then append lines. | ||
* See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle */ | ||
|
||
assert(length < RAND_MAX); | ||
char *out = output; | ||
if (length > 1) { | ||
for (size_t i = length - 1; i > 0; i--) { | ||
size_t j = (size_t)(rand() % (i+1)); | ||
struct text_line tmp = lines[j]; | ||
lines[j] = lines[i]; | ||
lines[i] = tmp; | ||
/* Append current line */ | ||
memcpy(out, lines[i].start, lines[i].length); | ||
out += lines[i].length; | ||
/* Ensure line ends with newline */ | ||
if (out[-1] != '\n') { | ||
out[0] = '\n'; | ||
out++; | ||
} | ||
} | ||
} | ||
return (size_t)(out - output); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include <stdint.h> | ||
|
||
struct text_line { | ||
const char *start; | ||
size_t length; | ||
}; | ||
|
||
size_t | ||
split_lines(const char *input, size_t input_length, | ||
struct text_line *output, size_t output_length); | ||
|
||
size_t | ||
shuffle_lines(struct text_line *lines, size_t length, char *output); |