xref: /AOO41X/main/sal/qa/rtl/doublelock/rtl_doublelocking.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sal.hxx"
30 //------------------------------------------------------------------------
31 // include files
32 //------------------------------------------------------------------------
33 #include <sal/types.h>
34 
35 #ifndef _RTL_USTRING_HXX_
36 #include <rtl/string.hxx>
37 #endif
38 
39 #ifndef _OSL_THREAD_HXX
40 #include <osl/thread.hxx>
41 #endif
42 #include <osl/time.h>
43 
44 #include <rtl/instance.hxx>
45 
46 #include <testshl/simpleheader.hxx>
47 
48 // -----------------------------------------------------------------------------
49 #define CONST_TEST_STRING "gregorian"
50 
51 namespace {
52 struct Gregorian : public rtl::StaticWithInit<const ::rtl::OUString, Gregorian> {
53     const ::rtl::OUString operator () () {
54         return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CONST_TEST_STRING ));
55     }
56 };
57 }
58 
59 inline void printOUString( ::rtl::OUString const & _suStr )
60 {
61     rtl::OString aString;
62 
63     t_print( "OUString: " );
64     aString = ::rtl::OUStringToOString( _suStr, RTL_TEXTENCODING_ASCII_US );
65     t_print( "'%s'\n", aString.getStr( ) );
66 }
67 
68 // -----------------------------------------------------------------------------
69 namespace ThreadHelper
70 {
71     // typedef enum {
72     //     QUIET=1,
73     //     VERBOSE
74     // } eSleepVerboseMode;
75 
76     void thread_sleep_tenth_sec(sal_Int32 _nTenthSec/*, eSleepVerboseMode nVerbose = VERBOSE*/)
77     {
78         // if (nVerbose == VERBOSE)
79         // {
80         //     t_print("wait %d tenth seconds. ", _nTenthSec );
81         //     fflush(stdout);
82         // }
83 #ifdef WNT      //Windows
84         Sleep(_nTenthSec * 100 );
85 #endif
86 #if ( defined UNX ) || ( defined OS2 )  //Unix
87         TimeValue nTV;
88         nTV.Seconds = static_cast<sal_uInt32>( _nTenthSec/10 );
89         nTV.Nanosec = ( (_nTenthSec%10 ) * 100000000 );
90         osl_waitThread(&nTV);
91 #endif
92         // if (nVerbose == VERBOSE)
93         // {
94         //     t_print("done\n");
95         // }
96     }
97 }
98 
99 // -----------------------------------------------------------------------------
100 
101 /** Simple thread for testing Thread-create.
102  * Just add 1 of value 0, and after running, result is 1.
103  */
104 class OGetThread : public osl::Thread
105 {
106     sal_Int32 m_nOK;
107     sal_Int32 m_nFails;
108 
109     rtl::OUString m_sConstStr;
110 public:
111     OGetThread()
112             :m_nOK(0),
113              m_nFails(0)
114         {
115             m_sConstStr = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CONST_TEST_STRING ));
116         }
117 
118     sal_Int32 getOK() { return m_nOK; }
119     sal_Int32 getFails() {return m_nFails;}
120 
121 protected:
122 
123     /** guarded value which initialized 0
124 
125         @see ThreadSafeValue
126     */
127     void SAL_CALL run()
128         {
129             while(schedule())
130             {
131                 rtl::OUString aStr = Gregorian::get();
132                 // printOUString(aStr);
133                 // printOUString(m_sConstStr);
134                 if (aStr.equals(m_sConstStr))
135                 {
136                     m_nOK++;
137                 }
138                 else
139                 {
140                     m_nFails++;
141                 }
142                 ThreadHelper::thread_sleep_tenth_sec(1);
143             }
144         }
145 
146 public:
147 
148     virtual void SAL_CALL suspend()
149         {
150             ::osl::Thread::suspend();
151         }
152 
153     ~OGetThread()
154         {
155             if (isRunning())
156             {
157                 t_print("error: not terminated.\n");
158             }
159         }
160 };
161 
162 // -----------------------------------------------------------------------------
163 namespace rtl_DoubleLocking
164 {
165 
166 /** Test of the osl::Thread::create method
167  */
168 
169     class getValue : public CppUnit::TestFixture
170     {
171     public:
172 
173         // initialise your test code values here.
174         void setUp()
175             {
176             }
177 
178         void tearDown()
179             {
180             }
181 
182 
183         void getValue_001()
184             {
185                 rtl::OUString aStr = Gregorian::get();
186                 printOUString(aStr);
187 
188                 CPPUNIT_ASSERT_MESSAGE(
189                     "Gregorian::get() failed, wrong value expected.",
190                     aStr.getLength() != 0
191                     );
192             }
193 
194         /** check 2 threads.
195 
196             ALGORITHM:
197             Here the function should show, that 2 different threads,
198             which only increase a value, should run at the same time with same prio.
199             The test fails, if the difference between the two values is more than 5%
200             but IMHO this isn't a failure, it's only a feature of the OS.
201         */
202 
203         void getValue_002()
204             {
205                 // initial 5 threads with different priorities
206                 OGetThread* pThread = new OGetThread();
207                 OGetThread* p2Thread = new OGetThread();
208 
209                 //Create them and start running at the same time
210                 pThread->create();
211                 p2Thread->create();
212 
213                 ThreadHelper::thread_sleep_tenth_sec(50);
214 
215                 pThread->terminate();
216                 p2Thread->terminate();
217 
218                 sal_Int32 nValueOK = 0;
219                 nValueOK = pThread->getOK();
220 
221                 sal_Int32 nValueOK2 = 0;
222                 nValueOK2 = p2Thread->getOK();
223 
224                 t_print("Value in Thread #1 is %d\n", nValueOK);
225                 t_print("Value in Thread #2 is %d\n", nValueOK2);
226 
227                 sal_Int32 nValueFails = 0;
228                 nValueFails = pThread->getFails();
229 
230                 sal_Int32 nValueFails2 = 0;
231                 nValueFails2 = p2Thread->getFails();
232 
233                 t_print("Fails in Thread #1 is %d\n", nValueFails);
234                 t_print("Fails in Thread #2 is %d\n", nValueFails2);
235 
236                 // ThreadHelper::thread_sleep_tenth_sec(1);
237                 pThread->join();
238                 p2Thread->join();
239 
240                 delete pThread;
241                 delete p2Thread;
242 
243                 CPPUNIT_ASSERT_MESSAGE(
244                     "getValue() failed, wrong value expected.",
245                     nValueOK != 0 && nValueFails == 0 && nValueFails2 == 0
246                     );
247             }
248 
249         CPPUNIT_TEST_SUITE(getValue);
250         CPPUNIT_TEST(getValue_001);
251         CPPUNIT_TEST(getValue_002);
252         CPPUNIT_TEST_SUITE_END();
253     }; // class create
254 // -----------------------------------------------------------------------------
255     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_DoubleLocking::getValue, "rtl_DoubleLocking");
256 } // namespace rtl_DoubleLocking
257 
258 // this macro creates an empty function, which will called by the RegisterAllFunctions()
259 // to let the user the possibility to also register some functions by hand.
260 NOADDITIONAL;
261