aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-03-08 23:39:37 +0100
committerDavid Robillard <d@drobilla.net>2019-04-13 19:48:23 +0200
commit65fbd3c8e9cbe78d1a342acd442019a010b058c2 (patch)
tree7b61e9d238849d8595d6bc0673028e5001c7c7fd
parenta3695dd1e422bd3e3b22b1ad78a4a0a59b34507c (diff)
downloadserd-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.h2
-rw-r--r--tests/serd_test.c65
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);