/*
 *  Copyright (c) 2017 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 <random>
#include <utility>

#include "webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h"
#include "webrtc/test/gtest.h"

namespace webrtc {

namespace {

// The test uses the following settings:
//
// recoverable ^
// packet-loss |   |  |
//             |  A| C|   FEC
//             |    \  \   ON
//             | FEC \ D\_______
//             | OFF B\_________
//             |-----------------> bandwidth
//
// A : (kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw)
// B : (kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw)
// C : (kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw)
// D : (kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw)

constexpr int kDisablingBandwidthLow = 15000;
constexpr float kDisablingRecoverablePacketLossAtLowBw = 0.08f;
constexpr int kDisablingBandwidthHigh = 64000;
constexpr float kDisablingRecoverablePacketLossAtHighBw = 0.01f;
constexpr int kEnablingBandwidthLow = 17000;
constexpr float kEnablingRecoverablePacketLossAtLowBw = 0.1f;
constexpr int kEnablingBandwidthHigh = 64000;
constexpr float kEnablingRecoverablePacketLossAtHighBw = 0.05f;

constexpr float kEpsilon = 1e-5f;

rtc::Optional<float> GetRandomProbabilityOrUnknown() {
  std::random_device rd;
  std::mt19937 generator(rd());
  std::uniform_real_distribution<> distribution(0, 1);

  if (distribution(generator) < 0.2) {
    return rtc::Optional<float>();
  } else {
    return rtc::Optional<float>(distribution(generator));
  }
}

std::unique_ptr<FecControllerRplrBased> CreateFecControllerRplrBased(
    bool initial_fec_enabled) {
  return std::unique_ptr<FecControllerRplrBased>(
      new FecControllerRplrBased(FecControllerRplrBased::Config(
          initial_fec_enabled,
          ThresholdCurve(
              kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw,
              kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw),
          ThresholdCurve(kDisablingBandwidthLow,
                         kDisablingRecoverablePacketLossAtLowBw,
                         kDisablingBandwidthHigh,
                         kDisablingRecoverablePacketLossAtHighBw))));
}

void UpdateNetworkMetrics(
    FecControllerRplrBased* controller,
    const rtc::Optional<int>& uplink_bandwidth_bps,
    const rtc::Optional<float>& uplink_packet_loss,
    const rtc::Optional<float>& uplink_recoveralbe_packet_loss) {
  // UpdateNetworkMetrics can accept multiple network metric updates at once.
  // However, currently, the most used case is to update one metric at a time.
  // To reflect this fact, we separate the calls.
  if (uplink_bandwidth_bps) {
    Controller::NetworkMetrics network_metrics;
    network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
    controller->UpdateNetworkMetrics(network_metrics);
  }
  if (uplink_packet_loss) {
    Controller::NetworkMetrics network_metrics;
    network_metrics.uplink_packet_loss_fraction = uplink_packet_loss;
    controller->UpdateNetworkMetrics(network_metrics);
  }
  if (uplink_recoveralbe_packet_loss) {
    Controller::NetworkMetrics network_metrics;
    network_metrics.uplink_recoverable_packet_loss_fraction =
        uplink_recoveralbe_packet_loss;
    controller->UpdateNetworkMetrics(network_metrics);
  }
}

void UpdateNetworkMetrics(
    FecControllerRplrBased* controller,
    const rtc::Optional<int>& uplink_bandwidth_bps,
    const rtc::Optional<float>& uplink_recoveralbe_packet_loss) {
  // FecControllerRplrBased doesn't currently use the PLR (general packet-loss
  // rate) at all. (This might be changed in the future.) The unit-tests will
  // use a random value (including unknown), to show this does not interfere.
  UpdateNetworkMetrics(controller, uplink_bandwidth_bps,
                       GetRandomProbabilityOrUnknown(),
                       uplink_recoveralbe_packet_loss);
}

void UpdateNetworkMetrics(FecControllerRplrBased* controller,
                          int uplink_bandwidth_bps,
                          float uplink_recoveralbe_packet_loss) {
  UpdateNetworkMetrics(controller, rtc::Optional<int>(uplink_bandwidth_bps),
                       rtc::Optional<float>(uplink_recoveralbe_packet_loss));
}

// Checks that the FEC decision and |uplink_packet_loss_fraction| given by
// |states->controller->MakeDecision| matches |expected_enable_fec| and
// |expected_uplink_packet_loss_fraction|, respectively.
void CheckDecision(FecControllerRplrBased* controller,
                   bool expected_enable_fec,
                   float expected_uplink_packet_loss_fraction) {
  AudioEncoderRuntimeConfig config;
  controller->MakeDecision(&config);

  // Less compact than comparing optionals, but yields more readable errors.
  EXPECT_TRUE(config.enable_fec);
  if (config.enable_fec) {
    EXPECT_EQ(expected_enable_fec, *config.enable_fec);
  }
  EXPECT_TRUE(config.uplink_packet_loss_fraction);
  if (config.uplink_packet_loss_fraction) {
    EXPECT_EQ(expected_uplink_packet_loss_fraction,
              *config.uplink_packet_loss_fraction);
  }
}

}  // namespace

TEST(FecControllerRplrBasedTest, OutputInitValueBeforeAnyInputsAreReceived) {
  for (bool initial_fec_enabled : {false, true}) {
    auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
    CheckDecision(controller.get(), initial_fec_enabled, 0);
  }
}

TEST(FecControllerRplrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) {
  // Regardless of the initial FEC state and the recoverable-packet-loss
  // rate, the initial FEC state is maintained as long as the BWE is unknown.
  for (bool initial_fec_enabled : {false, true}) {
    for (float recoverable_packet_loss :
         {kDisablingRecoverablePacketLossAtHighBw - kEpsilon,
          kDisablingRecoverablePacketLossAtHighBw,
          kDisablingRecoverablePacketLossAtHighBw + kEpsilon,
          kEnablingRecoverablePacketLossAtHighBw - kEpsilon,
          kEnablingRecoverablePacketLossAtHighBw,
          kEnablingRecoverablePacketLossAtHighBw + kEpsilon}) {
      auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
      UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(),
                           rtc::Optional<float>(recoverable_packet_loss));
      CheckDecision(controller.get(), initial_fec_enabled,
                    recoverable_packet_loss);
    }
  }
}

TEST(FecControllerRplrBasedTest,
     OutputInitValueWhenUplinkRecoverablePacketLossFractionUnknown) {
  // Regardless of the initial FEC state and the BWE, the initial FEC state
  // is maintained as long as the recoverable-packet-loss rate is unknown.
  for (bool initial_fec_enabled : {false, true}) {
    for (int bandwidth : {kDisablingBandwidthLow - 1, kDisablingBandwidthLow,
                          kDisablingBandwidthLow + 1, kEnablingBandwidthLow - 1,
                          kEnablingBandwidthLow, kEnablingBandwidthLow + 1}) {
      auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
      UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(bandwidth),
                           rtc::Optional<float>());
      CheckDecision(controller.get(), initial_fec_enabled, 0.0);
    }
  }
}

TEST(FecControllerRplrBasedTest, EnableFecForHighBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh,
                       kEnablingRecoverablePacketLossAtHighBw);
  CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw);
}

TEST(FecControllerRplrBasedTest, UpdateMultipleNetworkMetricsAtOnce) {
  // This test is similar to EnableFecForHighBandwidth. But instead of
  // using ::UpdateNetworkMetrics(...), which calls
  // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) multiple times, we
  // we call it only once. This is to verify that
  // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) can handle multiple
  // network updates at once. This is, however, not a common use case in current
  // audio_network_adaptor_impl.cc.
  auto controller = CreateFecControllerRplrBased(false);
  Controller::NetworkMetrics network_metrics;
  network_metrics.uplink_bandwidth_bps =
      rtc::Optional<int>(kEnablingBandwidthHigh);
  network_metrics.uplink_packet_loss_fraction =
      rtc::Optional<float>(GetRandomProbabilityOrUnknown());
  network_metrics.uplink_recoverable_packet_loss_fraction =
      rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw);
  controller->UpdateNetworkMetrics(network_metrics);
  CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw);
}

TEST(FecControllerRplrBasedTest, MaintainFecOffForHighBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  constexpr float kRecoverablePacketLoss =
      kEnablingRecoverablePacketLossAtHighBw * 0.99f;
  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, EnableFecForMediumBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  constexpr float kRecoverablePacketLoss =
      (kEnablingRecoverablePacketLossAtLowBw +
       kEnablingRecoverablePacketLossAtHighBw) / 2.0;
  UpdateNetworkMetrics(
      controller.get(),
      (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2,
      kRecoverablePacketLoss);
  CheckDecision(controller.get(), true, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, MaintainFecOffForMediumBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  constexpr float kRecoverablePacketLoss =
      kEnablingRecoverablePacketLossAtLowBw * 0.49f +
      kEnablingRecoverablePacketLossAtHighBw * 0.51f;
  UpdateNetworkMetrics(controller.get(),
                       (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, EnableFecForLowBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow,
                       kEnablingRecoverablePacketLossAtLowBw);
  CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtLowBw);
}

TEST(FecControllerRplrBasedTest, MaintainFecOffForLowBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  constexpr float kRecoverablePacketLoss =
      kEnablingRecoverablePacketLossAtLowBw * 0.99f;
  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, MaintainFecOffForVeryLowBandwidth) {
  auto controller = CreateFecControllerRplrBased(false);
  // Below |kEnablingBandwidthLow|, no recoverable packet loss fraction can
  // cause FEC to turn on.
  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow - 1, 1.0);
  CheckDecision(controller.get(), false, 1.0);
}

TEST(FecControllerRplrBasedTest, DisableFecForHighBandwidth) {
  auto controller = CreateFecControllerRplrBased(true);
  constexpr float kRecoverablePacketLoss =
      kDisablingRecoverablePacketLossAtHighBw - kEpsilon;
  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, MaintainFecOnForHighBandwidth) {
  // Note: Disabling happens when the value is strictly below the threshold.
  auto controller = CreateFecControllerRplrBased(true);
  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh,
                       kDisablingRecoverablePacketLossAtHighBw);
  CheckDecision(controller.get(), true,
                kDisablingRecoverablePacketLossAtHighBw);
}

TEST(FecControllerRplrBasedTest, DisableFecOnMediumBandwidth) {
  auto controller = CreateFecControllerRplrBased(true);
  constexpr float kRecoverablePacketLoss =
      ((kDisablingRecoverablePacketLossAtLowBw +
        kDisablingRecoverablePacketLossAtHighBw) / 2.0f) - kEpsilon;
  UpdateNetworkMetrics(
      controller.get(),
      (kDisablingBandwidthHigh + kDisablingBandwidthLow) / 2,
      kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, MaintainFecOnForMediumBandwidth) {
  auto controller = CreateFecControllerRplrBased(true);
  constexpr float kRecoverablePacketLoss =
      kDisablingRecoverablePacketLossAtLowBw * 0.51f +
      kDisablingRecoverablePacketLossAtHighBw * 0.49f - kEpsilon;
  UpdateNetworkMetrics(controller.get(),
                       (kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), true, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, DisableFecForLowBandwidth) {
  auto controller = CreateFecControllerRplrBased(true);
  constexpr float kRecoverablePacketLoss =
      kDisablingRecoverablePacketLossAtLowBw - kEpsilon;
  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow,
                       kRecoverablePacketLoss);
  CheckDecision(controller.get(), false, kRecoverablePacketLoss);
}

TEST(FecControllerRplrBasedTest, DisableFecForVeryLowBandwidth) {
  auto controller = CreateFecControllerRplrBased(true);
  // Below |kEnablingBandwidthLow|, any recoverable packet loss fraction can
  // cause FEC to turn off.
  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow - 1, 1.0);
  CheckDecision(controller.get(), false, 1.0);
}

TEST(FecControllerRplrBasedTest, CheckBehaviorOnChangingNetworkMetrics) {
  // In this test, we let the network metrics to traverse from 1 to 5.
  //
  // recoverable ^
  // packet-loss | 1 |  |
  //             |   | 2|
  //             |    \  \ 3
  //             |     \4 \_______
  //             |      \_________
  //             |---------5-------> bandwidth

  auto controller = CreateFecControllerRplrBased(true);
  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthLow - 1, 1.0);
  CheckDecision(controller.get(), false, 1.0);

  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthLow,
                       kEnablingRecoverablePacketLossAtLowBw * 0.99f);
  CheckDecision(controller.get(), false,
                kEnablingRecoverablePacketLossAtLowBw * 0.99f);

  UpdateNetworkMetrics(controller.get(), kEnablingBandwidthHigh,
                       kEnablingRecoverablePacketLossAtHighBw);
  CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw);

  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh,
                       kDisablingRecoverablePacketLossAtHighBw);
  CheckDecision(controller.get(), true,
                kDisablingRecoverablePacketLossAtHighBw);

  UpdateNetworkMetrics(controller.get(), kDisablingBandwidthHigh + 1, 0.0);
  CheckDecision(controller.get(), false, 0.0);
}

TEST(FecControllerRplrBasedTest, CheckBehaviorOnSpecialCurves) {
  // We test a special configuration, where the points to define the FEC
  // enabling/disabling curves are placed like the following, otherwise the test
  // is the same as CheckBehaviorOnChangingNetworkMetrics.
  //
  // recoverable ^
  // packet-loss |   |  |
  //             |   | C|
  //             |   |  |
  //             |   | D|_______
  //             |  A|___B______
  //             |-----------------> bandwidth

  constexpr int kEnablingBandwidthHigh = kEnablingBandwidthLow;
  constexpr float kDisablingRecoverablePacketLossAtLowBw =
      kDisablingRecoverablePacketLossAtHighBw;
  FecControllerRplrBased controller(FecControllerRplrBased::Config(
      true,
      ThresholdCurve(
          kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw,
          kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw),
      ThresholdCurve(
          kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw,
          kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw)));

  UpdateNetworkMetrics(&controller, kDisablingBandwidthLow - 1, 1.0);
  CheckDecision(&controller, false, 1.0);

  UpdateNetworkMetrics(&controller, kEnablingBandwidthLow,
                       kEnablingRecoverablePacketLossAtHighBw * 0.99f);
  CheckDecision(&controller, false,
                kEnablingRecoverablePacketLossAtHighBw * 0.99f);

  UpdateNetworkMetrics(&controller, kEnablingBandwidthHigh,
                       kEnablingRecoverablePacketLossAtHighBw);
  CheckDecision(&controller, true, kEnablingRecoverablePacketLossAtHighBw);

  UpdateNetworkMetrics(&controller, kDisablingBandwidthHigh,
                       kDisablingRecoverablePacketLossAtHighBw);
  CheckDecision(&controller, true, kDisablingRecoverablePacketLossAtHighBw);

  UpdateNetworkMetrics(&controller, kDisablingBandwidthHigh + 1, 0.0);
  CheckDecision(&controller, false, 0.0);
}

TEST(FecControllerRplrBasedTest, SingleThresholdCurveForEnablingAndDisabling) {
  // Note: To avoid numerical errors, keep kRecoverablePacketLossAtLowBw and
  // kRecoverablePacketLossAthighBw as (negative) integer powers of 2.
  // This is mostly relevant for the O3 case.
  constexpr int kBandwidthLow = 10000;
  constexpr float kRecoverablePacketLossAtLowBw = 0.25f;
  constexpr int kBandwidthHigh = 20000;
  constexpr float kRecoverablePacketLossAtHighBw = 0.125f;
  auto curve = ThresholdCurve(kBandwidthLow, kRecoverablePacketLossAtLowBw,
                              kBandwidthHigh, kRecoverablePacketLossAtHighBw);

  // B* stands for "below-curve", O* for "on-curve", and A* for "above-curve".
  //
  //                                            //
  // recoverable ^                              //
  // packet-loss |    |                         //
  //             | B1 O1                        //
  //             |    |                         //
  //             |    O2                        //
  //             |     \ A1                     //
  //             |      \                       //
  //             |       O3   A2                //
  //             |     B2 \                     //
  //             |         \                    //
  //             |          O4--O5----          //
  //             |                              //
  //             |            B3                //
  //             |-----------------> bandwidth  //

  struct NetworkState {
    int bandwidth;
    float recoverable_packet_loss;
  };

  std::vector<NetworkState> below{
      {kBandwidthLow - 1, kRecoverablePacketLossAtLowBw + 0.1f},  // B1
      {(kBandwidthLow + kBandwidthHigh) / 2,
       (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 -
           kEpsilon},                                                  // B2
      {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw - kEpsilon}  // B3
  };

  std::vector<NetworkState> on{
      {kBandwidthLow, kRecoverablePacketLossAtLowBw + 0.1f},  // O1
      {kBandwidthLow, kRecoverablePacketLossAtLowBw},         // O2
      {(kBandwidthLow + kBandwidthHigh) / 2,
       (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) /
           2},                                               // O3
      {kBandwidthHigh, kRecoverablePacketLossAtHighBw},      // O4
      {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw},  // O5
  };

  std::vector<NetworkState> above{
      {(kBandwidthLow + kBandwidthHigh) / 2,
       (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 +
           kEpsilon},                                                   // A1
      {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw + kEpsilon},  // A2
  };

  // Test that FEC is turned off whenever we're below the curve, independent
  // of the starting FEC state.
  for (NetworkState net_state : below) {
    for (bool initial_fec_enabled : {false, true}) {
      FecControllerRplrBased controller(
          FecControllerRplrBased::Config(initial_fec_enabled, curve, curve));
      UpdateNetworkMetrics(&controller, net_state.bandwidth,
                           net_state.recoverable_packet_loss);
      CheckDecision(&controller, false, net_state.recoverable_packet_loss);
    }
  }

  // Test that FEC is turned on whenever we're on the curve or above it,
  // independent of the starting FEC state.
  for (std::vector<NetworkState> states_list : {on, above}) {
    for (NetworkState net_state : states_list) {
      for (bool initial_fec_enabled : {false, true}) {
        FecControllerRplrBased controller(
            FecControllerRplrBased::Config(initial_fec_enabled, curve, curve));
        UpdateNetworkMetrics(&controller, net_state.bandwidth,
                             net_state.recoverable_packet_loss);
        CheckDecision(&controller, true, net_state.recoverable_packet_loss);
      }
    }
  }
}

TEST(FecControllerRplrBasedTest, FecAlwaysOff) {
  ThresholdCurve always_off_curve(0, 1.0f + kEpsilon, 0, 1.0f + kEpsilon);
  for (bool initial_fec_enabled : {false, true}) {
    for (int bandwidth : {0, 10000}) {
      for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) {
        FecControllerRplrBased controller(FecControllerRplrBased::Config(
            initial_fec_enabled, always_off_curve, always_off_curve));
        UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss);
        CheckDecision(&controller, false, recoverable_packet_loss);
      }
    }
  }
}

TEST(FecControllerRplrBasedTest, FecAlwaysOn) {
  ThresholdCurve always_on_curve(0, 0.0f, 0, 0.0f);
  for (bool initial_fec_enabled : {false, true}) {
    for (int bandwidth : {0, 10000}) {
      for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) {
        FecControllerRplrBased controller(FecControllerRplrBased::Config(
            initial_fec_enabled, always_on_curve, always_on_curve));
        UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss);
        CheckDecision(&controller, true, recoverable_packet_loss);
      }
    }
  }
}

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(FecControllerRplrBasedDeathTest, InvalidConfig) {
  EXPECT_DEATH(
      FecControllerRplrBased controller(FecControllerRplrBased::Config(
          true,
          ThresholdCurve(
              kDisablingBandwidthLow - 1, kEnablingRecoverablePacketLossAtLowBw,
              kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw),
          ThresholdCurve(kDisablingBandwidthLow,
                         kDisablingRecoverablePacketLossAtLowBw,
                         kDisablingBandwidthHigh,
                         kDisablingRecoverablePacketLossAtHighBw))),
      "Check failed");
}
#endif
}  // namespace webrtc
