]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
test: Add new fgetln() and fgetwln() unit test
authorGuillem Jover <guillem@hadrons.org>
Thu, 23 May 2013 00:05:19 +0000 (02:05 +0200)
committerGuillem Jover <guillem@hadrons.org>
Mon, 27 May 2013 00:49:28 +0000 (02:49 +0200)
test/.gitignore
test/Makefile.am
test/fgetln.c [new file with mode: 0644]

index 1c5d1f85838b35227f7f8a4de1ab9fbf676641e4..8fda062010a766408a3a7977f734c7a6338bc7e9 100644 (file)
@@ -1,3 +1,4 @@
 endian
+fgetln
 headers
 overlay
index 1d41b86d762757974ff3341dbed3b80b8019d5f5..f36b4087bdd86d3e0b22edb9033a9543bea10822 100644 (file)
@@ -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 (file)
index 0000000..83d120c
--- /dev/null
@@ -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;
+}