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 #include <rtl/ustring.h>
32 #include <rtl/ustring.hxx>
33 
34 #ifndef _OSL_THREAD_HXX
35 #include <osl/thread.hxx>
36 #endif
37 #include <osl/time.h>
38 
39 #include <rtl/instance.hxx>
40 
41 #include "gtest/gtest.h"
42 
43 // -----------------------------------------------------------------------------
44 #define CONST_TEST_STRING "gregorian"
45 
46 namespace {
47 struct Gregorian : public rtl::StaticWithInit<const ::rtl::OUString, Gregorian> {
48     const ::rtl::OUString operator () () {
49         return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CONST_TEST_STRING ));
50     }
51 };
52 }
53 
54 inline void printOUString( ::rtl::OUString const & _suStr )
55 {
56     rtl::OString aString;
57 
58     printf( "OUString: " );
59     aString = ::rtl::OUStringToOString( _suStr, RTL_TEXTENCODING_ASCII_US );
60     printf( "'%s'\n", aString.getStr( ) );
61 }
62 
63 // -----------------------------------------------------------------------------
64 namespace ThreadHelper
65 {
66     // typedef enum {
67     //     QUIET=1,
68     //     VERBOSE
69     // } eSleepVerboseMode;
70 
71     void thread_sleep_tenth_sec(sal_Int32 _nTenthSec/*, eSleepVerboseMode nVerbose = VERBOSE*/)
72     {
73         // if (nVerbose == VERBOSE)
74         // {
75         //     printf("wait %d tenth seconds. ", _nTenthSec );
76         //     fflush(stdout);
77         // }
78 #ifdef WNT      //Windows
79         Sleep(_nTenthSec * 100 );
80 #endif
81 #if ( defined UNX ) || ( defined OS2 )  //Unix
82         TimeValue nTV;
83         nTV.Seconds = static_cast<sal_uInt32>( _nTenthSec/10 );
84         nTV.Nanosec = ( (_nTenthSec%10 ) * 100000000 );
85         osl_waitThread(&nTV);
86 #endif
87         // if (nVerbose == VERBOSE)
88         // {
89         //     printf("done\n");
90         // }
91     }
92 }
93 
94 // -----------------------------------------------------------------------------
95 
96 /** Simple thread for testing Thread-create.
97  * Just add 1 of value 0, and after running, result is 1.
98  */
99 class OGetThread : public osl::Thread
100 {
101     sal_Int32 m_nOK;
102     sal_Int32 m_nFails;
103 
104     rtl::OUString m_sConstStr;
105 public:
106     OGetThread()
107             :m_nOK(0),
108              m_nFails(0)
109         {
110             m_sConstStr = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CONST_TEST_STRING ));
111         }
112 
113     sal_Int32 getOK() { return m_nOK; }
114     sal_Int32 getFails() {return m_nFails;}
115 
116 protected:
117 
118     /** guarded value which initialized 0
119 
120         @see ThreadSafeValue
121     */
122     void SAL_CALL run()
123         {
124             while(schedule())
125             {
126                 rtl::OUString aStr = Gregorian::get();
127                 // printOUString(aStr);
128                 // printOUString(m_sConstStr);
129                 if (aStr.equals(m_sConstStr))
130                 {
131                     m_nOK++;
132                 }
133                 else
134                 {
135                     m_nFails++;
136                 }
137                 ThreadHelper::thread_sleep_tenth_sec(1);
138             }
139         }
140 
141 public:
142 
143     virtual void SAL_CALL suspend()
144         {
145             ::osl::Thread::suspend();
146         }
147 
148     ~OGetThread()
149         {
150             if (isRunning())
151             {
152                 printf("error: not terminated.\n");
153             }
154         }
155 };
156 
157 // -----------------------------------------------------------------------------
158 namespace rtl_DoubleLocking
159 {
160 
161 /** Test of the osl::Thread::create method
162  */
163 
164     class getValue : public ::testing::Test
165     {
166     public:
167 
168         // initialise your test code values here.
169         void SetUp()
170             {
171             }
172 
173         void TearDown()
174             {
175             }
176     }; // class create
177 
178     TEST_F(getValue, getValue_001)
179     {
180         rtl::OUString aStr = Gregorian::get();
181         printOUString(aStr);
182 
183         ASSERT_TRUE(aStr.getLength() != 0)
184             << "Gregorian::get() failed, wrong value expected.";
185     }
186 
187     /** check 2 threads.
188 
189         ALGORITHM:
190         Here the function should show, that 2 different threads,
191         which only increase a value, should run at the same time with same prio.
192         The test fails, if the difference between the two values is more than 5%
193         but IMHO this isn't a failure, it's only a feature of the OS.
194     */
195     TEST_F(getValue, getValue_002)
196     {
197         // initial 5 threads with different priorities
198         OGetThread* pThread = new OGetThread();
199         OGetThread* p2Thread = new OGetThread();
200 
201         //Create them and start running at the same time
202         pThread->create();
203         p2Thread->create();
204 
205         ThreadHelper::thread_sleep_tenth_sec(50);
206 
207         pThread->terminate();
208         p2Thread->terminate();
209 
210         sal_Int32 nValueOK = 0;
211         nValueOK = pThread->getOK();
212 
213         sal_Int32 nValueOK2 = 0;
214         nValueOK2 = p2Thread->getOK();
215 
216         printf("Value in Thread #1 is %d\n", nValueOK);
217         printf("Value in Thread #2 is %d\n", nValueOK2);
218 
219         sal_Int32 nValueFails = 0;
220         nValueFails = pThread->getFails();
221 
222         sal_Int32 nValueFails2 = 0;
223         nValueFails2 = p2Thread->getFails();
224 
225         printf("Fails in Thread #1 is %d\n", nValueFails);
226         printf("Fails in Thread #2 is %d\n", nValueFails2);
227 
228         // ThreadHelper::thread_sleep_tenth_sec(1);
229         pThread->join();
230         p2Thread->join();
231 
232         delete pThread;
233         delete p2Thread;
234 
235         ASSERT_TRUE(nValueOK != 0 && nValueFails == 0 && nValueFails2 == 0)
236             << "getValue() failed, wrong value expected.";
237     }
238 
239 } // namespace rtl_DoubleLocking
240 
241 int main(int argc, char **argv)
242 {
243     ::testing::InitGoogleTest(&argc, argv);
244     return RUN_ALL_TESTS();
245 }
246