tests: modify queue-test to use 'check' framework
[pulseaudio-raopUDP/pulseaudio-raop-alac.git] / src / tests / alsa-time-test.c
bloba7cd938b4070a17ec02dad3f9df80400248332b7
1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
5 #include <assert.h>
6 #include <inttypes.h>
7 #include <time.h>
9 #include <check.h>
11 #include <alsa/asoundlib.h>
13 static const char *dev;
14 static int cap;
16 static uint64_t timespec_us(const struct timespec *ts) {
17 return
18 ts->tv_sec * 1000000LLU +
19 ts->tv_nsec / 1000LLU;
22 START_TEST (alsa_time_test) {
23 int r;
24 snd_pcm_hw_params_t *hwparams;
25 snd_pcm_sw_params_t *swparams;
26 snd_pcm_status_t *status;
27 snd_pcm_t *pcm;
28 unsigned rate = 44100;
29 unsigned periods = 2;
30 snd_pcm_uframes_t boundary, buffer_size = 44100/10; /* 100s */
31 int dir = 1;
32 struct timespec start, last_timestamp = { 0, 0 };
33 uint64_t start_us;
34 snd_pcm_sframes_t last_avail = 0, last_delay = 0;
35 struct pollfd *pollfds;
36 int n_pollfd;
37 int64_t sample_count = 0;
39 snd_pcm_hw_params_alloca(&hwparams);
40 snd_pcm_sw_params_alloca(&swparams);
41 snd_pcm_status_alloca(&status);
43 r = clock_gettime(CLOCK_MONOTONIC, &start);
44 fail_unless(r == 0);
46 start_us = timespec_us(&start);
48 if (cap == 0)
49 r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
50 else
51 r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_CAPTURE, 0);
52 fail_unless(r == 0);
54 r = snd_pcm_hw_params_any(pcm, hwparams);
55 fail_unless(r == 0);
57 r = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 0);
58 fail_unless(r == 0);
60 r = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
61 fail_unless(r == 0);
63 r = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE);
64 fail_unless(r == 0);
66 r = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, NULL);
67 fail_unless(r == 0);
69 r = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
70 fail_unless(r == 0);
72 r = snd_pcm_hw_params_set_periods_integer(pcm, hwparams);
73 fail_unless(r == 0);
75 r = snd_pcm_hw_params_set_periods_near(pcm, hwparams, &periods, &dir);
76 fail_unless(r == 0);
78 r = snd_pcm_hw_params_set_buffer_size_near(pcm, hwparams, &buffer_size);
79 fail_unless(r == 0);
81 r = snd_pcm_hw_params(pcm, hwparams);
82 fail_unless(r == 0);
84 r = snd_pcm_hw_params_current(pcm, hwparams);
85 fail_unless(r == 0);
87 r = snd_pcm_sw_params_current(pcm, swparams);
88 fail_unless(r == 0);
90 if (cap == 0)
91 r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 1);
92 else
93 r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 0);
94 fail_unless(r == 0);
96 r = snd_pcm_sw_params_set_period_event(pcm, swparams, 0);
97 fail_unless(r == 0);
99 r = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
100 fail_unless(r == 0);
101 r = snd_pcm_sw_params_set_start_threshold(pcm, swparams, buffer_size);
102 fail_unless(r == 0);
104 r = snd_pcm_sw_params_get_boundary(swparams, &boundary);
105 fail_unless(r == 0);
106 r = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary);
107 fail_unless(r == 0);
109 r = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE);
110 fail_unless(r == 0);
112 r = snd_pcm_sw_params(pcm, swparams);
113 fail_unless(r == 0);
115 r = snd_pcm_prepare(pcm);
116 fail_unless(r == 0);
118 r = snd_pcm_sw_params_current(pcm, swparams);
119 fail_unless(r == 0);
121 /* fail_unless(snd_pcm_hw_params_is_monotonic(hwparams) > 0); */
123 n_pollfd = snd_pcm_poll_descriptors_count(pcm);
124 fail_unless(n_pollfd > 0);
126 pollfds = malloc(sizeof(struct pollfd) * n_pollfd);
127 fail_unless(pollfds != NULL);
129 r = snd_pcm_poll_descriptors(pcm, pollfds, n_pollfd);
130 fail_unless(r == n_pollfd);
132 if (cap) {
133 r = snd_pcm_start(pcm);
134 fail_unless(r == 0);
137 for (;;) {
138 snd_pcm_sframes_t avail, delay;
139 struct timespec now, timestamp;
140 unsigned short revents;
141 int handled = 0;
142 uint64_t now_us, timestamp_us;
143 snd_pcm_state_t state;
144 unsigned long long pos;
146 r = poll(pollfds, n_pollfd, 0);
147 fail_unless(r >= 0);
149 r = snd_pcm_poll_descriptors_revents(pcm, pollfds, n_pollfd, &revents);
150 fail_unless(r == 0);
152 if (cap == 0)
153 fail_unless((revents & ~POLLOUT) == 0);
154 else
155 fail_unless((revents & ~POLLIN) == 0);
157 avail = snd_pcm_avail(pcm);
158 fail_unless(avail >= 0);
160 r = snd_pcm_status(pcm, status);
161 fail_unless(r == 0);
163 /* This assertion fails from time to time. ALSA seems to be broken */
164 /* fail_unless(avail == (snd_pcm_sframes_t) snd_pcm_status_get_avail(status)); */
165 /* printf("%lu %lu\n", (unsigned long) avail, (unsigned long) snd_pcm_status_get_avail(status)); */
167 snd_pcm_status_get_htstamp(status, &timestamp);
168 delay = snd_pcm_status_get_delay(status);
169 state = snd_pcm_status_get_state(status);
171 r = clock_gettime(CLOCK_MONOTONIC, &now);
172 fail_unless(r == 0);
174 fail_unless(!revents || avail > 0);
176 if ((!cap && avail) || (cap && (unsigned)avail >= buffer_size)) {
177 snd_pcm_sframes_t sframes;
178 static const uint16_t psamples[2] = { 0, 0 };
179 uint16_t csamples[2];
181 if (cap == 0)
182 sframes = snd_pcm_writei(pcm, psamples, 1);
183 else
184 sframes = snd_pcm_readi(pcm, csamples, 1);
185 fail_unless(sframes == 1);
187 handled = 1;
188 sample_count++;
191 if (!handled &&
192 memcmp(&timestamp, &last_timestamp, sizeof(timestamp)) == 0 &&
193 avail == last_avail &&
194 delay == last_delay) {
195 /* This is boring */
196 continue;
199 now_us = timespec_us(&now);
200 timestamp_us = timespec_us(&timestamp);
202 if (cap == 0)
203 pos = (unsigned long long) ((sample_count - handled - delay) * 1000000LU / 44100);
204 else
205 pos = (unsigned long long) ((sample_count - handled + delay) * 1000000LU / 44100);
207 printf("%llu\t%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
208 (unsigned long long) (now_us - start_us),
209 (unsigned long long) (timestamp_us ? timestamp_us - start_us : 0),
210 pos,
211 (unsigned long long) sample_count,
212 (signed long) avail,
213 (signed long) delay,
214 revents,
215 handled,
216 state);
218 if (cap == 0)
219 /** When this fail_unless is hit, most likely something bad
220 * happened, i.e. the avail jumped suddenly. */
221 fail_unless((unsigned) avail <= buffer_size);
223 last_avail = avail;
224 last_delay = delay;
225 last_timestamp = timestamp;
228 END_TEST
230 int main(int argc, char *argv[]) {
231 int failed = 0;
232 Suite *s;
233 TCase *tc;
234 SRunner *sr;
236 dev = argc > 1 ? argv[1] : "front:AudioPCI";
237 cap = argc > 2 ? atoi(argv[2]) : 0;
239 s = suite_create("ALSA Time");
240 tc = tcase_create("alsatime");
241 tcase_add_test(tc, alsa_time_test);
242 suite_add_tcase(s, tc);
244 sr = srunner_create(s);
245 srunner_run_all(sr, CK_NORMAL);
246 failed = srunner_ntests_failed(sr);
247 srunner_free(sr);
249 return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;