// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromecast/media/audio/cast_audio_output_stream.h"

#include <stdint.h>

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "chromecast/common/mojom/constants.mojom.h"
#include "chromecast/common/mojom/multiroom.mojom.h"
#include "chromecast/media/audio/cast_audio_manager.h"
#include "chromecast/media/audio/cast_audio_mixer.h"
#include "chromecast/media/cma/backend/cma_backend.h"
#include "chromecast/media/cma/base/decoder_buffer_base.h"
#include "chromecast/media/cma/test/mock_cma_backend_factory.h"
#include "chromecast/media/cma/test/mock_multiroom_manager.h"
#include "chromecast/public/task_runner.h"
#include "chromecast/public/volume_control.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/mock_audio_source_callback.h"
#include "media/audio/test_audio_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;
using testing::Invoke;
using testing::NiceMock;

namespace {

std::unique_ptr<service_manager::Connector> CreateConnector() {
  service_manager::mojom::ConnectorRequest request;
  return service_manager::Connector::Create(&request);
}

std::string DummyGetSessionId(std::string /* audio_group_id */) {
  return "AABBCCDDEE";
}

}  // namespace

namespace chromecast {
namespace media {
namespace {
const char kDefaultDeviceId[] = "";
const int64_t kDelayUs = 123;
const int64_t kDelayTimestampUs = 123456789;
const double kDefaultVolume = 1.0f;

int on_more_data_call_count_ = 0;
int OnMoreData(base::TimeDelta /* delay */,
               base::TimeTicks /* delay_timestamp */,
               int /* prior_frames_skipped */,
               ::media::AudioBus* dest) {
  on_more_data_call_count_++;
  dest->Zero();
  return dest->frames();
}

}  // namespace

class NotifyPushBufferCompleteTask : public chromecast::TaskRunner::Task {
 public:
  explicit NotifyPushBufferCompleteTask(CmaBackend::Decoder::Delegate* delegate)
      : delegate_(delegate) {}
  ~NotifyPushBufferCompleteTask() override = default;
  void Run() override {
    delegate_->OnPushBufferComplete(CmaBackend::BufferStatus::kBufferSuccess);
  }

 private:
  CmaBackend::Decoder::Delegate* const delegate_;
};

class FakeAudioDecoder : public CmaBackend::AudioDecoder {
 public:
  enum PipelineStatus {
    PIPELINE_STATUS_OK,
    PIPELINE_STATUS_BUSY,
    PIPELINE_STATUS_ERROR,
    PIPELINE_STATUS_ASYNC_ERROR,
  };

  explicit FakeAudioDecoder(const MediaPipelineDeviceParams& params)
      : params_(params),
        volume_(kDefaultVolume),
        pipeline_status_(PIPELINE_STATUS_OK),
        pending_push_(false),
        pushed_buffer_count_(0),
        delegate_(nullptr) {}
  ~FakeAudioDecoder() override {}

  // CmaBackend::AudioDecoder implementation:
  void SetDelegate(Delegate* delegate) override {
    DCHECK(delegate);
    delegate_ = delegate;
  }
  BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override {
    last_buffer_ = std::move(buffer);
    ++pushed_buffer_count_;

    switch (pipeline_status_) {
      case PIPELINE_STATUS_OK:
        return CmaBackend::BufferStatus::kBufferSuccess;
      case PIPELINE_STATUS_BUSY:
        pending_push_ = true;
        return CmaBackend::BufferStatus::kBufferPending;
      case PIPELINE_STATUS_ERROR:
        return CmaBackend::BufferStatus::kBufferFailed;
      case PIPELINE_STATUS_ASYNC_ERROR:
        delegate_->OnDecoderError();
        return CmaBackend::BufferStatus::kBufferSuccess;
      default:
        NOTREACHED();
        return CmaBackend::BufferStatus::kBufferFailed;
    }
  }
  void GetStatistics(Statistics* statistics) override {}
  bool SetConfig(const AudioConfig& config) override {
    config_ = config;
    return true;
  }
  bool SetVolume(float volume) override {
    volume_ = volume;
    return true;
  }
  RenderingDelay GetRenderingDelay() override { return rendering_delay_; }
  bool RequiresDecryption() override { return false; }

