/*
 *  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 "modules/audio_processing/aec3/render_delay_buffer.h"

#include <cstddef>
#include <memory>
#include <string>

#include "api/audio/echo_canceller3_config.h"
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/aec3/block.h"
#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

std::string ProduceDebugText(int sample_rate_hz) {
  StringBuilder ss;
  ss << "Sample rate: " << sample_rate_hz;
  return ss.Release();
}

}  // namespace

// Verifies that the buffer overflow is correctly reported.
TEST(RenderDelayBuffer, BufferOverflow) {
  const EchoCanceller3Config config;
  for (auto num_channels : {1, 2, 8}) {
    for (auto rate : {16000, 32000, 48000}) {
      SCOPED_TRACE(ProduceDebugText(rate));
      std::unique_ptr<RenderDelayBuffer> delay_buffer(
          RenderDelayBuffer::Create(config, rate, num_channels));
      Block block_to_insert(NumBandsForRate(rate), num_channels);
      for (size_t k = 0; k < 10; ++k) {
        EXPECT_EQ(RenderDelayBuffer::BufferingEvent::kNone,
                  delay_buffer->Insert(block_to_insert));
      }
      bool overrun_occurred = false;
      for (size_t k = 0; k < 1000; ++k) {
        RenderDelayBuffer::BufferingEvent event =
            delay_buffer->Insert(block_to_insert);
        overrun_occurred =
            overrun_occurred ||
            RenderDelayBuffer::BufferingEvent::kRenderOverrun == event;
      }

      EXPECT_TRUE(overrun_occurred);
    }
  }
}

// Verifies that the check for available block works.
TEST(RenderDelayBuffer, AvailableBlock) {
  constexpr size_t kNumChannels = 1;
  constexpr int kSampleRateHz = 48000;
  constexpr size_t kNumBands = NumBandsForRate(kSampleRateHz);
  std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create(
      EchoCanceller3Config(), kSampleRateHz, kNumChannels));
  Block input_block(kNumBands, kNumChannels, 1.0f);
  EXPECT_EQ(RenderDelayBuffer::BufferingEvent::kNone,
            delay_buffer->Insert(input_block));
  delay_buffer->PrepareCaptureProcessing();
}

// Verifies the AlignFromDelay method.
TEST(RenderDelayBuffer, AlignFromDelay) {
  EchoCanceller3Config config;
  std::unique_ptr<RenderDelayBuffer> delay_buffer(
      RenderDelayBuffer::Create(config, 16000, 1));
  ASSERT_TRUE(delay_buffer->Delay());
  delay_buffer->Reset();
  size_t initial_internal_delay = 0;
  for (size_t delay = initial_internal_delay;
       delay < initial_internal_delay + 20; ++delay) {
    ASSERT_TRUE(delay_buffer->AlignFromDelay(delay));
    EXPECT_EQ(delay, delay_buffer->Delay());
  }
}

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)

// Verifies the check for feasible delay.
// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
// tests on test bots has been fixed.
TEST(RenderDelayBufferDeathTest, DISABLED_WrongDelay) {
  std::unique_ptr<RenderDelayBuffer> delay_buffer(
      RenderDelayBuffer::Create(EchoCanceller3Config(), 48000, 1));
  EXPECT_DEATH(delay_buffer->AlignFromDelay(21), "");
}

// Verifies the check for the number of bands in the inserted blocks.
TEST(RenderDelayBufferDeathTest, WrongNumberOfBands) {
  for (auto rate : {16000, 32000, 48000}) {
    for (size_t num_channels : {1, 2, 8}) {
      SCOPED_TRACE(ProduceDebugText(rate));
      std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create(
          EchoCanceller3Config(), rate, num_channels));
      Block block_to_insert(
          NumBandsForRate(rate < 48000 ? rate + 16000 : 16000), num_channels);
      EXPECT_DEATH(delay_buffer->Insert(block_to_insert), "");
    }
  }
}

// Verifies the check for the number of channels in the inserted blocks.
TEST(RenderDelayBufferDeathTest, WrongNumberOfChannels) {
  for (auto rate : {16000, 32000, 48000}) {
    for (size_t num_channels : {1, 2, 8}) {
      SCOPED_TRACE(ProduceDebugText(rate));
      std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create(
          EchoCanceller3Config(), rate, num_channels));
      Block block_to_insert(NumBandsForRate(rate), num_channels + 1);
      EXPECT_DEATH(delay_buffer->Insert(block_to_insert), "");
    }
  }
}

#endif

}  // namespace webrtc
