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 */
17 #include <gtest/gtest.h>
19 #include <sys/mman.h>
20 #include <sys/types.h>
21 #include <unistd.h>
23 #include "TemporaryFile.h"
25 TEST(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 }
31 TEST(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 }
37 TEST(sys_mman, mmap_file_bad_offset) {
38 TemporaryFile tf;
40 void* map = mmap(NULL, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
41 ASSERT_EQ(MAP_FAILED, map);
42 }
44 TEST(sys_mman, mmap64_file_bad_offset) {
45 TemporaryFile tf;
47 void* map = mmap64(NULL, 100, PROT_READ, MAP_SHARED, tf.fd, 1);
48 ASSERT_EQ(MAP_FAILED, map);
49 }
51 #define STR_SSIZE(str) static_cast<ssize_t>(sizeof(str))
53 #define STRING_MSG "012345678\nabcdefgh\n"
54 #define INITIAL_MSG "000000000\n00000000\n"
56 TEST(sys_mman, mmap_file_read) {
57 TemporaryFile tf;
59 ASSERT_EQ(STR_SSIZE(STRING_MSG), write(tf.fd, STRING_MSG, sizeof(STRING_MSG)));
61 void* map = mmap(NULL, sizeof(STRING_MSG), PROT_READ, MAP_SHARED, tf.fd, 0);
62 ASSERT_NE(MAP_FAILED, map);
64 char* data = reinterpret_cast<char*>(map);
65 ASSERT_STREQ(STRING_MSG, data);
67 ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
68 }
70 TEST(sys_mman, mmap_file_write) {
71 TemporaryFile tf;
73 ASSERT_EQ(STR_SSIZE(INITIAL_MSG), write(tf.fd, INITIAL_MSG, sizeof(INITIAL_MSG)));
74 lseek(tf.fd, 0, SEEK_SET);
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);
80 memcpy(map, STRING_MSG, sizeof(STRING_MSG));
82 ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
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)));
89 ASSERT_STREQ(STRING_MSG, buf);
90 }
92 #define PAGE0_MSG "00PAGE00"
93 #define PAGE1_MSG "111PAGE111"
94 #define PAGE2_MSG "2222PAGE2222"
95 #define END_MSG "E"
97 TEST(sys_mman, mmap_file_read_at_offset) {
98 TemporaryFile tf;
99 size_t pagesize = sysconf(_SC_PAGESIZE);
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)));
110 ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));
112 void* map = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, tf.fd, pagesize);
113 ASSERT_NE(MAP_FAILED, map);
115 char* data = reinterpret_cast<char*>(map);
116 ASSERT_STREQ(PAGE1_MSG, data);
118 ASSERT_EQ(0, munmap(map, pagesize));
120 map = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, tf.fd, 2 * pagesize);
121 ASSERT_NE(MAP_FAILED, map);
123 data = reinterpret_cast<char*>(map);
124 ASSERT_STREQ(PAGE2_MSG, data);
125 ASSERT_STREQ(END_MSG, data+pagesize-sizeof(END_MSG));
127 ASSERT_EQ(0, munmap(map, pagesize));
128 }
130 #define NEWPAGE1_MSG "1NEW1PAGE1"
131 #define NEWPAGE2_MSG "22NEW22PAGE22"
133 TEST(sys_mman, mmap_file_write_at_offset) {
134 TemporaryFile tf;
135 size_t pagesize = sysconf(_SC_PAGESIZE);
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)));
146 ASSERT_NE(-1, lseek(tf.fd, 0, SEEK_SET));
148 void* map = mmap(NULL, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, pagesize);
149 ASSERT_NE(MAP_FAILED, map);
150 close(tf.fd);
152 memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG));
153 ASSERT_EQ(0, munmap(map, pagesize));
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);
160 memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG));
161 ASSERT_EQ(0, munmap(map, pagesize));
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 }