Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/libcubeb/gtest/test_sanity.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2011 Mozilla Foundation
3
 *
4
 * This program is made available under an ISC-style license.  See the
5
 * accompanying file LICENSE for details.
6
 */
7
#include "gtest/gtest.h"
8
#if !defined(_XOPEN_SOURCE)
9
#define _XOPEN_SOURCE 600
10
#endif
11
#include "cubeb/cubeb.h"
12
#include <atomic>
13
#include <stdio.h>
14
#include <string.h>
15
#include <math.h>
16
#include "common.h"
17
18
0
#define STREAM_RATE 44100
19
0
#define STREAM_LATENCY 100 * STREAM_RATE / 1000
20
0
#define STREAM_CHANNELS 1
21
0
#define STREAM_LAYOUT CUBEB_LAYOUT_MONO
22
0
#define STREAM_FORMAT CUBEB_SAMPLE_S16LE
23
24
int is_windows_7()
25
0
{
26
#ifdef __MINGW32__
27
  fprintf(stderr, "Warning: this test was built with MinGW.\n"
28
         "MinGW does not contain necessary version checking infrastructure. Claiming to be Windows 7, even if we're not.\n");
29
  return 1;
30
#endif
31
#if (defined(_WIN32) || defined(__WIN32__)) && ( !defined(__MINGW32__))
32
  OSVERSIONINFOEX osvi;
33
  DWORDLONG condition_mask = 0;
34
35
  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
36
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
37
38
  // NT 6.1 is Windows 7
39
  osvi.dwMajorVersion = 6;
40
  osvi.dwMinorVersion = 1;
41
42
  VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_EQUAL);
43
  VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
44
45
  return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition_mask);
46
#else
47
  return 0;
48
0
#endif
49
0
}
50
51
static int dummy;
52
static std::atomic<uint64_t> total_frames_written;
53
static int delay_callback;
54
55
static long
56
test_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
57
0
{
58
0
  EXPECT_TRUE(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
59
0
  assert(outputbuffer);
60
0
  memset(outputbuffer, 0, nframes * sizeof(short));
61
0
62
0
  total_frames_written += nframes;
63
0
  if (delay_callback) {
64
0
    delay(10);
65
0
  }
66
0
  return nframes;
67
0
}
68
69
void
70
test_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state /*state*/)
71
0
{
72
0
}
73
74
TEST(cubeb, init_destroy_context)
75
0
{
76
0
  int r;
77
0
  cubeb * ctx;
78
0
  char const* backend_id;
79
0
80
0
  r = common_init(&ctx, "test_sanity");
81
0
  ASSERT_EQ(r, CUBEB_OK);
82
0
  ASSERT_NE(ctx, nullptr);
83
0
84
0
  backend_id = cubeb_get_backend_id(ctx);
85
0
  ASSERT_TRUE(backend_id);
86
0
87
0
  fprintf(stderr, "Backend: %s\n", backend_id);
88
0
89
0
  cubeb_destroy(ctx);
90
0
}
91
92
TEST(cubeb, init_destroy_multiple_contexts)
93
0
{
94
0
  size_t i;
95
0
  int r;
96
0
  cubeb * ctx[4];
97
0
  int order[4] = {2, 0, 3, 1};
98
0
  ASSERT_EQ(ARRAY_LENGTH(ctx), ARRAY_LENGTH(order));
99
0
100
0
  for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
101
0
    r = common_init(&ctx[i], NULL);
102
0
    ASSERT_EQ(r, CUBEB_OK);
103
0
    ASSERT_NE(ctx[i], nullptr);
104
0
  }
105
0
106
0
  /* destroy in a different order */
107
0
  for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
108
0
    cubeb_destroy(ctx[order[i]]);
109
0
  }
