blob: 71a1c0426a49b27dea7ab41b05b16a83276a8fce [file] [log] [blame]
// 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 "base/bind.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_tts_api.h"
#include "chrome/browser/extensions/extension_tts_api_controller.h"
#include "chrome/browser/extensions/extension_tts_api_platform.h"
#include "chrome/common/chrome_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
// Needed for CreateFunctor.
#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
#include "testing/gmock_mutant.h"
using ::testing::AnyNumber;
using ::testing::CreateFunctor;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::StrictMock;
using ::testing::_;
class MockExtensionTtsPlatformImpl : public ExtensionTtsPlatformImpl {
public:
MockExtensionTtsPlatformImpl()
: ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {}
virtual bool PlatformImplAvailable() {
return true;
}
virtual bool SendsEvent(TtsEventType event_type) {
return (event_type == TTS_EVENT_END ||
event_type == TTS_EVENT_WORD);
}
MOCK_METHOD4(Speak,
bool(int utterance_id,
const std::string& utterance,
const std::string& lang,
const UtteranceContinuousParameters& params));
MOCK_METHOD0(StopSpeaking, bool(void));
void SetErrorToEpicFail() {
set_error("epic fail");
}
void SendEndEvent(int utterance_id,
const std::string& utterance,
const std::string& lang,
const UtteranceContinuousParameters& params) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(
&MockExtensionTtsPlatformImpl::SendEvent,
ptr_factory_.GetWeakPtr(),
false, utterance_id, TTS_EVENT_END, utterance.size(),
std::string()),
0);
}
void SendEndEventWhenQueueNotEmpty(
int utterance_id,
const std::string& utterance,
const std::string& lang,
const UtteranceContinuousParameters& params) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(
&MockExtensionTtsPlatformImpl::SendEvent,
ptr_factory_.GetWeakPtr(),
true, utterance_id, TTS_EVENT_END, utterance.size(), std::string()),
0);
}
void SendWordEvents(int utterance_id,
const std::string& utterance,
const std::string& lang,
const UtteranceContinuousParameters& params) {
for (int i = 0; i < static_cast<int>(utterance.size()); i++) {
if (i == 0 || utterance[i - 1] == ' ') {
MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(
&MockExtensionTtsPlatformImpl::SendEvent,
ptr_factory_.GetWeakPtr(),
false, utterance_id, TTS_EVENT_WORD, i,
std::string()),
0);
}
}
}
void SendEvent(bool wait_for_non_empty_queue,
int utterance_id,
TtsEventType event_type,
int char_index,
const std::string& message) {
ExtensionTtsController* controller = ExtensionTtsController::GetInstance();
if (wait_for_non_empty_queue && controller->QueueSize() == 0) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE, base::Bind(
&MockExtensionTtsPlatformImpl::SendEvent,
ptr_factory_.GetWeakPtr(),
true, utterance_id, event_type, char_index, message),
100);
return;
}
controller->OnTtsEvent(utterance_id, event_type, char_index, message);
}
private:
base::WeakPtrFactory<MockExtensionTtsPlatformImpl> ptr_factory_;
};
class TtsApiTest : public ExtensionApiTest {
public:
virtual void SetUpInProcessBrowserTestFixture() {
ExtensionApiTest::SetUpInProcessBrowserTestFixture();
ExtensionTtsController::GetInstance()->SetPlatformImpl(
&mock_platform_impl_);
}
protected:
StrictMock<MockExtensionTtsPlatformImpl> mock_platform_impl_;
};
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakOptionalArgs) {
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "", _, _))
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "Alpha", _, _))
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "Bravo", _, _))
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "Charlie", _, _))
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "Echo", _, _))
.WillOnce(Return(true));
ASSERT_TRUE(RunExtensionTest("tts/optional_args")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakFinishesImmediately) {
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/speak_once")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakInterrupt) {
// One utterance starts speaking, and then a second interrupts.
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _))
.WillOnce(Return(true));
// Expect the second utterance and allow it to finish.
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 2", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/interrupt")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakQueueInterrupt) {
// In this test, two utterances are queued, and then a third
// interrupts. Speak() never gets called on the second utterance.
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _))
.WillOnce(Return(true));
// Don't expect the second utterance, because it's queued up and the
// first never finishes.
// Expect the third utterance and allow it to finish successfully.
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 3", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/queue_interrupt")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakEnqueue) {
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 1", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEventWhenQueueNotEmpty),
Return(true)));
EXPECT_CALL(mock_platform_impl_, Speak(_, "text 2", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/enqueue")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakError) {
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "first try", _, _))
.WillOnce(DoAll(
InvokeWithoutArgs(
CreateFunctor(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SetErrorToEpicFail)),
Return(false)));
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "second try", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/speak_error")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformWordCallbacks) {
InSequence s;
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillOnce(Return(true));
EXPECT_CALL(mock_platform_impl_, Speak(_, "one two three", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendWordEvents),
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
ASSERT_TRUE(RunExtensionTest("tts/word_callbacks")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, RegisterEngine) {
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillRepeatedly(Return(true));
{
InSequence s;
EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech 2", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
EXPECT_CALL(mock_platform_impl_, Speak(_, "native speech 3", _, _))
.WillOnce(DoAll(
Invoke(&mock_platform_impl_,
&MockExtensionTtsPlatformImpl::SendEndEvent),
Return(true)));
}
ASSERT_TRUE(RunExtensionTest("tts_engine/register_engine")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineError) {
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillRepeatedly(Return(true));
ASSERT_TRUE(RunExtensionTest("tts_engine/engine_error")) << message_;
}
IN_PROC_BROWSER_TEST_F(TtsApiTest, EngineWordCallbacks) {
EXPECT_CALL(mock_platform_impl_, StopSpeaking())
.WillRepeatedly(Return(true));
ASSERT_TRUE(RunExtensionTest("tts_engine/engine_word_callbacks")) << message_;
}