1/***
2  This file is part of PulseAudio.
3
4  Copyright 2014 David Henningsson, Canonical Ltd.
5
6  PulseAudio is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation; either version 2.1 of the License,
9  or (at your option) any later version.
10
11  PulseAudio is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public License
17  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18***/
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <unistd.h>
25#include <check.h>
26
27#include <pulse/mainloop.h>
28#include <pulsecore/packet.h>
29#include <pulsecore/pstream.h>
30#include <pulsecore/iochannel.h>
31#include <pulsecore/memblock.h>
32
33static unsigned packets_received;
34static unsigned packets_checksum;
35static size_t packets_length;
36
37static void packet_received(pa_pstream *p, pa_packet *packet, pa_cmsg_ancil_data *ancil_data, void *userdata) {
38    const uint8_t *pdata;
39    size_t plen;
40    unsigned i;
41
42    pdata = pa_packet_data(packet, &plen);
43    fail_unless(packets_length == plen);
44
45    packets_received++;
46    for (i = 0; i < plen; i++)
47        packets_checksum += pdata[i];
48}
49
50static void packet_test(unsigned npackets, size_t plength, pa_mainloop *ml, pa_pstream *p1, pa_pstream *p2) {
51    pa_packet *packet = pa_packet_new(plength);
52    unsigned i;
53    unsigned psum = 0, totalsum = 0;
54    uint8_t *pdata;
55    size_t plen;
56
57    pa_log_info("Sending %d packets of length %zd", npackets, plength);
58    packets_received = 0;
59    packets_checksum = 0;
60    packets_length = plength;
61    pa_pstream_set_receive_packet_callback(p2, packet_received, NULL);
62
63    pdata = (uint8_t *) pa_packet_data(packet, &plen);
64    for (i = 0; i < plen; i++) {
65        pdata[i] = i;
66        psum += pdata[i];
67    }
68
69    for (i = 0; i < npackets; i++) {
70        pa_pstream_send_packet(p1, packet, NULL);
71        totalsum += psum;
72        pa_mainloop_iterate(ml, 0, NULL);
73    }
74
75    while (packets_received < npackets)
76        pa_mainloop_iterate(ml, 1, NULL);
77
78    fail_unless(packets_checksum == totalsum);
79    pa_log_debug("Correct checksum received (%d)", packets_checksum);
80    pa_packet_unref(packet);
81}
82
83START_TEST (srbchannel_test) {
84
85    int pipefd[4];
86
87    pa_mainloop *ml = pa_mainloop_new();
88    pa_mempool *mp = pa_mempool_new(PA_MEM_TYPE_SHARED_POSIX, 0, true);
89    pa_iochannel *io1, *io2;
90    pa_pstream *p1, *p2;
91    pa_srbchannel *sr1, *sr2;
92    pa_srbchannel_template srt;
93
94    fail_unless(pipe(pipefd) == 0);
95    fail_unless(pipe(&pipefd[2]) == 0);
96    io1 = pa_iochannel_new(pa_mainloop_get_api(ml), pipefd[2], pipefd[1]);
97    io2 = pa_iochannel_new(pa_mainloop_get_api(ml), pipefd[0], pipefd[3]);
98    p1 = pa_pstream_new(pa_mainloop_get_api(ml), io1, mp);
99    p2 = pa_pstream_new(pa_mainloop_get_api(ml), io2, mp);
100
101    pa_log_debug("Pipes: fd %d -> %d, %d -> %d", pipefd[1], pipefd[0], pipefd[3], pipefd[2]);
102
103    packet_test(250, 5, ml, p1, p2);
104    packet_test(10, 1234567, ml, p1, p2);
105
106    pa_log_debug("And now the same thing with srbchannel...");
107
108    sr1 = pa_srbchannel_new(pa_mainloop_get_api(ml), mp);
109    pa_srbchannel_export(sr1, &srt);
110    pa_pstream_set_srbchannel(p1, sr1);
111    sr2 = pa_srbchannel_new_from_template(pa_mainloop_get_api(ml), &srt);
112    pa_pstream_set_srbchannel(p2, sr2);
113
114    packet_test(250, 5, ml, p1, p2);
115    packet_test(10, 1234567, ml, p1, p2);
116
117    pa_pstream_unref(p1);
118    pa_pstream_unref(p2);
119    pa_mempool_unref(mp);
120    pa_mainloop_free(ml);
121}
122END_TEST
123
124
125int main(int argc, char *argv[]) {
126    int failed = 0;
127    Suite *s;
128    TCase *tc;
129    SRunner *sr;
130
131    if (!getenv("MAKE_CHECK"))
132        pa_log_set_level(PA_LOG_DEBUG);
133
134    s = suite_create("srbchannel");
135    tc = tcase_create("srbchannel");
136    tcase_add_test(tc, srbchannel_test);
137    suite_add_tcase(s, tc);
138
139    sr = srunner_create(s);
140    srunner_run_all(sr, CK_NORMAL);
141    failed = srunner_ntests_failed(sr);
142    srunner_free(sr);
143
144    return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
145}
146