  const AudioConfig& config() const { return config_; }
  float volume() const { return volume_; }
  void set_pipeline_status(PipelineStatus status) {
    if (status == PIPELINE_STATUS_OK && pending_push_) {
      pending_push_ = false;
      params_.task_runner->PostTask(new NotifyPushBufferCompleteTask(delegate_),
                                    0);
    }
    pipeline_status_ = status;
  }
  void set_rendering_delay(RenderingDelay rendering_delay) {
    rendering_delay_ = rendering_delay;
  }
  unsigned pushed_buffer_count() const { return pushed_buffer_count_; }
  const DecoderBufferBase* last_buffer() { return last_buffer_.get(); }

 private:
  const MediaPipelineDeviceParams params_;
  AudioConfig config_;
  float volume_;

  PipelineStatus pipeline_status_;
  bool pending_push_;
  int pushed_buffer_count_;
  scoped_refptr<DecoderBufferBase> last_buffer_;
  Delegate* delegate_;
  RenderingDelay rendering_delay_;
};

class FakeCmaBackend : public CmaBackend {
 public:
  enum State { kStateStopped, kStateRunning, kStatePaused };

  explicit FakeCmaBackend(const MediaPipelineDeviceParams& params)
      : params_(params), state_(kStateStopped), audio_decoder_(nullptr) {}
  ~FakeCmaBackend() override {}

  // CmaBackend implementation:
  AudioDecoder* CreateAudioDecoder() override {
    DCHECK(!audio_decoder_);
    audio_decoder_ = std::make_unique<FakeAudioDecoder>(params_);
    return audio_decoder_.get();
  }
  VideoDecoder* CreateVideoDecoder() override {
    NOTREACHED();
    return nullptr;
  }

  bool Initialize() override { return true; }
  bool Start(int64_t start_pts) override {
    EXPECT_EQ(kStateStopped, state_);
    state_ = kStateRunning;
    return true;
  }
  void Stop() override {
    EXPECT_TRUE(state_ == kStateRunning || state_ == kStatePaused);
    state_ = kStateStopped;
  }
  bool Pause() override {
    EXPECT_EQ(kStateRunning, state_);
    state_ = kStatePaused;
    return true;
  }
  bool Resume() override {
    EXPECT_EQ(kStatePaused, state_);
    state_ = kStateRunning;
    return true;
  }
  int64_t GetCurrentPts() override { return 0; }
  bool SetPlaybackRate(float rate) override { return true; }

  void LogicalPause() override {}
  void LogicalResume() override {}

  MediaPipelineDeviceParams params() const { return params_; }
  State state() const { return state_; }
  FakeAudioDecoder* audio_decoder() const { return audio_decoder_.get(); }

