diff options
Diffstat (limited to 'src/libdisfluid')
-rw-r--r-- | src/libdisfluid/Makefile.am | 3 | ||||
-rw-r--r-- | src/libdisfluid/disfluid-cache-entry.h | 504 | ||||
-rw-r--r-- | src/libdisfluid/disfluid-tests.h | 283 | ||||
-rw-r--r-- | src/libdisfluid/main.c | 100 |
4 files changed, 885 insertions, 5 deletions
diff --git a/src/libdisfluid/Makefile.am b/src/libdisfluid/Makefile.am index 97c2ba3..002074d 100644 --- a/src/libdisfluid/Makefile.am +++ b/src/libdisfluid/Makefile.am @@ -2,6 +2,7 @@ lib_LTLIBRARIES += %D%/libdisfluid.la %C%_libdisfluid_la_SOURCES = \ %D%/disfluid-authors.h \ + %D%/disfluid-cache-entry.h \ %D%/disfluid-init.h \ %D%/disfluid-tests.h \ %D%/disfluid-version.h \ @@ -22,6 +23,8 @@ lib_LTLIBRARIES += %D%/libdisfluid.la %C%_libdisfluid_la_LDFLAGS = \ -no-undefined \ -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ + $(CLOCK_TIME_LIB) \ + $(GETRANDOM_LIB) \ $(LIBTHREAD) \ $(LTLIBINTL) \ $(SETLOCALE_LIB) \ diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h new file mode 100644 index 0000000..c0ddaf2 --- /dev/null +++ b/src/libdisfluid/disfluid-cache-entry.h @@ -0,0 +1,504 @@ +#ifndef DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED +# define DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED + +MAYBE_UNUSED static struct disfluid_cache_entry *cache_entry_alloc (void); + +MAYBE_UNUSED static void +cache_entry_free (struct disfluid_cache_entry *entry); + +MAYBE_UNUSED static struct disfluid_cache_entry + *cache_entry_from_file_name (const char *file_name); + +MAYBE_UNUSED static struct disfluid_cache_entry *cache_entry_from_fd (int fd); + +MAYBE_UNUSED static int +cache_entry_save_other_file_name (const struct disfluid_cache_entry *entry, + const char *file_name); + +MAYBE_UNUSED static int +cache_entry_save_other_fd (const struct disfluid_cache_entry *entry, int fd); + +MAYBE_UNUSED static void +cache_entry_set_request_date (struct disfluid_cache_entry *entry, + const struct timespec *date); + +MAYBE_UNUSED static void +cache_entry_set_response_date (struct disfluid_cache_entry *entry, + const struct timespec *date); + +MAYBE_UNUSED static void +cache_entry_invalidate (struct disfluid_cache_entry *entry); + +MAYBE_UNUSED static void +cache_entry_set_invalidated (struct disfluid_cache_entry *entry, + bool invalidated); + +MAYBE_UNUSED static void +cache_entry_get_request_date (const struct disfluid_cache_entry *entry, + struct timespec *date); + +MAYBE_UNUSED static void +cache_entry_get_response_date (const struct disfluid_cache_entry *entry, + struct timespec *date); + +MAYBE_UNUSED static bool +cache_entry_invalidated (const struct disfluid_cache_entry *entry); + +# include <assert.h> + +# include "disfluid-init.h" + +struct disfluid_cache_entry +{ + int fd; + off_t start; + off_t header_stop; + struct timespec request_date; + struct timespec response_date; + bool invalidated; +}; + +static struct disfluid_cache_entry * +cache_entry_alloc (void) +{ + ensure_init (); + struct disfluid_cache_entry *ret = + malloc (sizeof (struct disfluid_cache_entry)); + if (ret == NULL) + { + abort (); + } + ret->fd = -1; + ret->start = 0; + ret->header_stop = 0; + ret->request_date.tv_sec = 0; + ret->request_date.tv_nsec = 0; + ret->response_date.tv_sec = 0; + ret->response_date.tv_nsec = 0; + ret->invalidated = false; + return ret; +} + +static void +cache_entry_free (struct disfluid_cache_entry *entry) +{ + if (entry != NULL) + { + if (entry->fd >= 0) + { + close (entry->fd); + } + } + free (entry); +} + +static struct disfluid_cache_entry * +cache_entry_from_file_name (const char *file_name) +{ + int fd = open (file_name, O_RDONLY, S_IRUSR); + if (fd < 0) + { + abort (); + } + struct disfluid_cache_entry *ret = cache_entry_from_fd (fd); + if (ret == NULL) + { + abort (); + } + return ret; +} + +static inline void +cache_entry_string_append (char **str, size_t *max, size_t *n, + size_t suffix_length, const char *suffix) +{ + if (*n + suffix_length > *max) + { + *str = realloc (*str, 2 * *max); + if (*str == NULL) + { + abort (); + } + *max *= 2; + cache_entry_string_append (str, max, n, suffix_length, suffix); + } + else + { + memcpy (&((*str)[*n]), suffix, suffix_length); + *n += suffix_length; + } +} + +static inline ssize_t +cache_entry_read_next_line_aux (int fd, size_t *restrict buffer_max, + size_t *restrict buffer_length, char **buffer, + size_t checked) +{ + while (checked + 1 < *buffer_length + && ((*buffer)[checked] != '\r' || (*buffer)[checked + 1] != '\n')) + { + checked++; + } + if (checked + 1 < *buffer_length) + { + return checked + 2; + } + if (*buffer_length == *buffer_max) + { + *buffer = realloc (*buffer, 2 * *buffer_max); + if (*buffer == NULL) + { + abort (); + } + *buffer_max *= 2; + } + assert (*buffer_max > *buffer_length); + ssize_t n_added = + read (fd, &((*buffer)[*buffer_length]), *buffer_max - *buffer_length); + if (n_added < 0) + { + abort (); + } + else if (n_added == 0) + { + return *buffer_length; + } + else + { + assert (*buffer_length + n_added <= *buffer_max); + *buffer_length += n_added; + } + return cache_entry_read_next_line_aux (fd, buffer_max, buffer_length, + buffer, checked); +} + +static inline void +cache_entry_read_next_line (int fd, size_t *restrict buffer_max, + size_t *restrict buffer_length, char **buffer, + char **line, size_t *line_length) +{ + ssize_t length = + cache_entry_read_next_line_aux (fd, buffer_max, buffer_length, buffer, 0); + if (length < 0) + { + abort (); + } + *line = malloc (length + 1); + if (*line == NULL) + { + abort (); + } + *line_length = length; + memcpy (*line, *buffer, length); + (*line)[length] = '\0'; + memmove (*buffer, &((*buffer)[length]), *buffer_length - length); + *buffer_length -= length; +} + +static inline void +cache_entry_enumerate_header_lines (const struct disfluid_cache_entry *entry, + void (*cb) (void *, const char *, + const char *), void *context) +{ + off_t start_offset = lseek (entry->fd, 0, SEEK_CUR); + if (start_offset < 0) + { + abort (); + } + size_t buffer_max = 1; + size_t buffer_length = 0; + char *buffer = malloc (buffer_max); + if (buffer == NULL) + { + abort (); + } + char *line; + size_t line_length; + while (true) + { + cache_entry_read_next_line (entry->fd, &buffer_max, &buffer_length, + &buffer, &line, &line_length); + if (line == NULL) + { + /* Memory error */ + abort (); + } + if (STREQ (line, "\r\n")) + { + /* End of parse */ + ssize_t undo = buffer_length; + lseek (entry->fd, -undo, SEEK_CUR); + free (buffer); + free (line); + return; + } + char *header_name = malloc (line_length + 1); + if (header_name == NULL) + { + abort (); + } + size_t header_name_length = 0; + for (header_name_length = 0; + header_name_length < line_length + && line[header_name_length] != ':'; header_name_length++) + { + if (line[header_name_length] >= 'A' + && line[header_name_length] <= 'Z') + { + line[header_name_length] = + (line[header_name_length] - 'A') + 'a'; + } + header_name[header_name_length] = line[header_name_length]; + } + header_name[header_name_length] = '\0'; + if (line[header_name_length] != ':') + { + /* HTTP bad header, restore position */ + lseek (entry->fd, start_offset, SEEK_SET); + free (buffer); + free (line); + free (header_name); + return; + } + header_name_length++; + cb (context, header_name, &(line[header_name_length])); + free (line); + free (header_name); + } +} + +static inline void +cache_entry_parse_timespec (const char *data, struct timespec *ts) +{ + /* A timespec is represented as SSS.NNN where SSS is the number of seconds, and NNN the number of nanoseconds. */ + while (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n') + { + data++; + } + struct timespec r = {.tv_sec = 0,.tv_nsec = 0 }; + size_t n_seconds_digits = 0; + for (n_seconds_digits = 0; + data[n_seconds_digits] >= '0' && data[n_seconds_digits] <= '9'; + n_seconds_digits++) + { + r.tv_sec *= 10; + r.tv_sec += (data[n_seconds_digits] - '0'); + } + data += n_seconds_digits; + const bool has_dot = (data[0] == '.'); + if (has_dot) + { + data++; + } + int nano_digits[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + for (size_t i = 0; i < 9 && data[i] >= '0' && data[i] <= '9'; i++) + { + nano_digits[i] = (data[i] - '0'); + } + for (size_t i = 0; i < 9; i++) + { + r.tv_nsec *= 10; + r.tv_nsec += nano_digits[i]; + } + ts->tv_sec = r.tv_sec; + ts->tv_nsec = r.tv_nsec; +} + +static inline void +cache_entry_iterate_metadata (void *ctx, const char *header, + const char *value) +{ + struct disfluid_cache_entry *entry = ctx; + if (STREQ (header, "request-date")) + { + cache_entry_parse_timespec (value, &(entry->request_date)); + } + else if (STREQ (header, "response-date")) + { + cache_entry_parse_timespec (value, &(entry->response_date)); + } + else if (STREQ (header, "invalidated")) + { + while (*value == ' ' || *value == '\t' || *value == '\r' + || *value == '\n') + { + value++; + } + if (STREQ (value, "true\r\n")) + { + entry->invalidated = true; + } + else if (STREQ (value, "false\r\n")) + { + entry->invalidated = false; + } + } +} + +static inline void +cache_entry_scan (struct disfluid_cache_entry *entry) +{ + entry->start = lseek (entry->fd, 0, SEEK_CUR); + cache_entry_enumerate_header_lines (entry, cache_entry_iterate_metadata, + entry); + entry->header_stop = lseek (entry->fd, 0, SEEK_CUR); + /* Reset the file descriptor position, in case it is shared */ + lseek (entry->fd, entry->start, SEEK_SET); +} + +static struct disfluid_cache_entry * +cache_entry_from_fd (int fd) +{ + struct disfluid_cache_entry *ret = cache_entry_alloc (); + if (ret == NULL) + { + abort (); + } + ret->fd = dup (fd); + if (ret->fd < 0) + { + abort (); + } + cache_entry_scan (ret); + assert (ret->start >= 0); + assert (ret->header_stop >= 0); + if (ret->header_stop == ret->start) + { + /* Assume that reading failed. */ + cache_entry_free (ret); + ret = NULL; + } + return ret; +} + +static int +cache_entry_save_other_file_name (const struct disfluid_cache_entry *entry, + const char *file_name) +{ + int fd = open (file_name, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP); + if (fd < 0) + { + return errno; + } + return cache_entry_save_other_fd (entry, fd); +} + +static int +cache_entry_save_other_fd (const struct disfluid_cache_entry *entry, int fd) +{ + char *set_request_date; + char *set_response_date; + char *set_invalidated; + char *meta_header; + int status; + status = + asprintf (&set_request_date, "Request-Date: %lld.%09ld\r\n", + (long long) entry->request_date.tv_sec, + (long) entry->request_date.tv_nsec); + if (status < 0) + { + abort (); + } + status = + asprintf (&set_response_date, "Response-Date: %lld.%09ld\r\n", + (long long) entry->response_date.tv_sec, + (long) entry->response_date.tv_nsec); + if (status < 0) + { + abort (); + } + if (entry->invalidated) + { + status = asprintf (&set_invalidated, "Invalidated: true\r\n"); + if (status < 0) + { + abort (); + } + } + else + { + set_invalidated = strdup (""); + if (set_invalidated == NULL) + { + abort (); + } + } + status = + asprintf (&meta_header, "%s%s%s\r\n", set_request_date, set_response_date, + set_invalidated); + free (set_request_date); + free (set_response_date); + free (set_invalidated); + if (status < 0) + { + abort (); + } + size_t n_written = 0; + while (n_written < strlen (meta_header)) + { + ssize_t n_written_this_time = write (fd, &(meta_header[n_written]), + strlen (meta_header) - n_written); + if (n_written_this_time <= 0) + { + free (meta_header); + return 2; + } + n_written += n_written_this_time; + } + free (meta_header); + return 0; +} + +static void +cache_entry_set_request_date (struct disfluid_cache_entry *entry, + const struct timespec *date) +{ + entry->request_date.tv_sec = date->tv_sec; + entry->request_date.tv_nsec = date->tv_nsec; +} + +static void +cache_entry_set_response_date (struct disfluid_cache_entry *entry, + const struct timespec *date) +{ + entry->response_date.tv_sec = date->tv_sec; + entry->response_date.tv_nsec = date->tv_nsec; +} + +static void +cache_entry_invalidate (struct disfluid_cache_entry *entry) +{ + cache_entry_set_invalidated (entry, true); +} + +static void +cache_entry_set_invalidated (struct disfluid_cache_entry *entry, + bool invalidated) +{ + entry->invalidated = invalidated; +} + +static void +cache_entry_get_request_date (const struct disfluid_cache_entry *entry, + struct timespec *date) +{ + date->tv_sec = entry->request_date.tv_sec; + date->tv_nsec = entry->request_date.tv_nsec; +} + +static void +cache_entry_get_response_date (const struct disfluid_cache_entry *entry, + struct timespec *date) +{ + date->tv_sec = entry->response_date.tv_sec; + date->tv_nsec = entry->response_date.tv_nsec; +} + +static bool +cache_entry_invalidated (const struct disfluid_cache_entry *entry) +{ + return entry->invalidated; +} + +#endif /* DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED */ diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h index e17c70e..0a40f20 100644 --- a/src/libdisfluid/disfluid-tests.h +++ b/src/libdisfluid/disfluid-tests.h @@ -8,10 +8,45 @@ static inline char *run_tests (size_t *n_tests, size_t *n_errors); # include <check.h> # include "disfluid-init.h" +# include "disfluid-version.h" +# include "disfluid-cache-entry.h" + +static inline int +test_open_file_with_content (const char *content) +{ + char name[] = "/tmp/disfluid-cache-entry-test-XXXXXX"; + int fd = mkstemp (name); + if (fd < 0) + { + abort (); + } + size_t n_written = 0; + while (n_written < strlen (content)) + { + ssize_t next = + write (fd, &(content[n_written]), strlen (content) - n_written); + if (next <= 0) + { + abort (); + } + n_written += next; + } + remove (name); + lseek (fd, 0, SEEK_SET); + return fd; +} + +static inline void +fwrite_text (FILE * file, const char *text) +{ + fwrite (text, 1, strlen (text), file); + fflush (file); +} /* *INDENT-OFF* */ START_TEST (test_check_version) /* *INDENT-ON* */ + { const char *lib_version = version (); ck_assert_str_eq (lib_version, VERSION); @@ -20,6 +55,244 @@ START_TEST (test_check_version) END_TEST /* *INDENT-ON* */ +/* *INDENT-OFF* */ +START_TEST (test_read_invalid_cache_entry_file) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("Hello, world!"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + ck_assert_ptr_null (entry); + close (fd_source); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_no_date) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("Invalidated: true\r\n\r\n"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + ck_assert_ptr_ne (entry, NULL); + close (fd_source); + struct timespec request_date = {.tv_sec = 42,.tv_nsec = 69 }; + struct timespec response_date = {.tv_sec = 42,.tv_nsec = 69 }; + disfluid_cache_entry_get_request_date (entry, &request_date); + disfluid_cache_entry_get_request_date (entry, &response_date); + ck_assert_int_eq (request_date.tv_sec, 0); + ck_assert_int_eq (request_date.tv_nsec, 0); + ck_assert_int_eq (response_date.tv_sec, 0); + ck_assert_int_eq (response_date.tv_nsec, 0); + ck_assert ((bool) disfluid_cache_entry_invalidated (entry)); + disfluid_cache_entry_free (entry); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_whole_seconds) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("\ +Request-Date: 42\r\n\ +Response-Date: 69\r\n\ +Invalidated: true\r\n\ +\r\n"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + close (fd_source); + ck_assert_ptr_ne (entry, NULL); + struct timespec request_date = {.tv_sec = 1,.tv_nsec = 3 }; + struct timespec response_date = {.tv_sec = 2,.tv_nsec = 4 }; + disfluid_cache_entry_get_request_date (entry, &request_date); + disfluid_cache_entry_get_response_date (entry, &response_date); + ck_assert_int_eq (request_date.tv_sec, 42); + ck_assert_int_eq (request_date.tv_nsec, 0); + ck_assert_int_eq (response_date.tv_sec, 69); + ck_assert_int_eq (response_date.tv_nsec, 0); + ck_assert ((bool) disfluid_cache_entry_invalidated (entry)); + disfluid_cache_entry_free (entry); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_whole_seconds_dot) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("\ +Request-Date: 42.\r\n\ +Response-Date: 69.\r\n\ +Invalidated: true\r\n\ +\r\n"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + close (fd_source); + ck_assert_ptr_ne (entry, NULL); + struct timespec request_date = {.tv_sec = 1,.tv_nsec = 3 }; + struct timespec response_date = {.tv_sec = 2,.tv_nsec = 4 }; + disfluid_cache_entry_get_request_date (entry, &request_date); + disfluid_cache_entry_get_response_date (entry, &response_date); + ck_assert_int_eq (request_date.tv_sec, 42); + ck_assert_int_eq (request_date.tv_nsec, 0); + ck_assert_int_eq (response_date.tv_sec, 69); + ck_assert_int_eq (response_date.tv_nsec, 0); + ck_assert ((bool) disfluid_cache_entry_invalidated (entry)); + disfluid_cache_entry_free (entry); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_milliseconds) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("\ +Request-Date: 42.123\r\n\ +Response-Date: 69.456\r\n\ +Invalidated: true\r\n\ +\r\n"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + close (fd_source); + ck_assert_ptr_ne (entry, NULL); + struct timespec request_date = {.tv_sec = 1,.tv_nsec = 3 }; + struct timespec response_date = {.tv_sec = 2,.tv_nsec = 4 }; + disfluid_cache_entry_get_request_date (entry, &request_date); + disfluid_cache_entry_get_response_date (entry, &response_date); + ck_assert_int_eq (request_date.tv_sec, 42); + ck_assert_int_eq (request_date.tv_nsec, 123000000); + ck_assert_int_eq (response_date.tv_sec, 69); + ck_assert_int_eq (response_date.tv_nsec, 456000000); + ck_assert ((bool) disfluid_cache_entry_invalidated (entry)); + disfluid_cache_entry_free (entry); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_precise) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("\ +Request-Date: 42.123456789\r\n\ +Response-Date: 69.456789123\r\n\ +Invalidated: true\r\n\ +\r\n"); + if (fd_source < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + close (fd_source); + ck_assert_ptr_ne (entry, NULL); + struct timespec request_date = {.tv_sec = 1,.tv_nsec = 3 }; + struct timespec response_date = {.tv_sec = 2,.tv_nsec = 4 }; + disfluid_cache_entry_get_request_date (entry, &request_date); + disfluid_cache_entry_get_response_date (entry, &response_date); + ck_assert_int_eq (request_date.tv_sec, 42); + ck_assert_int_eq (request_date.tv_nsec, 123456789); + ck_assert_int_eq (response_date.tv_sec, 69); + ck_assert_int_eq (response_date.tv_nsec, 456789123); + ck_assert ((bool) disfluid_cache_entry_invalidated (entry)); + disfluid_cache_entry_free (entry); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_read_cache_entry_ambiguous) +/* *INDENT-ON* */ + +{ + int fd_source = test_open_file_with_content ("\ +Request-Date: 42.123456789\r\n\ +Response-Date: 69.456789123\r\n"); + /* Notice how we don’t know if we’re at the end because of a missing + \r\n. */ + if (fd_source < 0) + { + abort (); + } + /* Is it the end? */ + struct disfluid_cache_entry *entry = + disfluid_cache_entry_from_fd (fd_source); + ck_assert_ptr_eq (entry, NULL); + close (fd_source); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +START_TEST (test_write_cache_entry) +/* *INDENT-ON* */ + +{ + int fd_dest = test_open_file_with_content ("hehe"); + if (fd_dest < 0) + { + abort (); + } + struct disfluid_cache_entry *entry = disfluid_cache_entry_alloc (); + if (entry == NULL) + { + abort (); + } + const struct timespec rq = { + .tv_sec = 123, + .tv_nsec = 456 + }; + const struct timespec rs = { + .tv_sec = 789, + .tv_nsec = 101112 + }; + disfluid_cache_entry_set_request_date (entry, &rq); + disfluid_cache_entry_set_response_date (entry, &rs); + int error = disfluid_cache_entry_save_other_fd (entry, fd_dest); + ck_assert_int_eq (error, 0); + disfluid_cache_entry_free (entry); + close (fd_dest); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + static inline char * tests_read_whole_file (int file) { @@ -53,6 +326,16 @@ run_tests (size_t *n_tests, size_t *n_errors) TCase *general = tcase_create (_("disfluid general tests")); tcase_add_test (general, test_check_version); suite_add_tcase (suite, general); + TCase *cache_entry = tcase_create (_("disfluid cache entry files")); + tcase_add_test (cache_entry, test_read_invalid_cache_entry_file); + tcase_add_test (cache_entry, test_read_cache_entry_no_date); + tcase_add_test (cache_entry, test_read_cache_entry_whole_seconds); + tcase_add_test (cache_entry, test_read_cache_entry_whole_seconds_dot); + tcase_add_test (cache_entry, test_read_cache_entry_milliseconds); + tcase_add_test (cache_entry, test_read_cache_entry_precise); + tcase_add_test (cache_entry, test_read_cache_entry_ambiguous); + tcase_add_test (cache_entry, test_write_cache_entry); + suite_add_tcase (suite, cache_entry); SRunner *runner = srunner_create (suite); char log_file_name[] = "/tmp/disfluid-unit-tests-XXXXXX"; int log_file = mkstemp (log_file_name); diff --git a/src/libdisfluid/main.c b/src/libdisfluid/main.c index 666061c..7a3753b 100644 --- a/src/libdisfluid/main.c +++ b/src/libdisfluid/main.c @@ -1,23 +1,28 @@ #include <config.h> -#include "attribute.h" -#include <disfluid.h> - #define STREQ(a, b) (strcmp ((a), (b)) == 0) #define STRNEQ(a, b) (! (STREQ (a, b))) +#include <errno.h> +#include <fcntl.h> #include <locale.h> #include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <time.h> #include <unistd.h> #include "gettext.h" #include "relocatable.h" +#include "attribute.h" +#include <disfluid.h> #define _(String) dgettext (PACKAGE, (String)) #define N_(String) (String) -#include "disfluid-version.h" -#include "disfluid-tests.h" #include "disfluid-authors.h" +#include "disfluid-cache-entry.h" +#include "disfluid-tests.h" +#include "disfluid-version.h" const char * disfluid_version (void) @@ -108,3 +113,88 @@ disfluid_translation_credits (void) { return translation_credits (); } + +struct disfluid_cache_entry * +disfluid_cache_entry_alloc (void) +{ + return cache_entry_alloc (); +} + +void +disfluid_cache_entry_free (struct disfluid_cache_entry *entry) +{ + return cache_entry_free (entry); +} + +struct disfluid_cache_entry * +disfluid_cache_entry_from_file_name (const char *file_name) +{ + return cache_entry_from_file_name (file_name); +} + +struct disfluid_cache_entry * +disfluid_cache_entry_from_fd (int fd) +{ + return cache_entry_from_fd (fd); +} + +int +disfluid_cache_entry_save_other_file_name (const struct disfluid_cache_entry + *entry, const char *file_name) +{ + return cache_entry_save_other_file_name (entry, file_name); +} + +int +disfluid_cache_entry_save_other_fd (const struct disfluid_cache_entry *entry, + int fd) +{ + return cache_entry_save_other_fd (entry, fd); +} + +void +disfluid_cache_entry_set_request_date (struct disfluid_cache_entry *entry, + const struct timespec *date) +{ + cache_entry_set_request_date (entry, date); +} + +void +disfluid_cache_entry_set_response_date (struct disfluid_cache_entry *entry, + const struct timespec *date) +{ + cache_entry_set_response_date (entry, date); +} + +void +disfluid_cache_entry_invalidate (struct disfluid_cache_entry *entry) +{ + cache_entry_invalidate (entry); +} + +void +disfluid_cache_entry_set_invalidated (struct disfluid_cache_entry *entry, + int invalidated) +{ + cache_entry_set_invalidated (entry, invalidated); +} + +void +disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry + *entry, struct timespec *date) +{ + cache_entry_get_request_date (entry, date); +} + +void +disfluid_cache_entry_get_response_date (const struct disfluid_cache_entry + *entry, struct timespec *date) +{ + cache_entry_get_response_date (entry, date); +} + +int +disfluid_cache_entry_invalidated (const struct disfluid_cache_entry *entry) +{ + return cache_entry_invalidated (entry); +} |