1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <gtest/gtest.h> 18 19#include <sys/mman.h> 20#include <sys/types.h> 21#include <unistd.h> 22 23#include "TemporaryFile.h" 24 25TEST(sys_mman, mmap_std) { 26 void* map = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 27 ASSERT_NE(MAP_FAILED, map); 28 ASSERT_EQ(0, munmap(map, 4096)); 29} 30 31TEST(sys_mman, mmap64_std) { 32 void* map = mmap64(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 33 ASSERT_NE(MAP_FAILED, map); 34 ASSERT_EQ(0, munmap(map, 4096)); 35} 36 37TEST(sys_mman, mmap_file_bad_offset) { 38 TemporaryFile tf; 39 40 void* map = mmap(NULL, 100, PROT_READ, MAP_SHARED, tf.fd, 1); 41 ASSERT_EQ(MAP_FAILED, map); 42} 43 44TEST(sys_mman, mmap64_file_bad_offset) { 45 TemporaryFile tf; 46 47 void* map = mmap64(NULL, 100, PROT_READ, MAP_SHARED, tf.fd, 1); 48 ASSERT_EQ(MAP_FAILED, map); 49} 50 51#define STR_SSIZE(str) static_cast<ssize_t>(sizeof(str)) 52 53#define STRING_MSG "012345678\nabcdefgh\n" 54#define INITIAL_MSG "000000000\n00000000\n" 55 56TEST(sys_mman, mmap_file_read) { 57 TemporaryFile tf; 58 59 ASSERT_EQ(STR_SSIZE(STRING_MSG), write(tf.fd, STRING_MSG, sizeof(STRING_MSG))); 60 61 void* map = mmap(NULL, sizeof(STRING_MSG), PROT_READ, MAP_SHARED, tf.fd, 0); 62 ASSERT_NE(MAP_FAILED, map); 63 64 char* data = reinterpret_cast<char*>(map); 65 ASSERT_STREQ(STRING_MSG, data); 66 67 ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG))); 68} 69 70TEST(sys_mman, mmap_file_write) { 71 TemporaryFile tf; 72 73 ASSERT_EQ(STR_SSIZE(INITIAL_MSG), write(tf.fd, INITIAL_MSG, sizeof(INITIAL_MSG))); 74 lseek(tf.fd, 0, SEEK_SET); 75 76 void* map = mmap(NULL, sizeof(STRING_MSG), PROT_WRITE, MAP_SHARED, tf.fd, 0); 77 ASSERT_NE(MAP_FAILED, map); 78 close(tf.fd); 79 80 memcpy(map, STRING_MSG, sizeof(STRING_MSG)); 81 82 ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG))); 83 84 tf.reopen(); 85 char buf[sizeof(STRING_MSG)]; 86 memset(buf, 0, sizeof(STRING_MSG)); 87 ASSERT_EQ(STR_SSIZE(STRING_MSG), read(tf.fd, buf, sizeof(STRING_MSG))); 88 89 ASSERT_STREQ(STRING_MSG, buf); 90} 91 92#define PAGE0_MSG "00PAGE00" 93#define PAGE1_MSG "111PAGE111" 94#define PAGE2_MSG "2222PAGE2222" 95#define END_MSG "E" 96 97TEST(sys_mman, mmap_file_read_at_offset) { 98 TemporaryFile tf; 99 size_t pagesize = sysconf(_SC_PAGESIZE); 100 101 // Create the file with three pages worth of data. 102 ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG))); 103 ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET)); 104 ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG))); 105 ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET)); 106 ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG))); 107 ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET)); 108 ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG))); 109 110 ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET)); 111 112 void* map = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, tf.fd, pagesize); 113 ASSERT_NE(MAP_FAILED, map); 114 115 char* data = reinterpret_cast<char*>(map); 116 ASSERT_STREQ(PAGE1_MSG, data); 117 118 ASSERT_EQ(0, munmap(map, pagesize)); 119 120 map = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, tf.fd, 2 * pagesize); 121 ASSERT_NE(MAP_FAILED, map); 122 123 data = reinterpret_cast<char*>(map); 124 ASSERT_STREQ(PAGE2_MSG, data); 125 ASSERT_STREQ(END_MSG, data+pagesize-sizeof(END_MSG)); 126 127 ASSERT_EQ(0, munmap(map, pagesize)); 128} 129 130#define NEWPAGE1_MSG "1NEW1PAGE1" 131#define NEWPAGE2_MSG "22NEW22PAGE22" 132 133TEST(sys_mman, mmap_file_write_at_offset) { 134 TemporaryFile tf; 135 size_t pagesize = sysconf(_SC_PAGESIZE); 136 137 // Create the file with three pages worth of data. 138 ASSERT_EQ(STR_SSIZE(PAGE0_MSG), write(tf.fd, PAGE0_MSG, sizeof(PAGE0_MSG))); 139 ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET)); 140 ASSERT_EQ(STR_SSIZE(PAGE1_MSG), write(tf.fd, PAGE1_MSG, sizeof(PAGE1_MSG))); 141 ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET)); 142 ASSERT_EQ(STR_SSIZE(PAGE2_MSG), write(tf.fd, PAGE2_MSG, sizeof(PAGE2_MSG))); 143 ASSERT_NE(-1, lseek(tf.fd, 3 * pagesize - sizeof(END_MSG), SEEK_SET)); 144 ASSERT_EQ(STR_SSIZE(END_MSG), write(tf.fd, END_MSG, sizeof(END_MSG))); 145 146 ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET)); 147 148 void* map = mmap(NULL, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, pagesize); 149 ASSERT_NE(MAP_FAILED, map); 150 close(tf.fd); 151 152 memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG)); 153 ASSERT_EQ(0, munmap(map, pagesize)); 154 155 tf.reopen(); 156 map = mmap(NULL, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, 2 * pagesize); 157 ASSERT_NE(MAP_FAILED, map); 158 close(tf.fd); 159 160 memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG)); 161 ASSERT_EQ(0, munmap(map, pagesize)); 162 163 tf.reopen(); 164 char buf[pagesize]; 165 ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize)); 166 ASSERT_STREQ(PAGE0_MSG, buf); 167 ASSERT_NE(-1, lseek(tf.fd, pagesize, SEEK_SET)); 168 ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize)); 169 ASSERT_STREQ(NEWPAGE1_MSG, buf); 170 ASSERT_NE(-1, lseek(tf.fd, 2 * pagesize, SEEK_SET)); 171 ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize)); 172 ASSERT_STREQ(NEWPAGE2_MSG, buf); 173 ASSERT_STREQ(END_MSG, buf+pagesize-sizeof(END_MSG)); 174} 175