1/* 2 * libjingle 3 * Copyright 2015 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "talk/app/webrtc/dtlsidentitystore.h" 29 30#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" 31#include "webrtc/base/gunit.h" 32#include "webrtc/base/logging.h" 33#include "webrtc/base/ssladapter.h" 34 35using webrtc::DtlsIdentityStoreImpl; 36 37static const int kTimeoutMs = 10000; 38 39class MockDtlsIdentityRequestObserver : 40 public webrtc::DtlsIdentityRequestObserver { 41 public: 42 MockDtlsIdentityRequestObserver() 43 : call_back_called_(false), last_request_success_(false) {} 44 void OnFailure(int error) override { 45 EXPECT_FALSE(call_back_called_); 46 call_back_called_ = true; 47 last_request_success_ = false; 48 } 49 void OnSuccess(const std::string& der_cert, 50 const std::string& der_private_key) override { 51 LOG(LS_WARNING) << "The string version of OnSuccess is called unexpectedly"; 52 EXPECT_TRUE(false); 53 } 54 void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> identity) override { 55 EXPECT_FALSE(call_back_called_); 56 call_back_called_ = true; 57 last_request_success_ = true; 58 } 59 60 void Reset() { 61 call_back_called_ = false; 62 last_request_success_ = false; 63 } 64 65 bool LastRequestSucceeded() const { 66 return call_back_called_ && last_request_success_; 67 } 68 69 bool call_back_called() const { 70 return call_back_called_; 71 } 72 73 private: 74 bool call_back_called_; 75 bool last_request_success_; 76}; 77 78class DtlsIdentityStoreTest : public testing::Test { 79 protected: 80 DtlsIdentityStoreTest() 81 : worker_thread_(new rtc::Thread()), 82 store_(new DtlsIdentityStoreImpl(rtc::Thread::Current(), 83 worker_thread_.get())), 84 observer_( 85 new rtc::RefCountedObject<MockDtlsIdentityRequestObserver>()) { 86 RTC_CHECK(worker_thread_->Start()); 87 } 88 ~DtlsIdentityStoreTest() {} 89 90 static void SetUpTestCase() { 91 rtc::InitializeSSL(); 92 } 93 static void TearDownTestCase() { 94 rtc::CleanupSSL(); 95 } 96 97 rtc::scoped_ptr<rtc::Thread> worker_thread_; 98 rtc::scoped_ptr<DtlsIdentityStoreImpl> store_; 99 rtc::scoped_refptr<MockDtlsIdentityRequestObserver> observer_; 100}; 101 102TEST_F(DtlsIdentityStoreTest, RequestIdentitySuccessRSA) { 103 EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(rtc::KT_RSA), kTimeoutMs); 104 105 store_->RequestIdentity(rtc::KT_RSA, observer_.get()); 106 EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); 107 108 EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(rtc::KT_RSA), kTimeoutMs); 109 110 observer_->Reset(); 111 112 // Verifies that the callback is async when a free identity is ready. 113 store_->RequestIdentity(rtc::KT_RSA, observer_.get()); 114 EXPECT_FALSE(observer_->call_back_called()); 115 EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); 116} 117 118TEST_F(DtlsIdentityStoreTest, RequestIdentitySuccessECDSA) { 119 // Since store currently does not preemptively generate free ECDSA identities 120 // we do not invoke HasFreeIdentityForTesting between requests. 121 122 store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); 123 EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); 124 125 observer_->Reset(); 126 127 // Verifies that the callback is async when a free identity is ready. 128 store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); 129 EXPECT_FALSE(observer_->call_back_called()); 130 EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); 131} 132 133TEST_F(DtlsIdentityStoreTest, DeleteStoreEarlyNoCrashRSA) { 134 EXPECT_FALSE(store_->HasFreeIdentityForTesting(rtc::KT_RSA)); 135 136 store_->RequestIdentity(rtc::KT_RSA, observer_.get()); 137 store_.reset(); 138 139 worker_thread_->Stop(); 140 EXPECT_FALSE(observer_->call_back_called()); 141} 142 143TEST_F(DtlsIdentityStoreTest, DeleteStoreEarlyNoCrashECDSA) { 144 EXPECT_FALSE(store_->HasFreeIdentityForTesting(rtc::KT_ECDSA)); 145 146 store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); 147 store_.reset(); 148 149 worker_thread_->Stop(); 150 EXPECT_FALSE(observer_->call_back_called()); 151} 152 153