// Copyright (c) 2011 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 "content/browser/media/media_internals.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
const int kTestComponentID = 0;
const char kTestInputDeviceID[] = "test-input-id";
const char kTestOutputDeviceID[] = "test-output-id";
}  // namespace

namespace content {

class MediaInternalsTest
    : public testing::TestWithParam<media::AudioLogFactory::AudioComponent> {
 public:
  MediaInternalsTest()
      : media_internals_(MediaInternals::GetInstance()),
        update_cb_(base::Bind(&MediaInternalsTest::UpdateCallbackImpl,
                              base::Unretained(this))),
        test_params_(media::AudioParameters::AUDIO_PCM_LINEAR,
                     media::CHANNEL_LAYOUT_MONO,
                     48000,
                     16,
                     128),
        test_component_(GetParam()),
        audio_log_(media_internals_->CreateAudioLog(test_component_)) {
    media_internals_->AddUpdateCallback(update_cb_);
  }

  virtual ~MediaInternalsTest() {
    media_internals_->RemoveUpdateCallback(update_cb_);
  }

 protected:
  // Extracts and deserializes the JSON update data; merges into |update_data_|.
  void UpdateCallbackImpl(const base::string16& update) {
    // Each update string looks like "<JavaScript Function Name>({<JSON>});", to
    // use the JSON reader we need to strip out the JavaScript code.
    std::string utf8_update = base::UTF16ToUTF8(update);
    const std::string::size_type first_brace = utf8_update.find('{');
    const std::string::size_type last_brace = utf8_update.rfind('}');
    scoped_ptr<base::Value> output_value(base::JSONReader::Read(
        utf8_update.substr(first_brace, last_brace - first_brace + 1)));
    CHECK(output_value);

    base::DictionaryValue* output_dict = NULL;
    CHECK(output_value->GetAsDictionary(&output_dict));
    update_data_.MergeDictionary(output_dict);
  }

  void ExpectInt(const std::string& key, int expected_value) {
    int actual_value = 0;
    ASSERT_TRUE(update_data_.GetInteger(key, &actual_value));
    EXPECT_EQ(expected_value, actual_value);
  }

  void ExpectString(const std::string& key, const std::string& expected_value) {
    std::string actual_value;
    ASSERT_TRUE(update_data_.GetString(key, &actual_value));
    EXPECT_EQ(expected_value, actual_value);
  }

  void ExpectStatus(const std::string& expected_value) {
    ExpectString("status", expected_value);
  }

  TestBrowserThreadBundle thread_bundle_;
  MediaInternals* const media_internals_;
  MediaInternals::UpdateCallback update_cb_;
  base::DictionaryValue update_data_;
  const media::AudioParameters test_params_;
  const media::AudioLogFactory::AudioComponent test_component_;
  scoped_ptr<media::AudioLog> audio_log_;
};

TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
  audio_log_->OnCreated(
      kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
  base::RunLoop().RunUntilIdle();

  ExpectString("channel_layout",
               media::ChannelLayoutToString(test_params_.channel_layout()));
  ExpectInt("sample_rate", test_params_.sample_rate());
  ExpectInt("frames_per_buffer", test_params_.frames_per_buffer());
  ExpectInt("channels", test_params_.channels());
  ExpectInt("input_channels", test_params_.input_channels());
  ExpectString("output_device_id", kTestOutputDeviceID);
  ExpectString("input_device_id", kTestInputDeviceID);
  ExpectInt("component_id", kTestComponentID);
  ExpectInt("component_type", test_component_);
  ExpectStatus("created");

  // Verify OnStarted().
  audio_log_->OnStarted(kTestComponentID);
  base::RunLoop().RunUntilIdle();
  ExpectStatus("started");

  // Verify OnStopped().
  audio_log_->OnStopped(kTestComponentID);
  base::RunLoop().RunUntilIdle();
  ExpectStatus("stopped");

  // Verify OnError().
  const char kErrorKey[] = "error_occurred";
  std::string no_value;
  ASSERT_FALSE(update_data_.GetString(kErrorKey, &no_value));
  audio_log_->OnError(kTestComponentID);
  base::RunLoop().RunUntilIdle();
  ExpectString(kErrorKey, "true");

  // Verify OnClosed().
  audio_log_->OnClosed(kTestComponentID);
  base::RunLoop().RunUntilIdle();
  ExpectStatus("closed");
}

TEST_P(MediaInternalsTest, AudioLogCreateClose) {
  audio_log_->OnCreated(
      kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
  base::RunLoop().RunUntilIdle();
  ExpectStatus("created");

  audio_log_->OnClosed(kTestComponentID);
  base::RunLoop().RunUntilIdle();
  ExpectStatus("closed");
}

INSTANTIATE_TEST_CASE_P(
    MediaInternalsTest, MediaInternalsTest, testing::Values(
        media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
        media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
        media::AudioLogFactory::AUDIO_OUTPUT_STREAM));

}  // namespace content
