michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original author: ekr@rtfm.com michael@0: #include michael@0: michael@0: #include "prio.h" michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsXPCOMGlue.h" michael@0: michael@0: #include "mozilla/RefPtr.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "nsIComponentRegistrar.h" michael@0: #include "nsIIOService.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsISocketTransportService.h" michael@0: michael@0: #include "nsASocketHandler.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: #include "runnable_utils.h" michael@0: #include "mtransport_test_utils.h" michael@0: michael@0: #define GTEST_HAS_RTTI 0 michael@0: #include "gtest/gtest.h" michael@0: #include "gtest_utils.h" michael@0: michael@0: using namespace mozilla; michael@0: MtransportTestUtils *test_utils; michael@0: michael@0: namespace { michael@0: michael@0: class Destructor { michael@0: public: michael@0: Destructor(bool* destroyed) : destroyed_(destroyed) {} michael@0: ~Destructor() { michael@0: std::cerr << "Destructor called" << std::endl; michael@0: *destroyed_ = true; michael@0: } michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Destructor) michael@0: michael@0: private: michael@0: bool *destroyed_; michael@0: }; michael@0: michael@0: class TargetClass { michael@0: public: michael@0: TargetClass(int *ran) : ran_(ran) {} michael@0: michael@0: void m1(int x) { michael@0: std::cerr << __FUNCTION__ << " " << x << std::endl; michael@0: *ran_ = 1; michael@0: } michael@0: michael@0: void m2(int x, int y) { michael@0: std::cerr << __FUNCTION__ << " " << x << " " << y << std::endl; michael@0: *ran_ = 2; michael@0: } michael@0: michael@0: void m1set(bool *z) { michael@0: std::cerr << __FUNCTION__ << std::endl; michael@0: *z = true; michael@0: } michael@0: int return_int(int x) { michael@0: std::cerr << __FUNCTION__ << std::endl; michael@0: return x; michael@0: } michael@0: void destructor_target(Destructor*) { michael@0: } michael@0: michael@0: void destructor_target_ref(RefPtr destructor) { michael@0: } michael@0: michael@0: int *ran_; michael@0: }; michael@0: michael@0: michael@0: class RunnableArgsTest : public ::testing::Test { michael@0: public: michael@0: RunnableArgsTest() : ran_(0), cl_(&ran_){} michael@0: michael@0: void Test1Arg() { michael@0: nsRunnable * r = WrapRunnable(&cl_, &TargetClass::m1, 1); michael@0: r->Run(); michael@0: ASSERT_EQ(1, ran_); michael@0: } michael@0: michael@0: void Test2Args() { michael@0: nsRunnable* r = WrapRunnable(&cl_, &TargetClass::m2, 1, 2); michael@0: r->Run(); michael@0: ASSERT_EQ(2, ran_); michael@0: } michael@0: michael@0: private: michael@0: int ran_; michael@0: TargetClass cl_; michael@0: }; michael@0: michael@0: class DispatchTest : public ::testing::Test { michael@0: public: michael@0: DispatchTest() : ran_(0), cl_(&ran_) {} michael@0: michael@0: void SetUp() { michael@0: nsresult rv; michael@0: target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); michael@0: ASSERT_TRUE(NS_SUCCEEDED(rv)); michael@0: } michael@0: michael@0: void Test1Arg() { michael@0: nsRunnable* r = WrapRunnable(&cl_, &TargetClass::m1, 1); michael@0: target_->Dispatch(r, NS_DISPATCH_SYNC); michael@0: ASSERT_EQ(1, ran_); michael@0: } michael@0: michael@0: void Test2Args() { michael@0: nsRunnable* r = WrapRunnable(&cl_, &TargetClass::m2, 1, 2); michael@0: target_->Dispatch(r, NS_DISPATCH_SYNC); michael@0: ASSERT_EQ(2, ran_); michael@0: } michael@0: michael@0: void Test1Set() { michael@0: bool x = false; michael@0: target_->Dispatch(WrapRunnable(&cl_, &TargetClass::m1set, &x), michael@0: NS_DISPATCH_SYNC); michael@0: ASSERT_TRUE(x); michael@0: } michael@0: michael@0: void TestRet() { michael@0: int z; michael@0: int x = 10; michael@0: michael@0: target_->Dispatch(WrapRunnableRet(&cl_, &TargetClass::return_int, x, &z), michael@0: NS_DISPATCH_SYNC); michael@0: ASSERT_EQ(10, z); michael@0: } michael@0: michael@0: protected: michael@0: int ran_; michael@0: TargetClass cl_; michael@0: nsCOMPtr target_; michael@0: }; michael@0: michael@0: michael@0: TEST_F(RunnableArgsTest, OneArgument) { michael@0: Test1Arg(); michael@0: } michael@0: michael@0: TEST_F(RunnableArgsTest, TwoArguments) { michael@0: Test2Args(); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, OneArgument) { michael@0: Test1Arg(); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TwoArguments) { michael@0: Test2Args(); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, Test1Set) { michael@0: Test1Set(); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TestRet) { michael@0: TestRet(); michael@0: } michael@0: michael@0: void SetNonMethod(TargetClass *cl, int x) { michael@0: cl->m1(x); michael@0: } michael@0: michael@0: int SetNonMethodRet(TargetClass *cl, int x) { michael@0: cl->m1(x); michael@0: michael@0: return x; michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TestNonMethod) { michael@0: test_utils->sts_target()->Dispatch( michael@0: WrapRunnableNM(SetNonMethod, &cl_, 10), NS_DISPATCH_SYNC); michael@0: michael@0: ASSERT_EQ(1, ran_); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TestNonMethodRet) { michael@0: int z; michael@0: michael@0: test_utils->sts_target()->Dispatch( michael@0: WrapRunnableNMRet(SetNonMethodRet, &cl_, 10, &z), NS_DISPATCH_SYNC); michael@0: michael@0: ASSERT_EQ(1, ran_); michael@0: ASSERT_EQ(10, z); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TestDestructor) { michael@0: bool destroyed = false; michael@0: RefPtr destructor = new Destructor(&destroyed); michael@0: target_->Dispatch(WrapRunnable(&cl_, &TargetClass::destructor_target, michael@0: destructor), michael@0: NS_DISPATCH_SYNC); michael@0: ASSERT_FALSE(destroyed); michael@0: destructor = nullptr; michael@0: ASSERT_TRUE(destroyed); michael@0: } michael@0: michael@0: TEST_F(DispatchTest, TestDestructorRef) { michael@0: bool destroyed = false; michael@0: RefPtr destructor = new Destructor(&destroyed); michael@0: target_->Dispatch(WrapRunnable(&cl_, &TargetClass::destructor_target_ref, michael@0: destructor), michael@0: NS_DISPATCH_SYNC); michael@0: ASSERT_FALSE(destroyed); michael@0: destructor = nullptr; michael@0: ASSERT_TRUE(destroyed); michael@0: } michael@0: michael@0: michael@0: } // end of namespace michael@0: michael@0: michael@0: int main(int argc, char **argv) { michael@0: test_utils = new MtransportTestUtils(); michael@0: michael@0: // Start the tests michael@0: ::testing::InitGoogleTest(&argc, argv); michael@0: michael@0: int rv = RUN_ALL_TESTS(); michael@0: delete test_utils; michael@0: return rv; michael@0: } michael@0: