1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/system/memory.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include <limits> 11 12 #include "mojo/public/c/system/macros.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace mojo { 16 namespace system { 17 namespace { 18 19 TEST(MemoryTest, Valid) { 20 char my_char; 21 int32_t my_int32; 22 int64_t my_int64_array[5] = {}; // Zero initialize. 23 24 UserPointer<char> my_char_ptr(&my_char); 25 UserPointer<int32_t> my_int32_ptr(&my_int32); 26 UserPointer<int64_t> my_int64_array_ptr(my_int64_array); 27 28 // |UserPointer<>::IsNull()|: 29 EXPECT_FALSE(my_char_ptr.IsNull()); 30 EXPECT_FALSE(my_int32_ptr.IsNull()); 31 EXPECT_FALSE(my_int64_array_ptr.IsNull()); 32 33 // |UserPointer<>::Put()| and |UserPointer<>::Get()|: 34 my_char_ptr.Put('x'); 35 EXPECT_EQ('x', my_char); 36 EXPECT_EQ('x', my_char_ptr.Get()); 37 my_int32_ptr.Put(123); 38 EXPECT_EQ(123, my_int32); 39 EXPECT_EQ(123, my_int32_ptr.Get()); 40 my_int64_array_ptr.Put(456); 41 EXPECT_EQ(456, my_int64_array[0]); 42 EXPECT_EQ(456, my_int64_array_ptr.Get()); 43 44 // |UserPointer<>::At()|, etc.: 45 my_int64_array_ptr.At(3).Put(789); 46 EXPECT_EQ(789, my_int64_array[3]); 47 { 48 // Copy construction: 49 UserPointer<int64_t> other(my_int64_array_ptr.At(3)); 50 EXPECT_FALSE(other.IsNull()); 51 EXPECT_EQ(789, other.Get()); 52 53 // Assignment: 54 other = my_int64_array_ptr; 55 EXPECT_FALSE(other.IsNull()); 56 EXPECT_EQ(456, other.Get()); 57 58 // Assignment to |NullUserPointer()|: 59 other = NullUserPointer(); 60 EXPECT_TRUE(other.IsNull()); 61 62 // |MakeUserPointer()|: 63 other = MakeUserPointer(&my_int64_array[1]); 64 other.Put(-123); 65 EXPECT_EQ(-123, my_int64_array_ptr.At(1).Get()); 66 } 67 68 // "const" |UserPointer<>|: 69 { 70 // Explicit constructor from |NullUserPointer()|: 71 UserPointer<const char> other((NullUserPointer())); 72 EXPECT_TRUE(other.IsNull()); 73 74 // Conversion to "const": 75 other = my_char_ptr; 76 EXPECT_EQ('x', other.Get()); 77 } 78 79 // Default constructor: 80 { 81 UserPointer<int32_t> other; 82 EXPECT_TRUE(other.IsNull()); 83 84 other = my_int32_ptr; 85 other.Put(-456); 86 EXPECT_EQ(-456, my_int32_ptr.Get()); 87 } 88 89 // |UserPointer<>::CheckArray()|: 90 my_int64_array_ptr.CheckArray(5); 91 92 // |UserPointer<>::GetArray()|: 93 { 94 // From a "const" |UserPointer<>| (why not?): 95 UserPointer<const int64_t> other(my_int64_array_ptr); 96 int64_t array[3] = {1, 2, 3}; 97 other.At(1).GetArray(array, 3); 98 EXPECT_EQ(-123, array[0]); 99 EXPECT_EQ(0, array[1]); 100 EXPECT_EQ(789, array[2]); 101 } 102 103 // |UserPointer<>::PutArray()|: 104 { 105 const int64_t array[2] = {654, 321}; 106 my_int64_array_ptr.At(3).PutArray(array, 2); 107 EXPECT_EQ(0, my_int64_array[2]); 108 EXPECT_EQ(654, my_int64_array[3]); 109 EXPECT_EQ(321, my_int64_array[4]); 110 } 111 112 // |UserPointer<>::Reader|: 113 { 114 UserPointer<int64_t>::Reader reader(my_int64_array_ptr, 5); 115 EXPECT_EQ(456, reader.GetPointer()[0]); 116 EXPECT_EQ(321, reader.GetPointer()[4]); 117 } 118 119 // Non-const to const: 120 { 121 UserPointer<const int64_t>::Reader reader(my_int64_array_ptr.At(3), 1); 122 const int64_t* ptr = reader.GetPointer(); 123 EXPECT_EQ(654, *ptr); 124 } 125 126 // |UserPointer<>::Writer|: 127 { 128 UserPointer<int64_t>::Writer writer(my_int64_array_ptr.At(2), 1); 129 int64_t* ptr = writer.GetPointer(); 130 *ptr = 1234567890123LL; 131 writer.Commit(); 132 EXPECT_EQ(1234567890123LL, my_int64_array[2]); 133 } 134 135 // |UserPointer<>::ReaderWriter|: 136 { 137 UserPointer<int32_t>::ReaderWriter reader_writer(my_int32_ptr, 1); 138 int32_t* ptr = reader_writer.GetPointer(); 139 EXPECT_EQ(-456, *ptr); 140 *ptr = 42; 141 reader_writer.Commit(); 142 EXPECT_EQ(42, my_int32); 143 } 144 145 // |UserPointer<>::ReinterpretCast<>|: 146 // (This assumes little-endian, etc.) 147 { 148 UserPointer<const char> other(my_int32_ptr.ReinterpretCast<char>()); 149 EXPECT_EQ(42, other.Get()); 150 EXPECT_EQ(0, other.At(1).Get()); 151 EXPECT_EQ(0, other.At(2).Get()); 152 EXPECT_EQ(0, other.At(3).Get()); 153 } 154 155 // |UserPointer<>::GetPointerValue()|: 156 { 157 UserPointer<int32_t> other; 158 EXPECT_EQ(0u, other.GetPointerValue()); 159 other = my_int32_ptr; 160 EXPECT_EQ(reinterpret_cast<uintptr_t>(&my_int32), other.GetPointerValue()); 161 } 162 } 163 164 TEST(MemoryTest, InvalidDeath) { 165 const char kMemoryCheckFailedRegex[] = "Check failed"; 166 167 // Note: |Check...()| are defined to be "best effort" checks (and may always 168 // return true). Thus these tests of invalid cases only reflect the current 169 // implementation. 170 171 // These tests depend on |int32_t| and |int64_t| having nontrivial alignment. 172 static_assert(MOJO_ALIGNOF(int32_t) != 1, 173 "int32_t does not require nontrivial alignment"); 174 static_assert(MOJO_ALIGNOF(int64_t) != 1, 175 "int64_t does not require nontrivial alignment"); 176 177 // Null: 178 { 179 UserPointer<char> ptr(nullptr); 180 char array[5] = {}; 181 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 182 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 183 EXPECT_DEATH_IF_SUPPORTED(ptr.Put('x'), kMemoryCheckFailedRegex); 184 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 185 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 186 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); 187 } 188 { 189 UserPointer<int32_t> ptr(nullptr); 190 int32_t array[5] = {}; 191 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 192 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 193 EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); 194 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 195 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 196 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); 197 } 198 { 199 UserPointer<int64_t> ptr(nullptr); 200 int64_t array[5] = {}; 201 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 202 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 203 EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); 204 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 205 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 206 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); 207 } 208 // Also check a const pointer: 209 { 210 UserPointer<const int32_t> ptr(nullptr); 211 int32_t array[5] = {}; 212 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 213 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 214 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 215 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 216 } 217 218 // Unaligned: 219 { 220 int32_t x[10]; 221 UserPointer<int32_t> ptr( 222 reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(x) + 1)); 223 int32_t array[5] = {}; 224 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 225 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 226 EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); 227 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 228 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 229 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); 230 } 231 { 232 int64_t x[10]; 233 UserPointer<int64_t> ptr( 234 reinterpret_cast<int64_t*>(reinterpret_cast<uintptr_t>(x) + 1)); 235 int64_t array[5] = {}; 236 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 237 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 238 EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex); 239 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 240 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 241 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex); 242 } 243 // Also check a const pointer: 244 { 245 int32_t x[10]; 246 UserPointer<const int32_t> ptr( 247 reinterpret_cast<const int32_t*>(reinterpret_cast<uintptr_t>(x) + 1)); 248 int32_t array[5] = {}; 249 EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex); 250 EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex); 251 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex); 252 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex); 253 } 254 255 // Count too big: 256 { 257 const size_t kTooBig = 258 std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1; 259 int32_t x = 0; 260 UserPointer<int32_t> ptr(&x); 261 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); 262 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), 263 kMemoryCheckFailedRegex); 264 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig), 265 kMemoryCheckFailedRegex); 266 } 267 { 268 const size_t kTooBig = 269 std::numeric_limits<size_t>::max() / sizeof(int64_t) + 1; 270 int64_t x = 0; 271 UserPointer<int64_t> ptr(&x); 272 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); 273 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), 274 kMemoryCheckFailedRegex); 275 EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig), 276 kMemoryCheckFailedRegex); 277 } 278 // Also check a const pointer: 279 { 280 const size_t kTooBig = 281 std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1; 282 int32_t x = 0; 283 UserPointer<const int32_t> ptr(&x); 284 EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex); 285 EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig), 286 kMemoryCheckFailedRegex); 287 } 288 289 // TODO(vtl): Tests for |UserPointer{Reader,Writer,ReaderWriter}|. 290 } 291 292 } // namespace 293 } // namespace system 294 } // namespace mojo 295