1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/options_validation.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stddef.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/c/system/macros.h" 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "testing/gtest/include/gtest/gtest.h" 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk { 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Declare a test options struct just as we do in actual public headers. 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezusing TestOptionsFlags = uint32_t; 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstatic_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct MOJO_ALIGNAS(8) TestOptions { 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t struct_size; 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestOptionsFlags flags; 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t member1; 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t member2; 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstatic_assert(sizeof(TestOptions) == 16, "TestOptions has wrong size"); 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions)); 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezTEST(OptionsValidationTest, Valid) { 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const TestOptions kOptions = {kSizeOfTestOptions}; 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(&kOptions); 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(reader.is_valid()); 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const TestOptions kOptions = {static_cast<uint32_t>( 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez offsetof(TestOptions, struct_size) + sizeof(uint32_t))}; 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(&kOptions); 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(reader.is_valid()); 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const TestOptions kOptions = { 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))}; 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(&kOptions); 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(reader.is_valid()); 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestOptions* options = reinterpret_cast<TestOptions*>(buf); 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez options->struct_size = kSizeOfTestOptions + 1; 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(options); 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(reader.is_valid()); 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestOptions* options = reinterpret_cast<TestOptions*>(buf); 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez options->struct_size = kSizeOfTestOptions + 4; 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(options); 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(reader.is_valid()); 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezTEST(OptionsValidationTest, Invalid) { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Size too small: 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < sizeof(uint32_t); i++) { 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestOptions options = {static_cast<uint32_t>(i)}; 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(&options); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_FALSE(reader.is_valid()) << i; 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// These test invalid arguments that should cause death if we're being paranoid 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// about checking arguments (which we would want to do if, e.g., we were in a 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// true "kernel" situation, but we might not want to do otherwise for 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// performance reasons). Probably blatant errors like passing in null pointers 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// (for required pointer arguments) will still cause death, but perhaps not 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// predictably. 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezTEST(OptionsValidationTest, InvalidDeath) { 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OFFICIAL_BUILD) 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char kMemoryCheckFailedRegex[] = ""; 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char kMemoryCheckFailedRegex[] = "Check failed"; 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Null: 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_DEATH_IF_SUPPORTED( 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { UserOptionsReader<TestOptions> reader((nullptr)); }, 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez kMemoryCheckFailedRegex); 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Unaligned: 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_DEATH_IF_SUPPORTED( 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader( 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reinterpret_cast<const TestOptions*>(1)); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez }, 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez kMemoryCheckFailedRegex); 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Note: The current implementation checks the size only after checking the 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // alignment versus that required for the |uint32_t| size, so it won't die in 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the expected way if you pass, e.g., 4. So we have to manufacture a valid 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // pointer at an offset of alignment 4. 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez EXPECT_DEATH_IF_SUPPORTED( 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t buffer[100] = {}; 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 8 == 0) 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ? reinterpret_cast<TestOptions*>(&buffer[1]) 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : reinterpret_cast<TestOptions*>(&buffer[0]); 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez options->struct_size = static_cast<uint32_t>(sizeof(TestOptions)); 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UserOptionsReader<TestOptions> reader(options); 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez }, 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez kMemoryCheckFailedRegex); 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace edk 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 135