aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-03-08 23:39:37 +0100
committerDavid Robillard <d@drobilla.net>2020-06-21 18:12:04 +0200
commit213b1f81520c848457f4560334392ec29c31fb10 (patch)
treed2fb81c3bf28fea8a950b97819180e9e5cfafee5
parent3cedb716d80451b93f26400baba2bb7526dc60f2 (diff)
downloadserd-213b1f81520c848457f4560334392ec29c31fb10.tar.gz
serd-213b1f81520c848457f4560334392ec29c31fb10.tar.bz2
serd-213b1f81520c848457f4560334392ec29c31fb10.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 198c92a8..9dc93620 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 7f75248b..2973e4a9 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);