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