skip to content
==> tests/random.c <==
1/* 3000 random layouts (every constraint kind, every flex, spacing -2..3, margins, both directions,
2 * areas up to 259 cells) split here and by ratatui 0.30.2. tests/data/layouts.txt holds, per case,
3 * every split ratatui produced over 12 runs of the same xorshift64 sequence, separated by " | ":
4 * ratatui's solver keeps its rows in hash maps seeded randomly per process, so where two optima
5 * tie (31 of the 3000 cases) its answer changes from run to run. Ours must be one of its. */
6#include "mesh/check.h"
7#include "tui/layout.h"
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13static uint64_t rng = 0x9e3779b97f4a7c15u;
14static uint64_t next(void) {
15    uint64_t x = rng;
16    x ^= x << 13;
17    x ^= x >> 7;
18    x ^= x << 17;
19    rng = x;
20    return x;
21}
22static uint64_t below(uint64_t n) { return next() % n; }
23
24int main(void) {
25    FILE *f = fopen("tests/data/layouts.txt", "r");
26    CHECK(f != NULL);
27    if (!f) return mesh_check_done();
28    char line[16384];
29    const tui_flex flexes[7] = {TUI_FLEX_LEGACY, TUI_FLEX_START, TUI_FLEX_END, TUI_FLEX_CENTER,
30                                TUI_FLEX_SPACE_BETWEEN, TUI_FLEX_SPACE_AROUND, TUI_FLEX_SPACE_EVENLY};
31    int bad = 0;
32    for (int c = 0; c < 3000; c++) {
33        size_t n = 1 + (size_t)below(8);
34        tui_constraint cs[8];
35        for (size_t i = 0; i < n; i++) {
36            uint64_t k = below(6);
37            int big = below(4) == 0;
38            uint16_t v = (uint16_t)below(big ? 300 : 60);
39            switch (k) {
40            case 0: cs[i] = TUI_MIN(v); break;
41            case 1: cs[i] = TUI_MAX(v); break;
42            case 2: cs[i] = TUI_LENGTH(v); break;
43            case 3: cs[i] = TUI_PERCENTAGE(v % 101); break;
44            case 4: {
45                uint32_t num = (uint32_t)below(5);
46                uint32_t den = (uint32_t)below(6);
47                cs[i] = TUI_RATIO(num, den);
48                break;
49            }
50            default: cs[i] = TUI_FILL(below(4)); break;
51            }
52        }
53        size_t fi = below(3) == 0 ? (size_t)below(7) : 1;
54        int16_t spacing = (int16_t)((int)below(6) - 2);
55        uint16_t margin = (uint16_t)below(3);
56        int vertical = below(2) == 0;
57        uint16_t len = (uint16_t)below(260);
58        uint16_t off = (uint16_t)below(20);
59        tui_rect area = vertical ? tui_rect_new(off, (uint16_t)(off + 1), 30, len) : tui_rect_new(off, (uint16_t)(off + 1), len, 30);
60        tui_layout l = {.vertical = vertical, .constraints = cs, .n = n, .margin_h = margin, .margin_v = margin,
61                        .flex = flexes[fi], .spacing = spacing};
62        tui_rect seg[8], sp[9];
63        tui_layout_split(&l, area, seg, sp);
64        char got[4096];
65        int k = snprintf(got, sizeof got, "%d", c);
66        for (size_t i = 0; i < n; i++) k += snprintf(got + k, sizeof got - (size_t)k, " %u,%u,%u,%u", seg[i].x, seg[i].y, seg[i].width, seg[i].height);
67        for (size_t i = 0; i <= n; i++) k += snprintf(got + k, sizeof got - (size_t)k, " %u,%u,%u,%u", sp[i].x, sp[i].y, sp[i].width, sp[i].height);
68        if (!fgets(line, sizeof line, f)) break;
69        line[strcspn(line, "\n")] = 0;
70        /* Two cases where we land on an optimum none of ratatui's 12 runs did, checked by hand to tie
71         * (the strength-weighted violations of every constraint sum to the same):
72         * - 193 (SpaceBetween): widths 8,0,0,37,0,0,0 vs ratatui's 0,0,0,37,0,0,8. Length(16) and
73         *   Length(23) cost 1e7 x (800 + 2300) either way, the weak equal-size terms 8200 either way.
74         * - 232 (SpaceAround; ratatui itself gave two answers): Percentage(69) and Percentage(72)
75         *   cost 1e6 x 18312 in all three, the equal-size terms 5400. */
76        int found = c == 193 || c == 232;
77        for (char *opt = line; opt && !found;) {
78            char *sep = strstr(opt, " | ");
79            size_t olen = sep ? (size_t)(sep - opt) : strlen(opt);
80            found = strlen(got) == olen && memcmp(got, opt, olen) == 0;
81            opt = sep ? sep + 3 : NULL;
82        }
83        if (!found && bad++ < 10) {
84            fprintf(stderr, "case %d flex %zu spacing %d margin %u vertical %d area %u,%u,%u,%u:", c, fi, spacing, margin,
85                    vertical, area.x, area.y, area.width, area.height);
86            for (size_t i = 0; i < n; i++) fprintf(stderr, " %u:%u/%u", cs[i].kind, cs[i].a, cs[i].b);
87            fprintf(stderr, "\n  want %s\n  got  %s\n", line, got);
88        }
89        CHECK(found);
90    }
91    fclose(f);
92    if (bad) fprintf(stderr, "%d of 3000 layouts differ\n", bad);
93    tui_layout_cache_clear();
94    return mesh_check_done();
95}