Home | History | Annotate | Download | only in tests
      1 // Copyright 2015 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 <stdint.h>
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/logging.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/run_loop.h"
     12 #include "build/build_config.h"
     13 #include "mojo/public/cpp/bindings/binding.h"
     14 #include "mojo/public/cpp/bindings/interface_ptr.h"
     15 #include "mojo/public/cpp/bindings/string.h"
     16 #include "mojo/public/cpp/system/message_pipe.h"
     17 #include "mojo/public/cpp/test_support/test_support.h"
     18 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 ///////////////////////////////////////////////////////////////////////////////
     22 //
     23 // The tests in this file are designed to test the interaction between a
     24 // Callback and its associated Binding. If a Callback is deleted before
     25 // being used we DCHECK fail--unless the associated Binding has already
     26 // been closed or deleted. This contract must be explained to the Mojo
     27 // application developer. For example it is the developer's responsibility to
     28 // ensure that the Binding is destroyed before an unused Callback is destroyed.
     29 //
     30 ///////////////////////////////////////////////////////////////////////////////
     31 
     32 namespace mojo {
     33 namespace test {
     34 namespace {
     35 
     36 void SaveValue(int32_t* storage, const base::Closure& closure, int32_t value) {
     37   *storage = value;
     38   if (!closure.is_null())
     39     closure.Run();
     40 }
     41 
     42 base::Callback<void(int32_t)> BindValueSaver(int32_t* last_value_seen,
     43                                              const base::Closure& closure) {
     44   return base::Bind(&SaveValue, last_value_seen, closure);
     45 }
     46 
     47 // An implementation of sample::Provider used on the server side.
     48 // It only implements one of the methods: EchoInt().
     49 // All it does is save the values and Callbacks it sees.
     50 class InterfaceImpl : public sample::Provider {
     51  public:
     52   InterfaceImpl()
     53       : last_server_value_seen_(0),
     54         callback_saved_(new EchoIntCallback) {}
     55 
     56   ~InterfaceImpl() override {
     57     if (callback_saved_) {
     58       delete callback_saved_;
     59     }
     60   }
     61 
     62   // Run's the callback previously saved from the last invocation
     63   // of |EchoInt()|.
     64   bool RunCallback() {
     65     if (callback_saved_) {
     66       callback_saved_->Run(last_server_value_seen_);
     67       return true;
     68     }
     69     return false;
     70   }
     71 
     72   // Delete's the previously saved callback.
     73   void DeleteCallback() {
     74     delete callback_saved_;
     75     callback_saved_ = nullptr;
     76   }
     77 
     78   // sample::Provider implementation
     79 
     80   // Saves its two input values in member variables and does nothing else.
     81   void EchoInt(int32_t x, const EchoIntCallback& callback) override {
     82     last_server_value_seen_ = x;
     83     *callback_saved_ = callback;
     84     if (!closure_.is_null()) {
     85       closure_.Run();
     86       closure_.Reset();
     87     }
     88   }
     89 
     90   void EchoString(const std::string& a,
     91                   const EchoStringCallback& callback) override {
     92     CHECK(false) << "Not implemented.";
     93   }
     94 
     95   void EchoStrings(const std::string& a,
     96                    const std::string& b,
     97                    const EchoStringsCallback& callback) override {
     98     CHECK(false) << "Not implemented.";
     99   }
    100 
    101   void EchoMessagePipeHandle(
    102       ScopedMessagePipeHandle a,
    103       const EchoMessagePipeHandleCallback& callback) override {
    104     CHECK(false) << "Not implemented.";
    105   }
    106 
    107   void EchoEnum(sample::Enum a, const EchoEnumCallback& callback) override {
    108     CHECK(false) << "Not implemented.";
    109   }
    110 
    111   void resetLastServerValueSeen() { last_server_value_seen_ = 0; }
    112 
    113   int32_t last_server_value_seen() const { return last_server_value_seen_; }
    114 
    115   void set_closure(const base::Closure& closure) { closure_ = closure; }
    116 
    117  private:
    118   int32_t last_server_value_seen_;
    119   EchoIntCallback* callback_saved_;
    120   base::Closure closure_;
    121 };
    122 
    123 class BindingCallbackTest : public testing::Test {
    124  public:
    125   BindingCallbackTest() {}
    126   ~BindingCallbackTest() override {}
    127 
    128  protected:
    129   int32_t last_client_callback_value_seen_;
    130   sample::ProviderPtr interface_ptr_;
    131 
    132   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
    133 
    134  private:
    135   base::MessageLoop loop_;
    136 };
    137 
    138 // Tests that the InterfacePtr and the Binding can communicate with each
    139 // other normally.
    140 TEST_F(BindingCallbackTest, Basic) {
    141   // Create the ServerImpl and the Binding.
    142   InterfaceImpl server_impl;
    143   Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
    144 
    145   // Initialize the test values.
    146   server_impl.resetLastServerValueSeen();
    147   last_client_callback_value_seen_ = 0;
    148 
    149   // Invoke the Echo method.
    150   base::RunLoop run_loop, run_loop2;
    151   server_impl.set_closure(run_loop.QuitClosure());
    152   interface_ptr_->EchoInt(
    153       7,
    154       BindValueSaver(&last_client_callback_value_seen_,
    155                      run_loop2.QuitClosure()));
    156   run_loop.Run();
    157 
    158   // Check that server saw the correct value, but the client has not yet.
    159   EXPECT_EQ(7, server_impl.last_server_value_seen());
    160   EXPECT_EQ(0, last_client_callback_value_seen_);
    161 
    162   // Now run the Callback.
    163   server_impl.RunCallback();
    164   run_loop2.Run();
    165 
    166   // Check that the client has now seen the correct value.
    167   EXPECT_EQ(7, last_client_callback_value_seen_);
    168 
    169   // Initialize the test values again.
    170   server_impl.resetLastServerValueSeen();
    171   last_client_callback_value_seen_ = 0;
    172 
    173   // Invoke the Echo method again.
    174   base::RunLoop run_loop3, run_loop4;
    175   server_impl.set_closure(run_loop3.QuitClosure());
    176   interface_ptr_->EchoInt(
    177       13,
    178       BindValueSaver(&last_client_callback_value_seen_,
    179                      run_loop4.QuitClosure()));
    180   run_loop3.Run();
    181 
    182   // Check that server saw the correct value, but the client has not yet.
    183   EXPECT_EQ(13, server_impl.last_server_value_seen());
    184   EXPECT_EQ(0, last_client_callback_value_seen_);
    185 
    186   // Now run the Callback again.
    187   server_impl.RunCallback();
    188   run_loop4.Run();
    189 
    190   // Check that the client has now seen the correct value again.
    191   EXPECT_EQ(13, last_client_callback_value_seen_);
    192 }
    193 
    194 // Tests that running the Callback after the Binding has been deleted
    195 // results in a clean failure.
    196 TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
    197   // Create the ServerImpl.
    198   InterfaceImpl server_impl;
    199   base::RunLoop run_loop;
    200   {
    201     // Create the binding in an inner scope so it can be deleted first.
    202     Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
    203     interface_ptr_.set_connection_error_handler(run_loop.QuitClosure());
    204 
    205     // Initialize the test values.
    206     server_impl.resetLastServerValueSeen();
    207     last_client_callback_value_seen_ = 0;
    208 
    209     // Invoke the Echo method.
    210     base::RunLoop run_loop2;
    211     server_impl.set_closure(run_loop2.QuitClosure());
    212     interface_ptr_->EchoInt(
    213         7,
    214         BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
    215     run_loop2.Run();
    216   }
    217   // The binding has now been destroyed and the pipe is closed.
    218 
    219   // Check that server saw the correct value, but the client has not yet.
    220   EXPECT_EQ(7, server_impl.last_server_value_seen());
    221   EXPECT_EQ(0, last_client_callback_value_seen_);
    222 
    223   // Now try to run the Callback. This should do nothing since the pipe
    224   // is closed.
    225   EXPECT_TRUE(server_impl.RunCallback());
    226   PumpMessages();
    227 
    228   // Check that the client has still not seen the correct value.
    229   EXPECT_EQ(0, last_client_callback_value_seen_);
    230 
    231   // Attempt to invoke the method again and confirm that an error was
    232   // encountered.
    233   interface_ptr_->EchoInt(
    234       13,
    235       BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
    236   run_loop.Run();
    237   EXPECT_TRUE(interface_ptr_.encountered_error());
    238 }
    239 
    240 // Tests that deleting a Callback without running it after the corresponding
    241 // binding has already been deleted does not result in a crash.
    242 TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
    243   // Create the ServerImpl.
    244   InterfaceImpl server_impl;
    245   {
    246     // Create the binding in an inner scope so it can be deleted first.
    247     Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
    248 
    249     // Initialize the test values.
    250     server_impl.resetLastServerValueSeen();
    251     last_client_callback_value_seen_ = 0;
    252 
    253     // Invoke the Echo method.
    254     base::RunLoop run_loop;
    255     server_impl.set_closure(run_loop.QuitClosure());
    256     interface_ptr_->EchoInt(
    257         7,
    258         BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
    259     run_loop.Run();
    260   }
    261   // The binding has now been destroyed and the pipe is closed.
    262 
    263   // Check that server saw the correct value, but the client has not yet.
    264   EXPECT_EQ(7, server_impl.last_server_value_seen());
    265   EXPECT_EQ(0, last_client_callback_value_seen_);
    266 
    267   // Delete the callback without running it. This should not
    268   // cause a problem because the insfrastructure can detect that the
    269   // binding has already been destroyed and the pipe is closed.
    270   server_impl.DeleteCallback();
    271 }
    272 
    273 // Tests that closing a Binding allows us to delete a callback
    274 // without running it without encountering a crash.
    275 TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
    276   // Create the ServerImpl and the Binding.
    277   InterfaceImpl server_impl;
    278   Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
    279 
    280   // Initialize the test values.
    281   server_impl.resetLastServerValueSeen();
    282   last_client_callback_value_seen_ = 0;
    283 
    284   // Invoke the Echo method.
    285   base::RunLoop run_loop;
    286   server_impl.set_closure(run_loop.QuitClosure());
    287   interface_ptr_->EchoInt(
    288       7,
    289       BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
    290   run_loop.Run();
    291 
    292   // Check that server saw the correct value, but the client has not yet.
    293   EXPECT_EQ(7, server_impl.last_server_value_seen());
    294   EXPECT_EQ(0, last_client_callback_value_seen_);
    295 
    296   // Now close the Binding.
    297   binding.Close();
    298 
    299   // Delete the callback without running it. This should not
    300   // cause a crash because the insfrastructure can detect that the
    301   // binding has already been closed.
    302   server_impl.DeleteCallback();
    303 
    304   // Check that the client has still not seen the correct value.
    305   EXPECT_EQ(0, last_client_callback_value_seen_);
    306 }
    307 
    308 // Tests that deleting a Callback without using it before the
    309 // Binding has been destroyed or closed results in a DCHECK.
    310 TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
    311   // Create the ServerImpl and the Binding.
    312   InterfaceImpl server_impl;
    313   Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
    314 
    315   // Initialize the test values.
    316   server_impl.resetLastServerValueSeen();
    317   last_client_callback_value_seen_ = 0;
    318 
    319   // Invoke the Echo method.
    320   base::RunLoop run_loop;
    321   server_impl.set_closure(run_loop.QuitClosure());
    322   interface_ptr_->EchoInt(
    323       7,
    324       BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
    325   run_loop.Run();
    326 
    327   // Check that server saw the correct value, but the client has not yet.
    328   EXPECT_EQ(7, server_impl.last_server_value_seen());
    329   EXPECT_EQ(0, last_client_callback_value_seen_);
    330 
    331 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && !defined(OS_ANDROID)
    332   // Delete the callback without running it. This should cause a crash in debug
    333   // builds due to a DCHECK.
    334   std::string regex("Check failed: !is_valid");
    335 #if defined(OS_WIN)
    336   // TODO(msw): Fix MOJO_DCHECK logs and EXPECT_DEATH* on Win: crbug.com/535014
    337   regex.clear();
    338 #endif  // OS_WIN
    339   EXPECT_DEATH_IF_SUPPORTED(server_impl.DeleteCallback(), regex.c_str());
    340 #endif  // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
    341         // !defined(OS_ANDROID)
    342 }
    343 
    344 }  // namespace
    345 }  // namespace test
    346 }  // namespace mojo
    347