110
0
}
111
112
TEST(cubeb, context_variables)
113
0
{
114
0
  int r;
115
0
  cubeb * ctx;
116
0
  uint32_t value;
117
0
  cubeb_stream_params params;
118
0
119
0
  r = common_init(&ctx, "test_context_variables");
120
0
  ASSERT_EQ(r, CUBEB_OK);
121
0
  ASSERT_NE(ctx, nullptr);
122
0
123
0
  params.channels = STREAM_CHANNELS;
124
0
  params.format = STREAM_FORMAT;
125
0
  params.rate = STREAM_RATE;
126
0
  params.layout = STREAM_LAYOUT;
127
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
128
0
129
0
  r = cubeb_get_min_latency(ctx, &params, &value);
130
0
  ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
131
0
  if (r == CUBEB_OK) {
132
0
    ASSERT_TRUE(value > 0);
133
0
  }
134
0
135
0
  r = cubeb_get_preferred_sample_rate(ctx, &value);
136
0
  ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
137
0
  if (r == CUBEB_OK) {
138
0
    ASSERT_TRUE(value > 0);
139
0
  }
140
0
141
0
  cubeb_destroy(ctx);
142
0
}
143
144
TEST(cubeb, init_destroy_stream)
145
0
{
146
0
  int r;
147
0
  cubeb * ctx;
148
0
  cubeb_stream * stream;
149
0
  cubeb_stream_params params;
150
0
151
0
  r = common_init(&ctx, "test_sanity");
152
0
  ASSERT_EQ(r, CUBEB_OK);
153
0
  ASSERT_NE(ctx, nullptr);
154
0
155
0
  params.format = STREAM_FORMAT;
156
0
  params.rate = STREAM_RATE;
157
0
  params.channels = STREAM_CHANNELS;
158
0
  params.layout = STREAM_LAYOUT;
159
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
160
0
161
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
162
0
                        test_data_callback, test_state_callback, &dummy);
163
0
  ASSERT_EQ(r, CUBEB_OK);
164
0
  ASSERT_NE(stream, nullptr);
165
0
166
0
  cubeb_stream_destroy(stream);
167
0
  cubeb_destroy(ctx);
168
0
}
169
170
TEST(cubeb, init_destroy_multiple_streams)
171
0
{
172
0
  size_t i;
173
0
  int r;
174
0
  cubeb * ctx;
175
0
  cubeb_stream * stream[8];
176
0
  cubeb_stream_params params;
177
0
178
0
  r = common_init(&ctx, "test_sanity");
179
0
  ASSERT_EQ(r, CUBEB_OK);
180
0
  ASSERT_NE(ctx, nullptr);
181
0
182
0
  params.format = STREAM_FORMAT;
183
0
  params.rate = STREAM_RATE;
184
0
  params.channels = STREAM_CHANNELS;
185
0
  params.layout = STREAM_LAYOUT;
186
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
187
0
188
0
  for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
189
0
    r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
190
0
                          test_data_callback, test_state_callback, &dummy);
191
0
    ASSERT_EQ(r, CUBEB_OK);
192
0
    ASSERT_NE(stream[i], nullptr);
193
0
  }
194
0
195
0
  for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
196
0
    cubeb_stream_destroy(stream[i]);
197
0
  }
198
0
199
0
  cubeb_destroy(ctx);
200
0
}
201
202
TEST(cubeb, configure_stream)
203
0
{
204
0
  int r;
205
0
  cubeb * ctx;
206
0
  cubeb_stream * stream;
207
0
  cubeb_stream_params params;
208
0
209
0
  r = common_init(&ctx, "test_sanity");
210
0
  ASSERT_EQ(r, CUBEB_OK);
211
0
  ASSERT_NE(ctx, nullptr);
212
0
213
0
  params.format = STREAM_FORMAT;
214
0
  params.rate = STREAM_RATE;
215
0
  params.channels = 2; // panning
216
0
  params.layout = CUBEB_LAYOUT_STEREO;
217
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
218
0
219
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
220
0
                        test_data_callback, test_state_callback, &dummy);
221
0
  ASSERT_EQ(r, CUBEB_OK);
222
0
  ASSERT_NE(stream, nullptr);
223
0
224
0
  r = cubeb_stream_set_volume(stream, 1.0f);
225
0
  ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
226
0
227
0
  r = cubeb_stream_set_panning(stream, 0.0f);
228
0
  ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
229
0
230
0
  cubeb_stream_destroy(stream);
231
0
  cubeb_destroy(ctx);
232
0
}
233
234
TEST(cubeb, configure_stream_undefined_layout)
235
0
{
236
0
  int r;
237
0
  cubeb * ctx;
238
0
  cubeb_stream * stream;
239
0
  cubeb_stream_params params;
240
0
241
0
  r = common_init(&ctx, "test_sanity");
242
0
  ASSERT_EQ(r, CUBEB_OK);
243
0
  ASSERT_NE(ctx, nullptr);
244
0
245
0
  params.format = STREAM_FORMAT;
246
0
  params.rate = STREAM_RATE;
247
0
  params.channels = 2; // panning
248
0
  params.layout = CUBEB_LAYOUT_UNDEFINED;
249
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
250
0
251
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
252
0
                        test_data_callback, test_state_callback, &dummy);
