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