summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Antipov <dmitry.antipov@linaro.org>2012-11-27 12:49:37 +0400
committerDmitry Antipov <dmitry.antipov@linaro.org>2012-11-27 12:49:37 +0400
commit6d75ab53586ff176d71556be4ebc3993ee69b59b (patch)
tree48e2e57d0864a20ad77ae799aef93bcae2880493
downloadlinaro-android-kernel-test-6d75ab53586ff176d71556be4ebc3993ee69b59b.tar.gz
Initial commit.
-rw-r--r--ashmemtest-basic/Android.mk8
-rw-r--r--ashmemtest-basic/ashmemtest.c347
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;
+}