diff options
author | David Robillard <d@drobilla.net> | 2019-03-08 23:39:37 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-04-13 19:48:23 +0200 |
commit | 65fbd3c8e9cbe78d1a342acd442019a010b058c2 (patch) | |
tree | 7b61e9d238849d8595d6bc0673028e5001c7c7fd | |
parent | a3695dd1e422bd3e3b22b1ad78a4a0a59b34507c (diff) | |
download | serd-65fbd3c8e9cbe78d1a342acd442019a010b058c2.tar.gz serd-65fbd3c8e9cbe78d1a342acd442019a010b058c2.tar.bz2 serd-65fbd3c8e9cbe78d1a342acd442019a010b058c2.zip |
Fix reading from socket-like streams and add test
-rw-r--r-- | src/byte_source.h | 2 | ||||
-rw-r--r-- | tests/serd_test.c | 65 |
2 files changed, 66 insertions, 1 deletions
diff --git a/src/byte_source.h b/src/byte_source.h index 4dfff70f..c12ab778 100644 --- a/src/byte_source.h +++ b/src/byte_source.h @@ -89,10 +89,10 @@ serd_byte_source_advance(SerdByteSource* source) if (source->from_stream) { if (source->page_size > 1) { if (++source->read_head == source->page_size) { - source->eof = false; st = serd_byte_source_page(source); } } else { + source->eof = false; if (!source->read_func(&source->read_byte, 1, 1, source->stream)) { source->eof = true; st = source->error_func(source->stream) ? SERD_ERR_UNKNOWN diff --git a/tests/serd_test.c b/tests/serd_test.c index 6f323f43..d3a8f514 100644 --- a/tests/serd_test.c +++ b/tests/serd_test.c @@ -74,6 +74,33 @@ count_statements(void* handle, return SERD_SUCCESS; } +/// Returns EOF after a statement, then succeeds again (like a socket) +static size_t +eof_test_read(void* buf, size_t size, size_t nmemb, void* stream) +{ + assert(nmemb == 1); + + static const char* const string = "_:s1 <http://example.org/p> _:o1 .\n" + "_:s2 <http://example.org/p> _:o2 .\n"; + + size_t* count = (size_t*)stream; + if (*count == 34 || *count == 35 || *count + nmemb >= strlen(string)) { + ++*count; + return 0; + } + + memcpy((char*)buf, string + *count, size * nmemb); + *count += nmemb; + return nmemb; +} + +static int +eof_test_error(void* stream) +{ + (void)stream; + return 0; +} + static int check_file_uri(const char* hostname, const char* path, @@ -647,6 +674,44 @@ main(void) assert(n_statements == 13); serd_reader_finish(reader); + // A reader a big page hits EOF then fails to read chunks immediately + { + FILE* temp = tmpfile(); + assert(temp); + fprintf(temp, "_:s <http://example.org/p> _:o .\n"); + fflush(temp); + fseek(temp, 0L, SEEK_SET); + + serd_reader_start_stream( + reader, + (SerdReadFunc)fread, (SerdStreamErrorFunc)ferror, temp, + NULL, + 4096); + + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + + serd_reader_finish(reader); + fclose(temp); + } + + // A byte-wise reader that hits EOF once then continues (like a socket) + { + size_t n_reads = 0; + serd_reader_start_stream(reader, + (SerdReadFunc)eof_test_read, + (SerdStreamErrorFunc)eof_test_error, + &n_reads, + NULL, + 1); + + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + } + serd_reader_free(reader); serd_sink_free(sink); fclose(fd); |