summaryrefslogtreecommitdiffstats
path: root/mojo/public/cpp/system/tests/macros_unittest.cc
blob: 27a61bdcb5a584728515aa50743e4cb1502ad606 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file tests the C++ Mojo system macros and consists of "positive" tests,
// i.e., those verifying that things work (without compile errors, or even
// warnings if warnings are treated as errors).
// TODO(vtl): Maybe rename "MacrosCppTest" -> "MacrosTest" if/when this gets
// compiled into a different binary from the C API tests.
// TODO(vtl): Fix no-compile tests (which are all disabled; crbug.com/105388)
// and write some "negative" tests.

#include "mojo/public/cpp/system/macros.h"

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace {

// Note: MSVS is very strict (and arguably buggy) about warnings for classes
// defined in a local scope, so define these globally.
struct TestOverrideBaseClass {
  virtual ~TestOverrideBaseClass() {}
  virtual void ToBeOverridden() {}
  virtual void AlsoToBeOverridden() = 0;
};

struct TestOverrideSubclass : public TestOverrideBaseClass {
  ~TestOverrideSubclass() override {}
  void ToBeOverridden() override {}
  void AlsoToBeOverridden() override {}
};

TEST(MacrosCppTest, Override) {
  TestOverrideSubclass x;
  x.ToBeOverridden();
  x.AlsoToBeOverridden();
}

// Note: MSVS is very strict (and arguably buggy) about warnings for classes
// defined in a local scope, so define these globally.
class TestDisallowCopyAndAssignClass {
 public:
  TestDisallowCopyAndAssignClass() {}
  explicit TestDisallowCopyAndAssignClass(int) {}
  void NoOp() {}

 private:
  MOJO_DISALLOW_COPY_AND_ASSIGN(TestDisallowCopyAndAssignClass);
};

TEST(MacrosCppTest, DisallowCopyAndAssign) {
  TestDisallowCopyAndAssignClass x;
  x.NoOp();
  TestDisallowCopyAndAssignClass y(789);
  y.NoOp();
}

// Test that |MOJO_ARRAYSIZE()| works in a |static_assert()|.
const int kGlobalArray[5] = {1, 2, 3, 4, 5};
static_assert(MOJO_ARRAYSIZE(kGlobalArray) == 5u,
              "MOJO_ARRAY_SIZE() failed in static_assert()");

TEST(MacrosCppTest, ArraySize) {
  double local_array[4] = {6.7, 7.8, 8.9, 9.0};
  // MSVS considers this local variable unused since MOJO_ARRAYSIZE only takes
  // the size of the type of the local and not the values itself.
  MOJO_ALLOW_UNUSED_LOCAL(local_array);
  EXPECT_EQ(4u, MOJO_ARRAYSIZE(local_array));
}

// Note: MSVS is very strict (and arguably buggy) about warnings for classes
// defined in a local scope, so define these globally.
class MoveOnlyInt {
  MOJO_MOVE_ONLY_TYPE(MoveOnlyInt)

 public:
  MoveOnlyInt() : is_set_(false), value_() {}
  explicit MoveOnlyInt(int value) : is_set_(true), value_(value) {}
  ~MoveOnlyInt() {}

  // Move-only constructor and operator=.
  MoveOnlyInt(MoveOnlyInt&& other) { *this = other.Pass(); }
  MoveOnlyInt& operator=(MoveOnlyInt&& other) {
    if (&other != this) {
      is_set_ = other.is_set_;
      value_ = other.value_;
      other.is_set_ = false;
    }
    return *this;
  }

  int value() const {
    assert(is_set());
    return value_;
  }
  bool is_set() const { return is_set_; }

 private:
  bool is_set_;
  int value_;
};

TEST(MacrosCppTest, MoveOnlyTypeForCpp03) {
  MoveOnlyInt x(123);
  EXPECT_TRUE(x.is_set());
  EXPECT_EQ(123, x.value());
  MoveOnlyInt y;
  EXPECT_FALSE(y.is_set());
  y = x.Pass();
  EXPECT_FALSE(x.is_set());
  EXPECT_TRUE(y.is_set());
  EXPECT_EQ(123, y.value());
  MoveOnlyInt z(y.Pass());
  EXPECT_FALSE(y.is_set());
  EXPECT_TRUE(z.is_set());
  EXPECT_EQ(123, z.value());
  z = z.Pass();
  EXPECT_TRUE(z.is_set());
  EXPECT_EQ(123, z.value());
}

}  // namespace
}  // namespace mojo