Home | History | Annotate | Download | only in glue
      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 "base/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/callback.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/synchronization/waitable_event.h"
     12 #include "base/threading/thread.h"
     13 #include "chrome/browser/sync/glue/ui_model_worker.h"
     14 #include "content/public/test/test_browser_thread.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 using browser_sync::UIModelWorker;
     18 using syncer::SyncerError;
     19 using content::BrowserThread;
     20 
     21 class UIModelWorkerVisitor {
     22  public:
     23   UIModelWorkerVisitor(base::WaitableEvent* was_run,
     24                        bool quit_loop)
     25      : quit_loop_when_run_(quit_loop),
     26        was_run_(was_run) { }
     27   virtual ~UIModelWorkerVisitor() { }
     28 
     29   virtual syncer::SyncerError DoWork() {
     30     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
     31     was_run_->Signal();
     32     if (quit_loop_when_run_)
     33       base::MessageLoop::current()->Quit();
     34     return syncer::SYNCER_OK;
     35   }
     36 
     37  private:
     38   bool quit_loop_when_run_;
     39   base::WaitableEvent* was_run_;
     40   DISALLOW_COPY_AND_ASSIGN(UIModelWorkerVisitor);
     41 };
     42 
     43 // A faux-syncer that only interacts with its model safe worker.
     44 class Syncer {
     45  public:
     46   explicit Syncer(UIModelWorker* worker) : worker_(worker) {}
     47   ~Syncer() {}
     48 
     49   void SyncShare(UIModelWorkerVisitor* visitor) {
     50     // We wait until the callback is executed. So it is safe to use Unretained.
     51     syncer::WorkCallback c = base::Bind(&UIModelWorkerVisitor::DoWork,
     52                                        base::Unretained(visitor));
     53     worker_->DoWorkAndWaitUntilDone(c);
     54   }
     55  private:
     56   scoped_refptr<UIModelWorker> worker_;
     57   DISALLOW_COPY_AND_ASSIGN(Syncer);
     58 };
     59 
     60 class SyncUIModelWorkerTest : public testing::Test {
     61  public:
     62   SyncUIModelWorkerTest() : faux_syncer_thread_("FauxSyncerThread"),
     63                             faux_core_thread_("FauxCoreThread") { }
     64 
     65   virtual void SetUp() {
     66     faux_syncer_thread_.Start();
     67     ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI,
     68                                                     &faux_ui_loop_));
     69     bmw_ = new UIModelWorker(NULL);
     70     syncer_.reset(new Syncer(bmw_.get()));
     71   }
     72 
     73   Syncer* syncer() { return syncer_.get(); }
     74   UIModelWorker* bmw() { return bmw_.get(); }
     75   base::Thread* core_thread() { return &faux_core_thread_; }
     76   base::Thread* syncer_thread() { return &faux_syncer_thread_; }
     77  private:
     78   base::MessageLoop faux_ui_loop_;
     79   scoped_ptr<content::TestBrowserThread> ui_thread_;
     80   base::Thread faux_syncer_thread_;
     81   base::Thread faux_core_thread_;
     82   scoped_refptr<UIModelWorker> bmw_;
     83   scoped_ptr<Syncer> syncer_;
     84 };
     85 
     86 TEST_F(SyncUIModelWorkerTest, ScheduledWorkRunsOnUILoop) {
     87   base::WaitableEvent v_was_run(false, false);
     88   scoped_ptr<UIModelWorkerVisitor> v(
     89       new UIModelWorkerVisitor(&v_was_run, true));
     90 
     91   syncer_thread()->message_loop()->PostTask(FROM_HERE,
     92       base::Bind(&Syncer::SyncShare, base::Unretained(syncer()), v.get()));
     93 
     94   // We are on the UI thread, so run our loop to process the
     95   // (hopefully) scheduled task from a SyncShare invocation.
     96   base::MessageLoop::current()->Run();
     97   syncer_thread()->Stop();
     98 }
     99