 private:
  const MediaPipelineDeviceParams params_;
  State state_;
  std::unique_ptr<FakeAudioDecoder> audio_decoder_;
};

class CastAudioOutputStreamTest : public ::testing::Test {
 public:
  CastAudioOutputStreamTest()
      : audio_thread_("CastAudioThread"),
        scoped_task_environment_(
            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
        format_(::media::AudioParameters::AUDIO_PCM_LINEAR),
        channel_layout_(::media::CHANNEL_LAYOUT_MONO),
        sample_rate_(::media::AudioParameters::kAudioCDSampleRate),
        frames_per_buffer_(256) {}

  void SetUp() override {
    CreateAudioManagerForTesting();
    SetUpCmaBackendFactory();
  }

  void TearDown() override {
    RunThreadsUntilIdle();
    audio_manager_->Shutdown();
    audio_thread_.Stop();
  }

  // Binds |multiroom_manager_| to the interface requested through the test
  // connector.
  void BindMultiroomManager(mojo::ScopedMessagePipeHandle handle) {
    multiroom_manager_.Bind(std::move(handle));
  }

 protected:
  CmaBackendFactory* GetCmaBackendFactory() {
    return mock_backend_factory_.get();
  }

  void CreateConnectorForTesting() {
    connector_ = CreateConnector();
    // Override the MultiroomManager interface for testing.
    connector_->OverrideBinderForTesting(
        service_manager::ServiceFilter::ByName(
            chromecast::mojom::kChromecastServiceName),
        mojom::MultiroomManager::Name_,
        base::BindRepeating(&CastAudioOutputStreamTest::BindMultiroomManager,
                            base::Unretained(this)));
  }

  void CreateAudioManagerForTesting(bool use_mixer = false) {
    if (!connector_)
      CreateConnectorForTesting();

    // Only one AudioManager may exist at a time, so destroy the one we're
    // currently holding before creating a new one.
    // Flush the message loop to run any shutdown tasks posted by AudioManager.
    if (audio_manager_) {
      audio_manager_->Shutdown();
      audio_manager_.reset();
    }

    if (audio_thread_.IsRunning())
      audio_thread_.Stop();
    CHECK(audio_thread_.StartAndWaitForTesting());
    mock_backend_factory_ = std::make_unique<MockCmaBackendFactory>();
    audio_manager_ = base::WrapUnique(new CastAudioManager(
        std::make_unique<::media::TestAudioThread>(), nullptr,
        base::BindRepeating(&CastAudioOutputStreamTest::GetCmaBackendFactory,
                            base::Unretained(this)),
        base::BindRepeating(&DummyGetSessionId),
        scoped_task_environment_.GetMainThreadTaskRunner(),
        audio_thread_.task_runner(), connector_.get(), use_mixer,
        true /* force_use_cma_backend_for_output*/));
    audio_manager_->SetConnectorForTesting(std::move(connector_));

    // A few AudioManager implementations post initialization tasks to
    // audio thread. Flush the thread to ensure that |audio_manager_| is
    // initialized and ready to use before returning from this function.
    // TODO(alokp): We should perhaps do this in AudioManager::Create().
    RunThreadsUntilIdle();
  }

  void SetUpCmaBackendFactory() {
    EXPECT_CALL(*mock_backend_factory_, CreateBackend(_))
        .WillRepeatedly(Invoke([this](const MediaPipelineDeviceParams& params) {
          auto fake_cma_backend = std::make_unique<FakeCmaBackend>(params);
          cma_backend_ = fake_cma_backend.get();
          return fake_cma_backend;
        }));
    EXPECT_EQ(mock_backend_factory_.get(),
              audio_manager_->cma_backend_factory());
  }

  void RunThreadsUntilIdle() {
    scoped_task_environment_.RunUntilIdle();
    audio_thread_.FlushForTesting();
  }

  ::media::AudioParameters GetAudioParams() {
    return ::media::AudioParameters(format_, channel_layout_, sample_rate_,
                                    frames_per_buffer_);
  }

  FakeAudioDecoder* GetAudioDecoder() {
    return (cma_backend_ ? cma_backend_->audio_decoder() : nullptr);
  }

  ::media::AudioOutputStream* CreateStream() {
    return audio_manager_->MakeAudioOutputStream(
        GetAudioParams(), kDefaultDeviceId,
        ::media::AudioManager::LogCallback());
  }

  base::Thread audio_thread_;
  base::test::ScopedTaskEnvironment scoped_task_environment_;
  std::unique_ptr<MockCmaBackendFactory> mock_backend_factory_;

  FakeCmaBackend* cma_backend_ = nullptr;
  std::unique_ptr<CastAudioManager> audio_manager_;
  std::unique_ptr<service_manager::Connector> connector_;
  MockMultiroomManager multiroom_manager_;

  // AudioParameters used to create AudioOutputStream.
  // Tests can modify these parameters before calling CreateStream.
  ::media::AudioParameters::Format format_;
  ::media::ChannelLayout channel_layout_;
  int sample_rate_;
  int frames_per_buffer_;
};

TEST_F(CastAudioOutputStreamTest, CloseWithoutStart) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, CloseWithoutStop) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, CloseCancelsOpen) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  stream->Close();
  RunThreadsUntilIdle();
  EXPECT_FALSE(cma_backend_);
}

TEST_F(CastAudioOutputStreamTest, CloseCancelsStart) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);

  stream->Close();
  RunThreadsUntilIdle();
  EXPECT_FALSE(cma_backend_);
}