253
0
  ASSERT_EQ(r, CUBEB_OK);
254
0
  ASSERT_NE(stream, nullptr);
255
0
256
0
  r = cubeb_stream_start(stream);
257
0
  ASSERT_EQ(r, CUBEB_OK);
258
0
259
0
  delay(100);
260
0
261
0
  r = cubeb_stream_stop(stream);
262
0
  ASSERT_EQ(r, CUBEB_OK);
263
0
264
0
  cubeb_stream_destroy(stream);
265
0
  cubeb_destroy(ctx);
266
0
}
267
268
static void
269
test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
270
0
{
271
0
  size_t i;
272
0
  int r;
273
0
  cubeb * ctx;
274
0
  cubeb_stream * stream[8];
275
0
  cubeb_stream_params params;
276
0
277
0
  r = common_init(&ctx, "test_sanity");
278
0
  ASSERT_EQ(r, CUBEB_OK);
279
0
  ASSERT_NE(ctx, nullptr);
280
0
281
0
  params.format = STREAM_FORMAT;
282
0
  params.rate = STREAM_RATE;
283
0
  params.channels = STREAM_CHANNELS;
284
0
  params.layout = STREAM_LAYOUT;
285
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
286
0
287
0
  for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
288
0
    r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
289
0
                          test_data_callback, test_state_callback, &dummy);
290
0
    ASSERT_EQ(r, CUBEB_OK);
291
0
    ASSERT_NE(stream[i], nullptr);
292
0
    if (early) {
293
0
      r = cubeb_stream_start(stream[i]);
294
0
      ASSERT_EQ(r, CUBEB_OK);
295
0
    }
296
0
  }
297
0
298
0
  if (!early) {
299
0
    for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
300
0
      r = cubeb_stream_start(stream[i]);
301
0
      ASSERT_EQ(r, CUBEB_OK);
302
0
    }
303
0
  }
304
0
305
0
  if (delay_ms) {
306
0
    delay(delay_ms);
307
0
  }
308
0
309
0
  if (!early) {
310
0
    for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
311
0
      r = cubeb_stream_stop(stream[i]);
312
0
      ASSERT_EQ(r, CUBEB_OK);
313
0
    }
314
0
  }
315
0
316
0
  for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
317
0
    if (early) {
318
0
      r = cubeb_stream_stop(stream[i]);
319
0
      ASSERT_EQ(r, CUBEB_OK);
320
0
    }
321
0
    cubeb_stream_destroy(stream[i]);
322
0
  }
323
0
324
0
  cubeb_destroy(ctx);
325
0
}
326
327
TEST(cubeb, init_start_stop_destroy_multiple_streams)
328
0
{
329
0
  /* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and
330
0
   * calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is
331
0
   * the HRESULT value for "Cannot create a file when that file already exists",
332
0
   * and is not documented as a possible return value for this call. Hence, we
333
0
   * try to limit the number of streams we create in this test. */
334
0
  if (!is_windows_7()) {
335
0
    delay_callback = 0;
336
0
    test_init_start_stop_destroy_multiple_streams(0, 0);
337
0
    test_init_start_stop_destroy_multiple_streams(1, 0);
338
0
    test_init_start_stop_destroy_multiple_streams(0, 150);
339
0
    test_init_start_stop_destroy_multiple_streams(1, 150);
340
0
    delay_callback = 1;
341
0
    test_init_start_stop_destroy_multiple_streams(0, 0);
342
0
    test_init_start_stop_destroy_multiple_streams(1, 0);
343
0
    test_init_start_stop_destroy_multiple_streams(0, 150);
344
0
    test_init_start_stop_destroy_multiple_streams(1, 150);
345
0
  }
346
0
}
347
348
TEST(cubeb, init_destroy_multiple_contexts_and_streams)
349
0
{
350
0
  size_t i, j;
351
0
  int r;
352
0
  cubeb * ctx[2];
353
0
  cubeb_stream * stream[8];
354
0
  cubeb_stream_params params;
355
0
  size_t streams_per_ctx = ARRAY_LENGTH(stream) / ARRAY_LENGTH(ctx);
356
0
  ASSERT_EQ(ARRAY_LENGTH(ctx) * streams_per_ctx, ARRAY_LENGTH(stream));
357
0
358
0
  /* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and
359
0
   * calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is
360
0
   * the HRESULT value for "Cannot create a file when that file already exists",
361
0
   * and is not documented as a possible return value for this call. Hence, we
362
0
   * try to limit the number of streams we create in this test. */
363
0
  if (is_windows_7())
364
0
    return;
365
0
366
0
  params.format = STREAM_FORMAT;
367
0
  params.rate = STREAM_RATE;
368
0
  params.channels = STREAM_CHANNELS;
369
0
  params.layout = STREAM_LAYOUT;
370
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
371
0
372
0
  for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
373
0
    r = common_init(&ctx[i], "test_sanity");
374
0
    ASSERT_EQ(r, CUBEB_OK);
375
0
    ASSERT_NE(ctx[i], nullptr);
376
0
377
0
    for (j = 0; j < streams_per_ctx; ++j) {
378
0
      r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
379
0
                            test_data_callback, test_state_callback, &dummy);
380
0
      ASSERT_EQ(r, CUBEB_OK);
381
0
      ASSERT_NE(stream[i * streams_per_ctx + j], nullptr);
382
0
    }
