/*
 *  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 <memory>
#include <string>
#include <vector>

#include "api/array_view.h"
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/random.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

std::string ProduceDebugText(int sample_rate_hz) {
  rtc::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