TEST_F(CastAudioOutputStreamTest, CloseCancelsStop) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  stream->Stop();

  stream->Close();
  RunThreadsUntilIdle();
  EXPECT_FALSE(cma_backend_);
}

TEST_F(CastAudioOutputStreamTest, StartImmediatelyAfterOpen) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  EXPECT_EQ(FakeCmaBackend::kStateRunning, cma_backend_->state());

  stream->Stop();
  RunThreadsUntilIdle();
  stream->Close();
  RunThreadsUntilIdle();
}

TEST_F(CastAudioOutputStreamTest, SetVolumeImmediatelyAfterOpen) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  stream->SetVolume(0.5);

  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  double volume = 0.0;
  stream->GetVolume(&volume);
  EXPECT_EQ(0.5, volume);
  EXPECT_EQ(0.5f, audio_decoder->volume());

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, StopCancelsStart) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  stream->Stop();
  RunThreadsUntilIdle();
  EXPECT_EQ(FakeCmaBackend::kStateStopped, cma_backend_->state());

  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, StopDoesNotCancelSetVolume) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());

  stream->SetVolume(0.5);
  stream->Stop();
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  double volume = 0.0;
  stream->GetVolume(&volume);
  EXPECT_EQ(0.5, volume);
  EXPECT_EQ(0.5, audio_decoder->volume());

  stream->Stop();
  LOG(INFO) << "Closing Stream";
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, StartStopStart) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  // Set to busy, so that the OnPushBufferComplete callback is not called after
  // the backend is stopped.
  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_BUSY);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  stream->Stop();

  // Ensure we fetch new data when restarting.
  int last_on_more_data_call_count = on_more_data_call_count_;
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  EXPECT_GT(on_more_data_call_count_, last_on_more_data_call_count);

  EXPECT_EQ(FakeCmaBackend::kStateRunning, cma_backend_->state());

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, StopPreventsCallbacks) {
  // Stream API details that Stop is synchronous and prevents calls to callback.
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  // Set to busy, so that the OnPushBufferComplete callback is not called after
  // the backend is stopped.
  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  stream->SetVolume(0.5);
  stream->Stop();
  // TODO(steinbock) Make this fail more reliably when stream->Stop() returns
  // asynchronously.
  stream->Close();
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _)).Times(0);
  RunThreadsUntilIdle();
}

TEST_F(CastAudioOutputStreamTest, Format) {
  ::media::AudioParameters::Format format[] = {
      ::media::AudioParameters::AUDIO_PCM_LINEAR,
      ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY};
  for (size_t i = 0; i < base::size(format); ++i) {
    format_ = format[i];
    ::media::AudioOutputStream* stream = CreateStream();
    ASSERT_TRUE(stream);
    EXPECT_TRUE(stream->Open());
    RunThreadsUntilIdle();

    FakeAudioDecoder* audio_decoder = GetAudioDecoder();
    ASSERT_TRUE(audio_decoder);
    const AudioConfig& audio_config = audio_decoder->config();
    EXPECT_EQ(kCodecPCM, audio_config.codec);
    EXPECT_EQ(kSampleFormatS16, audio_config.sample_format);
    EXPECT_EQ(audio_config.encryption_scheme, EncryptionScheme::kUnencrypted);

    stream->Close();
  }
}

TEST_F(CastAudioOutputStreamTest, ChannelLayout) {
  ::media::ChannelLayout layout[] = {::media::CHANNEL_LAYOUT_MONO,
                                     ::media::CHANNEL_LAYOUT_STEREO};
  for (size_t i = 0; i < base::size(layout); ++i) {
    channel_layout_ = layout[i];
    ::media::AudioOutputStream* stream = CreateStream();
    ASSERT_TRUE(stream);
    EXPECT_TRUE(stream->Open());
    RunThreadsUntilIdle();

    FakeAudioDecoder* audio_decoder = GetAudioDecoder();
    ASSERT_TRUE(audio_decoder);
    const AudioConfig& audio_config = audio_decoder->config();
    EXPECT_EQ(::media::ChannelLayoutToChannelCount(channel_layout_),
              audio_config.channel_number);

    stream->Close();
  }
}