383
0
  }
384
0
385
0
  for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
386
0
    for (j = 0; j < streams_per_ctx; ++j) {
387
0
      cubeb_stream_destroy(stream[i * streams_per_ctx + j]);
388
0
    }
389
0
    cubeb_destroy(ctx[i]);
390
0
  }
391
0
}
392
393
TEST(cubeb, basic_stream_operations)
394
0
{
395
0
  int r;
396
0
  cubeb * ctx;
397
0
  cubeb_stream * stream;
398
0
  cubeb_stream_params params;
399
0
  uint64_t position;
400
0
401
0
  r = common_init(&ctx, "test_sanity");
402
0
  ASSERT_EQ(r, CUBEB_OK);
403
0
  ASSERT_NE(ctx, nullptr);
404
0
405
0
  params.format = STREAM_FORMAT;
406
0
  params.rate = STREAM_RATE;
407
0
  params.channels = STREAM_CHANNELS;
408
0
  params.layout = STREAM_LAYOUT;
409
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
410
0
411
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
412
0
                        test_data_callback, test_state_callback, &dummy);
413
0
  ASSERT_EQ(r, CUBEB_OK);
414
0
  ASSERT_NE(stream, nullptr);
415
0
416
0
  /* position and volume before stream has started */
417
0
  r = cubeb_stream_get_position(stream, &position);
418
0
  ASSERT_EQ(r, CUBEB_OK);
419
0
  ASSERT_EQ(position, 0u);
420
0
421
0
  r = cubeb_stream_start(stream);
422
0
  ASSERT_EQ(r, CUBEB_OK);
423
0
424
0
  /* position and volume after while stream running */
425
0
  r = cubeb_stream_get_position(stream, &position);
426
0
  ASSERT_EQ(r, CUBEB_OK);
427
0
428
0
  r = cubeb_stream_stop(stream);
429
0
  ASSERT_EQ(r, CUBEB_OK);
430
0
431
0
  /* position and volume after stream has stopped */
432
0
  r = cubeb_stream_get_position(stream, &position);
433
0
  ASSERT_EQ(r, CUBEB_OK);
434
0
435
0
  cubeb_stream_destroy(stream);
436
0
  cubeb_destroy(ctx);
437
0
}
438
439
TEST(cubeb, stream_position)
440
0
{
441
0
  size_t i;
442
0
  int r;
443
0
  cubeb * ctx;
444
0
  cubeb_stream * stream;
445
0
  cubeb_stream_params params;
446
0
  uint64_t position, last_position;
447
0
448
0
  total_frames_written = 0;
449
0
450
0
  r = common_init(&ctx, "test_sanity");
451
0
  ASSERT_EQ(r, CUBEB_OK);
452
0
  ASSERT_NE(ctx, nullptr);
453
0
454
0
  params.format = STREAM_FORMAT;
455
0
  params.rate = STREAM_RATE;
456
0
  params.channels = STREAM_CHANNELS;
457
0
  params.layout = STREAM_LAYOUT;
458
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
459
0
460
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
461
0
                        test_data_callback, test_state_callback, &dummy);
