// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "absl/base/optimization.h"

#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/types/optional.h"

namespace {

// Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.
// The tests only verify that the macros are functionally correct - i.e. code
// behaves as if they weren't used. They don't try to check their impact on
// optimization.

TEST(PredictTest, PredictTrue) {
  EXPECT_TRUE(ABSL_PREDICT_TRUE(true));
  EXPECT_FALSE(ABSL_PREDICT_TRUE(false));
  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));
  EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));

  if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();
  if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();

  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);
  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);
}

TEST(PredictTest, PredictFalse) {
  EXPECT_TRUE(ABSL_PREDICT_FALSE(true));
  EXPECT_FALSE(ABSL_PREDICT_FALSE(false));
  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));
  EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));

  if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();
  if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();

  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);
  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);
}

TEST(PredictTest, OneEvaluation) {
  // Verify that the expression is only evaluated once.
  int x = 0;
  if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();
  EXPECT_EQ(x, 1);
  if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();
  EXPECT_EQ(x, 2);
}

TEST(PredictTest, OperatorOrder) {
  // Verify that operator order inside and outside the macro behaves well.
  // These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'
  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);
  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);
  EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));
  EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));
}

TEST(PredictTest, Pointer) {
  const int x = 3;
  const int *good_intptr = &x;
  const int *null_intptr = nullptr;
  EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
  EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
  EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
  EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
}

TEST(PredictTest, Optional) {
  // Note: An optional's truth value is the value's existence, not its truth.
  absl::optional<bool> has_value(false);
  absl::optional<bool> no_value;
  EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
  EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
  EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
  EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
}

class ImplictlyConvertibleToBool {
 public:
  explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
  operator bool() const {  // NOLINT(google-explicit-constructor)
    return value_;
  }

 private:
  bool value_;
};

TEST(PredictTest, ImplicitBoolConversion) {
  const ImplictlyConvertibleToBool is_true(true);
  const ImplictlyConvertibleToBool is_false(false);
  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
}

class ExplictlyConvertibleToBool {
 public:
  explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
  explicit operator bool() const { return value_; }

 private:
  bool value_;
};

TEST(PredictTest, ExplicitBoolConversion) {
  const ExplictlyConvertibleToBool is_true(true);
  const ExplictlyConvertibleToBool is_false(false);
  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
}

TEST(TrivallyRelocatable, Sanity) {
#if !defined(ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI) || \
    !ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
  GTEST_SKIP() << "No trivial ABI support.";
#endif

  struct Trivial {};
  struct NonTrivial {
    NonTrivial(const NonTrivial&) {}
  };
  struct ABSL_ATTRIBUTE_TRIVIAL_ABI TrivialAbi {
    TrivialAbi(const TrivialAbi&) {}
  };
  EXPECT_TRUE(ABSL_IS_TRIVIALLY_RELOCATABLE(Trivial));
  EXPECT_FALSE(ABSL_IS_TRIVIALLY_RELOCATABLE(NonTrivial));
  EXPECT_TRUE(ABSL_IS_TRIVIALLY_RELOCATABLE(TrivialAbi));
}

}  // namespace