TEST_F(CastAudioOutputStreamTest, SampleRate) {
  sample_rate_ = ::media::AudioParameters::kAudioCDSampleRate;
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  const AudioConfig& audio_config = audio_decoder->config();
  EXPECT_EQ(sample_rate_, audio_config.samples_per_second);
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, DeviceState) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);

  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  ASSERT_TRUE(cma_backend_);
  EXPECT_EQ(FakeCmaBackend::kStateStopped, cma_backend_->state());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  EXPECT_EQ(FakeCmaBackend::kStateRunning, cma_backend_->state());

  stream->Stop();
  RunThreadsUntilIdle();
  EXPECT_EQ(FakeCmaBackend::kStateStopped, cma_backend_->state());

  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, PushFrame) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  // Verify initial state.
  EXPECT_EQ(0u, audio_decoder->pushed_buffer_count());
  EXPECT_FALSE(audio_decoder->last_buffer());

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // No error must be reported to source callback.
  EXPECT_CALL(source_callback, OnError()).Times(0);
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  stream->Stop();

  // Verify that the stream pushed frames to the backend.
  EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
  EXPECT_TRUE(audio_decoder->last_buffer());

  // Verify decoder buffer.
  ::media::AudioParameters audio_params = GetAudioParams();
  const size_t expected_frame_size =
      audio_params.GetBytesPerBuffer(::media::kSampleFormatS16);
  const DecoderBufferBase* buffer = audio_decoder->last_buffer();
  EXPECT_TRUE(buffer->data());
  EXPECT_EQ(expected_frame_size, buffer->data_size());
  EXPECT_FALSE(buffer->decrypt_config());  // Null because of raw audio.
  EXPECT_FALSE(buffer->end_of_stream());

  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, PushFrameAfterStop) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // No error must be reported to source callback.
  EXPECT_CALL(source_callback, OnError()).Times(0);
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  // Verify that the stream pushed frames to the backend.
  EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
  EXPECT_TRUE(audio_decoder->last_buffer());

  stream->Stop();

  ASSERT_TRUE(cma_backend_);
  base::TimeDelta duration = GetAudioParams().GetBufferDuration() * 2;
  scoped_task_environment_.FastForwardBy(duration);
  RunThreadsUntilIdle();

  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, PushFrameAfterClose) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // No error must be reported to source callback.
  EXPECT_CALL(source_callback, OnError()).Times(0);
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  // Verify that the stream pushed frames to the backend.
  EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
  EXPECT_TRUE(audio_decoder->last_buffer());

  stream->Close();

  ASSERT_TRUE(cma_backend_);
  base::TimeDelta duration = GetAudioParams().GetBufferDuration() * 2;
  scoped_task_environment_.FastForwardBy(duration);
  RunThreadsUntilIdle();
}

// TODO(steinbock) fix test on server and reenable.
TEST_F(CastAudioOutputStreamTest, DISABLED_DeviceBusy) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_BUSY);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // No error must be reported to source callback.
  EXPECT_CALL(source_callback, OnError()).Times(0);
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  // Make sure that one frame was pushed.
  EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());

  // Sleep for a few frames and verify that more frames were not pushed
  // because the backend device was busy.
  RunThreadsUntilIdle();
  EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());

  // Unblock the pipeline and verify that PushFrame resumes.
  audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_OK);

  RunThreadsUntilIdle();
  stream->Stop();
  stream->Close();
  RunThreadsUntilIdle();
  EXPECT_LT(1u, audio_decoder->pushed_buffer_count());
}

