aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-03-08 23:39:37 +0100
committerDavid Robillard <d@drobilla.net>2019-12-20 10:26:55 -0500
commit12b217de575a35a05e8a09fd7403f7e9852f8485 (patch)
tree012f3c0d484abb60968fb576f27d4fa226d6c943
parent9301afbc10a7092994ed3868135975f6fbc6f351 (diff)
downloadserd-12b217de575a35a05e8a09fd7403f7e9852f8485.tar.gz
serd-12b217de575a35a05e8a09fd7403f7e9852f8485.tar.bz2
serd-12b217de575a35a05e8a09fd7403f7e9852f8485.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 1d2c672f..b29a905b 100644
--- a/src/byte_source.h
+++ b/src/byte_source.h
@@ -90,12 +90,12 @@ 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 if (source->read_head == source->buf_size) {
source->eof = true;
}
} 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 36c27e28..05f49b60 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -72,6 +72,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 void
test_file_uri(const char* hostname,
const char* path,
@@ -806,6 +833,44 @@ test_reader(const char* path)
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);