Home | History | Annotate | Download | only in js
      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