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() {
     38     ++called_num;
     39   }
     40  private:
     41   friend class base::RefCounted<CheckLockStateInDestructor>;
     42   ~CheckLockStateInDestructor() {
     43     CheckLockState();
     44   }
     45   DISALLOW_COPY_AND_ASSIGN(CheckLockStateInDestructor);
     46 };
     47 
     48 void TestCallback_0() {
     49   CheckLockState();
     50   ++called_num;
     51 }
     52 
     53 void TestCallback_1(int p1) {
     54   CheckLockState();
     55   ++called_num;
     56 }
     57 
     58 void TestCallback_2(int p1, const std::string& p2) {
     59   CheckLockState();
     60   ++called_num;
     61 }
     62 
     63 struct Param {};
     64 void TestCallback_3(int p1, const std::string& p2, Param p3) {
     65   CheckLockState();
     66   ++called_num;
     67 }
     68 
     69 }  // namespace
     70 
     71 TEST(PpapiProxyLockTest, Locking) {
     72   TestGlobals globals;
     73   expect_to_be_locked = true;
     74 
     75   base::Callback<void()> cb0;
     76   {
     77     ProxyAutoLock lock;
     78     cb0 = RunWhileLocked(base::Bind(TestCallback_0));
     79   }
     80   cb0.Run();
     81   ASSERT_EQ(1, called_num);
     82   called_num = 0;
     83 
     84   {
     85     ProxyAutoLock lock;
     86     cb0 = RunWhileLocked(base::Bind(TestCallback_1, 123));
     87   }
     88   cb0.Run();
     89   ASSERT_EQ(1, called_num);
     90   called_num = 0;
     91 
     92   {
     93     ProxyAutoLock lock;
     94     scoped_refptr<CheckLockStateInDestructor> object =
     95         new CheckLockStateInDestructor();
     96     cb0 = RunWhileLocked(
     97               base::Bind(&CheckLockStateInDestructor::Method,
     98                          object));
     99     // Note after this scope, the Callback owns the only reference.
    100   }
    101   cb0.Run();
    102   ASSERT_EQ(1, called_num);
    103   called_num = 0;
    104 
    105   base::Callback<void(int)> cb1;
    106   {
    107     ProxyAutoLock lock;
    108     cb1 = RunWhileLocked(base::Bind(TestCallback_1));
    109   }
    110   cb1.Run(123);
    111   ASSERT_EQ(1, called_num);
    112   called_num = 0;
    113 
    114   base::Callback<void(int, const std::string&)> cb2;
    115   {
    116     ProxyAutoLock lock;
    117     cb2 = RunWhileLocked(base::Bind(TestCallback_2));
    118   }
    119   cb2.Run(123, std::string("yo"));
    120   ASSERT_EQ(1, called_num);
    121   called_num = 0;
    122 
    123   base::Callback<void(int, const std::string&, Param)> cb3;
    124   {
    125     ProxyAutoLock lock;
    126     cb3 = RunWhileLocked(base::Bind(TestCallback_3));
    127   }
    128   cb3.Run(123, std::string("yo"), Param());
    129   ASSERT_EQ(1, called_num);
    130   called_num = 0;
    131 
    132   base::Callback<void(const std::string&)> cb1_string;
    133   {
    134     ProxyAutoLock lock;
    135     cb1_string = RunWhileLocked(base::Bind(TestCallback_2, 123));
    136   }
    137   cb1_string.Run(std::string("yo"));
    138   ASSERT_EQ(1, called_num);
    139   called_num = 0;
    140 
    141   {
    142     ProxyAutoLock lock;
    143     cb0 = RunWhileLocked(base::Bind(TestCallback_2, 123, std::string("yo")));
    144   }
    145   cb0.Run();
    146   ASSERT_EQ(1, called_num);
    147   called_num = 0;
    148 }
    149 
    150 TEST(PpapiProxyLockTest, Unlocking) {
    151   TestGlobals globals;
    152   expect_to_be_locked = false;
    153   // These calls should all try to _unlock_, so we must be locked before
    154   // entering them.
    155   ProxyAutoLock auto_lock;
    156 
    157   {
    158     CallWhileUnlocked(TestCallback_0);
    159     ASSERT_EQ(1, called_num);
    160     called_num = 0;
    161   } {
    162     CallWhileUnlocked(TestCallback_1, 123);
    163     ASSERT_EQ(1, called_num);
    164     called_num = 0;
    165   } {
    166     // TODO(dmichael): Make const-ref arguments work properly with type
    167     // deduction.
    168     CallWhileUnlocked<void, int, const std::string&>(
    169         TestCallback_2, 123, std::string("yo"));
    170     ASSERT_EQ(1, called_num);
    171     called_num = 0;
    172   } {
    173     base::Callback<void()> callback(base::Bind(TestCallback_0));
    174     CallWhileUnlocked(callback);
    175     ASSERT_EQ(1, called_num);
    176     called_num = 0;
    177   }
    178 }
    179 
    180 }  // namespace ppapi
    181