options_validation_unittest.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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/options_validation.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "mojo/public/c/system/macros.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. namespace mojo {
  10. namespace core {
  11. namespace {
  12. // Declare a test options struct just as we do in actual public headers.
  13. using TestOptionsFlags = uint32_t;
  14. static_assert(MOJO_ALIGNOF(int64_t) <= 8, "int64_t has weird alignment");
  15. struct MOJO_ALIGNAS(8) TestOptions {
  16. uint32_t struct_size;
  17. TestOptionsFlags flags;
  18. uint32_t member1;
  19. uint32_t member2;
  20. };
  21. static_assert(sizeof(TestOptions) == 16, "TestOptions has wrong size");
  22. const uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions));
  23. TEST(OptionsValidationTest, Valid) {
  24. {
  25. const TestOptions kOptions = {kSizeOfTestOptions};
  26. UserOptionsReader<TestOptions> reader(&kOptions);
  27. EXPECT_TRUE(reader.is_valid());
  28. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
  29. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
  30. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
  31. }
  32. {
  33. const TestOptions kOptions = {static_cast<uint32_t>(
  34. offsetof(TestOptions, struct_size) + sizeof(uint32_t))};
  35. UserOptionsReader<TestOptions> reader(&kOptions);
  36. EXPECT_TRUE(reader.is_valid());
  37. EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
  38. EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
  39. EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
  40. }
  41. {
  42. const TestOptions kOptions = {
  43. static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))};
  44. UserOptionsReader<TestOptions> reader(&kOptions);
  45. EXPECT_TRUE(reader.is_valid());
  46. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
  47. EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
  48. EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
  49. }
  50. {
  51. MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
  52. TestOptions* options = reinterpret_cast<TestOptions*>(buf);
  53. options->struct_size = kSizeOfTestOptions + 1;
  54. UserOptionsReader<TestOptions> reader(options);
  55. EXPECT_TRUE(reader.is_valid());
  56. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
  57. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
  58. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
  59. }
  60. {
  61. MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
  62. TestOptions* options = reinterpret_cast<TestOptions*>(buf);
  63. options->struct_size = kSizeOfTestOptions + 4;
  64. UserOptionsReader<TestOptions> reader(options);
  65. EXPECT_TRUE(reader.is_valid());
  66. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader));
  67. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader));
  68. EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader));
  69. }
  70. }
  71. TEST(OptionsValidationTest, Invalid) {
  72. // Size too small:
  73. for (size_t i = 0; i < sizeof(uint32_t); i++) {
  74. TestOptions options = {static_cast<uint32_t>(i)};
  75. UserOptionsReader<TestOptions> reader(&options);
  76. EXPECT_FALSE(reader.is_valid()) << i;
  77. }
  78. }
  79. // These test invalid arguments that should cause death if we're being paranoid
  80. // about checking arguments (which we would want to do if, e.g., we were in a
  81. // true "kernel" situation, but we might not want to do otherwise for
  82. // performance reasons). Probably blatant errors like passing in null pointers
  83. // (for required pointer arguments) will still cause death, but perhaps not
  84. // predictably.
  85. TEST(OptionsValidationTest, InvalidDeath) {
  86. #if defined(OFFICIAL_BUILD)
  87. const char kMemoryCheckFailedRegex[] = "";
  88. #else
  89. const char kMemoryCheckFailedRegex[] = "Check failed";
  90. #endif
  91. // Null:
  92. EXPECT_DEATH_IF_SUPPORTED(
  93. { UserOptionsReader<TestOptions> reader((nullptr)); },
  94. kMemoryCheckFailedRegex);
  95. // Unaligned:
  96. EXPECT_DEATH_IF_SUPPORTED(
  97. {
  98. UserOptionsReader<TestOptions> reader(
  99. reinterpret_cast<const TestOptions*>(1));
  100. },
  101. kMemoryCheckFailedRegex);
  102. // Note: The current implementation checks the size only after checking the
  103. // alignment versus that required for the |uint32_t| size, so it won't die in
  104. // the expected way if you pass, e.g., 4. So we have to manufacture a valid
  105. // pointer at an offset of alignment 4.
  106. EXPECT_DEATH_IF_SUPPORTED(
  107. {
  108. uint32_t buffer[100] = {};
  109. TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 8 == 0)
  110. ? reinterpret_cast<TestOptions*>(&buffer[1])
  111. : reinterpret_cast<TestOptions*>(&buffer[0]);
  112. options->struct_size = static_cast<uint32_t>(sizeof(TestOptions));
  113. UserOptionsReader<TestOptions> reader(options);
  114. },
  115. kMemoryCheckFailedRegex);
  116. }
  117. } // namespace
  118. } // namespace core
  119. } // namespace mojo