1 // Copyright (c) 2012 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 5 #include "sync/js/sync_js_controller.h" 6 7 #include "base/message_loop/message_loop.h" 8 #include "base/values.h" 9 #include "sync/js/js_arg_list.h" 10 #include "sync/js/js_event_details.h" 11 #include "sync/js/js_test_util.h" 12 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace syncer { 16 namespace { 17 18 using ::testing::_; 19 using ::testing::InSequence; 20 using ::testing::Mock; 21 using ::testing::StrictMock; 22 23 class SyncJsControllerTest : public testing::Test { 24 protected: 25 void PumpLoop() { 26 message_loop_.RunUntilIdle(); 27 } 28 29 private: 30 base::MessageLoop message_loop_; 31 }; 32 33 ACTION_P(ReplyToMessage, reply_name) { 34 arg2.Call(FROM_HERE, &JsReplyHandler::HandleJsReply, reply_name, JsArgList()); 35 } 36 37 TEST_F(SyncJsControllerTest, Messages) { 38 InSequence dummy; 39 // |mock_backend| needs to outlive |sync_js_controller|. 40 StrictMock<MockJsBackend> mock_backend; 41 StrictMock<MockJsReplyHandler> mock_reply_handler; 42 SyncJsController sync_js_controller; 43 44 base::ListValue arg_list1, arg_list2; 45 arg_list1.Append(new base::FundamentalValue(false)); 46 arg_list2.Append(new base::FundamentalValue(5)); 47 JsArgList args1(&arg_list1), args2(&arg_list2); 48 49 EXPECT_CALL(mock_backend, SetJsEventHandler(_)); 50 EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) 51 .WillOnce(ReplyToMessage("test1_reply")); 52 EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) 53 .WillOnce(ReplyToMessage("test2_reply")); 54 55 sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); 56 sync_js_controller.ProcessJsMessage("test1", 57 args2, 58 mock_reply_handler.AsWeakHandle()); 59 sync_js_controller.ProcessJsMessage("test2", 60 args1, 61 mock_reply_handler.AsWeakHandle()); 62 63 // The replies should be waiting on our message loop. 64 EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); 65 EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); 66 PumpLoop(); 67 68 // Let destructor of |sync_js_controller| call RemoveBackend(). 69 } 70 71 TEST_F(SyncJsControllerTest, QueuedMessages) { 72 // |mock_backend| needs to outlive |sync_js_controller|. 73 StrictMock<MockJsBackend> mock_backend; 74 StrictMock<MockJsReplyHandler> mock_reply_handler; 75 SyncJsController sync_js_controller; 76 77 base::ListValue arg_list1, arg_list2; 78 arg_list1.Append(new base::FundamentalValue(false)); 79 arg_list2.Append(new base::FundamentalValue(5)); 80 JsArgList args1(&arg_list1), args2(&arg_list2); 81 82 // Should queue messages. 83 sync_js_controller.ProcessJsMessage( 84 "test1", 85 args2, 86 mock_reply_handler.AsWeakHandle()); 87 sync_js_controller.ProcessJsMessage( 88 "test2", 89 args1, 90 mock_reply_handler.AsWeakHandle()); 91 92 // Should do nothing. 93 PumpLoop(); 94 Mock::VerifyAndClearExpectations(&mock_backend); 95 96 97 // Should call the queued messages. 98 EXPECT_CALL(mock_backend, SetJsEventHandler(_)); 99 EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) 100 .WillOnce(ReplyToMessage("test1_reply")); 101 EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) 102 .WillOnce(ReplyToMessage("test2_reply")); 103 EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); 104 EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); 105 106 sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); 107 PumpLoop(); 108 109 // Should do nothing. 110 sync_js_controller.AttachJsBackend(WeakHandle<JsBackend>()); 111 PumpLoop(); 112 113 // Should also do nothing. 114 sync_js_controller.AttachJsBackend(WeakHandle<JsBackend>()); 115 PumpLoop(); 116 } 117 118 TEST_F(SyncJsControllerTest, Events) { 119 InSequence dummy; 120 SyncJsController sync_js_controller; 121 122 base::DictionaryValue details_dict1, details_dict2; 123 details_dict1.SetString("foo", "bar"); 124 details_dict2.SetInteger("baz", 5); 125 JsEventDetails details1(&details_dict1), details2(&details_dict2); 126 127 StrictMock<MockJsEventHandler> event_handler1, event_handler2; 128 EXPECT_CALL(event_handler1, HandleJsEvent("event", HasDetails(details1))); 129 EXPECT_CALL(event_handler2, HandleJsEvent("event", HasDetails(details1))); 130 EXPECT_CALL(event_handler1, 131 HandleJsEvent("anotherevent", HasDetails(details2))); 132 EXPECT_CALL(event_handler2, 133 HandleJsEvent("anotherevent", HasDetails(details2))); 134 135 sync_js_controller.AddJsEventHandler(&event_handler1); 136 sync_js_controller.AddJsEventHandler(&event_handler2); 137 sync_js_controller.HandleJsEvent("event", details1); 138 sync_js_controller.HandleJsEvent("anotherevent", details2); 139 sync_js_controller.RemoveJsEventHandler(&event_handler1); 140 sync_js_controller.RemoveJsEventHandler(&event_handler2); 141 sync_js_controller.HandleJsEvent("droppedevent", details2); 142 143 PumpLoop(); 144 } 145 146 } // namespace 147 } // namespace syncer 148