| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/utf_string_conversions.h" |
| 5 #include "chrome/browser/chrome_thread.h" | 6 #include "chrome/browser/chrome_thread.h" |
| 6 #include "chrome/browser/speech/speech_input_bubble_controller.h" | 7 #include "chrome/browser/speech/speech_input_bubble_controller.h" |
| 7 #include "gfx/rect.h" | 8 #include "gfx/rect.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 10 |
| 10 namespace speech_input { | 11 namespace speech_input { |
| 11 | 12 |
| 12 // A mock bubble class which fakes a focus change or recognition cancel by the | 13 // A mock bubble class which fakes a focus change or recognition cancel by the |
| 13 // user and closing of the info bubble. | 14 // user and closing of the info bubble. |
| 14 class MockSpeechInputBubble : public SpeechInputBubble { | 15 class MockSpeechInputBubble : public SpeechInputBubbleBase { |
| 15 public: | 16 public: |
| 16 enum BubbleType { | 17 enum BubbleType { |
| 17 BUBBLE_TEST_FOCUS_CHANGED, | 18 BUBBLE_TEST_FOCUS_CHANGED, |
| 18 BUBBLE_TEST_RECOGNITION_CANCELLED | 19 BUBBLE_TEST_CLICK_CANCEL, |
| 20 BUBBLE_TEST_CLICK_TRY_AGAIN, |
| 19 }; | 21 }; |
| 20 | 22 |
| 21 MockSpeechInputBubble(TabContents*, Delegate* delegate, const gfx::Rect&) { | 23 MockSpeechInputBubble(TabContents*, Delegate* delegate, const gfx::Rect&) { |
| 22 MessageLoop::current()->PostTask( | 24 MessageLoop::current()->PostTask( |
| 23 FROM_HERE, NewRunnableFunction(&InvokeDelegate, delegate)); | 25 FROM_HERE, NewRunnableFunction(&InvokeDelegate, delegate)); |
| 24 } | 26 } |
| 25 | 27 |
| 26 static void InvokeDelegate(Delegate* delegate) { | 28 static void InvokeDelegate(Delegate* delegate) { |
| 27 if (type_ == BUBBLE_TEST_FOCUS_CHANGED) | 29 switch (type_) { |
| 28 delegate->InfoBubbleClosed(); | 30 case BUBBLE_TEST_FOCUS_CHANGED: |
| 29 else | 31 delegate->InfoBubbleFocusChanged(); |
| 30 delegate->RecognitionCancelled(); | 32 break; |
| 33 case BUBBLE_TEST_CLICK_CANCEL: |
| 34 delegate->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_CANCEL); |
| 35 break; |
| 36 case BUBBLE_TEST_CLICK_TRY_AGAIN: |
| 37 delegate->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_TRY_AGAIN); |
| 38 break; |
| 39 } |
| 31 } | 40 } |
| 32 | 41 |
| 33 static void set_type(BubbleType type) { | 42 static void set_type(BubbleType type) { |
| 34 type_ = type; | 43 type_ = type; |
| 35 } | 44 } |
| 45 static BubbleType type() { |
| 46 return type_; |
| 47 } |
| 36 | 48 |
| 37 virtual void SetRecognizingMode() {} | 49 virtual void Show() {} |
| 50 virtual void Hide() {} |
| 51 virtual void UpdateLayout() {} |
| 38 | 52 |
| 39 private: | 53 private: |
| 40 static BubbleType type_; | 54 static BubbleType type_; |
| 41 }; | 55 }; |
| 42 | 56 |
| 43 // The test fixture. | 57 // The test fixture. |
| 44 class SpeechInputBubbleControllerTest | 58 class SpeechInputBubbleControllerTest |
| 45 : public SpeechInputBubbleControllerDelegate, | 59 : public SpeechInputBubbleControllerDelegate, |
| 46 public testing::Test { | 60 public testing::Test { |
| 47 public: | 61 public: |
| 48 SpeechInputBubbleControllerTest() | 62 SpeechInputBubbleControllerTest() |
| 49 : io_loop_(MessageLoop::TYPE_IO), | 63 : io_loop_(MessageLoop::TYPE_IO), |
| 50 ui_thread_(ChromeThread::UI), // constructs a new thread and loop | 64 ui_thread_(ChromeThread::UI), // constructs a new thread and loop |
| 51 io_thread_(ChromeThread::IO, &io_loop_), // resuses main thread loop | 65 io_thread_(ChromeThread::IO, &io_loop_), // resuses main thread loop |
| 52 recognition_cancelled_(false), | 66 cancel_clicked_(false), |
| 53 focus_changed_(false) { | 67 try_again_clicked_(false), |
| 68 focus_changed_(false), |
| 69 controller_(ALLOW_THIS_IN_INITIALIZER_LIST( |
| 70 new SpeechInputBubbleController(this))) { |
| 71 EXPECT_EQ(NULL, test_fixture_); |
| 72 test_fixture_ = this; |
| 73 } |
| 74 |
| 75 ~SpeechInputBubbleControllerTest() { |
| 76 test_fixture_ = NULL; |
| 54 } | 77 } |
| 55 | 78 |
| 56 // SpeechInputBubbleControllerDelegate methods. | 79 // SpeechInputBubbleControllerDelegate methods. |
| 57 virtual void RecognitionCancelled(int caller_id) { | 80 virtual void InfoBubbleButtonClicked(int caller_id, |
| 81 SpeechInputBubble::Button button) { |
| 58 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 82 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| 59 recognition_cancelled_ = true; | 83 if (button == SpeechInputBubble::BUTTON_CANCEL) { |
| 84 cancel_clicked_ = true; |
| 85 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) { |
| 86 try_again_clicked_ = true; |
| 87 } |
| 60 MessageLoop::current()->Quit(); | 88 MessageLoop::current()->Quit(); |
| 61 } | 89 } |
| 62 | 90 |
| 63 virtual void SpeechInputFocusChanged(int caller_id) { | 91 virtual void InfoBubbleFocusChanged(int caller_id) { |
| 64 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 92 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| 65 focus_changed_ = true; | 93 focus_changed_ = true; |
| 66 MessageLoop::current()->Quit(); | 94 MessageLoop::current()->Quit(); |
| 67 } | 95 } |
| 68 | 96 |
| 69 // testing::Test methods. | 97 // testing::Test methods. |
| 70 virtual void SetUp() { | 98 virtual void SetUp() { |
| 71 SpeechInputBubble::set_factory( | 99 SpeechInputBubble::set_factory( |
| 72 &SpeechInputBubbleControllerTest::CreateBubble); | 100 &SpeechInputBubbleControllerTest::CreateBubble); |
| 73 ui_thread_.Start(); | 101 ui_thread_.Start(); |
| 74 } | 102 } |
| 75 | 103 |
| 76 virtual void TearDown() { | 104 virtual void TearDown() { |
| 77 SpeechInputBubble::set_factory(NULL); | 105 SpeechInputBubble::set_factory(NULL); |
| 78 ui_thread_.Stop(); | 106 ui_thread_.Stop(); |
| 79 } | 107 } |
| 80 | 108 |
| 109 static void ActivateBubble() { |
| 110 if (MockSpeechInputBubble::type() == |
| 111 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED) { |
| 112 test_fixture_->controller_->SetBubbleRecordingMode(kBubbleCallerId); |
| 113 } else { |
| 114 test_fixture_->controller_->SetBubbleMessage(kBubbleCallerId, |
| 115 ASCIIToUTF16("Test")); |
| 116 } |
| 117 } |
| 118 |
| 81 static SpeechInputBubble* CreateBubble(TabContents* tab_contents, | 119 static SpeechInputBubble* CreateBubble(TabContents* tab_contents, |
| 82 SpeechInputBubble::Delegate* delegate, | 120 SpeechInputBubble::Delegate* delegate, |
| 83 const gfx::Rect& element_rect) { | 121 const gfx::Rect& element_rect) { |
| 84 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 122 EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 123 // Set up to activate the bubble soon after it gets created, since we test |
| 124 // events sent by the bubble and those are handled only when the bubble is |
| 125 // active. |
| 126 MessageLoop::current()->PostTask(FROM_HERE, |
| 127 NewRunnableFunction(&ActivateBubble)); |
| 85 return new MockSpeechInputBubble(tab_contents, delegate, element_rect); | 128 return new MockSpeechInputBubble(tab_contents, delegate, element_rect); |
| 86 } | 129 } |
| 87 | 130 |
| 88 protected: | 131 protected: |
| 89 // The main thread of the test is marked as the IO thread and we create a new | 132 // The main thread of the test is marked as the IO thread and we create a new |
| 90 // one for the UI thread. | 133 // one for the UI thread. |
| 91 MessageLoop io_loop_; | 134 MessageLoop io_loop_; |
| 92 ChromeThread ui_thread_; | 135 ChromeThread ui_thread_; |
| 93 ChromeThread io_thread_; | 136 ChromeThread io_thread_; |
| 94 bool recognition_cancelled_; | 137 bool cancel_clicked_; |
| 138 bool try_again_clicked_; |
| 95 bool focus_changed_; | 139 bool focus_changed_; |
| 140 scoped_refptr<SpeechInputBubbleController> controller_; |
| 141 |
| 142 static const int kBubbleCallerId; |
| 143 static SpeechInputBubbleControllerTest* test_fixture_; |
| 96 }; | 144 }; |
| 97 | 145 |
| 146 SpeechInputBubbleControllerTest* |
| 147 SpeechInputBubbleControllerTest::test_fixture_ = NULL; |
| 148 |
| 149 const int SpeechInputBubbleControllerTest::kBubbleCallerId = 1; |
| 150 |
| 98 MockSpeechInputBubble::BubbleType MockSpeechInputBubble::type_ = | 151 MockSpeechInputBubble::BubbleType MockSpeechInputBubble::type_ = |
| 99 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED; | 152 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED; |
| 100 | 153 |
| 101 // Test that the speech bubble UI gets created in the UI thread and that the | 154 // Test that the speech bubble UI gets created in the UI thread and that the |
| 102 // focus changed callback comes back in the IO thread. | 155 // focus changed callback comes back in the IO thread. |
| 103 // | 156 // |
| 104 // Crashes on Win only. http://crbug.com/54044 | 157 // Crashes on Win only. http://crbug.com/54044 |
| 105 #if defined(OS_WIN) | 158 #if defined(OS_WIN) |
| 106 #define MAYBE_TestFocusChanged DISABLED_TestFocusChanged | 159 #define MAYBE_TestFocusChanged DISABLED_TestFocusChanged |
| 107 #else | 160 #else |
| 108 #define MAYBE_TestFocusChanged TestFocusChanged | 161 #define MAYBE_TestFocusChanged TestFocusChanged |
| 109 #endif | 162 #endif |
| 110 TEST_F(SpeechInputBubbleControllerTest, MAYBE_TestFocusChanged) { | 163 TEST_F(SpeechInputBubbleControllerTest, MAYBE_TestFocusChanged) { |
| 111 MockSpeechInputBubble::set_type( | 164 MockSpeechInputBubble::set_type( |
| 112 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED); | 165 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED); |
| 113 | 166 |
| 114 scoped_refptr<SpeechInputBubbleController> controller( | 167 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); |
| 115 new SpeechInputBubbleController(this)); | |
| 116 | |
| 117 controller->CreateBubble(0, 1, 1, gfx::Rect(1, 1)); | |
| 118 MessageLoop::current()->Run(); | 168 MessageLoop::current()->Run(); |
| 119 EXPECT_TRUE(focus_changed_); | 169 EXPECT_TRUE(focus_changed_); |
| 120 EXPECT_FALSE(recognition_cancelled_); | 170 EXPECT_FALSE(cancel_clicked_); |
| 171 EXPECT_FALSE(try_again_clicked_); |
| 172 controller_->CloseBubble(kBubbleCallerId); |
| 121 } | 173 } |
| 122 | 174 |
| 123 // Test that the speech bubble UI gets created in the UI thread and that the | 175 // Test that the speech bubble UI gets created in the UI thread and that the |
| 124 // recognition cancelled callback comes back in the IO thread. | 176 // recognition cancelled callback comes back in the IO thread. |
| 125 TEST_F(SpeechInputBubbleControllerTest, TestRecognitionCancelled) { | 177 TEST_F(SpeechInputBubbleControllerTest, TestRecognitionCancelled) { |
| 126 MockSpeechInputBubble::set_type( | 178 MockSpeechInputBubble::set_type( |
| 127 MockSpeechInputBubble::BUBBLE_TEST_RECOGNITION_CANCELLED); | 179 MockSpeechInputBubble::BUBBLE_TEST_CLICK_CANCEL); |
| 128 | 180 |
| 129 scoped_refptr<SpeechInputBubbleController> controller( | 181 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); |
| 130 new SpeechInputBubbleController(this)); | 182 MessageLoop::current()->Run(); |
| 183 EXPECT_TRUE(cancel_clicked_); |
| 184 EXPECT_FALSE(try_again_clicked_); |
| 185 EXPECT_FALSE(focus_changed_); |
| 186 controller_->CloseBubble(kBubbleCallerId); |
| 187 } |
| 131 | 188 |
| 132 controller->CreateBubble(0, 1, 1, gfx::Rect(1, 1)); | 189 // Test that the speech bubble UI gets created in the UI thread and that the |
| 190 // try-again button click event comes back in the IO thread. |
| 191 TEST_F(SpeechInputBubbleControllerTest, TestTryAgainClicked) { |
| 192 MockSpeechInputBubble::set_type( |
| 193 MockSpeechInputBubble::BUBBLE_TEST_CLICK_TRY_AGAIN); |
| 194 |
| 195 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); |
| 133 MessageLoop::current()->Run(); | 196 MessageLoop::current()->Run(); |
| 134 EXPECT_TRUE(recognition_cancelled_); | 197 EXPECT_FALSE(cancel_clicked_); |
| 198 EXPECT_TRUE(try_again_clicked_); |
| 135 EXPECT_FALSE(focus_changed_); | 199 EXPECT_FALSE(focus_changed_); |
| 200 controller_->CloseBubble(kBubbleCallerId); |
| 136 } | 201 } |
| 137 | 202 |
| 138 } // namespace speech_input | 203 } // namespace speech_input |
| OLD | NEW |