1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4#include "base/command_line.h"
5#include "chrome/browser/extensions/extension_apitest.h"
6#include "chrome/browser/extensions/extension_tts_api.h"
7#include "chrome/common/chrome_switches.h"
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11// Needed for CreateFunctor.
12#define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING
13#include "testing/gmock_mutant.h"
14
15#if defined(OS_CHROMEOS)
16#include "chrome/browser/chromeos/cros/cros_mock.h"
17#endif
18
19using ::testing::AnyNumber;
20using ::testing::CreateFunctor;
21using ::testing::DoAll;
22using ::testing::InSequence;
23using ::testing::InvokeWithoutArgs;
24using ::testing::Return;
25using ::testing::StrictMock;
26using ::testing::_;
27
28class MockExtensionTtsPlatformImpl : public ExtensionTtsPlatformImpl {
29 public:
30  MOCK_METHOD6(Speak,
31               bool(const std::string& utterance,
32                    const std::string& locale,
33                    const std::string& gender,
34                    double rate,
35                    double pitch,
36                    double volume));
37  MOCK_METHOD0(StopSpeaking, bool(void));
38  MOCK_METHOD0(IsSpeaking, bool(void));
39
40  void SetErrorToEpicFail() {
41    set_error("epic fail");
42  }
43};
44
45class TtsApiTest : public ExtensionApiTest {
46 public:
47  virtual void SetUpCommandLine(CommandLine* command_line) {
48    ExtensionApiTest::SetUpCommandLine(command_line);
49    command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
50  }
51
52  virtual void SetUpInProcessBrowserTestFixture() {
53    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
54    ExtensionTtsController::GetInstance()->SetPlatformImpl(
55        &mock_platform_impl_);
56  }
57
58 protected:
59  StrictMock<MockExtensionTtsPlatformImpl> mock_platform_impl_;
60};
61
62IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakFinishesImmediately) {
63  InSequence s;
64  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
65      .WillOnce(Return(true));
66  EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _, _))
67      .WillOnce(Return(true));
68  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
69      .WillOnce(Return(false));
70  ASSERT_TRUE(RunExtensionTest("tts/speak_once")) << message_;
71}
72
73IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakKeepsSpeakingTwice) {
74  InSequence s;
75  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
76      .WillOnce(Return(true));
77  EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _, _))
78      .WillOnce(Return(true));
79  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
80      .WillOnce(Return(true))
81      .WillOnce(Return(true))
82      .WillOnce(Return(false));
83  ASSERT_TRUE(RunExtensionTest("tts/speak_once")) << message_;
84}
85
86IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakInterrupt) {
87  // One utterances starts speaking, and then a second interrupts.
88  InSequence s;
89  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
90      .WillOnce(Return(true));
91  EXPECT_CALL(mock_platform_impl_, Speak("text 1", _, _, _, _, _))
92      .WillOnce(Return(true));
93
94  // Ensure that the first utterance keeps going until it's interrupted.
95  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
96      .Times(AnyNumber())
97      .WillRepeatedly(Return(true));
98
99  // Expect the second utterance and allow it to continue for two calls to
100  // IsSpeaking and then finish successfully.
101  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
102      .WillOnce(Return(true));
103  EXPECT_CALL(mock_platform_impl_, Speak("text 2", _, _, _, _, _))
104      .WillOnce(Return(true));
105  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
106      .WillOnce(Return(true))
107      .WillOnce(Return(true))
108      .WillOnce(Return(false));
109  ASSERT_TRUE(RunExtensionTest("tts/interrupt")) << message_;
110}
111
112IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakQueueInterrupt) {
113  // In this test, two utterances are queued, and then a third
114  // interrupts. Speak() never gets called on the second utterance.
115  InSequence s;
116  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
117      .WillOnce(Return(true));
118  EXPECT_CALL(mock_platform_impl_, Speak("text 1", _, _, _, _, _))
119      .WillOnce(Return(true));
120
121  // Ensure that the first utterance keeps going until it's interrupted.
122  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
123      .Times(AnyNumber())
124      .WillRepeatedly(Return(true));
125
126  // Expect the third utterance and allow it to continue for two calls to
127  // IsSpeaking and then finish successfully.
128  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
129      .WillOnce(Return(true));
130  EXPECT_CALL(mock_platform_impl_, Speak("text 3", _, _, _, _, _))
131      .WillOnce(Return(true));
132  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
133      .WillOnce(Return(true))
134      .WillOnce(Return(true))
135      .WillOnce(Return(false));
136  ASSERT_TRUE(RunExtensionTest("tts/queue_interrupt")) << message_;
137}
138
139IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakEnqueue) {
140  InSequence s;
141  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
142      .WillOnce(Return(true));
143  EXPECT_CALL(mock_platform_impl_, Speak("text 1", _, _, _, _, _))
144      .WillOnce(Return(true));
145  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
146      .WillOnce(Return(true))
147      .WillOnce(Return(true))
148      .WillOnce(Return(false));
149  EXPECT_CALL(mock_platform_impl_, Speak("text 2", _, _, _, _, _))
150      .WillOnce(Return(true));
151  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
152      .WillOnce(Return(true))
153      .WillOnce(Return(true))
154      .WillOnce(Return(false));
155  ASSERT_TRUE(RunExtensionTest("tts/enqueue")) << message_;
156}
157
158IN_PROC_BROWSER_TEST_F(TtsApiTest, PlatformSpeakError) {
159  InSequence s;
160  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
161      .WillOnce(Return(true));
162  EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _, _))
163      .WillOnce(Return(true));
164  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
165      .WillOnce(Return(false));
166  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
167      .WillOnce(Return(true));
168  EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _, _))
169      .WillOnce(DoAll(
170          InvokeWithoutArgs(
171              CreateFunctor(&mock_platform_impl_,
172                            &MockExtensionTtsPlatformImpl::SetErrorToEpicFail)),
173          Return(false)));
174  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
175      .WillOnce(Return(true));
176  EXPECT_CALL(mock_platform_impl_, Speak(_, _, _, _, _, _))
177      .WillOnce(Return(true));
178  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
179      .WillOnce(Return(false));
180  ASSERT_TRUE(RunExtensionTest("tts/speak_error")) << message_;
181}
182
183#if defined(OS_WIN)
184// Flakily fails on Windows: http://crbug.com/70198
185#define MAYBE_Provide FLAKY_Provide
186#else
187#define MAYBE_Provide Provide
188#endif
189IN_PROC_BROWSER_TEST_F(TtsApiTest, MAYBE_Provide) {
190  EXPECT_CALL(mock_platform_impl_, StopSpeaking())
191      .WillRepeatedly(Return(true));
192  EXPECT_CALL(mock_platform_impl_, IsSpeaking())
193      .WillRepeatedly(Return(false));
194
195  {
196    InSequence s;
197    EXPECT_CALL(mock_platform_impl_, Speak("native speech", _, _, _, _, _))
198        .WillOnce(Return(true));
199    EXPECT_CALL(mock_platform_impl_, Speak("native speech 2", _, _, _, _, _))
200        .WillOnce(Return(true));
201    EXPECT_CALL(mock_platform_impl_, Speak("native speech 3", _, _, _, _, _))
202        .WillOnce(Return(true));
203  }
204
205  ASSERT_TRUE(RunExtensionTest("tts/provide")) << message_;
206}
207
208#if defined(OS_CHROMEOS)
209IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TtsChromeOs) {
210  CommandLine::ForCurrentProcess()->AppendSwitch(
211      switches::kEnableExperimentalExtensionApis);
212
213  chromeos::CrosMock crosMock;
214  crosMock.InitMockSpeechSynthesisLibrary();
215  crosMock.SetSpeechSynthesisLibraryExpectations();
216
217  ASSERT_TRUE(RunExtensionTest("tts/chromeos")) << message_;
218}
219#endif
220