summaryrefslogtreecommitdiffstats
path: root/src/libsystemd/sd-bus/test-bus-track.c
blob: 5604e84f522a32cd4d0000713da55f4731553843 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <errno.h>
#include <sys/socket.h>

#include "sd-bus.h"

#include "macro.h"
#include "tests.h"

static bool track_cb_called_x = false;
static bool track_cb_called_y = false;
static bool track_destroy_called_z = false;

static int track_cb_x(sd_bus_track *t, void *userdata) {

        log_error("TRACK CB X");

        assert_se(!track_cb_called_x);
        track_cb_called_x = true;

        /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works
         * as it should. */

        assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0);
        return 1;
}

static int track_cb_y(sd_bus_track *t, void *userdata) {

        log_error("TRACK CB Y");

        assert_se(!track_cb_called_y);
        track_cb_called_y = true;

        /* We got disconnected, let's close everything */

        assert_se(sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS) >= 0);

        return 0;
}

static int track_cb_z(sd_bus_track *t, void *userdata) {
        assert_not_reached();
}

static void track_destroy_z(void *userdata) {
        track_destroy_called_z = true;
}

int main(int argc, char *argv[]) {
        _cleanup_(sd_event_unrefp) sd_event *event = NULL;
        _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL, *z = NULL;
        _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
        bool use_system_bus = false;
        const char *unique;
        int r;

        test_setup_logging(LOG_INFO);

        assert_se(sd_event_default(&event) >= 0);

        r = sd_bus_open_user(&a);
        if (IN_SET(r, -ECONNREFUSED, -ENOENT, -ENOMEDIUM)) {
                r = sd_bus_open_system(&a);
                if (IN_SET(r, -ECONNREFUSED, -ENOENT))
                        return log_tests_skipped("Failed to connect to bus");
                use_system_bus = true;
        }
        assert_se(r >= 0);

        assert_se(sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL) >= 0);

        if (use_system_bus)
                assert_se(sd_bus_open_system(&b) >= 0);
        else
                assert_se(sd_bus_open_user(&b) >= 0);

        assert_se(sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL) >= 0);

        /* Watch b's name from a */
        assert_se(sd_bus_track_new(a, &x, track_cb_x, NULL) >= 0);

        assert_se(sd_bus_get_unique_name(b, &unique) >= 0);

        assert_se(sd_bus_track_add_name(x, unique) >= 0);

        /* Watch's a's own name from a */
        assert_se(sd_bus_track_new(a, &y, track_cb_y, NULL) >= 0);

        assert_se(sd_bus_get_unique_name(a, &unique) >= 0);

        assert_se(sd_bus_track_add_name(y, unique) >= 0);

        /* Basic tests. */
        assert_se(sd_bus_track_new(a, &z, track_cb_z, NULL) >= 0);

        /* non-recursive case */
        assert_se(sd_bus_track_set_recursive(z, false) >= 0);
        assert_se(sd_bus_track_get_recursive(z) == 0);
        assert_se(!sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 0);
        assert_se(sd_bus_track_remove_name(z, unique) == 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_set_recursive(z, true) == -EBUSY);
        assert_se(sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 1);
        assert_se(sd_bus_track_remove_name(z, unique) == 1);
        assert_se(!sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 0);
        assert_se(sd_bus_track_remove_name(z, unique) == 0);

        /* recursive case */
        assert_se(sd_bus_track_set_recursive(z, true) >= 0);
        assert_se(sd_bus_track_get_recursive(z) == 1);
        assert_se(!sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 0);
        assert_se(sd_bus_track_remove_name(z, unique) == 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_add_name(z, unique) >= 0);
        assert_se(sd_bus_track_set_recursive(z, false) == -EBUSY);
        assert_se(sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 3);
        assert_se(sd_bus_track_remove_name(z, unique) == 1);
        assert_se(sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 2);
        assert_se(sd_bus_track_remove_name(z, unique) == 1);
        assert_se(sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 1);
        assert_se(sd_bus_track_remove_name(z, unique) == 1);
        assert_se(!sd_bus_track_contains(z, unique));
        assert_se(sd_bus_track_count_name(z, unique) == 0);
        assert_se(sd_bus_track_remove_name(z, unique) == 0);

        assert_se(sd_bus_track_set_destroy_callback(z, track_destroy_z) >= 0);
        z = sd_bus_track_unref(z);
        assert_se(track_destroy_called_z);

        /* Now make b's name disappear */
        sd_bus_close(b);

        assert_se(sd_event_loop(event) >= 0);

        assert_se(track_cb_called_x);
        assert_se(track_cb_called_y);

        return 0;
}