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
5#include <stddef.h>
6
7#include <limits>
8
9#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
10#include "mojo/public/cpp/bindings/lib/serialization_util.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace mojo {
14namespace test {
15namespace {
16
17bool IsZero(void* p_buf, size_t size) {
18  char* buf = reinterpret_cast<char*>(p_buf);
19  for (size_t i = 0; i < size; ++i) {
20    if (buf[i] != 0)
21      return false;
22  }
23  return true;
24}
25
26// Tests that FixedBuffer allocates memory aligned to 8 byte boundaries.
27TEST(FixedBufferTest, Alignment) {
28  internal::FixedBufferForTesting buf(internal::Align(10) * 2);
29  ASSERT_EQ(buf.size(), 16u * 2);
30
31  void* a = buf.Allocate(10);
32  ASSERT_TRUE(a);
33  EXPECT_TRUE(IsZero(a, 10));
34  EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(a) % 8);
35
36  void* b = buf.Allocate(10);
37  ASSERT_TRUE(b);
38  EXPECT_TRUE(IsZero(b, 10));
39  EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(b) % 8);
40
41  // Any more allocations would result in an assert, but we can't test that.
42}
43
44// Tests that FixedBufferForTesting::Leak passes ownership to the caller.
45TEST(FixedBufferTest, Leak) {
46  void* ptr = nullptr;
47  void* buf_ptr = nullptr;
48  {
49    internal::FixedBufferForTesting buf(8);
50    ASSERT_EQ(8u, buf.size());
51
52    ptr = buf.Allocate(8);
53    ASSERT_TRUE(ptr);
54    buf_ptr = buf.Leak();
55
56    // The buffer should point to the first element allocated.
57    // TODO(mpcomplete): Is this a reasonable expectation?
58    EXPECT_EQ(ptr, buf_ptr);
59
60    // The FixedBufferForTesting should be empty now.
61    EXPECT_EQ(0u, buf.size());
62    EXPECT_FALSE(buf.Leak());
63  }
64
65  // Since we called Leak, ptr is still writable after FixedBufferForTesting
66  // went out of scope.
67  memset(ptr, 1, 8);
68  free(buf_ptr);
69}
70
71#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
72TEST(FixedBufferTest, TooBig) {
73  internal::FixedBufferForTesting buf(24);
74
75  // A little bit too large.
76  EXPECT_EQ(reinterpret_cast<void*>(0), buf.Allocate(32));
77
78  // Move the cursor forward.
79  EXPECT_NE(reinterpret_cast<void*>(0), buf.Allocate(16));
80
81  // A lot too large.
82  EXPECT_EQ(reinterpret_cast<void*>(0),
83            buf.Allocate(std::numeric_limits<size_t>::max() - 1024u));
84
85  // A lot too large, leading to possible integer overflow.
86  EXPECT_EQ(reinterpret_cast<void*>(0),
87            buf.Allocate(std::numeric_limits<size_t>::max() - 8u));
88}
89#endif
90
91}  // namespace
92}  // namespace test
93}  // namespace mojo
94