Home | History | Annotate | Download | only in shared_impl
      1 // Copyright (c) 2013 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 <string>
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/logging.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "ppapi/shared_impl/proxy_lock.h"
     13 #include "ppapi/shared_impl/test_globals.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace ppapi {
     17 
     18 namespace {
     19 
     20 bool expect_to_be_locked = false;
     21 void CheckLockState() {
     22   if (expect_to_be_locked) {
     23     ProxyLock::AssertAcquired();
     24   } else {
     25     // If we expect to be unlocked, try to lock. We rely on the checking inside
     26     // base::Lock that prevents recursive locking.
     27     ProxyAutoLock lock;
     28   }
     29 }
     30 
     31 int called_num = 0;
     32 
     33 class CheckLockStateInDestructor
     34     : public base::RefCounted<CheckLockStateInDestructor> {
     35  public:
     36   CheckLockStateInDestructor() {}
     37   void Method() { ++called_num; }
     38 
     39  private:
     40   friend class base::RefCounted<CheckLockStateInDestructor>;
     41   ~CheckLockStateInDestructor() { CheckLockState(); }
     42   DISALLOW_COPY_AND_ASSIGN(CheckLockStateInDestructor);
     43 };
     44 
     45 void TestCallback_0() {
     46   CheckLockState();
     47   ++called_num;
     48 }
     49 
     50 void TestCallback_1(int p1) {
     51   CheckLockState();
     52   ++called_num;
     53 }
     54 
     55 void TestCallback_2(int p1, const std::string& p2) {
     56   CheckLockState();
     57   ++called_num;
     58 }
     59 
     60 struct Param {};
     61 void TestCallback_3(int p1, const std::string& p2, Param p3) {
     62   CheckLockState();
     63   ++called_num;
     64 }
     65 
     66 }  // namespace
     67 
     68 TEST(PpapiProxyLockTest, Locking) {
     69   TestGlobals globals;
     70   expect_to_be_locked = true;
     71 
     72   base::Callback<void()> cb0;
     73   {
     74     ProxyAutoLock lock;
     75     cb0 = RunWhileLocked(base::Bind(TestCallback_0));
     76   }
     77   cb0.Run();
     78   ASSERT_EQ(1, called_num);
     79   called_num = 0;
     80 
     81   {
     82     ProxyAutoLock lock;
     83     cb0 = RunWhileLocked(base::Bind(TestCallback_1, 123));
     84   }
     85   cb0.Run();
     86   ASSERT_EQ(1, called_num);
     87   called_num = 0;
     88 
     89   {
     90     ProxyAutoLock lock;
     91     scoped_refptr<CheckLockStateInDestructor> object =
     92         new CheckLockStateInDestructor();
     93     cb0 =
     94         RunWhileLocked(base::Bind(&CheckLockStateInDestructor::Method, object));
     95     // Note after this scope, the Callback owns the only reference.
     96   }
     97   cb0.Run();
     98   ASSERT_EQ(1, called_num);
     99   called_num = 0;
    100 
    101   base::Callback<void(int)> cb1;
    102   {
    103     ProxyAutoLock lock;
    104     cb1 = RunWhileLocked(base::Bind(TestCallback_1));
    105   }
    106   cb1.Run(123);
    107   ASSERT_EQ(1, called_num);
    108   called_num = 0;
    109 
    110   base::Callback<void(int, const std::string&)> cb2;
    111   {
    112     ProxyAutoLock lock;
    113     cb2 = RunWhileLocked(base::Bind(TestCallback_2));
    114   }
    115   cb2.Run(123, std::string("yo"));
    116   ASSERT_EQ(1, called_num);
    117   called_num = 0;
    118 
    119   base::Callback<void(int, const std::string&, Param)> cb3;
    120   {
    121     ProxyAutoLock lock;
    122     cb3 = RunWhileLocked(base::Bind(TestCallback_3));
    123   }
    124   cb3.Run(123, std::string("yo"), Param());
    125   ASSERT_EQ(1, called_num);
    126   called_num = 0;
    127 
    128   base::Callback<void(const std::string&)> cb1_string;
    129   {
    130     ProxyAutoLock lock;
    131     cb1_string = RunWhileLocked(base::Bind(TestCallback_2, 123));
    132   }
    133   cb1_string.Run(std::string("yo"));
    134   ASSERT_EQ(1, called_num);
    135   called_num = 0;
    136 
    137   {
    138     ProxyAutoLock lock;
    139     cb0 = RunWhileLocked(base::Bind(TestCallback_2, 123, std::string("yo")));
    140   }
    141   cb0.Run();
    142   ASSERT_EQ(1, called_num);
    143   called_num = 0;
    144 }
    145 
    146 TEST(PpapiProxyLockTest, Unlocking) {
    147   TestGlobals globals;
    148   expect_to_be_locked = false;
    149   // These calls should all try to _unlock_, so we must be locked before
    150   // entering them.
    151   ProxyAutoLock auto_lock;
    152 
    153   {
    154     CallWhileUnlocked(TestCallback_0);
    155     ASSERT_EQ(1, called_num);
    156     called_num = 0;
    157   }
    158   {
    159     CallWhileUnlocked(TestCallback_1, 123);
    160     ASSERT_EQ(1, called_num);
    161     called_num = 0;
    162   }
    163   {
    164     // TODO(dmichael): Make const-ref arguments work properly with type
    165     // deduction.
    166     CallWhileUnlocked<void, int, const std::string&>(
    167         TestCallback_2, 123, std::string("yo"));
    168     ASSERT_EQ(1, called_num);
    169     called_num = 0;
    170   }
    171   {
    172     base::Callback<void()> callback(base::Bind(TestCallback_0));
    173     CallWhileUnlocked(callback);
    174     ASSERT_EQ(1, called_num);
    175     called_num = 0;
    176   }
    177 }
    178 
    179 }  // namespace ppapi
    180