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/embedder/simple_platform_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(SimplePlatformSharedBufferTest
, 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
<SimplePlatformSharedBuffer
> buffer(
26 SimplePlatformSharedBuffer::Create(kNumBytes
));
27 ASSERT_TRUE(buffer
.get());
29 // Map it all, scribble some stuff, and then unmap it.
31 EXPECT_TRUE(buffer
->IsValidMap(0, kNumBytes
));
32 scoped_ptr
<PlatformSharedBufferMapping
> mapping(buffer
->Map(0, kNumBytes
));
34 ASSERT_TRUE(mapping
->GetBase());
35 int* stuff
= static_cast<int*>(mapping
->GetBase());
36 for (size_t i
= 0; i
< kNumInts
; i
++)
37 stuff
[i
] = static_cast<int>(i
) + kFudge
;
40 // Map it all again, check that our scribbling is still there, then do a
41 // partial mapping and scribble on that, check that everything is coherent,
42 // unmap the first mapping, scribble on some of the second mapping, and then
45 ASSERT_TRUE(buffer
->IsValidMap(0, kNumBytes
));
46 // Use |MapNoCheck()| this time.
47 scoped_ptr
<PlatformSharedBufferMapping
> mapping1(
48 buffer
->MapNoCheck(0, kNumBytes
));
49 ASSERT_TRUE(mapping1
);
50 ASSERT_TRUE(mapping1
->GetBase());
51 int* stuff1
= static_cast<int*>(mapping1
->GetBase());
52 for (size_t i
= 0; i
< kNumInts
; i
++)
53 EXPECT_EQ(static_cast<int>(i
) + kFudge
, stuff1
[i
]) << i
;
55 scoped_ptr
<PlatformSharedBufferMapping
> mapping2(
56 buffer
->Map((kNumInts
/ 2) * sizeof(int), 2 * sizeof(int)));
57 ASSERT_TRUE(mapping2
);
58 ASSERT_TRUE(mapping2
->GetBase());
59 int* stuff2
= static_cast<int*>(mapping2
->GetBase());
60 EXPECT_EQ(static_cast<int>(kNumInts
/ 2) + kFudge
, stuff2
[0]);
61 EXPECT_EQ(static_cast<int>(kNumInts
/ 2) + 1 + kFudge
, stuff2
[1]);
65 EXPECT_EQ(123, stuff1
[kNumInts
/ 2]);
66 EXPECT_EQ(456, stuff1
[kNumInts
/ 2 + 1]);
70 EXPECT_EQ(123, stuff2
[0]);
71 EXPECT_EQ(456, stuff2
[1]);
75 // Do another partial mapping and check that everything is the way we expect
78 EXPECT_TRUE(buffer
->IsValidMap(sizeof(int), kNumBytes
- sizeof(int)));
79 scoped_ptr
<PlatformSharedBufferMapping
> mapping(
80 buffer
->Map(sizeof(int), kNumBytes
- sizeof(int)));
82 ASSERT_TRUE(mapping
->GetBase());
83 int* stuff
= static_cast<int*>(mapping
->GetBase());
85 for (size_t j
= 0; j
< kNumInts
- 1; j
++) {
86 int i
= static_cast<int>(j
) + 1;
87 if (i
== kNumInts
/ 2) {
88 EXPECT_EQ(123, stuff
[j
]);
89 } else if (i
== kNumInts
/ 2 + 1) {
90 EXPECT_EQ(789, stuff
[j
]);
92 EXPECT_EQ(i
+ kFudge
, stuff
[j
]) << i
;
98 // TODO(vtl): Bigger buffers.
100 TEST(SimplePlatformSharedBufferTest
, InvalidMappings
) {
101 scoped_refptr
<SimplePlatformSharedBuffer
> buffer(
102 SimplePlatformSharedBuffer::Create(100));
103 ASSERT_TRUE(buffer
.get());
105 // Zero length not allowed.
106 EXPECT_FALSE(buffer
->Map(0, 0));
107 EXPECT_FALSE(buffer
->IsValidMap(0, 0));
110 EXPECT_TRUE(buffer
->Map(0, 100));
111 EXPECT_TRUE(buffer
->IsValidMap(0, 100));
112 // Offset + length too big.
113 EXPECT_FALSE(buffer
->Map(0, 101));
114 EXPECT_FALSE(buffer
->IsValidMap(0, 101));
115 EXPECT_FALSE(buffer
->Map(1, 100));
116 EXPECT_FALSE(buffer
->IsValidMap(1, 100));
119 EXPECT_TRUE(buffer
->Map(50, 50));
120 EXPECT_TRUE(buffer
->IsValidMap(50, 50));
121 // Offset + length too big.
122 EXPECT_FALSE(buffer
->Map(50, 51));
123 EXPECT_FALSE(buffer
->IsValidMap(50, 51));
124 EXPECT_FALSE(buffer
->Map(51, 50));
125 EXPECT_FALSE(buffer
->IsValidMap(51, 50));
128 TEST(SimplePlatformSharedBufferTest
, TooBig
) {
129 // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds
130 // (since it only involves creating a 4 GB file).
131 const size_t kMaxSizeT
= std::numeric_limits
<size_t>::max();
132 scoped_refptr
<SimplePlatformSharedBuffer
> buffer(
133 SimplePlatformSharedBuffer::Create(kMaxSizeT
));
134 // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should
137 EXPECT_FALSE(buffer
->Map(0, kMaxSizeT
));
140 // Tests that separate mappings get distinct addresses.
141 // Note: It's not inconceivable that the OS could ref-count identical mappings
142 // and reuse the same address, in which case we'd have to be more careful about
143 // using the address as the key for unmapping.
144 TEST(SimplePlatformSharedBufferTest
, MappingsDistinct
) {
145 scoped_refptr
<SimplePlatformSharedBuffer
> buffer(
146 SimplePlatformSharedBuffer::Create(100));
147 scoped_ptr
<PlatformSharedBufferMapping
> mapping1(buffer
->Map(0, 100));
148 scoped_ptr
<PlatformSharedBufferMapping
> mapping2(buffer
->Map(0, 100));
149 EXPECT_NE(mapping1
->GetBase(), mapping2
->GetBase());
152 TEST(SimplePlatformSharedBufferTest
, BufferZeroInitialized
) {
153 static const size_t kSizes
[] = {10, 100, 1000, 10000, 100000};
154 for (size_t i
= 0; i
< arraysize(kSizes
); i
++) {
155 scoped_refptr
<SimplePlatformSharedBuffer
> buffer(
156 SimplePlatformSharedBuffer::Create(kSizes
[i
]));
157 scoped_ptr
<PlatformSharedBufferMapping
> mapping(buffer
->Map(0, kSizes
[i
]));
158 for (size_t j
= 0; j
< kSizes
[i
]; j
++) {
159 // "Assert" instead of "expect" so we don't spam the output with thousands
160 // of failures if we fail.
161 ASSERT_EQ('\0', static_cast<char*>(mapping
->GetBase())[j
])
162 << "size " << kSizes
[i
] << ", offset " << j
;
167 TEST(SimplePlatformSharedBufferTest
, MappingsOutliveBuffer
) {
168 scoped_ptr
<PlatformSharedBufferMapping
> mapping1
;
169 scoped_ptr
<PlatformSharedBufferMapping
> mapping2
;
172 scoped_refptr
<SimplePlatformSharedBuffer
> buffer(
173 SimplePlatformSharedBuffer::Create(100));
174 mapping1
= buffer
->Map(0, 100).Pass();
175 mapping2
= buffer
->Map(50, 50).Pass();
176 static_cast<char*>(mapping1
->GetBase())[50] = 'x';
179 EXPECT_EQ('x', static_cast<char*>(mapping2
->GetBase())[0]);
181 static_cast<char*>(mapping2
->GetBase())[1] = 'y';
182 EXPECT_EQ('y', static_cast<char*>(mapping1
->GetBase())[51]);
186 } // namespace embedder