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