diff options
author | Colin Cross <ccross@android.com> | 2013-11-07 23:06:58 -0800 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2013-12-19 19:31:46 -0800 |
commit | 363441b120aa7ff4ec7c639bac099e775c2ace69 (patch) | |
tree | 4aef851bb4d982f88748694f9e67baf6e480ed84 /libion | |
parent | b04f75ab129e471eb0b45571f0c319c516de0c02 (diff) | |
download | system_core-363441b120aa7ff4ec7c639bac099e775c2ace69.zip system_core-363441b120aa7ff4ec7c639bac099e775c2ace69.tar.gz system_core-363441b120aa7ff4ec7c639bac099e775c2ace69.tar.bz2 |
libion: initial unit tests
Change-Id: I5502b71d0c7c24d7fd59e4880033657f840b341a
Diffstat (limited to 'libion')
-rw-r--r-- | libion/Android.mk | 2 | ||||
-rw-r--r-- | libion/tests/Android.mk | 34 | ||||
-rw-r--r-- | libion/tests/allocate_test.cpp | 145 | ||||
-rw-r--r-- | libion/tests/device_test.cpp | 568 | ||||
-rw-r--r-- | libion/tests/exit_test.cpp | 227 | ||||
-rw-r--r-- | libion/tests/formerly_valid_handle_test.cpp | 63 | ||||
-rw-r--r-- | libion/tests/invalid_values_test.cpp | 186 | ||||
-rw-r--r-- | libion/tests/ion_test_fixture.cpp | 73 | ||||
-rw-r--r-- | libion/tests/ion_test_fixture.h | 46 | ||||
-rw-r--r-- | libion/tests/map_test.cpp | 162 |
10 files changed, 1506 insertions, 0 deletions
diff --git a/libion/Android.mk b/libion/Android.mk index 42e6f07..e5d495b 100644 --- a/libion/Android.mk +++ b/libion/Android.mk @@ -16,3 +16,5 @@ LOCAL_MODULE_TAGS := optional tests LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/kernel-headers LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_EXECUTABLE) + +include $(call first-makefiles-under,$(LOCAL_PATH)) diff --git a/libion/tests/Android.mk b/libion/tests/Android.mk new file mode 100644 index 0000000..8dc7f9d --- /dev/null +++ b/libion/tests/Android.mk @@ -0,0 +1,34 @@ +# +# Copyright (C) 2013 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := ion-unit-tests +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers +LOCAL_SHARED_LIBRARIES += libion +LOCAL_STATIC_LIBRARIES += libgtest_main +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../kernel-headers +LOCAL_SRC_FILES := \ + ion_test_fixture.cpp \ + allocate_test.cpp \ + formerly_valid_handle_test.cpp \ + invalid_values_test.cpp \ + map_test.cpp \ + device_test.cpp \ + exit_test.cpp +include $(BUILD_NATIVE_TEST) diff --git a/libion/tests/allocate_test.cpp b/libion/tests/allocate_test.cpp new file mode 100644 index 0000000..e26b302 --- /dev/null +++ b/libion/tests/allocate_test.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/mman.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> +#include "ion_test_fixture.h" + +class Allocate : public IonAllHeapsTest { +}; + +TEST_F(Allocate, Allocate) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ion_user_handle_t handle = 0; + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle)); + ASSERT_TRUE(handle != 0); + ASSERT_EQ(0, ion_free(m_ionFd, handle)); + } + } +} + +TEST_F(Allocate, AllocateCached) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ion_user_handle_t handle = 0; + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &handle)); + ASSERT_TRUE(handle != 0); + ASSERT_EQ(0, ion_free(m_ionFd, handle)); + } + } +} + +TEST_F(Allocate, AllocateCachedNeedsSync) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ion_user_handle_t handle = 0; + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED_NEEDS_SYNC, &handle)); + ASSERT_TRUE(handle != 0); + ASSERT_EQ(0, ion_free(m_ionFd, handle)); + } + } +} + +TEST_F(Allocate, RepeatedAllocate) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ion_user_handle_t handle = 0; + + for (unsigned int i = 0; i < 1024; i++) { + SCOPED_TRACE(::testing::Message() << "iteration " << i); + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle)); + ASSERT_TRUE(handle != 0); + ASSERT_EQ(0, ion_free(m_ionFd, handle)); + } + } + } +} + +TEST_F(Allocate, Zeroed) +{ + void *zeroes = calloc(4096, 1); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int fds[16]; + for (unsigned int i = 0; i < 16; i++) { + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr = NULL; + ptr = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + memset(ptr, 0xaa, 4096); + + ASSERT_EQ(0, munmap(ptr, 4096)); + fds[i] = map_fd; + } + + for (unsigned int i = 0; i < 16; i++) { + ASSERT_EQ(0, close(fds[i])); + } + + int newIonFd = ion_open(); + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(newIonFd, 4096, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr = NULL; + ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, memcmp(ptr, zeroes, 4096)); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(zeroes); + +} + +TEST_F(Allocate, Large) +{ + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + ion_user_handle_t handle = 0; + ASSERT_EQ(-ENOMEM, ion_alloc(m_ionFd, 3UL*1024*1024*1024, 0, heapMask, 0, &handle)); + } +} diff --git a/libion/tests/device_test.cpp b/libion/tests/device_test.cpp new file mode 100644 index 0000000..6f6e1bd --- /dev/null +++ b/libion/tests/device_test.cpp @@ -0,0 +1,568 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <linux/ion_test.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +#define ALIGN(x,y) (((x) + ((y) - 1)) & ~((y) - 1)) + +class Device : public IonAllHeapsTest { + public: + virtual void SetUp(); + virtual void TearDown(); + int m_deviceFd; + void readDMA(int fd, void *buf, size_t size); + void writeDMA(int fd, void *buf, size_t size); + void readKernel(int fd, void *buf, size_t size); + void writeKernel(int fd, void *buf, size_t size); + void blowCache(); + void dirtyCache(void *ptr, size_t size); +}; + +void Device::SetUp() +{ + IonAllHeapsTest::SetUp(); + m_deviceFd = open("/dev/ion-test", O_RDWR); + ASSERT_GE(m_deviceFd, 0); +} + +void Device::TearDown() +{ + ASSERT_EQ(0, close(m_deviceFd)); + IonAllHeapsTest::TearDown(); +} + +void Device::readDMA(int fd, void *buf, size_t size) +{ + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd)); + struct ion_test_rw_data ion_test_rw_data = { + .ptr = (uint64_t)buf, + .offset = 0, + .size = size, + .write = 0, + }; + + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data)); + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1)); +} + +void Device::writeDMA(int fd, void *buf, size_t size) +{ + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd)); + struct ion_test_rw_data ion_test_rw_data = { + .ptr = (uint64_t)buf, + .offset = 0, + .size = size, + .write = 1, + }; + + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data)); + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1)); +} + +void Device::readKernel(int fd, void *buf, size_t size) +{ + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd)); + struct ion_test_rw_data ion_test_rw_data = { + .ptr = (uint64_t)buf, + .offset = 0, + .size = size, + .write = 0, + }; + + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data)); + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1)); +} + +void Device::writeKernel(int fd, void *buf, size_t size) +{ + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd)); + struct ion_test_rw_data ion_test_rw_data = { + .ptr = (uint64_t)buf, + .offset = 0, + .size = size, + .write = 1, + }; + + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data)); + ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1)); +} + +void Device::blowCache() +{ + const size_t bigger_than_cache = 8*1024*1024; + void *buf1 = malloc(bigger_than_cache); + void *buf2 = malloc(bigger_than_cache); + memset(buf1, 0xaa, bigger_than_cache); + memcpy(buf2, buf1, bigger_than_cache); + free(buf1); + free(buf2); +} + +void Device::dirtyCache(void *ptr, size_t size) +{ + /* try to dirty cache lines */ + for (size_t i = size-1; i > 0; i--) { + ((volatile char *)ptr)[i]; + ((char *)ptr)[i] = i; + } +} + +TEST_F(Device, KernelReadCached) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + ((char*)buf)[4096] = 0x12; + readKernel(map_fd, buf, 4096); + ASSERT_EQ(((char*)buf)[4096], 0x12); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, KernelWriteCached) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeKernel(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMAReadCached) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + readDMA(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMAWriteCached) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeDMA(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, KernelReadCachedNeedsSync) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + ((char*)buf)[4096] = 0x12; + readKernel(map_fd, buf, 4096); + ASSERT_EQ(((char*)buf)[4096], 0x12); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, KernelWriteCachedNeedsSync) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeKernel(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMAReadCachedNeedsSync) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + ion_sync_fd(m_ionFd, map_fd); + + readDMA(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMAWriteCachedNeedsSync) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeDMA(map_fd, buf, 4096); + + ion_sync_fd(m_ionFd, map_fd); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} +TEST_F(Device, KernelRead) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = 0; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + ((char*)buf)[4096] = 0x12; + readKernel(map_fd, buf, 4096); + ASSERT_EQ(((char*)buf)[4096], 0x12); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, KernelWrite) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = 0; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeKernel(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMARead) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = 0; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + for (int i = 0; i < 4096; i++) + ((char *)ptr)[i] = i; + + readDMA(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)buf)[i]); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, DMAWrite) +{ + void *alloc = malloc(8192 + 1024); + void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024); + + for (int i = 0; i < 4096; i++) + ((char *)buf)[i] = i; + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = 0; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + writeDMA(map_fd, buf, 4096); + + for (int i = 0; i < 4096; i++) + ASSERT_EQ((char)i, ((char *)ptr)[i]) << i; + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } + + free(alloc); +} + +TEST_F(Device, IsCached) +{ + void *buf = malloc(4096); + + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + dirtyCache(ptr, 4096); + + readDMA(map_fd, buf, 4096); + + bool same = true; + for (int i = 4096-16; i >= 0; i -= 16) + if (((char *)buf)[i] != i) + same = false; + ASSERT_FALSE(same); + + ASSERT_EQ(0, munmap(ptr, 4096)); + ASSERT_EQ(0, close(map_fd)); + } +} diff --git a/libion/tests/exit_test.cpp b/libion/tests/exit_test.cpp new file mode 100644 index 0000000..cdd3e27 --- /dev/null +++ b/libion/tests/exit_test.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/mman.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +class Exit : public IonAllHeapsTest { +}; + +TEST_F(Exit, WithAlloc) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + ion_user_handle_t handle = 0; + + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle)); + ASSERT_TRUE(handle != 0); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } +} + +TEST_F(Exit, WithAllocFd) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int handle_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &handle_fd)); + ASSERT_NE(-1, handle_fd); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } +} + +TEST_F(Exit, WithRepeatedAllocFd) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + for (unsigned int i = 0; i < 1024; i++) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ASSERT_EXIT({ + int handle_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &handle_fd)); + ASSERT_NE(-1, handle_fd); + exit(0); + }, ::testing::ExitedWithCode(0), "") + << "failed on heap " << heapMask + << " and size " << size + << " on iteration " << i; + } + } + } +} + + +TEST_F(Exit, WithMapping) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } + +} + +TEST_F(Exit, WithPartialMapping) +{ + static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, munmap(ptr, size / 2)); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } +} + +TEST_F(Exit, WithMappingCached) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } + +} + +TEST_F(Exit, WithPartialMappingCached) +{ + static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, munmap(ptr, size / 2)); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } +} + +TEST_F(Exit, WithMappingNeedsSync) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } + +} + +TEST_F(Exit, WithPartialMappingNeedsSync) +{ + static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + EXPECT_EXIT({ + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, munmap(ptr, size / 2)); + exit(0); + }, ::testing::ExitedWithCode(0), ""); + } + } +} diff --git a/libion/tests/formerly_valid_handle_test.cpp b/libion/tests/formerly_valid_handle_test.cpp new file mode 100644 index 0000000..01ab8f3 --- /dev/null +++ b/libion/tests/formerly_valid_handle_test.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/mman.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +class FormerlyValidHandle : public IonTest { + public: + virtual void SetUp(); + virtual void TearDown(); + ion_user_handle_t m_handle; +}; + +void FormerlyValidHandle::SetUp() +{ + IonTest::SetUp(); + ASSERT_EQ(0, ion_alloc(m_ionFd, 4096, 0, 1/* ion_env->m_firstHeap */, 0, &m_handle)); + ASSERT_TRUE(m_handle != 0); + ASSERT_EQ(0, ion_free(m_ionFd, m_handle)); +} + +void FormerlyValidHandle::TearDown() +{ + m_handle = 0; +} + +TEST_F(FormerlyValidHandle, free) +{ + ASSERT_EQ(-EINVAL, ion_free(m_ionFd, m_handle)); +} + +TEST_F(FormerlyValidHandle, map) +{ + int map_fd; + unsigned char *ptr; + + ASSERT_EQ(-EINVAL, ion_map(m_ionFd, m_handle, 4096, PROT_READ, 0, 0, &ptr, &map_fd)); +} + +TEST_F(FormerlyValidHandle, share) +{ + int share_fd; + + ASSERT_EQ(-EINVAL, ion_share(m_ionFd, m_handle, &share_fd)); +} diff --git a/libion/tests/invalid_values_test.cpp b/libion/tests/invalid_values_test.cpp new file mode 100644 index 0000000..77fea17 --- /dev/null +++ b/libion/tests/invalid_values_test.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/mman.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +class InvalidValues : public IonAllHeapsTest { + public: + virtual void SetUp(); + virtual void TearDown(); + ion_user_handle_t m_validHandle; + int m_validShareFd; + ion_user_handle_t const m_badHandle = -1; +}; + +void InvalidValues::SetUp() +{ + IonAllHeapsTest::SetUp(); + ASSERT_EQ(0, ion_alloc(m_ionFd, 4096, 0, m_firstHeap, 0, &m_validHandle)) + << m_ionFd << " " << m_firstHeap; + ASSERT_TRUE(m_validHandle != 0); + ASSERT_EQ(0, ion_share(m_ionFd, m_validHandle, &m_validShareFd)); +} + +void InvalidValues::TearDown() +{ + ASSERT_EQ(0, ion_free(m_ionFd, m_validHandle)); + ASSERT_EQ(0, close(m_validShareFd)); + m_validHandle = 0; + IonAllHeapsTest::TearDown(); +} + +TEST_F(InvalidValues, ion_close) +{ + EXPECT_EQ(-EBADF, ion_close(-1)); +} + +TEST_F(InvalidValues, ion_alloc) +{ + ion_user_handle_t handle; + /* invalid ion_fd */ + int ret = ion_alloc(0, 4096, 0, m_firstHeap, 0, &handle); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion_fd */ + EXPECT_EQ(-EBADF, ion_alloc(-1, 4096, 0, m_firstHeap, 0, &handle)); + /* no heaps */ + EXPECT_EQ(-ENODEV, ion_alloc(m_ionFd, 4096, 0, 0, 0, &handle)); + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + /* zero size */ + EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 0, 0, heapMask, 0, &handle)); + /* too large size */ + EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, -1, 0, heapMask, 0, &handle)); + /* bad alignment */ + EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 4096, -1, heapMask, 0, &handle)); + /* NULL handle */ + EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 4096, 0, heapMask, 0, NULL)); + } +} + +TEST_F(InvalidValues, ion_alloc_fd) +{ + int fd; + /* invalid ion_fd */ + int ret = ion_alloc_fd(0, 4096, 0, m_firstHeap, 0, &fd); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion_fd */ + EXPECT_EQ(-EBADF, ion_alloc_fd(-1, 4096, 0, m_firstHeap, 0, &fd)); + /* no heaps */ + EXPECT_EQ(-ENODEV, ion_alloc_fd(m_ionFd, 4096, 0, 0, 0, &fd)); + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + /* zero size */ + EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 0, 0, heapMask, 0, &fd)); + /* too large size */ + EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, -1, 0, heapMask, 0, &fd)); + /* bad alignment */ + EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 4096, -1, heapMask, 0, &fd)); + /* NULL handle */ + EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, 0, NULL)); + } +} + +TEST_F(InvalidValues, ion_free) +{ + /* invalid ion fd */ + int ret = ion_free(0, m_validHandle); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion fd */ + EXPECT_EQ(-EBADF, ion_free(-1, m_validHandle)); + /* zero handle */ + EXPECT_EQ(-EINVAL, ion_free(m_ionFd, 0)); + /* bad handle */ + EXPECT_EQ(-EINVAL, ion_free(m_ionFd, m_badHandle)); +} + +TEST_F(InvalidValues, ion_map) +{ + int map_fd; + unsigned char *ptr; + + /* invalid ion fd */ + int ret = ion_map(0, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion fd */ + EXPECT_EQ(-EBADF, ion_map(-1, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd)); + /* zero handle */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, 0, 4096, PROT_READ, 0, 0, &ptr, &map_fd)); + /* bad handle */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_badHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd)); + /* zero length */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 0, PROT_READ, 0, 0, &ptr, &map_fd)); + /* bad prot */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, -1, 0, 0, &ptr, &map_fd)); + /* bad offset */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, -1, &ptr, &map_fd)); + /* NULL ptr */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, 0, NULL, &map_fd)); + /* NULL map_fd */ + EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, NULL)); +} + +TEST_F(InvalidValues, ion_share) +{ + int share_fd; + + /* invalid ion fd */ + int ret = ion_share(0, m_validHandle, &share_fd); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion fd */ + EXPECT_EQ(-EBADF, ion_share(-1, m_validHandle, &share_fd)); + /* zero handle */ + EXPECT_EQ(-EINVAL, ion_share(m_ionFd, 0, &share_fd)); + /* bad handle */ + EXPECT_EQ(-EINVAL, ion_share(m_ionFd, m_badHandle, &share_fd)); + /* NULL share_fd */ + EXPECT_EQ(-EINVAL, ion_share(m_ionFd, m_validHandle, NULL)); +} + +TEST_F(InvalidValues, ion_import) +{ + ion_user_handle_t handle; + + /* invalid ion fd */ + int ret = ion_import(0, m_validShareFd, &handle); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion fd */ + EXPECT_EQ(-EBADF, ion_import(-1, m_validShareFd, &handle)); + /* bad share_fd */ + EXPECT_EQ(-EINVAL, ion_import(m_ionFd, 0, &handle)); + /* invalid share_fd */ + EXPECT_EQ(-EBADF, ion_import(m_ionFd, -1, &handle)); + /* NULL handle */ + EXPECT_EQ(-EINVAL, ion_import(m_ionFd, m_validShareFd, NULL)); +} + +TEST_F(InvalidValues, ion_sync_fd) +{ + /* invalid ion fd */ + int ret = ion_sync_fd(0, m_validShareFd); + EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY); + /* invalid ion fd */ + EXPECT_EQ(-EBADF, ion_sync_fd(-1, m_validShareFd)); + /* bad share_fd */ + EXPECT_EQ(-EINVAL, ion_sync_fd(m_ionFd, 0)); + /* invalid share_fd */ + EXPECT_EQ(-EBADF, ion_sync_fd(m_ionFd, -1)); +} diff --git a/libion/tests/ion_test_fixture.cpp b/libion/tests/ion_test_fixture.cpp new file mode 100644 index 0000000..e20c730 --- /dev/null +++ b/libion/tests/ion_test_fixture.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +IonTest::IonTest() : m_ionFd(-1) +{ +} + +void IonTest::SetUp() { + m_ionFd = ion_open(); + ASSERT_GE(m_ionFd, 0); +} + +void IonTest::TearDown() { + ion_close(m_ionFd); +} + +IonAllHeapsTest::IonAllHeapsTest() : + m_firstHeap(0), + m_lastHeap(0), + m_allHeaps() +{ +} + +void IonAllHeapsTest::SetUp() { + int fd = ion_open(); + ASSERT_GE(fd, 0); + + for (int i = 1; i != 0; i <<= 1) { + ion_user_handle_t handle = 0; + int ret; + ret = ion_alloc(fd, 4096, 0, i, 0, &handle); + if (ret == 0 && handle != 0) { + ion_free(fd, handle); + if (!m_firstHeap) { + m_firstHeap = i; + } + m_lastHeap = i; + m_allHeaps.push_back(i); + } else { + ASSERT_EQ(-ENODEV, ret); + } + } + ion_close(fd); + + EXPECT_NE(0U, m_firstHeap); + EXPECT_NE(0U, m_lastHeap); + + RecordProperty("Heaps", m_allHeaps.size()); + IonTest::SetUp(); +} + +void IonAllHeapsTest::TearDown() { + IonTest::TearDown(); +} diff --git a/libion/tests/ion_test_fixture.h b/libion/tests/ion_test_fixture.h new file mode 100644 index 0000000..4098214 --- /dev/null +++ b/libion/tests/ion_test_fixture.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ION_TEST_FIXTURE_H_ +#define ION_TEST_FIXTURE_H_ + +#include <gtest/gtest.h> + +using ::testing::Test; + +class IonTest : public virtual Test { + public: + IonTest(); + virtual ~IonTest() {}; + virtual void SetUp(); + virtual void TearDown(); + int m_ionFd; +}; + +class IonAllHeapsTest : public IonTest { + public: + IonAllHeapsTest(); + virtual ~IonAllHeapsTest() {}; + virtual void SetUp(); + virtual void TearDown(); + + unsigned int m_firstHeap; + unsigned int m_lastHeap; + + std::vector<unsigned int> m_allHeaps; +}; + +#endif /* ION_TEST_FIXTURE_H_ */ diff --git a/libion/tests/map_test.cpp b/libion/tests/map_test.cpp new file mode 100644 index 0000000..c006dc8 --- /dev/null +++ b/libion/tests/map_test.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/mman.h> + +#include <gtest/gtest.h> + +#include <ion/ion.h> + +#include "ion_test_fixture.h" + +class Map : public IonAllHeapsTest { +}; + +TEST_F(Map, MapHandle) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + ion_user_handle_t handle = 0; + + ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle)); + ASSERT_TRUE(handle != 0); + + int map_fd = -1; + unsigned char *ptr = NULL; + ASSERT_EQ(0, ion_map(m_ionFd, handle, size, PROT_READ | PROT_WRITE, MAP_SHARED, 0, &ptr, &map_fd)); + ASSERT_TRUE(ptr != NULL); + ASSERT_GE(map_fd, 0); + + ASSERT_EQ(0, close(map_fd)); + + ASSERT_EQ(0, ion_free(m_ionFd, handle)); + + memset(ptr, 0xaa, size); + + ASSERT_EQ(0, munmap(ptr, size)); + } + } +} + +TEST_F(Map, MapFd) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, close(map_fd)); + + memset(ptr, 0xaa, size); + + ASSERT_EQ(0, munmap(ptr, size)); + } + } +} + +TEST_F(Map, MapOffset) +{ + for (unsigned int heapMask : m_allHeaps) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + int map_fd = -1; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, PAGE_SIZE * 2, 0, heapMask, 0, &map_fd)); + ASSERT_GE(map_fd, 0); + + unsigned char *ptr; + ptr = (unsigned char *)mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + memset(ptr, 0, PAGE_SIZE); + memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE); + + ASSERT_EQ(0, munmap(ptr, PAGE_SIZE * 2)); + + ptr = (unsigned char *)mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, PAGE_SIZE); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(ptr[0], 0xaa); + ASSERT_EQ(ptr[PAGE_SIZE - 1], 0xaa); + + ASSERT_EQ(0, munmap(ptr, PAGE_SIZE)); + + ASSERT_EQ(0, close(map_fd)); + } +} + +TEST_F(Map, MapCached) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, close(map_fd)); + + memset(ptr, 0xaa, size); + + ASSERT_EQ(0, munmap(ptr, size)); + } + } +} + +TEST_F(Map, MapCachedNeedsSync) +{ + static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024}; + for (unsigned int heapMask : m_allHeaps) { + for (size_t size : allocationSizes) { + SCOPED_TRACE(::testing::Message() << "heap " << heapMask); + SCOPED_TRACE(::testing::Message() << "size " << size); + int map_fd = -1; + unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + + ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, flags, &map_fd)); + ASSERT_GE(map_fd, 0); + + void *ptr; + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); + ASSERT_TRUE(ptr != NULL); + + ASSERT_EQ(0, close(map_fd)); + + memset(ptr, 0xaa, size); + + ASSERT_EQ(0, munmap(ptr, size)); + } + } +} |