/*
 *  Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/alr_detector.h"

#include "rtc_base/experiments/alr_experiment.h"
#include "test/field_trial.h"
#include "test/gtest.h"

namespace {

constexpr int kEstimatedBitrateBps = 300000;

}  // namespace

namespace webrtc {
namespace webrtc_cc {

namespace {
class SimulateOutgoingTrafficIn {
 public:
  explicit SimulateOutgoingTrafficIn(AlrDetector* alr_detector,
                                     int64_t* timestamp_ms)
      : alr_detector_(alr_detector), timestamp_ms_(timestamp_ms) {
    RTC_CHECK(alr_detector_);
  }

  SimulateOutgoingTrafficIn& ForTimeMs(int time_ms) {
    interval_ms_ = time_ms;
    ProduceTraffic();
    return *this;
  }

  SimulateOutgoingTrafficIn& AtPercentOfEstimatedBitrate(int usage_percentage) {
    usage_percentage_.emplace(usage_percentage);
    ProduceTraffic();
    return *this;
  }

 private:
  void ProduceTraffic() {
    if (!interval_ms_ || !usage_percentage_)
      return;
    const int kTimeStepMs = 10;
    for (int t = 0; t < *interval_ms_; t += kTimeStepMs) {
      *timestamp_ms_ += kTimeStepMs;
      alr_detector_->OnBytesSent(kEstimatedBitrateBps * *usage_percentage_ *
                                     kTimeStepMs / (8 * 100 * 1000),
                                 *timestamp_ms_);
    }
    int remainder_ms = *interval_ms_ % kTimeStepMs;
    if (remainder_ms > 0) {
      *timestamp_ms_ += kTimeStepMs;
      alr_detector_->OnBytesSent(kEstimatedBitrateBps * *usage_percentage_ *
                                     remainder_ms / (8 * 100 * 1000),
                                 *timestamp_ms_);
    }
  }
  AlrDetector* const alr_detector_;
  int64_t* timestamp_ms_;
  absl::optional<int> interval_ms_;
  absl::optional<int> usage_percentage_;
};
}  // namespace

class AlrDetectorTest : public testing::Test {
 public:
  void SetUp() override {
    alr_detector_.SetEstimatedBitrate(kEstimatedBitrateBps);
  }

 protected:
  AlrDetector alr_detector_;
  int64_t timestamp_ms_ = 1000;
};

TEST_F(AlrDetectorTest, AlrDetection) {
  // Start in non-ALR state.
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // Stay in non-ALR state when usage is close to 100%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(1000)
      .AtPercentOfEstimatedBitrate(90);
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // Verify that we ALR starts when bitrate drops below 20%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(1500)
      .AtPercentOfEstimatedBitrate(20);
  EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // Verify that ALR ends when usage is above 65%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(4000)
      .AtPercentOfEstimatedBitrate(100);
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
}

TEST_F(AlrDetectorTest, ShortSpike) {
  // Start in non-ALR state.
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // Verify that we ALR starts when bitrate drops below 20%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(1000)
      .AtPercentOfEstimatedBitrate(20);
  EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // Verify that we stay in ALR region even after a short bitrate spike.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(100)
      .AtPercentOfEstimatedBitrate(150);
  EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // ALR ends when usage is above 65%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(3000)
      .AtPercentOfEstimatedBitrate(100);
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
}

TEST_F(AlrDetectorTest, BandwidthEstimateChanges) {
  // Start in non-ALR state.
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // ALR starts when bitrate drops below 20%.
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(1000)
      .AtPercentOfEstimatedBitrate(20);
  EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());

  // When bandwidth estimate drops the detector should stay in ALR mode and quit
  // it shortly afterwards as the sender continues sending the same amount of
  // traffic. This is necessary to ensure that ProbeController can still react
  // to the BWE drop by initiating a new probe.
  alr_detector_.SetEstimatedBitrate(kEstimatedBitrateBps / 5);
  EXPECT_TRUE(alr_detector_.GetApplicationLimitedRegionStartTime());
  SimulateOutgoingTrafficIn(&alr_detector_, &timestamp_ms_)
      .ForTimeMs(1000)
      .AtPercentOfEstimatedBitrate(50);
  EXPECT_FALSE(alr_detector_.GetApplicationLimitedRegionStartTime());
}

TEST_F(AlrDetectorTest, ParseControlFieldTrial) {
  webrtc::test::ScopedFieldTrials field_trial(
      "WebRTC-ProbingScreenshareBwe/Control/");
  absl::optional<AlrExperimentSettings> parsed_params =
      AlrExperimentSettings::CreateFromFieldTrial(
          "WebRTC-ProbingScreenshareBwe");
  EXPECT_FALSE(static_cast<bool>(parsed_params));
}

TEST_F(AlrDetectorTest, ParseActiveFieldTrial) {
  webrtc::test::ScopedFieldTrials field_trial(
      "WebRTC-ProbingScreenshareBwe/1.1,2875,85,20,-20,1/");
  absl::optional<AlrExperimentSettings> parsed_params =
      AlrExperimentSettings::CreateFromFieldTrial(
          "WebRTC-ProbingScreenshareBwe");
  ASSERT_TRUE(static_cast<bool>(parsed_params));
  EXPECT_EQ(1.1f, parsed_params->pacing_factor);
  EXPECT_EQ(2875, parsed_params->max_paced_queue_time);
  EXPECT_EQ(85, parsed_params->alr_bandwidth_usage_percent);
  EXPECT_EQ(20, parsed_params->alr_start_budget_level_percent);
  EXPECT_EQ(-20, parsed_params->alr_stop_budget_level_percent);
  EXPECT_EQ(1, parsed_params->group_id);
}

}  // namespace webrtc_cc
}  // namespace webrtc
