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.
5 #include "mojo/system/raw_shared_buffer.h"
9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "testing/gtest/include/gtest/gtest.h"
18 TEST(RawSharedBufferTest
, Basic
) {
19 const size_t kNumInts
= 100;
20 const size_t kNumBytes
= kNumInts
* sizeof(int);
21 // A fudge so that we're not just writing zero bytes 75% of the time.
22 const int kFudge
= 1234567890;
25 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(kNumBytes
));
28 // Map it all, scribble some stuff, and then unmap it.
30 EXPECT_TRUE(buffer
->IsValidMap(0, kNumBytes
));
31 scoped_ptr
<RawSharedBufferMapping
> mapping(buffer
->Map(0, kNumBytes
));
33 ASSERT_TRUE(mapping
->base());
34 int* stuff
= static_cast<int*>(mapping
->base());
35 for (size_t i
= 0; i
< kNumInts
; i
++)
36 stuff
[i
] = static_cast<int>(i
) + kFudge
;
39 // Map it all again, check that our scribbling is still there, then do a
40 // partial mapping and scribble on that, check that everything is coherent,
41 // unmap the first mapping, scribble on some of the second mapping, and then
44 ASSERT_TRUE(buffer
->IsValidMap(0, kNumBytes
));
45 // Use |MapNoCheck()| this time.
46 scoped_ptr
<RawSharedBufferMapping
> mapping1(
47 buffer
->MapNoCheck(0, kNumBytes
));
48 ASSERT_TRUE(mapping1
);
49 ASSERT_TRUE(mapping1
->base());
50 int* stuff1
= static_cast<int*>(mapping1
->base());
51 for (size_t i
= 0; i
< kNumInts
; i
++)
52 EXPECT_EQ(static_cast<int>(i
) + kFudge
, stuff1
[i
]) << i
;
54 scoped_ptr
<RawSharedBufferMapping
> mapping2(
55 buffer
->Map((kNumInts
/ 2) * sizeof(int), 2 * sizeof(int)));
56 ASSERT_TRUE(mapping2
);
57 ASSERT_TRUE(mapping2
->base());
58 int* stuff2
= static_cast<int*>(mapping2
->base());
59 EXPECT_EQ(static_cast<int>(kNumInts
/ 2) + kFudge
, stuff2
[0]);
60 EXPECT_EQ(static_cast<int>(kNumInts
/ 2) + 1 + kFudge
, stuff2
[1]);
64 EXPECT_EQ(123, stuff1
[kNumInts
/ 2]);
65 EXPECT_EQ(456, stuff1
[kNumInts
/ 2 + 1]);
69 EXPECT_EQ(123, stuff2
[0]);
70 EXPECT_EQ(456, stuff2
[1]);
74 // Do another partial mapping and check that everything is the way we expect
77 EXPECT_TRUE(buffer
->IsValidMap(sizeof(int), kNumBytes
- sizeof(int)));
78 scoped_ptr
<RawSharedBufferMapping
> mapping(
79 buffer
->Map(sizeof(int), kNumBytes
- sizeof(int)));
81 ASSERT_TRUE(mapping
->base());
82 int* stuff
= static_cast<int*>(mapping
->base());
84 for (size_t j
= 0; j
< kNumInts
- 1; j
++) {
85 int i
= static_cast<int>(j
) + 1;
86 if (i
== kNumInts
/ 2) {
87 EXPECT_EQ(123, stuff
[j
]);
88 } else if (i
== kNumInts
/ 2 + 1) {
89 EXPECT_EQ(789, stuff
[j
]);
91 EXPECT_EQ(i
+ kFudge
, stuff
[j
]) << i
;
97 // TODO(vtl): Bigger buffers.
99 TEST(RawSharedBufferTest
, InvalidMappings
) {
100 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(100));
103 // Zero length not allowed.
104 EXPECT_FALSE(buffer
->Map(0, 0));
105 EXPECT_FALSE(buffer
->IsValidMap(0, 0));
108 EXPECT_TRUE(buffer
->Map(0, 100));
109 EXPECT_TRUE(buffer
->IsValidMap(0, 100));
110 // Offset + length too big.
111 EXPECT_FALSE(buffer
->Map(0, 101));
112 EXPECT_FALSE(buffer
->IsValidMap(0, 101));
113 EXPECT_FALSE(buffer
->Map(1, 100));
114 EXPECT_FALSE(buffer
->IsValidMap(1, 100));
117 EXPECT_TRUE(buffer
->Map(50, 50));
118 EXPECT_TRUE(buffer
->IsValidMap(50, 50));
119 // Offset + length too big.
120 EXPECT_FALSE(buffer
->Map(50, 51));
121 EXPECT_FALSE(buffer
->IsValidMap(50, 51));
122 EXPECT_FALSE(buffer
->Map(51, 50));
123 EXPECT_FALSE(buffer
->IsValidMap(51, 50));
126 TEST(RawSharedBufferTest
, TooBig
) {
127 // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds
128 // (since it only involves creating a 4 GB file).
129 const size_t kMaxSizeT
= std::numeric_limits
<size_t>::max();
130 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(kMaxSizeT
));
131 // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should
134 EXPECT_FALSE(buffer
->Map(0, kMaxSizeT
));
137 // Tests that separate mappings get distinct addresses.
138 // Note: It's not inconceivable that the OS could ref-count identical mappings
139 // and reuse the same address, in which case we'd have to be more careful about
140 // using the address as the key for unmapping.
141 TEST(RawSharedBufferTest
, MappingsDistinct
) {
142 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(100));
143 scoped_ptr
<RawSharedBufferMapping
> mapping1(buffer
->Map(0, 100));
144 scoped_ptr
<RawSharedBufferMapping
> mapping2(buffer
->Map(0, 100));
145 EXPECT_NE(mapping1
->base(), mapping2
->base());
148 TEST(RawSharedBufferTest
, BufferZeroInitialized
) {
149 static const size_t kSizes
[] = { 10, 100, 1000, 10000, 100000 };
150 for (size_t i
= 0; i
< arraysize(kSizes
); i
++) {
151 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(kSizes
[i
]));
152 scoped_ptr
<RawSharedBufferMapping
> mapping(buffer
->Map(0, kSizes
[i
]));
153 for (size_t j
= 0; j
< kSizes
[i
]; j
++) {
154 // "Assert" instead of "expect" so we don't spam the output with thousands
155 // of failures if we fail.
156 ASSERT_EQ('\0', static_cast<char*>(mapping
->base())[j
])
157 << "size " << kSizes
[i
] << ", offset " << j
;
162 TEST(RawSharedBufferTest
, MappingsOutliveBuffer
) {
163 scoped_ptr
<RawSharedBufferMapping
> mapping1
;
164 scoped_ptr
<RawSharedBufferMapping
> mapping2
;
167 scoped_refptr
<RawSharedBuffer
> buffer(RawSharedBuffer::Create(100));
168 mapping1
= buffer
->Map(0, 100).Pass();
169 mapping2
= buffer
->Map(50, 50).Pass();
170 static_cast<char*>(mapping1
->base())[50] = 'x';
173 EXPECT_EQ('x', static_cast<char*>(mapping2
->base())[0]);
175 static_cast<char*>(mapping2
->base())[1] = 'y';
176 EXPECT_EQ('y', static_cast<char*>(mapping1
->base())[51]);
180 } // namespace system