/* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // First include (the generated) my_config.h, to get correct platform defines. #include "my_config.h" #include #ifdef _WIN32 #include #else #include #endif #include "runtime.hpp" #include "yassl_int.hpp" #include "thread_utils.h" namespace { using thread::Notification; using thread::Thread; class Yassl_thread : public Thread { public: Yassl_thread(Notification *go, Notification *done) : m_sessions_instance(NULL), m_go(go), m_done(done) {} virtual void run() { // Wait until my creator tells me to go. m_go->wait_for_notification(); yaSSL::Sessions &sessions= yaSSL::GetSessions(); m_sessions_instance= &sessions; // Tell my creator I'm done. m_done->notify(); } yaSSL::Sessions *m_sessions_instance; private: Notification *m_go; Notification *m_done; }; /** Verify that yaSSL::sessionsInstance is indeed a singleton. If any of the EXPECT_EQ below reports an error, it is not. We can also run 'valgrind ./yassl-t'. If there are errors, valgrind will report a multiple of sizeof(yaSSL::Sessions) == 80 bytes lost. */ TEST(YasslTest, ManySessions) { Notification go[5]; Notification done[5]; Yassl_thread t0(&go[0], &done[0]); Yassl_thread t1(&go[1], &done[1]); Yassl_thread t2(&go[2], &done[2]); Yassl_thread t3(&go[3], &done[3]); Yassl_thread t4(&go[4], &done[4]); t0.start(); t1.start(); t2.start(); t3.start(); t4.start(); for (int ix= 0; ix < 5; ++ix) go[ix].notify(); for (int ix= 0; ix < 5; ++ix) done[ix].wait_for_notification(); // These are most likely to fail unless we use pthread_once. EXPECT_EQ(t0.m_sessions_instance, t1.m_sessions_instance); EXPECT_EQ(t0.m_sessions_instance, t2.m_sessions_instance); EXPECT_EQ(t0.m_sessions_instance, t3.m_sessions_instance); EXPECT_EQ(t0.m_sessions_instance, t4.m_sessions_instance); // These rarely fail. If they do, we have more than two instances. EXPECT_EQ(t1.m_sessions_instance, t2.m_sessions_instance); EXPECT_EQ(t1.m_sessions_instance, t3.m_sessions_instance); EXPECT_EQ(t1.m_sessions_instance, t4.m_sessions_instance); EXPECT_EQ(t2.m_sessions_instance, t3.m_sessions_instance); EXPECT_EQ(t2.m_sessions_instance, t4.m_sessions_instance); EXPECT_EQ(t3.m_sessions_instance, t4.m_sessions_instance); t0.join(); t1.join(); t2.join(); t3.join(); t4.join(); yaSSL_CleanUp(); } }