add new tests from libc-testsuit (fcntl, f[w]scanf, setjmp, socket, stat)
authorSzabolcs Nagy <nsz@port70.net>
Fri, 5 Jul 2013 22:12:13 +0000 (22:12 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Fri, 5 Jul 2013 22:12:13 +0000 (22:12 +0000)
src/functional/fcntl.c [new file with mode: 0644]
src/functional/fscanf.c
src/functional/fwscanf.c [new file with mode: 0644]
src/functional/setjmp.c [new file with mode: 0644]
src/functional/socket.c [new file with mode: 0644]
src/functional/stat.c [new file with mode: 0644]
src/functional/strtol.c

diff --git a/src/functional/fcntl.c b/src/functional/fcntl.c
new file mode 100644 (file)
index 0000000..83ea950
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include "test.h"
+
+#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TESTE(c) (errno=0, TEST(c, "errno = %s\n", strerror(errno))
+
+int main(void)
+{
+       struct flock fl = {0};
+       FILE *f;
+       int fd;
+       pid_t pid;
+       int status;
+
+       if (!TESTE(f=tmpfile())) return test_status;
+       fd = fileno(f);
+
+       fl.l_type = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = 0;
+       fl.l_len = 0;
+       TESTE(fcntl(fd, F_SETLK, &fl)==0);
+
+       pid = fork();
+       if (!pid) {
+               fl.l_type = F_RDLCK;
+               _exit(fcntl(fd, F_SETLK, &fl)==0 ||
+                       (errno!=EAGAIN && errno!=EACCES));
+       }
+       while (waitpid(pid, &status, 0)<0 && errno==EINTR);
+       TEST(status==0, "lock failed to work\n");
+
+       pid = fork();
+       if (!pid) {
+               fl.l_type = F_WRLCK;
+               _exit(fcntl(fd, F_GETLK, &fl) || fl.l_pid != getppid());
+       }
+       while (waitpid(pid, &status, 0)<0 && errno==EINTR);
+       TEST(status==0, "child failed to detect lock held by parent\n");
+
+       fclose(f);
+
+       return test_status;
+}
index 62627b7..c8063e0 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
 #include "test.h"
 
-#define T(f, x, m) do { \
-       r = (f); \
-       if (r != (x)) \
-               error("%s failed (got %d, expected %d, errno \"%s\") (%s)\n", \
-                       #f, r, x, errno ? strerror(errno) : "", m); \
-       errno = 0; \
-} while (0)
+#define TEST(r, f, x, m) ( \
+       errno=0, ((r) = (f)) == (x) || \
+       (error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
 
-#define S(s, x, m) do { \
-       if (strcmp(s, x) != 0) \
-               error("got [%s] want [%s] (%s)\n", s, x, m); \
-} while(0)
+#define TEST_S(s, x, m) ( \
+       !strcmp((s),(x)) || \
+       (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+
+static FILE *writetemp(const char *data)
+{
+       FILE *f = tmpfile();
+       if (!f) return 0;
+       if (!fwrite(data, strlen(data), 1, f)) {
+               fclose(f);
+               return 0;
+       }
+       rewind(f);
+       return f;
+}
 
 int main(void)
 {
-       int r, x, y;
+       int i, x, y;
+       double u;
        char a[100], b[100];
-       int p[2];
        FILE *f;
+       int p[2];
+
+       TEST(i, pipe(p), 0, "failed to open pipe %d!=%d (%s)");
+       TEST(i, !(f = fdopen(p[0], "rb")), 0, "failed to fdopen pipe %d!=%d (%s)");
 
-       T(pipe(p), 0, "open pipe");
-       T(!(f = fdopen(p[0], "rb")), 0, "fdopen pipe");
        if (!f) {
                close(p[0]);
                close(p[1]);
-               return test_status;
+               return 1;
        }
 
-       T(write(p[1], "hello, world\n", 13), 13, "write to pipe");
-       T(fscanf(f, "%s %[own]", a, b), 2, "");
-       S(a, "hello,", "wrong result for %s");
-       S(b, "wo", "wrong result for %[own]");
-       T(fgetc(f), 'r', "fgetc 'r'");
+       TEST(i, write(p[1], "hello, world\n", 13), 13, "write error %d!=%d (%s)");
+       TEST(i, fscanf(f, "%s %[own]", a, b), 2, "got %d fields, expected %d");
+       TEST_S(a, "hello,", "wrong result for %s");
+       TEST_S(b, "wo", "wrong result for %[own]");
+       TEST(i, fgetc(f), 'r', "'%c' != '%c') (%s)");
 
-       T(write(p[1], " 0x12 0x34", 10), 10, "");
-       T(fscanf(f, "ld %5i%2i", &x, &y), 1, "");
-       T(x, 0x12, "");
-       T(fgetc(f), '3', "fgetc '3'");
+       TEST(i, write(p[1], " 0x12 0x34", 10), 10, "write error %d!=%d (%s)");
+       TEST(i, fscanf(f, "ld %5i%2i", &x, &y), 1, "got %d fields, expected %d");
+       TEST(i, x, 0x12, "%d != %d");
+       TEST(i, fgetc(f), '3', "'%c' != '%c'");
 
        fclose(f);
        close(p[1]);
+
+       TEST(i, !!(f=writetemp("      42")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fscanf(f, " %n%*d%n", &x, &y), 0, "%d != %d");
+               TEST(i, x, 6, "%d != %d");
+               TEST(i, y, 8, "%d != %d");
+               TEST(i, ftell(f), 8, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("[abc123]....x")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fscanf(f, "%10[^]]%n%10[].]%n", a, &x, b, &y), 2, "%d != %d");
+               TEST_S(a, "[abc123", "wrong result for %[^]]");
+               TEST_S(b, "]....", "wrong result for %[].]");
+               TEST(i, x, 7, "%d != %d");
+               TEST(i, y, 12, "%d != %d");
+               TEST(i, ftell(f), 12, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               TEST(i, fgetc(f), 'x', "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0x1p 12")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               u=-1;
+               TEST(i, fscanf(f, "%lf%n %d", &u, &x, &y), 0, "%d != %d");
+               TEST(u, u, -1.0, "%g != %g");
+               TEST(i, x, -1, "%d != %d");
+               TEST(i, y, -1, "%d != %d");
+               TEST(i, ftell(f), 4, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               TEST(i, fgetc(f), ' ', "%d != %d");
+               rewind(f);
+               TEST(i, fgetc(f), '0', "%d != %d");
+               TEST(i, fgetc(f), 'x', "%d != %d");
+               TEST(i, fscanf(f, "%lf%n%c %d", &u, &x, a, &y), 3, "%d != %d");
+               TEST(u, u, 1.0, "%g != %g");
+               TEST(i, x, 1, "%d != %d");
+               TEST(i, a[0], 'p', "%d != %d");
+               TEST(i, y, 12, "%d != %d");
+               TEST(i, ftell(f), 7, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0x.1p4    012")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               u=-1;
+               TEST(i, fscanf(f, "%lf%n %i", &u, &x, &y), 2, "%d != %d");
+               TEST(u, u, 1.0, "%g != %g");
+               TEST(i, x, 6, "%d != %d");
+               TEST(i, y, 10, "%d != %d");
+               TEST(i, ftell(f), 13, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0xx")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fscanf(f, "%x%n", &x, &y), 0, "%d != %d");
+               TEST(i, x, -1, "%d != %d");
+               TEST(i, y, -1, "%d != %d");
+               TEST(i, ftell(f), 2, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               fclose(f);
+       }
+
        return test_status;
 }
diff --git a/src/functional/fwscanf.c b/src/functional/fwscanf.c
new file mode 100644 (file)
index 0000000..70ba50b
--- /dev/null
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <wchar.h>
+#include "test.h"
+
+#define TEST(r, f, x, m) ( \
+       errno=0, ((r) = (f)) == (x) || \
+       (error("%s failed (" m ")\n", #f, r, x, strerror(errno)), 0) )
+
+#define TEST_S(s, x, m) ( \
+       !strcmp((s),(x)) || \
+       (error("[%s] != [%s] (%s)\n", s, x, m), 0) )
+
+static FILE *writetemp(const char *data)
+{
+       FILE *f = tmpfile();
+       if (!f) return 0;
+       if (!fwrite(data, strlen(data), 1, f)) {
+               fclose(f);
+               return 0;
+       }
+       rewind(f);
+       return f;
+}
+
+int main(void)
+{
+       int i, x, y;
+       double u;
+       char a[100], b[100];
+       FILE *f;
+
+       TEST(i, !!(f=writetemp("      42")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fwscanf(f, L" %n%*d%n", &x, &y), 0, "%d != %d");
+               TEST(i, x, 6, "%d != %d");
+               TEST(i, y, 8, "%d != %d");
+               TEST(i, ftell(f), 8, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("[abc123]....x")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fwscanf(f, L"%10[^]]%n%10[].]%n", a, &x, b, &y), 2, "%d != %d");
+               TEST_S(a, "[abc123", "wrong result for %[^]]");
+               TEST_S(b, "]....", "wrong result for %[].]");
+               TEST(i, x, 7, "%d != %d");
+               TEST(i, y, 12, "%d != %d");
+               TEST(i, ftell(f), 12, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               TEST(i, fgetc(f), 'x', "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0x1p 12")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               u=-1;
+               TEST(i, fwscanf(f, L"%lf%n %d", &u, &x, &y), 0, "%d != %d");
+               TEST(u, u, -1.0, "%g != %g");
+               TEST(i, x, -1, "%d != %d");
+               TEST(i, y, -1, "%d != %d");
+               TEST(i, ftell(f), 4, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               TEST(i, fgetc(f), ' ', "%d != %d");
+               rewind(f);
+               TEST(i, fgetc(f), '0', "%d != %d");
+               TEST(i, fgetc(f), 'x', "%d != %d");
+               TEST(i, fwscanf(f, L"%lf%n%c %d", &u, &x, a, &y), 3, "%d != %d");
+               TEST(u, u, 1.0, "%g != %g");
+               TEST(i, x, 1, "%d != %d");
+               TEST(i, a[0], 'p', "%d != %d");
+               TEST(i, y, 12, "%d != %d");
+               TEST(i, ftell(f), 7, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0x.1p4    012")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               u=-1;
+               TEST(i, fwscanf(f, L"%lf%n %i", &u, &x, &y), 2, "%d != %d");
+               TEST(u, u, 1.0, "%g != %g");
+               TEST(i, x, 6, "%d != %d");
+               TEST(i, y, 10, "%d != %d");
+               TEST(i, ftell(f), 13, "%d != %d");
+               TEST(i, !!feof(f), 1, "%d != %d");
+               fclose(f);
+       }
+
+       TEST(i, !!(f=writetemp("0xx")), 1, "failed to make temp file");
+       if (f) {
+               x=y=-1;
+               TEST(i, fwscanf(f, L"%x%n", &x, &y), 0, "%d != %d");
+               TEST(i, x, -1, "%d != %d");
+               TEST(i, y, -1, "%d != %d");
+               TEST(i, ftell(f), 2, "%d != %d");
+               TEST(i, feof(f), 0, "%d != %d");
+               fclose(f);
+       }
+
+       return test_status;
+}
diff --git a/src/functional/setjmp.c b/src/functional/setjmp.c
new file mode 100644 (file)
index 0000000..7bd534b
--- /dev/null
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+#include "test.h"
+
+#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TESTE(c) (errno=0, TEST(c, "errno = %s\n", strerror(errno)))
+
+int main(void)
+{
+       volatile int x = 0, r;
+       jmp_buf jb;
+       sigjmp_buf sjb;
+       volatile sigset_t oldset;
+       sigset_t set;
+
+       if (!setjmp(jb)) {
+               x = 1;
+               longjmp(jb, 1);
+       }
+       TEST(x==1, "setjmp/longjmp seems to have been bypassed\n");
+
+       x = 0;
+       r = setjmp(jb);
+       if (!x) {
+               x = 1;
+               longjmp(jb, 0);
+       }
+       TEST(r==1, "longjmp(jb, 0) caused setjmp to return %d\n", r);
+
+       sigemptyset(&set);
+       sigaddset(&set, SIGUSR1);
+       sigprocmask(SIG_UNBLOCK, &set, &set);
+       oldset = set;
+
+       /* Improve the chances of catching failure of sigsetjmp to
+        * properly save the signal mask in the sigjmb_buf. */
+       memset(&sjb, -1, sizeof sjb);
+
+       if (!sigsetjmp(sjb, 1)) {
+               sigemptyset(&set);
+               sigaddset(&set, SIGUSR1);
+               sigprocmask(SIG_BLOCK, &set, 0);
+               siglongjmp(sjb, 1);
+       }
+       set = oldset;
+       sigprocmask(SIG_SETMASK, &set, &set);
+       TEST(sigismember(&set, SIGUSR1)==0, "siglongjmp failed to restore mask\n");
+
+       return test_status;
+}
diff --git a/src/functional/socket.c b/src/functional/socket.c
new file mode 100644 (file)
index 0000000..fc01e67
--- /dev/null
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include "test.h"
+
+#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+#define TESTE(c) (errno=0, TEST(c, "errno = %s\n", strerror(errno))
+
+int main(void)
+{
+       struct sockaddr_in sa = { .sin_family = AF_INET };
+       int s, c, t;
+       char buf[100];
+
+       TESTE((s=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))>=0);
+       TESTE(bind(s, (void *)&sa, sizeof sa)==0);
+       TESTE(getsockname(s, (void *)&sa, (socklen_t[]){sizeof sa})==0);
+
+       TESTE(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
+               &(struct timeval){.tv_usec=1}, sizeof(struct timeval))==0);
+
+       TESTE((c=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))>=0);
+       sa.sin_addr.s_addr = htonl(0x7f000001);
+       TESTE(sendto(c, "x", 1, 0, (void *)&sa, sizeof sa)==1);
+       TESTE(recvfrom(s, buf, sizeof buf, 0, (void *)&sa, (socklen_t[]){sizeof sa})==1);
+       TEST(buf[0]=='x', "'%c'\n", buf[0]);
+
+       close(c);
+       close(s);
+
+       memset(&sa, 0, sizeof sa);
+       sa.sin_family = AF_INET;
+       TESTE((s=socket(PF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_TCP))>=0);
+       TEST(fcntl(s, F_GETFD)&FD_CLOEXEC, "SOCK_CLOEXEC did not work\n");
+       TESTE(bind(s, (void *)&sa, sizeof sa)==0);
+       TESTE(getsockname(s, (void *)&sa, (socklen_t[]){sizeof sa})==0);
+       sa.sin_addr.s_addr = htonl(0x7f000001);
+
+       TESTE(listen(s, 1)==0);
+
+       TESTE((c=socket(PF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP))>=0);
+       TEST(fcntl(c, F_GETFL)&O_NONBLOCK, "SOCK_NONBLOCK did not work\n");
+
+       TESTE(connect(c, (void *)&sa, sizeof sa)==0 || errno==EINPROGRESS);
+
+       TESTE((t=accept(s, (void *)&sa, &(socklen_t){sizeof sa}))>=0);
+
+       close(t);
+       close(c);
+       close(s);
+
+       return test_status;
+}
diff --git a/src/functional/stat.c b/src/functional/stat.c
new file mode 100644 (file)
index 0000000..12abd7c
--- /dev/null
@@ -0,0 +1,43 @@
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "test.h"
+
+#define TEST(c, ...) ((c) ? 1 : (error(#c" failed: " __VA_ARGS__),0))
+
+int main(void)
+{
+       struct stat st;
+       FILE *f;
+       time_t t;
+
+       if (TEST(stat(".",&st)==0, "errno = %s\n", strerror(errno))) {
+               TEST(S_ISDIR(st.st_mode), "\n");
+               TEST(st.st_nlink>0, "%ju\n", (uintmax_t)st.st_nlink);
+               t = time(0);
+               TEST(st.st_ctime<=t, "%jd > %jd\n", (intmax_t)st.st_ctime, (intmax_t)t);
+               TEST(st.st_mtime<=t, "%jd > %jd\n", (intmax_t)st.st_mtime, (intmax_t)t);
+               TEST(st.st_atime<=t, "%jd > %jd\n", (intmax_t)st.st_atime, (intmax_t)t);
+       }
+
+       if (TEST(stat("/dev/null",&st)==0, "errno = %s\n", strerror(errno))) {
+               TEST(S_ISCHR(st.st_mode), "\n");
+       }
+
+       if ((f = tmpfile())) {
+               fputs("hello", f);
+               fflush(f);
+               if (TEST(fstat(fileno(f),&st)==0, "errnp = %s\n", strerror(errno))) {
+                       TEST(st.st_uid==geteuid(), "%d vs %d\n", (int)st.st_uid, (int)geteuid());
+                       TEST(st.st_gid==getegid(), "%d vs %d\n", (int)st.st_uid, (int)geteuid());
+                       TEST(st.st_size==5, "%jd vs 5\n", (intmax_t)st.st_size);
+               }
+               fclose(f);
+       }
+
+       return test_status;
+}
index 81df887..676a2c7 100644 (file)
@@ -70,5 +70,11 @@ int main(void)
        TEST(l, strtol(s="123", &c, 37), 0, "%ld != %ld");
        TEST2(i, c-s, 0, "wrong final position %d != %d");
        TEST2(i, errno, EINVAL, "%d != %d");
+
+       TEST(l, strtol(s="  15437", &c, 8), 015437, "%ld != %ld");
+       TEST2(i, c-s, 7, "wrong final position %d != %d");
+
+       TEST(l, strtol(s="  1", &c, 0), 1, "%ld != %ld");
+       TEST2(i, c-s, 3, "wrong final position %d != %d");
        return test_status;
 }