TEST_F(CastAudioOutputStreamTest, DeviceError) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_ERROR);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // AudioOutputStream must report error to source callback.
  EXPECT_CALL(source_callback, OnError());
  stream->Start(&source_callback);
  RunThreadsUntilIdle();
  // Make sure that AudioOutputStream attempted to push the initial frame.
  EXPECT_LT(0u, audio_decoder->pushed_buffer_count());

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  audio_decoder->set_pipeline_status(
      FakeAudioDecoder::PIPELINE_STATUS_ASYNC_ERROR);

  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  // AudioOutputStream must report error to source callback.
  EXPECT_CALL(source_callback, OnError()).Times(testing::AtLeast(1));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  // Make sure that one frame was pushed.
  EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, Volume) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  EXPECT_TRUE(stream->Open());
  RunThreadsUntilIdle();
  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);

  double volume = 0.0;
  stream->GetVolume(&volume);
  EXPECT_EQ(1.0, volume);
  EXPECT_EQ(1.0f, audio_decoder->volume());

  stream->SetVolume(0.5);
  RunThreadsUntilIdle();
  stream->GetVolume(&volume);
  EXPECT_EQ(0.5, volume);
  EXPECT_EQ(0.5f, audio_decoder->volume());
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, AudioDelay) {
  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  FakeAudioDecoder* audio_decoder = GetAudioDecoder();
  ASSERT_TRUE(audio_decoder);
  audio_decoder->set_rendering_delay(
      CmaBackend::AudioDecoder::RenderingDelay(kDelayUs, kDelayTimestampUs));

  ::media::MockAudioSourceCallback source_callback;
  const base::TimeDelta delay(base::TimeDelta::FromMicroseconds(kDelayUs));
  const base::TimeTicks delay_timestamp(
      base::TimeTicks() + base::TimeDelta::FromMicroseconds(kDelayTimestampUs));
  EXPECT_CALL(source_callback, OnMoreData(delay, delay_timestamp, _, _))
      .WillRepeatedly(Invoke(OnMoreData));

  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, MultiroomInfo) {
  chromecast::mojom::MultiroomInfo info(true, AudioChannel::kAll,
                                        base::TimeDelta::FromSeconds(3));
  multiroom_manager_.SetMultiroomInfo(info);

  ::media::AudioOutputStream* stream = CreateStream();
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  // We will start/stop the stream, because as a test, we do not care about
  // whether the info was fetched during Open() or Start() so we test across
  // both.
  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  ASSERT_TRUE(cma_backend_);
  MediaPipelineDeviceParams params = cma_backend_->params();
  EXPECT_EQ(params.multiroom, true);
  EXPECT_EQ(params.audio_channel, AudioChannel::kAll);
  EXPECT_EQ(params.output_delay_us,
            base::TimeDelta::FromSeconds(3).InMicroseconds());

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, SessionId) {
  format_ = ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
  ::media::AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
      GetAudioParams(), "DummyGroupId", ::media::AudioManager::LogCallback());
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  // We will start/stop the stream, because as a test, we do not care about
  // whether the info was fetched during Open() or Start() so we test across
  // both.
  ::media::MockAudioSourceCallback source_callback;
  EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
      .WillRepeatedly(Invoke(OnMoreData));
  stream->Start(&source_callback);
  RunThreadsUntilIdle();

  // TODO(awolter, b/111669896): Verify that the session id is correct after
  // piping has been added. For now, we want to verify that the session id is
  // empty, so that basic MZ continues to work.
  std::string session_id = DummyGetSessionId("");
  ASSERT_TRUE(cma_backend_);
  EXPECT_EQ(multiroom_manager_.GetLastSessionId(), session_id);
  MediaPipelineDeviceParams params = cma_backend_->params();
  EXPECT_EQ(params.session_id, session_id);

  stream->Stop();
  stream->Close();
}

TEST_F(CastAudioOutputStreamTest, CommunicationsDeviceId) {
  format_ = ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
  ::media::AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
      GetAudioParams(),
      ::media::AudioDeviceDescription::kCommunicationsDeviceId,
      ::media::AudioManager::LogCallback());
  ASSERT_TRUE(stream);
  ASSERT_TRUE(stream->Open());
  RunThreadsUntilIdle();

  ASSERT_TRUE(cma_backend_);
  MediaPipelineDeviceParams params = cma_backend_->params();
  EXPECT_EQ(params.content_type, AudioContentType::kCommunication);
  EXPECT_EQ(params.device_id,
            ::media::AudioDeviceDescription::kCommunicationsDeviceId);

  stream->Stop();
  stream->Close();
}

}  // namespace media
}  // namespace chromecast
