PageRenderTime 29ms CodeModel.GetById 14ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/seek/seek-read-error.c

https://bitbucket.org/achurch_/libnogg
C | 177 lines | 143 code | 20 blank | 14 comment | 31 complexity | 46aa7a934849fc07c9ea55bf0022c4f0 MD5 | raw file
  1/*
  2 * libnogg: a decoder library for Ogg Vorbis streams
  3 * Copyright (c) 2014-2015 Andrew Church <achurch@achurch.org>
  4 *
  5 * This software may be copied and redistributed under certain conditions;
  6 * see the file "COPYING" in the source code distribution for details.
  7 * NO WARRANTY is provided with this software.
  8 */
  9
 10#include "include/nogg.h"
 11#include "src/common.h"  // For lenof().
 12#include "tests/common.h"
 13
 14#include "tests/data/noise-6ch_float.h"  // Defines expected_pcm[].
 15
 16
 17static int64_t length(void *opaque)
 18{
 19    FILE *f = (FILE *)opaque;
 20    const long saved_offset = ftell(f);
 21    if (fseek(f, 0, SEEK_END) != 0) {
 22        return -1;
 23    }
 24    const int64_t len = ftell(f);
 25    if (fseek(f, saved_offset, SEEK_SET) != 0) {
 26        return -1;
 27    }
 28    return len;
 29}
 30
 31static int64_t tell(void *opaque)
 32{
 33    return ftell((FILE *)opaque);
 34}
 35
 36static void seek(void *opaque, int64_t offset)
 37{
 38    fseek((FILE *)opaque, offset, SEEK_SET);
 39}
 40
 41static int read_count;
 42static int32_t read(void *opaque, void *buf, int32_t len)
 43{
 44    if (read_count > 0) {
 45        read_count--;
 46        return fread(buf, 1, len, (FILE *)opaque);
 47    } else {
 48        return 0;
 49    }
 50}
 51
 52static void close(void *opaque)
 53{
 54    fclose((FILE *)opaque);
 55}
 56
 57
 58int main(void)
 59{
 60    FILE *f;
 61    vorbis_t *vorbis;
 62
 63    read_count = 10000;
 64    EXPECT_TRUE(f = fopen("tests/data/6ch-all-page-types.ogg", "rb"));
 65    EXPECT_TRUE(vorbis = vorbis_open_callbacks(((const vorbis_callbacks_t){
 66                                                   .length = length,
 67                                                   .tell = tell,
 68                                                   .seek = seek,
 69                                                   .read = read,
 70                                                   .close = close}),
 71                                               f, 0, NULL));
 72
 73    /* Make sure the first and last page data is cached before we start
 74     * failing read operations, or seeks won't work at all. */
 75    EXPECT_TRUE(vorbis_seek(vorbis, 0));
 76
 77    static const int seek_offsets[] = {0, 2000, 8499};
 78    for (int i = 0; i < lenof(seek_offsets); i++) {
 79        const int offset = seek_offsets[i];
 80        int32_t j;
 81        for (j = 0; j < 10000; j++) {
 82            read_count = j;
 83            if (vorbis_seek(vorbis, offset)) {
 84                break;
 85            }
 86        }
 87        if (j == 10000) {
 88            printf("%s:%d: Seek to %d failed\n", __FILE__, __LINE__, offset);
 89            return EXIT_FAILURE;
 90        }
 91        read_count = 10000;
 92
 93        float pcm[6];
 94        vorbis_error_t error = (vorbis_error_t)-1;
 95        const int num_read = vorbis_read_float(vorbis, pcm, 1, &error);
 96        if (num_read == 0 && error == VORBIS_ERROR_STREAM_END) {
 97            /* The decode_frame() call in vorbis_seek() hit a read error
 98             * at a page boundary, which gets interpreted as end-of-stream.
 99             * There's not much we can do about this case, so just let it
100             * slide. */
101            continue;
102        }
103        if (num_read != 1) {
104            fprintf(stderr, "%s:%d: Failed to read sample %d (error %d)\n",
105                    __FILE__, __LINE__, offset, error);
106            return EXIT_FAILURE;
107        }
108        if (error != VORBIS_NO_ERROR) {
109            fprintf(stderr, "%s:%d: error was %d but should have been %d"
110                    " for sample %d\n", __FILE__, __LINE__, error,
111                    VORBIS_NO_ERROR, offset);
112            return EXIT_FAILURE;
113        }
114        for (j = 0; j < 6; j++) {
115            if (fabsf(pcm[j] - expected_pcm[offset*6+j]) > 1.0e-6f) {
116                fprintf(stderr, "%s:%d: Sample %d+%d was %.8g but should have"
117                        " been near %.8g\n", __FILE__, __LINE__, offset, j,
118                        pcm[j], expected_pcm[offset*6+j]);
119                return EXIT_FAILURE;
120            }
121        }
122    }
123
124    vorbis_close(vorbis);
125
126    read_count = 10000;
127    EXPECT_TRUE(f = fopen("tests/data/6ch-long-first-packet.ogg", "rb"));
128    EXPECT_TRUE(vorbis = vorbis_open_callbacks(((const vorbis_callbacks_t){
129                                                   .length = length,
130                                                   .tell = tell,
131                                                   .seek = seek,
132                                                   .read = read,
133                                                   .close = close}),
134                                               f, 0, NULL));
135    EXPECT_TRUE(vorbis_seek(vorbis, 0));
136
137    const int offset = 500;
138    int32_t j;
139    for (j = 0; j < 10000; j++) {
140        read_count = j;
141        if (vorbis_seek(vorbis, offset)) {
142            break;
143        }
144    }
145    if (j == 10000) {
146        printf("%s:%d: Seek to %d failed\n", __FILE__, __LINE__, offset);
147        return EXIT_FAILURE;
148    }
149    read_count = 10000;
150
151    float pcm[6];
152    vorbis_error_t error = (vorbis_error_t)-1;
153    const int num_read = vorbis_read_float(vorbis, pcm, 1, &error);
154    if (num_read != 1) {
155        fprintf(stderr, "%s:%d: Failed to read sample %d (error %d)\n",
156                __FILE__, __LINE__, offset, error);
157        return EXIT_FAILURE;
158    }
159    if (error != VORBIS_NO_ERROR) {
160        fprintf(stderr, "%s:%d: error was %d but should have been %d"
161                " for sample %d\n", __FILE__, __LINE__, error,
162                VORBIS_NO_ERROR, offset);
163        return EXIT_FAILURE;
164    }
165    for (j = 0; j < 6; j++) {
166        if (fabsf(pcm[j] - expected_pcm[offset*6+j]) > 1.0e-6f) {
167            fprintf(stderr, "%s:%d: Sample %d+%d was %.8g but should have"
168                    " been near %.8g\n", __FILE__, __LINE__, offset, j,
169                    pcm[j], expected_pcm[offset*6+j]);
170            return EXIT_FAILURE;
171        }
172    }
173
174    vorbis_close(vorbis);
175
176    return EXIT_SUCCESS;
177}