diff options
author | Dmitry Antipov <dmitry.antipov@linaro.org> | 2012-11-27 12:49:37 +0400 |
---|---|---|
committer | Dmitry Antipov <dmitry.antipov@linaro.org> | 2012-11-27 12:49:37 +0400 |
commit | 6d75ab53586ff176d71556be4ebc3993ee69b59b (patch) | |
tree | 48e2e57d0864a20ad77ae799aef93bcae2880493 | |
download | linaro-android-kernel-test-6d75ab53586ff176d71556be4ebc3993ee69b59b.tar.gz |
Initial commit.
-rw-r--r-- | ashmemtest-basic/Android.mk | 8 | ||||
-rw-r--r-- | ashmemtest-basic/ashmemtest.c | 347 |
2 files changed, 355 insertions, 0 deletions
diff --git a/ashmemtest-basic/Android.mk b/ashmemtest-basic/Android.mk new file mode 100644 index 0000000..0c70ebf --- /dev/null +++ b/ashmemtest-basic/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ashmemtest.c +LOCAL_MODULE := ashmemtest +LOCAL_MODULE_TAGS := optional tests + +include $(BUILD_EXECUTABLE) diff --git a/ashmemtest-basic/ashmemtest.c b/ashmemtest-basic/ashmemtest.c new file mode 100644 index 0000000..a1f25fe --- /dev/null +++ b/ashmemtest-basic/ashmemtest.c @@ -0,0 +1,347 @@ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <stdint.h> +#include <stdarg.h> + +#include "ashmem.h" /* frameworks/native/include/utils/ashmem.h */ + +#ifndef ASHMEM_MAJOR +#define ASHMEM_MAJOR 10 /* misc device, should match MISC_DEVICE in linux/major.h */ +#endif + +#ifndef _LINUX_ASHMEM_H +/* only if not defined already */ +struct ashmem_pin { + uint32_t offset; + uint32_t len; +}; +#endif + +int testno = -1; + +void fatal (int error, const char *fmt, ...) +{ + va_list ap; + + fprintf (stderr, "Test %d: ", testno); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + if (error) + fprintf (stderr, " (error %d [%s])", error, strerror (error)); + va_end (ap); + fprintf (stderr, "\n"); + exit (1); +} + +int test_open (char *name, mode_t mode) +{ + int fd; + + fd = open (name, mode); + if (fd < 0) + fatal (errno, "can't open %s", name); + return fd; +} + +void test_close (int fd) +{ + if (close (fd) < 0) + fatal (errno, "can't close fd %d", fd); +} + +void ashmem_basic (char *ashmemdev) +{ + int fd; + struct stat st; + + testno++; + + /* make sure we can open it */ + fd = test_open (ashmemdev, O_RDWR); + + /* check whether it's a valid device file */ + if (fstat (fd, &st) < 0) + fatal (errno, "can't stat %s (fd %d)", ashmemdev, fd); + if (!S_ISCHR (st.st_mode)) + fatal (0, "%s is not a character device", ashmemdev); + if (major (st.st_dev) != ASHMEM_MAJOR) + fatal (0, "%s is not a device with major %d", ashmemdev, ASHMEM_MAJOR); + + /* check that close works too */ + test_close (fd); + + printf ("%d: test passed\n", testno); +} + +void ashmem_anonymous_region (char *ashmemdev, size_t pagesize) +{ + int fd, ret; + char name[ASHMEM_NAME_LEN]; + size_t size; + + testno++; + + /* test zero-sized region */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, 0); + if (ret >= 0) + fatal (0, "ASHMEM_SET_SIZE should not allow zero-sized anonymous region"); + test_close (fd); + + /* test non-page-rounded size */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize + 7); + if (ret >= 0) + fatal (0, "ASHMEM_SET_SIZE should not allow non-page-rounded anonymous region"); + test_close (fd); + + /* test max possible size */ + fd = test_open (ashmemdev, O_RDWR); + size = (SIZE_MAX - pagesize - 1) & ~(pagesize - 1); + ret = ioctl (fd, ASHMEM_SET_SIZE, size); + if (ret < 0 && errno != ENOMEM) + fatal (errno, "ENOMEM expected if too large size for ASHMEM_SET_SIZE is used"); + test_close (fd); + + /* test whether normal anonymous region has the default name */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", pagesize); + ret = ioctl (fd, ASHMEM_GET_NAME, name); + if (ret < 0) + fatal (errno, "can't get region name"); + if (strcmp (name, ASHMEM_NAME_DEF)) + fatal (0, "expect %s, but got %s for anonymous region name", ASHMEM_NAME_DEF, name); + test_close (fd); + + printf ("%d: test passed\n", testno); +} + +void ashmem_named_region (char *ashmemdev, size_t pagesize) +{ + int fd, ret, i; + char name[ASHMEM_NAME_LEN * 2], name2[ASHMEM_NAME_LEN]; + + testno++; + + /* test zero-sized region with zero-length name */ + fd = test_open (ashmemdev, O_RDWR); + name[0] = '\0'; + ret = ioctl (fd, ASHMEM_SET_NAME, name); + if (ret >= 0) + fatal (0, "zero-sized name is not allowed for ASHMEM_SET_NAME"); + ret = ioctl (fd, ASHMEM_SET_SIZE, 0); + if (ret >= 0) + fatal (0, "ASHMEM_SET_SIZE should not allow zero-sized named region"); + test_close (fd); + + /* test too long name */ + srand (getpid ()); + for (i = 0; i < ASHMEM_NAME_LEN * 2 - 1; i++) + name[i] = 'a' + rand () % ('z' - 'a'); + name[i] ='\0'; + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_NAME, name); + if (ret >= 0) + fatal (0, "ASHMEM_SET_NAME should not allow such a long name %s", name); + test_close (fd); + + /* test whether normal name matches between set and get */ + snprintf (name, ASHMEM_NAME_LEN, "Test memory region"); + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_NAME, name); + if (ret < 0) + fatal (errno, "can't set name '%s'", name); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize); + if (ret < 0) + fatal (errno, "can't set size to %ld bytes", pagesize); + ret = ioctl (fd, ASHMEM_GET_NAME, name2); + if (strcmp (name, name2)) + fatal (0, "name mismatch: expect '%s', got '%s'", name, name2); + test_close (fd); + + printf ("%d: test passed\n", testno); +} + +void ashmem_pin_unpin (char *ashmemdev, size_t pagesize) +{ + int fd, ret; + size_t size; + struct ashmem_pin pin; + + testno++; + + /* normal pin/unpin for the whole single-page region */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", pagesize); + pin.offset = 0, pin.len = pagesize; + ret = ioctl (fd, ASHMEM_PIN, 0, &pin); + if (ret < 0) + fatal (errno, "can't pin region with offset %ld and size %ld", 0, pagesize); + ret = ioctl (fd, ASHMEM_UNPIN, 0, &pin); + if (ret < 0) + fatal (errno, "can't unpin region with offset %ld and size %ld", 0, pagesize); + test_close (fd); + + /* make sure we can't pin zero bytes */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", pagesize); + pin.offset = 0, pin.len = 0; + ret = ioctl (fd, ASHMEM_PIN, &pin); + if (ret >= 0) + fatal (errno, "should not be able to pin zero bytes"); + test_close (fd); + + /* make sure we can't pin across page boundaries */ + fd = test_open (ashmemdev, O_RDWR); + size = pagesize * 16; + ret = ioctl (fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", size); + pin.offset = pagesize + 7, pin.len = 3 * pagesize + 11; + ret = ioctl (fd, ASHMEM_PIN, &pin); + if (ret >= 0) + fatal (errno, "should not be able to pin across page boundaries"); + test_close (fd); + + /* make sure we can't pin more than requested */ + fd = test_open (ashmemdev, O_RDWR); + size = pagesize * 8; + ret = ioctl (fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", size); + pin.offset = 0, pin.len = size * 2; + ret = ioctl (fd, ASHMEM_PIN, 0, &pin); + if (ret >= 0) + fatal (errno, "should not be able to pin more than allocated"); + test_close (fd); + + /* make sure we can't pin beyond the region */ + fd = test_open (ashmemdev, O_RDWR); + size = pagesize * 8; + ret = ioctl (fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", size); + pin.offset = size * 2, pin.len = pagesize; + ret = ioctl (fd, ASHMEM_PIN, &pin); + if (ret >= 0) + fatal (errno, "should not be able to pin beyond the region"); + test_close (fd); + + printf ("%d: test passsed\n", testno); +} + +void ashmem_pin_status (char *ashmemdev, size_t pagesize) +{ + int fd, ret; + struct ashmem_pin pin; + size_t size = pagesize * 4; + + testno++; + + /* get 4-pages region */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, size); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region", size); + + /* make sure we can't examine zero-sized region */ + pin.offset = 0, pin.len = 0; + ret = ioctl (fd, ASHMEM_ISPINNED, &pin); + if (ret >= 0) + fatal (errno, "should not be able to ask status of zero-sized region"); + + /* make sure we can't examine across page boundaries */ + pin.offset = pagesize + 11, pin.len = pagesize + 17; + ret = ioctl (fd, ASHMEM_ISPINNED, &pin); + if (ret >= 0) + fatal (errno, "should not be able to ask across page boundaries"); + + /* make sure we can't examine beyond the region */ + pin.offset = size * 2, pin.len = pagesize; + ret = ioctl (fd, ASHMEM_ISPINNED, &pin); + if (ret >= 0) + fatal (errno, "should not be able to ask beyond the region"); + + /* make sure it's initially not pinned */ + pin.offset = 0, pin.len = size; + ret = ioctl (fd, ASHMEM_ISPINNED, 0, size); + if (ret != ASHMEM_NOW_UNPINNED) + fatal (0, "expect initially unpinned region"); + + /* pin the whole region */ + pin.offset = 0, pin.len = size; + ret = ioctl (fd, ASHMEM_PIN, &pin); + if (ret < 0) + fatal (errno, "can't pin region"); + + /* make sure it's now pinned */ + pin.offset = 0, pin.len = size; + ret = ioctl (fd, ASHMEM_ISPINNED, &pin); + if (ret != ASHMEM_NOW_PINNED) + fatal (0, "expect pinned region"); + + /* unpin it back */ + pin.offset = 0, pin.len = size; + ret = ioctl (fd, ASHMEM_UNPIN, &pin); + if (ret < 0) + fatal (errno, "can't unpin region"); + + /* make sure it's not pinned again */ + pin.offset = 0, pin.len = size; + ret = ioctl (fd, ASHMEM_ISPINNED, &pin); + if (ret != ASHMEM_NOW_UNPINNED) + fatal (0, "expect unpinned region"); + + test_close (fd); + + printf ("%d: test passsed\n", testno); +} + +void ashmem_size (char *ashmemdev, size_t pagesize) +{ + int fd, ret; + + testno++; + + /* check whether set and get sizes match */ + fd = test_open (ashmemdev, O_RDWR); + ret = ioctl (fd, ASHMEM_SET_SIZE, pagesize); + if (ret < 0) + fatal (errno, "can't allocate %ld-bytes region"); + ret = ioctl (fd, ASHMEM_GET_SIZE, 0); + if (ret != pagesize) + fatal (0, "size mismatch: expect %ld, got %d", pagesize, ret); + test_close (fd); + + printf ("%d: test passed\n", testno); +} + +int main(int argc, char *argv[]) +{ + char ashmemdev[64]; + size_t pagesize = getpagesize (); + + snprintf (ashmemdev, sizeof (ashmemdev), "/%s", ASHMEM_NAME_DEF); + + ashmem_basic (ashmemdev); + ashmem_anonymous_region (ashmemdev, pagesize); + ashmem_named_region (ashmemdev, pagesize); + ashmem_pin_unpin (ashmemdev, pagesize); + ashmem_pin_status (ashmemdev, pagesize); + ashmem_size (ashmemdev, pagesize); + + return 0; +} |