/*
 *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <cstdint>
#include <limits>
#include <type_traits>

#include "modules/include/module_common_types_public.h"
#include "net/dcsctp/common/sequence_numbers.h"
#include "rtc_base/numerics/sequence_number_unwrapper.h"
#include "rtc_base/strong_alias.h"
#include "rtc_base/time_utils.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

using ::testing::Test;

using dcsctp::UnwrappedSequenceNumber;
using Wrapped = StrongAlias<class WrappedTag, uint32_t>;
using TestSequence = UnwrappedSequenceNumber<Wrapped>;

template <typename T>
class UnwrapperHelper;

template <>
class UnwrapperHelper<TestSequence::Unwrapper> {
 public:
  int64_t Unwrap(uint32_t val) {
    TestSequence s = unwrapper_.Unwrap(Wrapped(val));
    // UnwrappedSequenceNumber starts counting at 2^32.
    constexpr int64_t kDcsctpUnwrapStart = int64_t{1} << 32;
    return s.value() - kDcsctpUnwrapStart;
  }

 private:
  TestSequence::Unwrapper unwrapper_;
};

// MaxVal is the max of the wrapped space, ie MaxVal + 1 = 0 when wrapped.
template <typename U, int64_t MaxVal = std::numeric_limits<uint32_t>::max()>
struct FixtureParams {
  using Unwrapper = U;
  static constexpr int64_t kMaxVal = MaxVal;
};

template <typename F>
class UnwrapperConformanceFixture : public Test {
 public:
  static constexpr int64_t kMaxVal = F::kMaxVal;
  static constexpr int64_t kMaxIncrease = kMaxVal / 2;
  static constexpr int64_t kMaxBackwardsIncrease = kMaxVal - kMaxIncrease + 1;

  template <typename U>
  static constexpr bool UnwrapperIs() {
    return std::is_same<typename F::Unwrapper, U>();
  }

  typename F::Unwrapper ref_unwrapper_;
};

TYPED_TEST_SUITE_P(UnwrapperConformanceFixture);

TYPED_TEST_P(UnwrapperConformanceFixture, PositiveWrapAround) {
  EXPECT_EQ(0, this->ref_unwrapper_.Unwrap(0));
  EXPECT_EQ(TestFixture::kMaxIncrease,
            this->ref_unwrapper_.Unwrap(TestFixture::kMaxIncrease));
  EXPECT_EQ(2 * TestFixture::kMaxIncrease,
            this->ref_unwrapper_.Unwrap(2 * TestFixture::kMaxIncrease));
  // Now unwrapping 0 should wrap around to be kMaxVal + 1.
  EXPECT_EQ(TestFixture::kMaxVal + 1, this->ref_unwrapper_.Unwrap(0));
  EXPECT_EQ(TestFixture::kMaxVal + 1 + TestFixture::kMaxIncrease,
            this->ref_unwrapper_.Unwrap(TestFixture::kMaxIncrease));
}

TYPED_TEST_P(UnwrapperConformanceFixture, NegativeUnwrap) {
  using UnwrapperT = decltype(this->ref_unwrapper_);
  // TimestampUnwrapper known to not handle negative numbers.
  // rtc::TimestampWrapAroundHandler does not wrap around correctly.
  if constexpr (std::is_same<UnwrapperT, TimestampUnwrapper>() ||
                std::is_same<UnwrapperT, rtc::TimestampWrapAroundHandler>()) {
    return;
  }
  EXPECT_EQ(0, this->ref_unwrapper_.Unwrap(0));
  // Max backwards wrap is negative.
  EXPECT_EQ(-TestFixture::kMaxIncrease,
            this->ref_unwrapper_.Unwrap(this->kMaxBackwardsIncrease));
  // Increase to a larger negative number.
  EXPECT_EQ(-2, this->ref_unwrapper_.Unwrap(TestFixture::kMaxVal - 1));
  // Increase back positive.
  EXPECT_EQ(1, this->ref_unwrapper_.Unwrap(1));
}

TYPED_TEST_P(UnwrapperConformanceFixture, BackwardUnwrap) {
  EXPECT_EQ(127, this->ref_unwrapper_.Unwrap(127));
  EXPECT_EQ(128, this->ref_unwrapper_.Unwrap(128));
  EXPECT_EQ(127, this->ref_unwrapper_.Unwrap(127));
}

TYPED_TEST_P(UnwrapperConformanceFixture, MultiplePositiveWrapArounds) {
  using UnwrapperT = decltype(this->ref_unwrapper_);
  // rtc::TimestampWrapAroundHandler does not wrap around correctly.
  if constexpr (std::is_same<UnwrapperT, rtc::TimestampWrapAroundHandler>()) {
    return;
  }
  int64_t val = 0;
  uint32_t wrapped_val = 0;
  for (int i = 0; i < 16; ++i) {
    EXPECT_EQ(val, this->ref_unwrapper_.Unwrap(wrapped_val));
    val += TestFixture::kMaxIncrease;
    wrapped_val =
        (wrapped_val + TestFixture::kMaxIncrease) % (TestFixture::kMaxVal + 1);
  }
}

TYPED_TEST_P(UnwrapperConformanceFixture, WrapBoundaries) {
  EXPECT_EQ(0, this->ref_unwrapper_.Unwrap(0));
  EXPECT_EQ(TestFixture::kMaxIncrease,
            this->ref_unwrapper_.Unwrap(TestFixture::kMaxIncrease));
  // Increases by more than TestFixture::kMaxIncrease which indicates a negative
  // rollback.
  EXPECT_EQ(0, this->ref_unwrapper_.Unwrap(0));
  EXPECT_EQ(10, this->ref_unwrapper_.Unwrap(10));
}

TYPED_TEST_P(UnwrapperConformanceFixture, MultipleNegativeWrapArounds) {
  using UnwrapperT = decltype(this->ref_unwrapper_);
  // TimestampUnwrapper known to not handle negative numbers.
  // SequenceNumberUnwrapper can only wrap negative once.
  // rtc::TimestampWrapAroundHandler does not wrap around correctly.
  if constexpr (std::is_same<UnwrapperT, TimestampUnwrapper>() ||
                std::is_same<UnwrapperT,
                             UnwrapperHelper<TestSequence::Unwrapper>>() ||
                std::is_same<UnwrapperT, rtc::TimestampWrapAroundHandler>()) {
    return;
  }
  int64_t val = 0;
  uint32_t wrapped_val = 0;
  for (int i = 0; i < 16; ++i) {
    EXPECT_EQ(val, this->ref_unwrapper_.Unwrap(wrapped_val));
    val -= TestFixture::kMaxIncrease;
    wrapped_val = (wrapped_val + this->kMaxBackwardsIncrease) %
                  (TestFixture::kMaxVal + 1);
  }
}

REGISTER_TYPED_TEST_SUITE_P(UnwrapperConformanceFixture,
                            NegativeUnwrap,
                            PositiveWrapAround,
                            BackwardUnwrap,
                            WrapBoundaries,
                            MultiplePositiveWrapArounds,
                            MultipleNegativeWrapArounds);

constexpr int64_t k15BitMax = (int64_t{1} << 15) - 1;
using UnwrapperTypes = ::testing::Types<
    FixtureParams<rtc::TimestampWrapAroundHandler>,
    FixtureParams<TimestampUnwrapper>,
    FixtureParams<RtpTimestampUnwrapper>,
    FixtureParams<UnwrapperHelper<TestSequence::Unwrapper>>,
    // SeqNumUnwrapper supports arbitrary limits.
    FixtureParams<SeqNumUnwrapper<uint32_t, k15BitMax + 1>, k15BitMax>>;

class TestNames {
 public:
  template <typename T>
  static std::string GetName(int) {
    if constexpr (std::is_same<typename T::Unwrapper,
                               rtc::TimestampWrapAroundHandler>())
      return "TimestampWrapAroundHandler";
    if constexpr (std::is_same<typename T::Unwrapper, TimestampUnwrapper>())
      return "TimestampUnwrapper";
    if constexpr (std::is_same<typename T::Unwrapper,
                               SeqNumUnwrapper<uint32_t>>())
      return "SeqNumUnwrapper";
    if constexpr (std::is_same<typename T::Unwrapper,
                               SeqNumUnwrapper<uint32_t, k15BitMax + 1>>())
      return "SeqNumUnwrapper15bit";
    if constexpr (std::is_same<typename T::Unwrapper,
                               UnwrapperHelper<TestSequence::Unwrapper>>())
      return "UnwrappedSequenceNumber";
  }
};

INSTANTIATE_TYPED_TEST_SUITE_P(UnwrapperConformanceTest,
                               UnwrapperConformanceFixture,
                               UnwrapperTypes,
                               TestNames);

}  // namespace
}  // namespace webrtc
