optimization_test.cc (4504B)
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 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 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 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 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 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 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 ImplicitlyConvertibleToBool { 92 public: 93 explicit ImplicitlyConvertibleToBool(bool value) : value_(value) {} 94 operator bool() const { // NOLINT(google-explicit-constructor) 95 return value_; 96 } 97 98 private: 99 bool value_; 100 }; 101 102 TEST(PredictTest, ImplicitBoolConversion) { 103 const ImplicitlyConvertibleToBool is_true(true); 104 const ImplicitlyConvertibleToBool 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 ExplicitlyConvertibleToBool { 112 public: 113 explicit ExplicitlyConvertibleToBool(bool value) : value_(value) {} 114 explicit operator bool() const { return value_; } 115 116 private: 117 bool value_; 118 }; 119 120 TEST(PredictTest, ExplicitBoolConversion) { 121 const ExplicitlyConvertibleToBool is_true(true); 122 const ExplicitlyConvertibleToBool 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 // This verifies that ABSL_ASSUME compiles in a variety of contexts. 130 // It does not test optimization. 131 TEST(AbslAssume, Compiles) { 132 int x = 0; 133 ABSL_ASSUME(x >= 0); 134 EXPECT_EQ(x, 0); 135 136 // https://github.com/abseil/abseil-cpp/issues/1814 137 ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x; 138 EXPECT_EQ(x, 1); 139 } 140 141 } // namespace