// Copyright (c) 2012 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 "base/basictypes.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/filters/fake_demuxer_stream.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

const int kNumBuffersInOneConfig = 9;
const int kNumBuffersToReadFirst = 5;
const int kNumConfigs = 3;
COMPILE_ASSERT(kNumBuffersToReadFirst < kNumBuffersInOneConfig,
               do_not_read_too_many_buffers);
COMPILE_ASSERT(kNumConfigs > 0, need_multiple_configs_to_trigger_config_change);

class FakeDemuxerStreamTest : public testing::Test {
 public:
  FakeDemuxerStreamTest()
      : status_(DemuxerStream::kAborted),
        read_pending_(false),
        num_buffers_received_(0) {}
  virtual ~FakeDemuxerStreamTest() {}

  void BufferReady(DemuxerStream::Status status,
                   const scoped_refptr<DecoderBuffer>& buffer) {
    DCHECK(read_pending_);
    read_pending_ = false;
    status_ = status;
    buffer_ = buffer;
    if (status == DemuxerStream::kOk && !buffer->end_of_stream())
      num_buffers_received_++;
  }

  enum ReadResult {
    OK,
    ABORTED,
    CONFIG_CHANGED,
    EOS,
    PENDING
  };

  void EnterNormalReadState() {
    stream_.reset(
        new FakeDemuxerStream(kNumConfigs, kNumBuffersInOneConfig, false));
    for (int i = 0; i < kNumBuffersToReadFirst; ++i)
      ReadAndExpect(OK);
    DCHECK_EQ(kNumBuffersToReadFirst, num_buffers_received_);
  }

  void EnterBeforeEOSState() {
    stream_.reset(new FakeDemuxerStream(1, kNumBuffersInOneConfig, false));
    for (int i = 0; i < kNumBuffersInOneConfig; ++i)
      ReadAndExpect(OK);
    DCHECK_EQ(kNumBuffersInOneConfig, num_buffers_received_);
  }

  void ExpectReadResult(ReadResult result) {
    switch (result) {
      case OK:
        EXPECT_FALSE(read_pending_);
        EXPECT_EQ(DemuxerStream::kOk, status_);
        ASSERT_TRUE(buffer_.get());
        EXPECT_FALSE(buffer_->end_of_stream());
        break;

      case ABORTED:
        EXPECT_FALSE(read_pending_);
        EXPECT_EQ(DemuxerStream::kAborted, status_);
        EXPECT_FALSE(buffer_.get());
        break;

      case CONFIG_CHANGED:
        EXPECT_TRUE(stream_->SupportsConfigChanges());
        EXPECT_FALSE(read_pending_);
        EXPECT_EQ(DemuxerStream::kConfigChanged, status_);
        EXPECT_FALSE(buffer_.get());
        break;

      case EOS:
        EXPECT_FALSE(read_pending_);
        EXPECT_EQ(DemuxerStream::kOk, status_);
        ASSERT_TRUE(buffer_.get());
        EXPECT_TRUE(buffer_->end_of_stream());
        break;

      case PENDING:
        EXPECT_TRUE(read_pending_);
        break;
    }
  }

  void ReadAndExpect(ReadResult result) {
    EXPECT_FALSE(read_pending_);
    read_pending_ = true;
    stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady,
                             base::Unretained(this)));
    message_loop_.RunUntilIdle();
    ExpectReadResult(result);
  }

  void ReadUntilPending() {
    while (1) {
      read_pending_ = true;
      stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady,
                               base::Unretained(this)));
      message_loop_.RunUntilIdle();
      if (read_pending_)
        break;
    }
  }

  void SatisfyReadAndExpect(ReadResult result) {
    EXPECT_TRUE(read_pending_);
    stream_->SatisfyRead();
    message_loop_.RunUntilIdle();
    ExpectReadResult(result);
  }

  void Reset() {
    bool had_read_pending = read_pending_;
    stream_->Reset();
    message_loop_.RunUntilIdle();

    EXPECT_FALSE(read_pending_);
    if (had_read_pending)
      ExpectReadResult(ABORTED);
  }

  void ReadAllBuffers(int num_configs, int num_buffers_in_one_config) {
    DCHECK_EQ(0, num_buffers_received_);
    for (int i = 0; i < num_configs; ++i) {
      for (int j = 0; j < num_buffers_in_one_config; ++j) {
        ReadAndExpect(OK);
        EXPECT_EQ(num_buffers_received_, stream_->num_buffers_returned());
      }

      if (i == num_configs - 1)
        ReadAndExpect(EOS);
      else
        ReadAndExpect(CONFIG_CHANGED);
    }

    // Will always get EOS after we hit EOS.
    ReadAndExpect(EOS);

    EXPECT_EQ(num_configs * num_buffers_in_one_config, num_buffers_received_);
  }

  void TestRead(int num_configs,
                int num_buffers_in_one_config,
                bool is_encrypted) {
    stream_.reset(new FakeDemuxerStream(
        num_configs, num_buffers_in_one_config, is_encrypted));

    const VideoDecoderConfig& config = stream_->video_decoder_config();
    EXPECT_TRUE(config.IsValidConfig());
    EXPECT_EQ(is_encrypted, config.is_encrypted());

    ReadAllBuffers(num_configs, num_buffers_in_one_config);
  }

  base::MessageLoop message_loop_;
  scoped_ptr<FakeDemuxerStream> stream_;

  DemuxerStream::Status status_;
  scoped_refptr<DecoderBuffer> buffer_;
  bool read_pending_;
  int num_buffers_received_;

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeDemuxerStreamTest);
};

