shared_buffer_dispatcher_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. #include "mojo/core/shared_buffer_dispatcher.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <limits>
  8. #include "base/memory/platform_shared_memory_region.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/memory/writable_shared_memory_region.h"
  11. #include "mojo/core/dispatcher.h"
  12. #include "mojo/core/platform_shared_memory_mapping.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. namespace mojo {
  15. namespace core {
  16. namespace {
  17. // NOTE(vtl): There's currently not much to test for in
  18. // |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be
  19. // expanded if/when options are added, so I've kept the general form of the
  20. // tests from data_pipe_unittest.cc.
  21. const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions);
  22. // Does a cursory sanity check of |validated_options|. Calls
  23. // |ValidateCreateOptions()| on already-validated options. The validated options
  24. // should be valid, and the revalidated copy should be the same.
  25. void RevalidateCreateOptions(
  26. const MojoCreateSharedBufferOptions& validated_options) {
  27. EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size);
  28. // Nothing to check for flags.
  29. MojoCreateSharedBufferOptions revalidated_options = {};
  30. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
  31. &validated_options, &revalidated_options));
  32. EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
  33. EXPECT_EQ(validated_options.flags, revalidated_options.flags);
  34. }
  35. class SharedBufferDispatcherTest : public testing::Test {
  36. public:
  37. SharedBufferDispatcherTest() = default;
  38. SharedBufferDispatcherTest(const SharedBufferDispatcherTest&) = delete;
  39. SharedBufferDispatcherTest& operator=(const SharedBufferDispatcherTest&) =
  40. delete;
  41. ~SharedBufferDispatcherTest() override = default;
  42. };
  43. // Tests valid inputs to |ValidateCreateOptions()|.
  44. TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
  45. // Default options.
  46. {
  47. MojoCreateSharedBufferOptions validated_options = {};
  48. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
  49. nullptr, &validated_options));
  50. RevalidateCreateOptions(validated_options);
  51. }
  52. // Different flags.
  53. MojoCreateSharedBufferFlags flags_values[] = {
  54. MOJO_CREATE_SHARED_BUFFER_FLAG_NONE};
  55. for (size_t i = 0; i < std::size(flags_values); i++) {
  56. const MojoCreateSharedBufferFlags flags = flags_values[i];
  57. // Different capacities (size 1).
  58. for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
  59. MojoCreateSharedBufferOptions options = {
  60. kSizeOfCreateOptions, // |struct_size|.
  61. flags // |flags|.
  62. };
  63. MojoCreateSharedBufferOptions validated_options = {};
  64. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
  65. &options, &validated_options))
  66. << capacity;
  67. RevalidateCreateOptions(validated_options);
  68. EXPECT_EQ(options.flags, validated_options.flags);
  69. }
  70. }
  71. }
  72. TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
  73. // Invalid |struct_size|.
  74. {
  75. MojoCreateSharedBufferOptions options = {
  76. 1, // |struct_size|.
  77. MOJO_CREATE_SHARED_BUFFER_FLAG_NONE // |flags|.
  78. };
  79. MojoCreateSharedBufferOptions unused;
  80. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  81. SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
  82. }
  83. // Unknown |flags|.
  84. {
  85. MojoCreateSharedBufferOptions options = {
  86. kSizeOfCreateOptions, // |struct_size|.
  87. ~0u // |flags|.
  88. };
  89. MojoCreateSharedBufferOptions unused;
  90. EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
  91. SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
  92. }
  93. }
  94. TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) {
  95. scoped_refptr<SharedBufferDispatcher> dispatcher;
  96. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  97. SharedBufferDispatcher::kDefaultCreateOptions,
  98. nullptr, 100, &dispatcher));
  99. ASSERT_TRUE(dispatcher);
  100. EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
  101. // Make a couple of mappings.
  102. std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
  103. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
  104. ASSERT_TRUE(mapping1);
  105. ASSERT_TRUE(mapping1->GetBase());
  106. EXPECT_EQ(100u, mapping1->GetLength());
  107. // Write something.
  108. static_cast<char*>(mapping1->GetBase())[50] = 'x';
  109. std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
  110. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
  111. ASSERT_TRUE(mapping2);
  112. ASSERT_TRUE(mapping2->GetBase());
  113. EXPECT_EQ(50u, mapping2->GetLength());
  114. EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
  115. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
  116. // Check that we can still read/write to mappings after the dispatcher has
  117. // gone away.
  118. static_cast<char*>(mapping2->GetBase())[1] = 'y';
  119. EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
  120. }
  121. TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) {
  122. base::WritableSharedMemoryRegion region =
  123. base::WritableSharedMemoryRegion::Create(100);
  124. ASSERT_TRUE(region.IsValid());
  125. scoped_refptr<SharedBufferDispatcher> dispatcher;
  126. EXPECT_EQ(MOJO_RESULT_OK,
  127. SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
  128. base::WritableSharedMemoryRegion::TakeHandleForSerialization(
  129. std::move(region)),
  130. &dispatcher));
  131. ASSERT_TRUE(dispatcher);
  132. EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
  133. // Make a couple of mappings.
  134. std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
  135. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
  136. ASSERT_TRUE(mapping1);
  137. ASSERT_TRUE(mapping1->GetBase());
  138. EXPECT_EQ(100u, mapping1->GetLength());
  139. // Write something.
  140. static_cast<char*>(mapping1->GetBase())[50] = 'x';
  141. std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
  142. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
  143. ASSERT_TRUE(mapping2);
  144. ASSERT_TRUE(mapping2->GetBase());
  145. EXPECT_EQ(50u, mapping2->GetLength());
  146. EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
  147. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
  148. // Check that we can still read/write to mappings after the dispatcher has
  149. // gone away.
  150. static_cast<char*>(mapping2->GetBase())[1] = 'y';
  151. EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
  152. }
  153. TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
  154. scoped_refptr<SharedBufferDispatcher> dispatcher1;
  155. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  156. SharedBufferDispatcher::kDefaultCreateOptions,
  157. nullptr, 100, &dispatcher1));
  158. // Map and write something.
  159. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  160. EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer(0, 100, &mapping));
  161. static_cast<char*>(mapping->GetBase())[0] = 'x';
  162. mapping.reset();
  163. // Duplicate |dispatcher1| and then close it.
  164. scoped_refptr<Dispatcher> dispatcher2;
  165. EXPECT_EQ(MOJO_RESULT_OK,
  166. dispatcher1->DuplicateBufferHandle(nullptr, &dispatcher2));
  167. ASSERT_TRUE(dispatcher2);
  168. EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType());
  169. EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
  170. // Map |dispatcher2| and read something.
  171. EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, &mapping));
  172. EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]);
  173. EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
  174. }
  175. TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) {
  176. scoped_refptr<SharedBufferDispatcher> dispatcher1;
  177. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  178. SharedBufferDispatcher::kDefaultCreateOptions,
  179. nullptr, 100, &dispatcher1));
  180. scoped_refptr<SharedBufferDispatcher> dispatcher2;
  181. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  182. SharedBufferDispatcher::kDefaultCreateOptions,
  183. nullptr, 100, &dispatcher2));
  184. MojoDuplicateBufferHandleOptions kReadOnlyOptions = {
  185. sizeof(MojoCreateSharedBufferOptions),
  186. MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY};
  187. // NOTE: We forbid handles from being duplicated read-only after they've been
  188. // duplicated non-read-only; conversely we also forbid handles from being
  189. // duplicated non-read-only after they've been duplicated read-only.
  190. scoped_refptr<Dispatcher> writable_duped_dispatcher1;
  191. scoped_refptr<Dispatcher> read_only_duped_dispatcher1;
  192. EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
  193. nullptr, &writable_duped_dispatcher1));
  194. EXPECT_TRUE(writable_duped_dispatcher1);
  195. EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
  196. writable_duped_dispatcher1->GetType());
  197. {
  198. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  199. EXPECT_EQ(MOJO_RESULT_OK,
  200. writable_duped_dispatcher1->MapBuffer(0, 100, &mapping));
  201. }
  202. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
  203. dispatcher1->DuplicateBufferHandle(&kReadOnlyOptions,
  204. &read_only_duped_dispatcher1));
  205. EXPECT_FALSE(read_only_duped_dispatcher1);
  206. scoped_refptr<Dispatcher> read_only_duped_dispatcher2;
  207. scoped_refptr<Dispatcher> writable_duped_dispatcher2;
  208. EXPECT_EQ(MOJO_RESULT_OK,
  209. dispatcher2->DuplicateBufferHandle(&kReadOnlyOptions,
  210. &read_only_duped_dispatcher2));
  211. EXPECT_TRUE(read_only_duped_dispatcher2);
  212. EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
  213. read_only_duped_dispatcher2->GetType());
  214. {
  215. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  216. EXPECT_EQ(MOJO_RESULT_OK,
  217. read_only_duped_dispatcher2->MapBuffer(0, 100, &mapping));
  218. }
  219. EXPECT_EQ(
  220. MOJO_RESULT_FAILED_PRECONDITION,
  221. dispatcher2->DuplicateBufferHandle(nullptr, &writable_duped_dispatcher2));
  222. EXPECT_FALSE(writable_duped_dispatcher2);
  223. EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
  224. EXPECT_EQ(MOJO_RESULT_OK, writable_duped_dispatcher1->Close());
  225. EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
  226. EXPECT_EQ(MOJO_RESULT_OK, read_only_duped_dispatcher2->Close());
  227. }
  228. TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
  229. scoped_refptr<SharedBufferDispatcher> dispatcher1;
  230. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  231. SharedBufferDispatcher::kDefaultCreateOptions,
  232. nullptr, 100, &dispatcher1));
  233. // Invalid |struct_size|.
  234. {
  235. MojoDuplicateBufferHandleOptions options = {
  236. 1u, MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_NONE};
  237. scoped_refptr<Dispatcher> dispatcher2;
  238. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  239. dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
  240. EXPECT_FALSE(dispatcher2);
  241. }
  242. // Unknown |flags|.
  243. {
  244. MojoDuplicateBufferHandleOptions options = {
  245. sizeof(MojoDuplicateBufferHandleOptions), ~0u};
  246. scoped_refptr<Dispatcher> dispatcher2;
  247. EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
  248. dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
  249. EXPECT_FALSE(dispatcher2);
  250. }
  251. EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
  252. }
  253. TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) {
  254. // Size too big.
  255. scoped_refptr<SharedBufferDispatcher> dispatcher;
  256. EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
  257. SharedBufferDispatcher::Create(
  258. SharedBufferDispatcher::kDefaultCreateOptions, nullptr,
  259. std::numeric_limits<uint64_t>::max(), &dispatcher));
  260. EXPECT_FALSE(dispatcher);
  261. // Zero size.
  262. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  263. SharedBufferDispatcher::Create(
  264. SharedBufferDispatcher::kDefaultCreateOptions, nullptr, 0,
  265. &dispatcher));
  266. EXPECT_FALSE(dispatcher);
  267. }
  268. TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
  269. scoped_refptr<SharedBufferDispatcher> dispatcher;
  270. EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
  271. SharedBufferDispatcher::kDefaultCreateOptions,
  272. nullptr, 100, &dispatcher));
  273. MojoSharedBufferInfo info = {sizeof(info), 0u};
  274. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->GetBufferInfo(&info));
  275. std::unique_ptr<PlatformSharedMemoryMapping> mapping;
  276. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  277. dispatcher->MapBuffer(0, info.size + 1, &mapping));
  278. EXPECT_FALSE(mapping);
  279. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  280. dispatcher->MapBuffer(1, info.size, &mapping));
  281. EXPECT_FALSE(mapping);
  282. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
  283. dispatcher->MapBuffer(0, 0, &mapping));
  284. EXPECT_FALSE(mapping);
  285. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
  286. }
  287. } // namespace
  288. } // namespace core
  289. } // namespace mojo