memory_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
15namespace mojo {
16namespace system {
17namespace {
18
19TEST(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
164TEST(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