TEST_F(FakeDemuxerStreamTest, Read_OneConfig) {
  TestRead(1, 5, false);
}

TEST_F(FakeDemuxerStreamTest, Read_MultipleConfigs) {
  TestRead(3, 5, false);
}

TEST_F(FakeDemuxerStreamTest, Read_OneBufferPerConfig) {
  TestRead(3, 1, false);
}

TEST_F(FakeDemuxerStreamTest, Read_Encrypted) {
  TestRead(6, 3, true);
}

TEST_F(FakeDemuxerStreamTest, HoldRead_Normal) {
  EnterNormalReadState();
  stream_->HoldNextRead();
  ReadAndExpect(PENDING);
  SatisfyReadAndExpect(OK);
}

TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeConfigChanged) {
  EnterNormalReadState();
  stream_->HoldNextConfigChangeRead();
  ReadUntilPending();
  SatisfyReadAndExpect(CONFIG_CHANGED);
}

TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeEOS) {
  EnterBeforeEOSState();
  stream_->HoldNextRead();
  ReadAndExpect(PENDING);
  SatisfyReadAndExpect(EOS);
}

TEST_F(FakeDemuxerStreamTest, Reset_Normal) {
  EnterNormalReadState();
  Reset();
  ReadAndExpect(OK);
}

TEST_F(FakeDemuxerStreamTest, Reset_AfterHoldRead) {
  EnterNormalReadState();
  stream_->HoldNextRead();
  Reset();
  ReadAndExpect(OK);
}

TEST_F(FakeDemuxerStreamTest, Reset_DuringPendingRead) {
  EnterNormalReadState();
  stream_->HoldNextRead();
  ReadAndExpect(PENDING);
  Reset();
  ReadAndExpect(OK);
}

TEST_F(FakeDemuxerStreamTest, Reset_BeforeConfigChanged) {
  EnterNormalReadState();
  stream_->HoldNextConfigChangeRead();
  ReadUntilPending();
  Reset();
  ReadAndExpect(CONFIG_CHANGED);
}

TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) {
  EnterBeforeEOSState();
  stream_->HoldNextRead();
  ReadAndExpect(PENDING);
  Reset();
  ReadAndExpect(EOS);
}

TEST_F(FakeDemuxerStreamTest, NoConfigChanges) {
  stream_.reset(
      new FakeDemuxerStream(1, kNumBuffersInOneConfig, false));
  EXPECT_FALSE(stream_->SupportsConfigChanges());
  for (int i = 0; i < kNumBuffersInOneConfig; ++i)
    ReadAndExpect(OK);
  ReadAndExpect(EOS);
}

TEST_F(FakeDemuxerStreamTest, SeekToStart_Normal) {
  EnterNormalReadState();
  stream_->SeekToStart();
  num_buffers_received_ = 0;
  ReadAllBuffers(kNumConfigs, kNumBuffersInOneConfig);
}

TEST_F(FakeDemuxerStreamTest, SeekToStart_BeforeEOS) {
  EnterBeforeEOSState();
  stream_->SeekToStart();
  num_buffers_received_ = 0;
  ReadAllBuffers(1, kNumBuffersInOneConfig);
}

TEST_F(FakeDemuxerStreamTest, SeekToStart_AfterEOS) {
  TestRead(3, 5, false);
  stream_->SeekToStart();
  num_buffers_received_ = 0;
  ReadAllBuffers(3, 5);
}

}  // namespace media
