diff options
author | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-24 20:22:12 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-24 20:22:12 +0200 |
commit | 7988979a722b4cdf287b2093956a76a3f19b9897 (patch) | |
tree | d35e251d0472ceca55a2eef61cff261c8ee68fab /test/mmap |
add uClibc-ng test directory
Diffstat (limited to 'test/mmap')
-rw-r--r-- | test/mmap/Makefile | 8 | ||||
-rw-r--r-- | test/mmap/Makefile.in | 2 | ||||
-rw-r--r-- | test/mmap/mmap.c | 73 | ||||
-rw-r--r-- | test/mmap/mmap2.c | 46 | ||||
-rw-r--r-- | test/mmap/mmap64.c | 29 | ||||
-rw-r--r-- | test/mmap/tst-mmap-eofsync.c | 106 | ||||
-rw-r--r-- | test/mmap/tst-mmap-fflushsync.c | 99 | ||||
-rw-r--r-- | test/mmap/tst-mmap-offend.c | 86 | ||||
-rw-r--r-- | test/mmap/tst-mmap-setvbuf.c | 81 |
9 files changed, 530 insertions, 0 deletions
diff --git a/test/mmap/Makefile b/test/mmap/Makefile new file mode 100644 index 0000000..89e7195 --- /dev/null +++ b/test/mmap/Makefile @@ -0,0 +1,8 @@ +# uClibc mmap tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +top_srcdir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/test/mmap/Makefile.in b/test/mmap/Makefile.in new file mode 100644 index 0000000..581f3b0 --- /dev/null +++ b/test/mmap/Makefile.in @@ -0,0 +1,2 @@ +# uClibc mmap tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. diff --git a/test/mmap/mmap.c b/test/mmap/mmap.c new file mode 100644 index 0000000..8b29737 --- /dev/null +++ b/test/mmap/mmap.c @@ -0,0 +1,73 @@ + +/* The mmap test is useful, since syscalls with 6 arguments + * (as mmap) are done differently on various architectures. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/mman.h> + +#define SIZEOF_ARRAY(type) (sizeof(type)/sizeof(*type)) + +struct mmap_test { + void *ret; + int err; + struct { + void *start; + size_t length; + int prot; + int flags; + int fd; + off_t offset; + } args; +}; + +struct mmap_test tests[] = { + [0] { + .err = 0, + .args.start = NULL, + .args.length = 4096, + .args.prot = PROT_READ|PROT_WRITE, + .args.flags = MAP_PRIVATE|MAP_ANONYMOUS, + .args.fd = 0, + .args.offset = 0 + }, +}; + +#define err(fmt, args...) \ + do { \ + fprintf(stderr, fmt "\n" , ## args); \ + exit(1); \ + } while (0) +#define errp(fmt, args...) err(fmt ": %s" , ## args , strerror(errno)) + +int main(int argc, char **argv) +{ + int i; + struct mmap_test *t; + + for (i=0; i<SIZEOF_ARRAY(tests); ++i) { + t = tests + i; + + errno = 0; + t->ret = mmap(t->args.start, t->args.length, t->args.prot, + t->args.flags, t->args.fd, t->args.offset); + + if (t->err) { + if (t->ret != MAP_FAILED) + err("mmap test %i should have failed, but gave us %p", i, t->ret); + else if (t->err != errno) + errp("mmap test %i failed, but gave us wrong errno (got %i instead of %i)", i, errno, t->err); + } else { + if (t->ret == MAP_FAILED) + errp("mmap test %i failed", i); + else if (munmap(t->ret, t->args.length) != 0) + errp("munmap test %i failed", i); + } + } + + exit(0); +} diff --git a/test/mmap/mmap2.c b/test/mmap/mmap2.c new file mode 100644 index 0000000..1d5f5db --- /dev/null +++ b/test/mmap/mmap2.c @@ -0,0 +1,46 @@ +/* When trying to map /dev/mem with offset 0xFFFFF000 on the ARM platform, mmap + * returns -EOVERFLOW. + * + * Since off_t is defined as a long int and the sign bit is set in the address, + * the shift operation shifts in ones instead of zeroes + * from the left. This results the offset sent to the kernel function becomes + * 0xFFFFFFFF instead of 0x000FFFFF with MMAP2_PAGE_SHIFT set to 12. + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> + +#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ + __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) + +#define MAP_SIZE sysconf(_SC_PAGESIZE) +#define MAP_MASK (MAP_SIZE - 1) + +int main(int argc, char **argv) { + void* map_base = 0; + int fd; + off_t target = 0xfffff000; + if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { + /* skip test for non-root users */ + if (errno == EACCES) + return 0; + FATAL; + } + printf("/dev/mem opened.\n"); + fflush(stdout); + + /* Map one page */ + map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, target & ~MAP_MASK); + if(map_base == (void *) -1) FATAL; + printf("Memory mapped at address %p.\n", map_base); + fflush(stdout); + if(munmap(map_base, MAP_SIZE) == -1) FATAL; + close(fd); + return 0; +} diff --git a/test/mmap/mmap64.c b/test/mmap/mmap64.c new file mode 100644 index 0000000..87165fe --- /dev/null +++ b/test/mmap/mmap64.c @@ -0,0 +1,29 @@ + +/* The mmap test is useful, since syscalls with 6 arguments + * (as mmap) are done differently on various architectures. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <features.h> + +int main(int argc, char **argv) +{ +#ifdef __UCLIBC_HAS_LFS__ + void *ptr; + + ptr = mmap64(NULL, 4096, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + + if (ptr == MAP_FAILED) { + perror("mmap"); + exit(1); + } + printf("mmap returned %p\n", ptr); + exit(0); +#else + exit(0); +#endif +} diff --git a/test/mmap/tst-mmap-eofsync.c b/test/mmap/tst-mmap-eofsync.c new file mode 100644 index 0000000..e8ef727 --- /dev/null +++ b/test/mmap/tst-mmap-eofsync.c @@ -0,0 +1,106 @@ +/* Test program for synchronization of stdio state with file after EOF. */ + +#include <stdio.h> +#include <error.h> +#include <errno.h> + +static void do_prepare (void); +#define PREPARE(argc, argv) do_prepare () +static int do_test (void); +#define TEST_FUNCTION do_test () +#include <test-skeleton.c> + +static char *temp_file; +static int temp_fd; + +static char text1[] = "Line the first\n"; +static char text2[] = "Line the second\n"; + +static void +do_prepare (void) +{ + temp_fd = create_temp_file ("tst-mmap-eofsync.", &temp_file); + if (temp_fd == -1) + error (1, errno, "cannot create temporary file"); + else + { + ssize_t cc = write (temp_fd, text1, sizeof text1 - 1); + if (cc != sizeof text1 - 1) + error (1, errno, "cannot write to temporary file"); + } +} + +static int +do_test (void) +{ + FILE *f; + char buf[128]; + int result = 0; + int c; + + f = fopen (temp_file, "rm"); + if (f == NULL) + { + perror (temp_file); + return 1; + } + + if (fgets (buf, sizeof buf, f) == NULL) + { + perror ("fgets"); + return 1; + } + + if (strcmp (buf, text1)) + { + printf ("read \"%s\", expected \"%s\"\n", buf, text1); + result = 1; + } + + printf ("feof = %d, ferror = %d immediately after fgets\n", + feof (f), ferror (f)); + +#if 1 + c = fgetc (f); + if (c == EOF) + printf ("fgetc -> EOF (feof = %d, ferror = %d)\n", + feof (f), ferror (f)); + else + { + printf ("fgetc returned %o (feof = %d, ferror = %d)\n", + c, feof (f), ferror (f)); + result = 1; + } +#endif + + c = write (temp_fd, text2, sizeof text2 - 1); + if (c == sizeof text2 - 1) + printf ("wrote more to file\n"); + else + { + printf ("wrote %d != %zd (%m)\n", c, sizeof text2 - 1); + result = 1; + } + + if (fgets (buf, sizeof buf, f) == NULL) + { + printf ("second fgets fails: feof = %d, ferror = %d (%m)\n", + feof (f), ferror (f)); + clearerr (f); + if (fgets (buf, sizeof buf, f) == NULL) + { + printf ("retry fgets fails: feof = %d, ferror = %d (%m)\n", + feof (f), ferror (f)); + result = 1; + } + } + if (result == 0 && strcmp (buf, text2)) + { + printf ("second time read \"%s\", expected \"%s\"\n", buf, text2); + result = 1; + } + + fclose (f); + + return result; +} diff --git a/test/mmap/tst-mmap-fflushsync.c b/test/mmap/tst-mmap-fflushsync.c new file mode 100644 index 0000000..24ae33c --- /dev/null +++ b/test/mmap/tst-mmap-fflushsync.c @@ -0,0 +1,99 @@ +/* Test program for synchronization of stdio state with file after fflush. */ + +#include <stdio.h> +#include <error.h> +#include <errno.h> + +static void do_prepare (void); +#define PREPARE(argc, argv) do_prepare () +static int do_test (void); +#define TEST_FUNCTION do_test () +#include <test-skeleton.c> + +static char *temp_file; +static int temp_fd; + +static char text1[] = "Line the first\n"; +static char text2[] = "Line the second\n"; + +static void +do_prepare (void) +{ + temp_fd = create_temp_file ("tst-mmap-eofsync.", &temp_file); + if (temp_fd == -1) + error (1, errno, "cannot create temporary file"); + else + { + ssize_t cc = write (temp_fd, text1, sizeof text1 - 1); + if (cc != sizeof text1 - 1) + error (1, errno, "cannot write to temporary file"); + } +} + +static int +do_test (void) +{ + FILE *f; + char buf[128]; + int result = 0; + int c; + + f = fopen (temp_file, "rm"); + if (f == NULL) + { + perror (temp_file); + return 1; + } + + if (fgets (buf, sizeof buf, f) == NULL) + { + perror ("fgets"); + return 1; + } + + if (strcmp (buf, text1)) + { + printf ("read \"%s\", expected \"%s\"\n", buf, text1); + result = 1; + } + + printf ("feof = %d, ferror = %d immediately after fgets\n", + feof (f), ferror (f)); + + if (fflush (f) != 0) + { + printf ("fflush failed! %m\n"); + result = 1; + } + + c = write (temp_fd, text2, sizeof text2 - 1); + if (c == sizeof text2 - 1) + printf ("wrote more to file\n"); + else + { + printf ("wrote %d != %zd (%m)\n", c, sizeof text2 - 1); + result = 1; + } + + if (fgets (buf, sizeof buf, f) == NULL) + { + printf ("second fgets fails: feof = %d, ferror = %d (%m)\n", + feof (f), ferror (f)); + clearerr (f); + if (fgets (buf, sizeof buf, f) == NULL) + { + printf ("retry fgets fails: feof = %d, ferror = %d (%m)\n", + feof (f), ferror (f)); + result = 1; + } + } + if (result == 0 && strcmp (buf, text2)) + { + printf ("second time read \"%s\", expected \"%s\"\n", buf, text2); + result = 1; + } + + fclose (f); + + return result; +} diff --git a/test/mmap/tst-mmap-offend.c b/test/mmap/tst-mmap-offend.c new file mode 100644 index 0000000..19732e6 --- /dev/null +++ b/test/mmap/tst-mmap-offend.c @@ -0,0 +1,86 @@ +/* Test case for bug with mmap stdio read past end of file. */ + +#include <stdio.h> +#include <error.h> +#include <errno.h> + +static void do_prepare (void); +#define PREPARE(argc, argv) do_prepare () +static int do_test (void); +#define TEST_FUNCTION do_test () +#include <test-skeleton.c> + +static char *temp_file; + +static const char text1[] = "hello\n"; + +static void +do_prepare (void) +{ + int temp_fd = create_temp_file ("tst-mmap-offend.", &temp_file); + if (temp_fd == -1) + error (1, errno, "cannot create temporary file"); + else + { + ssize_t cc = write (temp_fd, text1, sizeof text1 - 1); + if (cc != sizeof text1 - 1) + error (1, errno, "cannot write to temporary file"); + } + close (temp_fd); +} + +static int +do_test (void) +{ + unsigned char buffer[8192]; + int result = 0; + FILE *f = fopen (temp_file, "rm"); + size_t cc; + + if (f == NULL) + { + perror (temp_file); + return 1; + } + + cc = fread (buffer, 1, sizeof (buffer), f); + printf ("fread %zu: \"%.*s\"\n", cc, (int) cc, buffer); + if (cc != sizeof text1 - 1) + { + perror ("fread"); + result = 1; + } + + if (fseek (f, 2048, SEEK_SET) != 0) + { + perror ("fseek off end"); + result = 1; + } + + if (fread (buffer, 1, sizeof (buffer), f) != 0 + || ferror (f) || !feof (f)) + { + printf ("after fread error %d eof %d\n", + ferror (f), feof (f)); + result = 1; + } + + printf ("ftell %ld\n", ftell (f)); + + if (fseek (f, 0, SEEK_SET) != 0) + { + perror ("fseek rewind"); + result = 1; + } + + cc = fread (buffer, 1, sizeof (buffer), f); + printf ("fread after rewind %zu: \"%.*s\"\n", cc, (int) cc, buffer); + if (cc != sizeof text1 - 1) + { + perror ("fread after rewind"); + result = 1; + } + + fclose (f); + return result; +} diff --git a/test/mmap/tst-mmap-setvbuf.c b/test/mmap/tst-mmap-setvbuf.c new file mode 100644 index 0000000..33d60b7 --- /dev/null +++ b/test/mmap/tst-mmap-setvbuf.c @@ -0,0 +1,81 @@ +/* Test setvbuf on readonly fopen (using mmap stdio). + Copyright (C) 2002-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int main (void) +{ + char name[] = "/tmp/tst-mmap-setvbuf.XXXXXX"; + char buf[4096]; + const char * const test = "Let's see if mmap stdio works with setvbuf.\n"; + char temp[strlen (test) + 1]; + int fd = mkstemp (name); + FILE *f; + + if (fd == -1) + { + printf ("%u: cannot open temporary file: %m\n", __LINE__); + exit (1); + } + + f = fdopen (fd, "w"); + if (f == NULL) + { + printf ("%u: cannot fdopen temporary file: %m\n", __LINE__); + exit (1); + } + + fputs (test, f); + fclose (f); + + f = fopen (name, "rm"); + if (f == NULL) + { + printf ("%u: cannot fopen temporary file: %m\n", __LINE__); + exit (1); + } + + if (setvbuf (f, buf, _IOFBF, sizeof buf)) + { + printf ("%u: setvbuf failed: %m\n", __LINE__); + exit (1); + } + + if (fread (temp, 1, strlen (test), f) != strlen (test)) + { + printf ("%u: couldn't read the file back: %m\n", __LINE__); + exit (1); + } + temp [strlen (test)] = '\0'; + + if (strcmp (test, temp)) + { + printf ("%u: read different string than was written:\n%s%s", + __LINE__, test, temp); + exit (1); + } + + fclose (f); + + unlink (name); + exit (0); +} |