15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/ui_model_worker.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using browser_sync::UIModelWorker; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::SyncerError; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UIModelWorkerVisitor { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UIModelWorkerVisitor(base::WaitableEvent* was_run, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool quit_loop) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : quit_loop_when_run_(quit_loop), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) was_run_(was_run) { } 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~UIModelWorkerVisitor() { } 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual syncer::SyncerError DoWork() { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) was_run_->Signal(); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (quit_loop_when_run_) 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->Quit(); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return syncer::SYNCER_OK; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool quit_loop_when_run_; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* was_run_; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(UIModelWorkerVisitor); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A faux-syncer that only interacts with its model safe worker. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Syncer { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit Syncer(UIModelWorker* worker) : worker_(worker) {} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Syncer() {} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SyncShare(UIModelWorkerVisitor* visitor) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait until the callback is executed. So it is safe to use Unretained. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::WorkCallback c = base::Bind(&UIModelWorkerVisitor::DoWork, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(visitor)); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) worker_->DoWorkAndWaitUntilDone(c); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<UIModelWorker> worker_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Syncer); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncUIModelWorkerTest : public testing::Test { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncUIModelWorkerTest() : faux_syncer_thread_("FauxSyncerThread"), 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) faux_core_thread_("FauxCoreThread") { } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) faux_syncer_thread_.Start(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &faux_ui_loop_)); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bmw_ = new UIModelWorker(NULL); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer_.reset(new Syncer(bmw_.get())); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Syncer* syncer() { return syncer_.get(); } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UIModelWorker* bmw() { return bmw_.get(); } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread* core_thread() { return &faux_core_thread_; } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread* syncer_thread() { return &faux_syncer_thread_; } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop faux_ui_loop_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<content::TestBrowserThread> ui_thread_; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread faux_syncer_thread_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread faux_core_thread_; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<UIModelWorker> bmw_; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Syncer> syncer_; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SyncUIModelWorkerTest, ScheduledWorkRunsOnUILoop) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent v_was_run(false, false); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<UIModelWorkerVisitor> v( 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new UIModelWorkerVisitor(&v_was_run, true)); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer_thread()->message_loop()->PostTask(FROM_HERE, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Syncer::SyncShare, base::Unretained(syncer()), v.get())); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are on the UI thread, so run our loop to process the 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (hopefully) scheduled task from a SyncShare invocation. 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->Run(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer_thread()->Stop(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 99