/*
 *  Copyright (c) 2012 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 "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h"
#include "webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h"
#include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/test/testsupport/mock/mock_frame_reader.h"
#include "webrtc/test/testsupport/mock/mock_frame_writer.h"
#include "webrtc/test/testsupport/packet_reader.h"
#include "webrtc/test/testsupport/unittest_utils.h"
#include "webrtc/typedefs.h"

using ::testing::_;
using ::testing::AtLeast;
using ::testing::Return;

namespace webrtc {
namespace test {

// Very basic testing for VideoProcessor. It's mostly tested by running the
// video_quality_measurement program.
class VideoProcessorTest: public testing::Test {
 protected:
  MockVideoEncoder encoder_mock_;
  MockVideoDecoder decoder_mock_;
  MockFrameReader frame_reader_mock_;
  MockFrameWriter frame_writer_mock_;
  MockPacketManipulator packet_manipulator_mock_;
  Stats stats_;
  TestConfig config_;
  VideoCodec codec_settings_;

  VideoProcessorTest() {}
  virtual ~VideoProcessorTest() {}
  void SetUp() {
    // Get a codec configuration struct and configure it.
    VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
    config_.codec_settings = &codec_settings_;
    config_.codec_settings->startBitrate = 100;
    config_.codec_settings->width = 352;
    config_.codec_settings->height = 288;
  }
  void TearDown() {}

  void ExpectInit() {
    EXPECT_CALL(encoder_mock_, InitEncode(_, _, _))
      .Times(1);
    EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback(_))
      .Times(AtLeast(1));
    EXPECT_CALL(decoder_mock_, InitDecode(_, _))
      .Times(1);
    EXPECT_CALL(decoder_mock_, RegisterDecodeCompleteCallback(_))
      .Times(AtLeast(1));
    EXPECT_CALL(frame_reader_mock_, NumberOfFrames())
      .WillOnce(Return(1));
    EXPECT_CALL(frame_reader_mock_, FrameLength())
      .WillOnce(Return(152064));
  }
};

TEST_F(VideoProcessorTest, Init) {
  ExpectInit();
  VideoProcessorImpl video_processor(&encoder_mock_, &decoder_mock_,
                                     &frame_reader_mock_,
                                     &frame_writer_mock_,
                                     &packet_manipulator_mock_, config_,
                                     &stats_);
  ASSERT_TRUE(video_processor.Init());
}

TEST_F(VideoProcessorTest, ProcessFrame) {
  ExpectInit();
  EXPECT_CALL(encoder_mock_, Encode(_, _, _))
    .Times(1);
  EXPECT_CALL(frame_reader_mock_, ReadFrame(_))
    .WillOnce(Return(true));
  // Since we don't return any callback from the mock, the decoder will not
  // be more than initialized...
  VideoProcessorImpl video_processor(&encoder_mock_, &decoder_mock_,
                                     &frame_reader_mock_,
                                     &frame_writer_mock_,
                                     &packet_manipulator_mock_, config_,
                                     &stats_);
  ASSERT_TRUE(video_processor.Init());
  video_processor.ProcessFrame(0);
}

}  // namespace test
}  // namespace webrtc
