// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_TEST_HELPERS_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_TEST_HELPERS_H_

#include <algorithm>
#include <array>
#include <iostream>
#include <type_traits>

#include <gtest/gtest.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/lib/fxl/strings/string_printf.h"

// Run |statement| and return if a fatal test error occurred. Include the file
// name and line number in the output.
//
// This is useful for running test helpers in subroutines. For example, if a
// test helper posted ASSERTs checks inside of a dispatcher task:
//
//   RETURN_IF_FATAL(RunLoopUntilIdle());
//
// would return if any of the tasks had an ASSERT failure.
//
// Fatal failures in Google Test such as ASSERT_* failures and calls to FAIL()
// set a global flag for the failure (see testing::Test::HasFatalFailure) and
// return from the function where they occur. However, the change in flow
// control is limited to that subroutine scope. Test code higher up the stack
// must propagate the failure in order to exit the test.
//
// Note in the above example, if a task in the test loop has a fatal failure, it
// does not prevent the remaining due tasks in the loop from running. The test
// case would not exit until RunLoopFromIdle returns.
#define RETURN_IF_FATAL(statement)      \
  do {                                  \
    SCOPED_TRACE("");                   \
    ASSERT_NO_FATAL_FAILURE(statement); \
  } while (false)

namespace bt {

template <class InputIt>
std::string ByteContainerToString(InputIt begin, InputIt end) {
  std::string bytes_string;
  for (InputIt iter = begin; iter != end; ++iter) {
    bytes_string += fxl::StringPrintf("0x%.2x ", *iter);
  }
  return bytes_string;
}

template <class Container>
std::string ByteContainerToString(const Container& c) {
  return ByteContainerToString(c.begin(), c.end());
}

template <class InputIt>
void PrintByteContainer(InputIt begin, InputIt end) {
  std::cout << ByteContainerToString(begin, end);
}

// Prints the contents of a container as a string.
template <class Container>
void PrintByteContainer(const Container& c) {
  PrintByteContainer(c.begin(), c.end());
}

// Function-template for comparing contents of two iterable byte containers for
// equality. If the contents are not equal, this logs a GTEST-style error
// message to stdout. Meant to be used from unit tests.
template <class InputIt1, class InputIt2>
bool ContainersEqual(InputIt1 expected_begin, InputIt1 expected_end, InputIt2 actual_begin,
                     InputIt2 actual_end) {
  if (std::equal(expected_begin, expected_end, actual_begin, actual_end))
    return true;
  std::cout << "Expected: (" << (expected_end - expected_begin) << " bytes) { ";
  PrintByteContainer(expected_begin, expected_end);
  std::cout << "}\n   Found: (" << (actual_end - actual_begin) << " bytes) { ";
  PrintByteContainer(actual_begin, actual_end);
  std::cout << "}" << std::endl;
  return false;
}

template <class Container1, class Container2>
bool ContainersEqual(const Container1& expected, const Container2& actual) {
  return ContainersEqual(expected.begin(), expected.end(), actual.begin(), actual.end());
}

template <class Container1>
bool ContainersEqual(const Container1& expected, const uint8_t* actual_bytes,
                     size_t actual_num_bytes) {
  return ContainersEqual(expected.begin(), expected.end(), actual_bytes,
                         actual_bytes + actual_num_bytes);
}

// Returns a managed pointer to a heap allocated MutableByteBuffer.
template <typename... T>
MutableByteBufferPtr NewBuffer(T... bytes) {
  return std::make_unique<StaticByteBuffer<sizeof...(T)>>(std::forward<T>(bytes)...);
}

// Returns the value of |x| as a little-endian array, i.e. the first byte of the array has the value
// of the least significant byte of |x|.
template <typename T>
constexpr std::array<uint8_t, sizeof(T)> ToBytes(T x) {
  static_assert(std::is_integral_v<T>, "Must use integral types for safe bytewise access");
  std::array<uint8_t, sizeof(T)> bytes;
  for (auto& byte : bytes) {
    byte = x;
    x >>= 8;
  }
  return bytes;
}

// Returns the Upper/Lower bits of a uint16_t
constexpr uint8_t UpperBits(const uint16_t x) { return ToBytes(x).back(); }
constexpr uint8_t LowerBits(const uint16_t x) { return ToBytes(x).front(); }

}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_TEST_HELPERS_H_
