summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGuillem Jover <guillem@hadrons.org>2013-05-23 02:05:19 +0200
committerGuillem Jover <guillem@hadrons.org>2013-05-27 02:49:28 +0200
commit7196b4dccaaa796dd96358162fdf143393162a8d (patch)
tree02ea4f8c01aa5ae63963c84544ce9f36df63aea9 /test
parenta97ce513e031b29a47965b740be14fb9a84277fc (diff)
test: Add new fgetln() and fgetwln() unit test
Diffstat (limited to 'test')
-rw-r--r--test/.gitignore1
-rw-r--r--test/Makefile.am3
-rw-r--r--test/fgetln.c263
3 files changed, 267 insertions, 0 deletions
diff --git a/test/.gitignore b/test/.gitignore
index 1c5d1f8..8fda062 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,3 +1,4 @@
endian
+fgetln
headers
overlay
diff --git a/test/Makefile.am b/test/Makefile.am
index 1d41b86..f36b408 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -11,6 +11,9 @@ check_PROGRAMS = \
headers \
overlay \
endian \
+ fgetln \
$(nil)
+fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la
+
TESTS = $(check_PROGRAMS)
diff --git a/test/fgetln.c b/test/fgetln.c
new file mode 100644
index 0000000..83d120c
--- /dev/null
+++ b/test/fgetln.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2013 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/wait.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <wchar.h>
+
+#define skip(msg) \
+ do { \
+ printf("skip: %s\n", (msg)); \
+ return; \
+ } while (0)
+
+#define DATA_LINES 3
+
+static const char *data_ascii[] = {
+ "this represents an ascii sequence of lines to test the\n",
+ "fgetln() family of functions\n",
+ "last line without an ending newline",
+};
+static const wchar_t *data_wide[] = {
+ L"this represénts an utf-8 seqüence of lînes to test the\n",
+ L"«fgetln()» family of functions § but with an extremely long "
+ "line to test that the reallocation logic works fine, and that "
+ "the strings end up being equal…\n",
+ L"last line ☭ without an ‽ ending newline ♥",
+};
+
+#define FILE_COUNT 32
+
+#define LINE_COUNT 2
+#define LINE_LEN 2
+
+struct file {
+ FILE *fp;
+ const void **lines;
+
+ const void *got_buf;
+ int got_len;
+};
+
+static FILE *
+pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
+{
+ FILE *fp;
+ int rc;
+ int pipefd[2];
+ pid_t pid;
+
+ rc = pipe(pipefd);
+ assert(rc >= 0);
+
+ pid = fork();
+ assert(pid >= 0);
+
+ if (pid == 0) {
+ int line;
+
+ /* Child writes data to pipe. */
+ rc = close(pipefd[0]);
+ assert(rc >= 0);
+
+ fp = fdopen(pipefd[1], "w");
+ assert(fp);
+
+ for (line = 0; line < buf_nmemb; line++) {
+ rc = fprintf(fp, fmt, buf[line]);
+ assert(rc >= 0);
+ }
+
+ rc = fclose(fp);
+ assert(rc >= 0);
+
+ _exit(0);
+ } else {
+ /* Parent gets a FILE and reads from it. */
+ rc = close(pipefd[1]);
+ assert(rc >= 0);
+
+ fp = fdopen(pipefd[0], "r");
+ assert(fp);
+
+ return fp;
+ }
+}
+
+static void
+pipe_close(FILE *fp)
+{
+ fclose(fp);
+ wait(NULL);
+}
+
+static void
+test_fgetln_single(void)
+{
+ FILE *fp;
+ size_t len;
+ int i;
+
+ fp = pipe_feed("%s", (const void **)data_ascii, DATA_LINES);
+ for (i = 0; i < DATA_LINES; i++) {
+ char *str = fgetln(fp, &len);
+
+ assert(str);
+ assert(memcmp(str, data_ascii[i], len) == 0);
+ }
+ assert(fgetln(fp, &len) == NULL);
+ pipe_close(fp);
+}
+
+static void
+test_fgetln_multi(void)
+{
+ struct file files[FILE_COUNT];
+ int i, l;
+
+ for (i = 0; i < FILE_COUNT; i++) {
+ char *str;
+
+ str = strdup("A\n");
+ str[0] += i;
+
+ files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
+ files[i].lines[0] = str;
+ files[i].lines[1] = str;
+ files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
+ }
+
+ for (l = 0; l < LINE_COUNT; l++) {
+ for (i = 0; i < FILE_COUNT; i++) {
+ size_t len;
+ char *str;
+
+ str = fgetln(files[i].fp, &len);
+
+ assert(str);
+ assert(len == LINE_LEN);
+
+ files[i].got_len = len;
+ files[i].got_buf = str;
+ }
+
+ for (i = 0; i < FILE_COUNT; i++) {
+ assert(memcmp(files[i].lines[l], files[i].got_buf,
+ files[i].got_len) == 0);
+ }
+ }
+
+ for (i = 0; i < LINE_COUNT; i++)
+ pipe_close(files[i].fp);
+}
+
+static void
+test_fgetwln_single(void)
+{
+ FILE *fp;
+ size_t len;
+ int i;
+
+ fp = pipe_feed("%ls", (const void **)data_wide, DATA_LINES);
+ for (i = 0; i < DATA_LINES; i++) {
+ wchar_t *wstr;
+
+ wstr = fgetwln(fp, &len);
+ assert(wstr);
+
+ assert(wmemcmp(data_wide[i], wstr, len) == 0);
+ }
+ assert(fgetwln(fp, &len) == NULL);
+ pipe_close(fp);
+}
+
+static void
+test_fgetwln_multi(void)
+{
+ struct file files[FILE_COUNT];
+ int i, l;
+
+ for (i = 0; i < FILE_COUNT; i++) {
+ wchar_t *wstr;
+
+ wstr = wcsdup(L"A\n");
+ wstr[0] += i;
+
+ files[i].lines = malloc(sizeof(char *) * LINE_COUNT);
+ files[i].lines[0] = wstr;
+ files[i].lines[1] = wstr;
+ files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);
+ }
+
+ for (l = 0; l < LINE_COUNT; l++) {
+ for (i = 0; i < FILE_COUNT; i++) {
+ size_t len;
+ wchar_t *wstr;
+
+ wstr = fgetwln(files[i].fp, &len);
+
+ assert(wstr);
+ assert(len == LINE_LEN);
+
+ files[i].got_len = len;
+ files[i].got_buf = wstr;
+ }
+
+ for (i = 0; i < FILE_COUNT; i++) {
+ assert(wmemcmp(files[i].lines[l], files[i].got_buf,
+ files[i].got_len) == 0);
+ }
+ }
+
+ for (i = 0; i < LINE_COUNT; i++)
+ pipe_close(files[i].fp);
+}
+
+static void
+test_fgetwln(void)
+{
+ if (setlocale(LC_ALL, "C.UTF-8") == NULL &&
+ setlocale(LC_ALL, "en_US.UTF-8") == NULL)
+ skip("no default UTF-8 locale found");
+
+ test_fgetwln_single();
+ test_fgetwln_multi();
+}
+
+int
+main(int argc, char **argv)
+{
+ test_fgetln_single();
+ test_fgetln_multi();
+ test_fgetwln();
+
+ return 0;
+}