462
0
  ASSERT_EQ(r, CUBEB_OK);
463
0
  ASSERT_NE(stream, nullptr);
464
0
465
0
  /* stream position should not advance before starting playback */
466
0
  r = cubeb_stream_get_position(stream, &position);
467
0
  ASSERT_EQ(r, CUBEB_OK);
468
0
  ASSERT_EQ(position, 0u);
469
0
470
0
  delay(500);
471
0
472
0
  r = cubeb_stream_get_position(stream, &position);
473
0
  ASSERT_EQ(r, CUBEB_OK);
474
0
  ASSERT_EQ(position, 0u);
475
0
476
0
  /* stream position should advance during playback */
477
0
  r = cubeb_stream_start(stream);
478
0
  ASSERT_EQ(r, CUBEB_OK);
479
0
480
0
  /* XXX let start happen */
481
0
  delay(500);
482
0
483
0
  /* stream should have prefilled */
484
0
  ASSERT_TRUE(total_frames_written.load() > 0);
485
0
486
0
  r = cubeb_stream_get_position(stream, &position);
487
0
  ASSERT_EQ(r, CUBEB_OK);
488
0
  last_position = position;
489
0
490
0
  delay(500);
491
0
492
0
  r = cubeb_stream_get_position(stream, &position);
493
0
  ASSERT_EQ(r, CUBEB_OK);
494
0
  ASSERT_GE(position, last_position);
495
0
  last_position = position;
496
0
497
0
  /* stream position should not exceed total frames written */
498
0
  for (i = 0; i < 5; ++i) {
499
0
    r = cubeb_stream_get_position(stream, &position);
500
0
    ASSERT_EQ(r, CUBEB_OK);
501
0
    ASSERT_GE(position, last_position);
502
0
    ASSERT_LE(position, total_frames_written.load());
503
0
    last_position = position;
504
0
    delay(500);
505
0
  }
506
0
507
0
  /* test that the position is valid even when starting and
508
0
   * stopping the stream.  */
509
0
  for (i = 0; i < 5; ++i) {
510
0
    r = cubeb_stream_stop(stream);
511
0
    ASSERT_EQ(r, CUBEB_OK);
512
0
    r = cubeb_stream_get_position(stream, &position);
513
0
    ASSERT_EQ(r, CUBEB_OK);
514
0
    ASSERT_TRUE(last_position < position);
515
0
    last_position = position;
516
0
    delay(500);
517
0
    r = cubeb_stream_start(stream);
518
0
    ASSERT_EQ(r, CUBEB_OK);
519
0
    delay(500);
520
0
  }
521
0
522
0
  ASSERT_NE(last_position, 0u);
523
0
524
0
  /* stream position should not advance after stopping playback */
525
0
  r = cubeb_stream_stop(stream);
526
0
  ASSERT_EQ(r, CUBEB_OK);
527
0
528
0
  /* XXX allow stream to settle */
529
0
  delay(500);
530
0
531
0
  r = cubeb_stream_get_position(stream, &position);
532
0
  ASSERT_EQ(r, CUBEB_OK);
533
0
  last_position = position;
534
0
535
0
  delay(500);
536
0
537
0
  r = cubeb_stream_get_position(stream, &position);
538
0
  ASSERT_EQ(r, CUBEB_OK);
539
0
  ASSERT_EQ(position, last_position);
540
0
541
0
  cubeb_stream_destroy(stream);
542
0
  cubeb_destroy(ctx);
