1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef CHRE_PLATFORM_LINUX_ASSERT_H_
18#define CHRE_PLATFORM_LINUX_ASSERT_H_
19
20#include <cassert>
21
22#define CHRE_ASSERT_USES_STDLIB_ASSERT
23
24#ifdef GTEST
25
26#include "chre/platform/log.h"
27#include "gmock/gmock.h"
28
29class MockAssert;
30extern MockAssert *gMockAssert;
31
32class AssertInterface {
33 public:
34  virtual void doAssert() = 0;
35};
36
37class MockAssert : public AssertInterface {
38 public:
39  MockAssert() {
40    gMockAssert = this;
41  }
42  ~MockAssert() {
43    gMockAssert = nullptr;
44  }
45
46  MOCK_METHOD0(doAssert, void());
47};
48
49/**
50 * Helper macro that wraps a statement in a block that sets up the mock for
51 * CHRE_ASSERT and expects it to be called at least once. This allows for
52 * verification that the code to be tested throws an expected assertion failure,
53 * and also handles the failure gracefully when assertions are compiled out.
54 * Triggered assertions are logged using LOGI, so they can be manually checked
55 * in the test output.
56 *
57 * Example:
58 * @code{.cpp}
59 *   TEST(DynamicVector, InsertToSparseIndexFails) {
60 *     DynamicVector<int> vector;
61 *     EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.insert(5));
62 *   }
63 * @endcode
64 */
65#define EXPECT_CHRE_ASSERT(statement)                                     \
66  do {                                                                    \
67    ASSERT_EQ(gMockAssert, nullptr);                                      \
68    MockAssert chreMockAssert;                                            \
69    EXPECT_CALL(chreMockAssert, doAssert()).Times(::testing::AtLeast(1)); \
70    statement;                                                            \
71  } while (0)
72
73#define CHRE_ASSERT(condition)                           \
74  do {                                                   \
75    if (gMockAssert != nullptr && !(condition)) {        \
76      LOGI("Mocked assertion " #condition " triggered"); \
77      gMockAssert->doAssert();                           \
78    } else {                                             \
79      assert(condition);                                 \
80    }                                                    \
81  } while (0)
82
83#else  // if !defined(GTEST)
84
85#define CHRE_ASSERT(condition) assert(condition)
86
87#endif  // GTEST
88
89#endif  // CHRE_PLATFORM_LINUX_ASSERT_H_
90