1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/base/optimization.h"
16
17 #include "gtest/gtest.h"
18 #include "absl/types/optional.h"
19
20 namespace {
21
22 // Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.
23 // The tests only verify that the macros are functionally correct - i.e. code
24 // behaves as if they weren't used. They don't try to check their impact on
25 // optimization.
26
TEST(PredictTest,PredictTrue)27 TEST(PredictTest, PredictTrue) {
28 EXPECT_TRUE(ABSL_PREDICT_TRUE(true));
29 EXPECT_FALSE(ABSL_PREDICT_TRUE(false));
30 EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));
31 EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));
32
33 if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();
34 if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();
35
36 EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);
37 EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);
38 }
39
TEST(PredictTest,PredictFalse)40 TEST(PredictTest, PredictFalse) {
41 EXPECT_TRUE(ABSL_PREDICT_FALSE(true));
42 EXPECT_FALSE(ABSL_PREDICT_FALSE(false));
43 EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));
44 EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));
45
46 if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();
47 if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();
48
49 EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);
50 EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);
51 }
52
TEST(PredictTest,OneEvaluation)53 TEST(PredictTest, OneEvaluation) {
54 // Verify that the expression is only evaluated once.
55 int x = 0;
56 if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();
57 EXPECT_EQ(x, 1);
58 if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();
59 EXPECT_EQ(x, 2);
60 }
61
TEST(PredictTest,OperatorOrder)62 TEST(PredictTest, OperatorOrder) {
63 // Verify that operator order inside and outside the macro behaves well.
64 // These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'
65 EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);
66 EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);
67 EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));
68 EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));
69 }
70
TEST(PredictTest,Pointer)71 TEST(PredictTest, Pointer) {
72 const int x = 3;
73 const int *good_intptr = &x;
74 const int *null_intptr = nullptr;
75 EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
76 EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
77 EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
78 EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
79 }
80
TEST(PredictTest,Optional)81 TEST(PredictTest, Optional) {
82 // Note: An optional's truth value is the value's existence, not its truth.
83 absl::optional<bool> has_value(false);
84 absl::optional<bool> no_value;
85 EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
86 EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
87 EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
88 EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
89 }
90
91 class ImplictlyConvertibleToBool {
92 public:
ImplictlyConvertibleToBool(bool value)93 explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
operator bool() const94 operator bool() const { // NOLINT(google-explicit-constructor)
95 return value_;
96 }
97
98 private:
99 bool value_;
100 };
101
TEST(PredictTest,ImplicitBoolConversion)102 TEST(PredictTest, ImplicitBoolConversion) {
103 const ImplictlyConvertibleToBool is_true(true);
104 const ImplictlyConvertibleToBool is_false(false);
105 if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
106 if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
107 if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
108 if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
109 }
110
111 class ExplictlyConvertibleToBool {
112 public:
ExplictlyConvertibleToBool(bool value)113 explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
operator bool() const114 explicit operator bool() const { return value_; }
115
116 private:
117 bool value_;
118 };
119
TEST(PredictTest,ExplicitBoolConversion)120 TEST(PredictTest, ExplicitBoolConversion) {
121 const ExplictlyConvertibleToBool is_true(true);
122 const ExplictlyConvertibleToBool is_false(false);
123 if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
124 if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
125 if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
126 if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
127 }
128
129 } // namespace
130