543
0
}
544
545
static std::atomic<int> do_drain;
546
static std::atomic<int> got_drain;
547
548
static long
549
test_drain_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
550
0
{
551
0
  EXPECT_TRUE(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
552
0
  assert(outputbuffer);
553
0
  if (do_drain == 1) {
554
0
    do_drain = 2;
555
0
    return 0;
556
0
  }
557
0
  /* once drain has started, callback must never be called again */
558
0
  EXPECT_TRUE(do_drain != 2);
559
0
  memset(outputbuffer, 0, nframes * sizeof(short));
560
0
  total_frames_written += nframes;
561
0
  return nframes;
562
0
}
563
564
void
565
test_drain_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state state)
566
0
{
567
0
  if (state == CUBEB_STATE_DRAINED) {
568
0
    ASSERT_TRUE(!got_drain);
569
0
    got_drain = 1;
570
0
  }
571
0
}
572
573
TEST(cubeb, drain)
574
0
{
575
0
  int r;
576
0
  cubeb * ctx;
577
0
  cubeb_stream * stream;
578
0
  cubeb_stream_params params;
579
0
  uint64_t position;
580
0
581
0
  delay_callback = 0;
582
0
  total_frames_written = 0;
583
0
584
0
  r = common_init(&ctx, "test_sanity");
585
0
  ASSERT_EQ(r, CUBEB_OK);
586
0
  ASSERT_NE(ctx, nullptr);
587
0
588
0
  params.format = STREAM_FORMAT;
589
0
  params.rate = STREAM_RATE;
590
0
  params.channels = STREAM_CHANNELS;
591
0
  params.layout = STREAM_LAYOUT;
592
0
  params.prefs = CUBEB_STREAM_PREF_NONE;
593
0
594
0
  r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
595
0
                        test_drain_data_callback, test_drain_state_callback, &dummy);
596
0
  ASSERT_EQ(r, CUBEB_OK);
597
0
  ASSERT_NE(stream, nullptr);
598
0
599
0
  r = cubeb_stream_start(stream);
600
0
  ASSERT_EQ(r, CUBEB_OK);
601
0
602
0
  delay(500);
603
0
604
0
  do_drain = 1;
605
0
606
0
  for (;;) {
607
0
    r = cubeb_stream_get_position(stream, &position);
608
0
    ASSERT_EQ(r, CUBEB_OK);
609
0
    if (got_drain) {
610
0
      break;
611
0
    } else {
612
0
      ASSERT_LE(position, total_frames_written.load());
613
0
    }
614
0
    delay(500);
615
0
  }
616
0
617
0
  r = cubeb_stream_get_position(stream, &position);
618
0
  ASSERT_EQ(r, CUBEB_OK);
619
0
  ASSERT_TRUE(got_drain);
620
0
621
0
  // Really, we should be able to rely on position reaching our final written frame, but
622
0
  // for now let's make sure it doesn't continue beyond that point.
623
0
  //ASSERT_LE(position, total_frames_written.load());
624
0
625
0
  cubeb_stream_destroy(stream);
626
0
  cubeb_destroy(ctx);
627
0
628
0
  got_drain = 0;
629
0
  do_drain = 0;
630
0
}
631
632
TEST(cubeb, DISABLED_eos_during_prefill)
633
0
{
634
0
  // This test needs to be implemented.
635
0
}
636
637
TEST(cubeb, DISABLED_stream_destroy_pending_drain)
638
0
{
639
0
  // This test needs to be implemented.
640
0
}
641
642
TEST(cubeb, stable_devid)
643
0
{
644
0
  /* Test that the devid field of cubeb_device_info is stable
645
0
   * (ie. compares equal) over two invocations of
646
0
   * cubeb_enumerate_devices(). */
647
0
648
0
  int r;
649
0
  cubeb * ctx;
650
0
  cubeb_device_collection first;
651
0
  cubeb_device_collection second;
652
0
  cubeb_device_type all_devices =
653
0
    (cubeb_device_type) (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT);
654
0
  size_t n;
655
0
656
0
  r = common_init(&ctx, "test_sanity");
657
0
  ASSERT_EQ(r, CUBEB_OK);
658
0
  ASSERT_NE(ctx, nullptr);
659
0
660
0
  r = cubeb_enumerate_devices(ctx, all_devices, &first);
661
0
  if (r == CUBEB_ERROR_NOT_SUPPORTED)
662
0
    return;
663
0
664
0
  ASSERT_EQ(r, CUBEB_OK);
665
0
666
0
  r = cubeb_enumerate_devices(ctx, all_devices, &second);
667
0
  ASSERT_EQ(r, CUBEB_OK);
668
0
669
0
  ASSERT_EQ(first.count, second.count);
670
0
  for (n = 0; n < first.count; n++) {
671
0
    ASSERT_EQ(first.device[n].devid, second.device[n].devid);
672
0
  }
673
0
674
0
  r = cubeb_device_collection_destroy(ctx, &first);
675
0
  ASSERT_EQ(r, CUBEB_OK);
676
0
  r = cubeb_device_collection_destroy(ctx, &second);
677
0
  ASSERT_EQ(r, CUBEB_OK);
678
0
  cubeb_destroy(ctx);
679
0
}