summaryrefslogtreecommitdiff
path: root/tests/common/test_public_api.c
blob: a53a8ec3d3bcf4be1be76946f9cd8c955e3e742f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <yasl/yasl.h>
#include <assert.h>
#include <string.h>

/* Before yasl_init there is no display: argument errors are reported first, owner-thread
 * calls fail with ENODEV, and queries return their documented fallbacks. Nothing here may
 * open a display, so only invalid arguments reach the constructors and openers. */
int main(void)
{
    static char anchor; /* A fake handle; it is compared and never dereferenced. */
    yasl_surface *fake = (yasl_surface *)&anchor;

    assert(yasl_shutdown() == 0 && yasl_shutdown() == 0);
    assert(yasl_get_backend() == YASL_BACKEND_AUTO && yasl_get_features() == 0);
    assert(yasl_get_appearance() == 0 && yasl_get_double_click_ms() == 400);

    /* Invalid constructor arguments fail before any display is opened. */
    assert(!yasl_surface_create(&(struct yasl_surface_options){.width = 32767, .height = 32767}) &&
           errno == EINVAL);
    assert(!yasl_surface_create(&(struct yasl_surface_options){.width = 32768, .height = 1}) &&
           errno == EINVAL);
    assert(!yasl_surface_create(&(struct yasl_surface_options){
               .width = 8, .height = 8, .type = YASL_SURFACE_GL, .gl = {.share = fake}}) &&
           errno == EINVAL);

    /* Owner-thread calls need a display, whatever the surface argument is. */
    assert(yasl_surface_destroy(NULL) == 0 && yasl_surface_destroy(fake) == -ENODEV);
    assert(yasl_surface_set_userdata(NULL, &anchor) == -ENODEV);
    assert(yasl_surface_set_title(NULL, "x") == -ENODEV);
    assert(yasl_surface_set_title(fake, NULL) == -ENODEV);
    assert(yasl_surface_request(NULL, YASL_REQUEST_MAXIMIZE) == -ENODEV);
    assert(yasl_surface_request(fake, (enum yasl_request)9) == -ENODEV);
    assert(yasl_surface_request_size(NULL, 10, 10) == -ENODEV);
    assert(yasl_surface_set_cursor(NULL, YASL_CURSOR_ARROW) == -ENODEV);
    assert(yasl_surface_set_text_input(NULL, NULL) == -ENODEV);
    assert(yasl_surface_begin_move_resize(NULL, 0) == -ENODEV);
    assert(yasl_surface_show_window_menu(NULL, 1, 1) == -ENODEV);
    assert(yasl_surface_bell(NULL) == -ENODEV);
    assert(yasl_surface_place_under_pointer(NULL, 1, 1) == -ENODEV);
    assert(yasl_drag_carry(NULL, 1, 1) == -ENODEV);
    assert(yasl_drag_start(NULL, NULL) == -ENODEV);
    assert(yasl_drag_cancel() == -ENODEV);
    assert(yasl_clipboard_set(YASL_CLIPBOARD, "x") == -ENODEV);
    assert(yasl_clipboard_set(YASL_PRIMARY, NULL) == -ENODEV);
    assert(yasl_clipboard_request(NULL, YASL_CLIPBOARD) == -ENODEV);
    assert(yasl_notify("title", NULL) == -ENODEV);
    assert(yasl_cpu_present(NULL) == -ENODEV);
    assert(yasl_gl_set_swap_interval(NULL, 1) == -ENODEV);
    assert(yasl_gl_present(NULL) == -ENODEV);
    assert(yasl_gl_make_current(fake) == -ENODEV);
    assert(!yasl_gl_get_proc_address("glClear") && errno == ENODEV);
    assert(!yasl_gl_get_proc_address(NULL) && errno == ENODEV);
    assert(!yasl_metal_get_layer(NULL) && errno == ENODEV);
    struct yasl_popup_options popup = {.width = 4, .height = 4};
    assert(yasl_popup_reposition(NULL, &popup) == -ENODEV);
    assert(!yasl_popup_create(NULL, &popup) && errno == ENODEV);

    /* Queries name their fallbacks. */
    assert(yasl_surface_get_userdata(NULL) == NULL && yasl_surface_get_userdata(fake) == NULL);
    struct yasl_surface_info info = yasl_surface_get_info(NULL);
    assert(info.width == 0 && info.height == 0 && info.pixel_width == 0 && info.pixel_height == 0 &&
           info.scale == 1.0 && info.state == 0);
    info = yasl_surface_get_info(fake);
    assert(info.width == 0 && info.pixel_height == 0 && info.scale == 1.0);
    int w = 7, h = 7;
    assert(!yasl_cpu_pixels(NULL, &w, &h) && errno == ENODEV && w == 0 && h == 0);
    assert(!yasl_cpu_pixels(NULL, NULL, NULL) && errno == ENODEV);
    struct yasl_native native = {.x11_window = 7};
    assert(yasl_surface_get_native(NULL, NULL) == -EINVAL);
    assert(yasl_surface_get_native(NULL, &native) == -ENODEV && native.x11_window == 0);

    /* Waiting needs a display; yasl_wake with no display does nothing and does not crash. */
    yasl_event e = {.type = YASL_EVENT_QUIT};
    assert(yasl_wait_event(&e, 0) == -ENODEV && e.type == YASL_EVENT_NONE);
    yasl_wake();
    yasl_wake();
    assert(yasl_shutdown() == 0);

    /* The event clock never runs backwards. */
    uint64_t last = yasl_time_ns();
    assert(last > 0);
    for (int i = 0; i < 1000; i++) {
        uint64_t now = yasl_time_ns();
        assert(now >= last);
        last = now;
    }

    /* yasl_open_uri rejects bad URIs without opening anything. */
    assert(yasl_open_uri(NULL) == -EINVAL);
    assert(yasl_open_uri("") == -EINVAL);
    assert(yasl_open_uri("no-colon") == -EINVAL);
    assert(yasl_open_uri("1http://x") == -EINVAL);
    assert(yasl_open_uri("http://x\n") == -EINVAL);

    /* yasl_drop_next_path walks a text/uri-list: local file lines only, comments skipped. */
    static const char uris[] =
        "file:///a/b\r\nhttp://x/y\r\n# comment\r\nfile://localhost/c%20d\r\n";
    const char *cursor = uris;
    char out[64] = "keep";
    assert(yasl_drop_next_path(&cursor, NULL, 0) == 4 && cursor == uris);
    assert(yasl_drop_next_path(&cursor, out, 4) == 4 && cursor == uris && !strcmp(out, "keep"));
    assert(yasl_drop_next_path(&cursor, out, 5) == 4 && cursor != uris && !strcmp(out, "/a/b"));
    assert(yasl_drop_next_path(&cursor, out, sizeof out) == 4 && !strcmp(out, "/c d"));
    assert(yasl_drop_next_path(&cursor, out, sizeof out) == 0);
    assert(yasl_drop_next_path(NULL, out, sizeof out) == 0);
    const char *fresh = uris;
    assert(yasl_drop_next_path(&fresh, NULL, 1) == 0 && fresh == uris);

    /* yasl_get_system_string: length first, the NUL only when the capacity exceeds it. */
    char path[4096], full[4096], locale[64];
    size_t n = yasl_get_system_string(YASL_EXECUTABLE_PATH, NULL, 0);
    assert(n > 0 && n < sizeof full);
    assert(yasl_get_system_string(YASL_EXECUTABLE_PATH, full, sizeof full) == n && strlen(full) == n);
    memset(path, 'x', sizeof path);
    assert(yasl_get_system_string(YASL_EXECUTABLE_PATH, path, n) == n && path[n - 1] == 'x' &&
           path[n] == 'x');
    assert(yasl_get_system_string(YASL_EXECUTABLE_PATH, path, n - 1) == n && path[n - 2] == 'x' &&
           path[n] == 'x');
    assert(yasl_get_system_string(YASL_EXECUTABLE_PATH, path, n + 1) == n && path[n] == '\0' &&
           !strcmp(path, full));
    size_t ln = yasl_get_system_string(YASL_LOCALE, locale, sizeof locale);
    assert(ln > 0 && ln < sizeof locale && strlen(locale) == ln && !strpbrk(locale, ".@"));
    assert(yasl_get_system_string(YASL_LOCALE, NULL, 16) == 0 && errno == EINVAL);
    assert(yasl_get_system_string((enum yasl_system_string)9, locale, sizeof locale) == 0 &&
           errno == EINVAL);
#if defined(__linux__)
    errno = 0;
    assert(yasl_get_system_string(YASL_RESOURCE_DIR, path, sizeof path) == 0 && errno == ENOTSUP);
#endif
    return 0;
}