xref: /trunk/main/sal/qa/osl/security/osl_Security.cxx (revision 63045d55)
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 //------------------------------------------------------------------------
28 // header file
29 //------------------------------------------------------------------------
30 #include <osl_Security_Const.h>
31 
32 using namespace	osl;
33 using namespace	rtl;
34 
35 
36 //------------------------------------------------------------------------
37 // helper functions and classes
38 //------------------------------------------------------------------------
39 
40 /** print Boolean value.
41 */
42 inline void printBool( sal_Bool bOk )
43 {
44 	//printf("#printBool# " );
45 	( sal_True == bOk ) ? printf("TRUE!\n" ): printf("FALSE!\n" );
46 }
47 
48 /** print a UNI_CODE String.
49 */
50 inline void printUString( const ::rtl::OUString & str )
51 {
52 	rtl::OString aString;
53 
54 	//printf("#printUString_u# " );
55 	aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
56 	printf("%s\n", aString.getStr( ) );
57 }
58 
59 
60 //------------------------------------------------------------------------
61 // test code start here
62 //------------------------------------------------------------------------
63 
64 namespace osl_Security
65 {
66 
67 	/** testing the method:
68 		Security()
69 	*/
70 	class ctors : public ::testing::Test
71 	{
72 	public:
73 		sal_Bool bRes, bRes1;
74 
75 	}; // class ctors
76 
77 	TEST_F(ctors, ctors_001)
78 	{
79 		::osl::Security aSec;
80 
81 		ASSERT_TRUE(aSec.getHandle( ) != NULL) << "#test comment#: create a security  its handle should not be NULL.";
82 	}
83 
84 	/** testing the methods:
85 		inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString& strName,
86 									   const ::rtl::OUString& strPasswd);
87 		inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString & strName,
88 									   const ::rtl::OUString & strPasswd,
89 									   const ::rtl::OUString & strFileServer);
90 	*/
91 	class logonUser : public ::testing::Test
92 	{
93 	public:
94 		sal_Bool bRes;
95 
96 		void logonUser_user_pwd( )
97 		{
98 			::osl::Security aSec;
99 			bRes = aSec.logonUser( aLogonUser, aLogonPasswd );
100 
101 			ASSERT_TRUE(( sal_True == bRes )) << "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).";
102 		}
103 
104 		void logonUser_user_pwd_server( )
105 		{
106 			::osl::Security aSec;
107 			bRes = aSec.logonUser( aLogonUser, aLogonPasswd, aFileServer );
108 
109 			ASSERT_TRUE(( sal_True == bRes )) << "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).";
110 		}
111 	}; // class logonUser
112 
113 	TEST_F(logonUser, logonUser_001)
114 	{
115 		if  ( !aStringForward.equals( aNullURL )  && aStringForward.indexOf( (sal_Unicode)' ' ) != -1 && ( aStringForward.indexOf( ( sal_Unicode ) ' ' ) ==  aStringForward.lastIndexOf( ( sal_Unicode ) ' ' ) ) )
116 		/// if user name and passwd are forwarded
117 		{
118 			logonUser_user_pwd();
119 		}
120 	}
121 
122 	TEST_F(logonUser, logonUser_002)
123 	{
124 		if  ( !aStringForward.equals( aNullURL )  && aStringForward.indexOf( (sal_Unicode)' ' ) != -1 && ( aStringForward.indexOf( ( sal_Unicode ) ' ' ) !=  aStringForward.lastIndexOf( ( sal_Unicode ) ' ' ) ) )
125 		/// if user name and passwd and file server are forwarded
126 		{
127 			logonUser_user_pwd_server();
128 		}
129 	}
130 
131 	/** testing the method:
132 		inline sal_Bool Security::getUserIdent( rtl::OUString& strIdent) const
133 	*/
134 	class getUserIdent : public ::testing::Test
135 	{
136 	public:
137 		sal_Bool bRes, bRes1;
138 	}; // class getUserIdent
139 
140 	TEST_F(getUserIdent, getUserIdent_001)
141 	{
142 		::osl::Security aSec;
143 		::rtl::OUString strID;
144 		bRes = aSec.getUserIdent( strID );
145 
146 		ASSERT_TRUE(( sal_True == strUserID.equals( strID ) ) && ( sal_True == bRes )) << "#test comment#: get UserID and compare it with names got at the beginning of the test.";
147 	}
148 
149 
150 	/** testing the method:
151 		inline sal_Bool SAL_CALL getUserName( ::rtl::OUString& strName) const;
152 	*/
153 	class getUserName : public ::testing::Test
154 	{
155 	public:
156 		sal_Bool bRes, bRes1;
157 	}; // class getUserName
158 
159 	TEST_F(getUserName, getUserName_001)
160 	{
161 		::osl::Security aSec;
162 #ifdef WNT
163 		::rtl::OUString strName( strUserName ), strGetName;
164 #else
165 		::rtl::OUString strName( strUserName ), strGetName;
166 #endif
167 		bRes = aSec.getUserName( strGetName );
168 
169 		sal_Int32 nPos = -1;
170 		if (strName.getLength() > 0)
171 		{
172 			nPos = strGetName.indexOf(strName);
173 		}
174 		ASSERT_TRUE(( nPos >= 0 ) && ( sal_True == bRes )) << "#test comment#: get UserName and compare it with names got at the beginning of the test.";
175 	}
176 
177 	/** testing the method:
178 		inline sal_Bool SAL_CALL getHomeDir( ::rtl::OUString& strDirectory) const;
179 	*/
180 	class getHomeDir : public ::testing::Test
181 	{
182 	public:
183 		sal_Bool bRes, bRes1;
184 	}; // class getHomeDir
185 
186 	TEST_F(getHomeDir, getHomeDir_001)
187 	{
188 		::osl::Security aSec;
189 		::rtl::OUString strHome;
190 		bRes = aSec.getHomeDir( strHome );
191 
192 		ASSERT_TRUE(( sal_True == strHomeDirectory.equals( strHome ) ) && ( sal_True == bRes )) << "#test comment#: getHomeDir and compare it with the info we get at the beginning.";
193 	}
194 
195 	/** testing the method:
196 		inline sal_Bool Security::getConfigDir( rtl::OUString& strDirectory ) const
197 	*/
198 	class getConfigDir : public ::testing::Test
199 	{
200 	public:
201 		sal_Bool bRes, bRes1;
202 	}; // class getConfigDir
203 
204 	TEST_F(getConfigDir, getConfigDir_001)
205 	{
206 		::osl::Security aSec;
207 		::rtl::OUString strConfig;
208 		bRes = aSec.getConfigDir( strConfig );
209 
210 		ASSERT_TRUE(( sal_True == strConfigDirectory.equals( strConfig ) ) && ( sal_True == bRes )) << "#test comment#: getHomeDir and compare it with the info we get at the beginning.";
211 	}
212 
213 	/** testing the method:
214 		inline sal_Bool SAL_CALL isAdministrator() const;
215 	*/
216 	class isAdministrator : public ::testing::Test
217 	{
218 	public:
219 		sal_Bool bRes;
220 	}; // class isAdministrator
221 
222 	TEST_F(isAdministrator, isAdministrator_001)
223 	{
224 		::osl::Security aSec;
225 		bRes = aSec.isAdministrator(  );
226 
227 		ASSERT_TRUE(bRes == isAdmin) << "#test comment#: check if the user is administrator at beginning, compare here.";
228 	}
229 
230 	/** testing the method:
231 		inline oslSecurity getHandle() const;
232 	*/
233 	class getHandle : public ::testing::Test
234 	{
235 	public:
236 		sal_Bool bRes;
237 	}; // class getHandle
238 
239 	TEST_F(getHandle, getHandle_001)
240 	{
241 		::osl::Security aSec;
242 		bRes = aSec.isAdministrator( ) == osl_isAdministrator( aSec.getHandle( ) );
243 
244 		ASSERT_TRUE(bRes == sal_True) << "#test comment#: use getHandle function to call C API.";
245 	}
246 
247     class UserProfile : public ::testing::Test
248     {
249     public:
250     }; // class UserProfile
251 
252     TEST_F(UserProfile, loadUserProfile)
253     {
254         ::osl::Security aSec;
255         sal_Bool bValue = osl_loadUserProfile(aSec.getHandle());
256 
257         ASSERT_TRUE(bValue == sal_False) << "empty function.";
258     }
259 
260     TEST_F(UserProfile, unloadUserProfile)
261     {
262         ::osl::Security aSec;
263         osl_unloadUserProfile(aSec.getHandle());
264         ASSERT_TRUE(sal_True) << "empty function.";
265     }
266 
267     class loginUserOnFileServer : public ::testing::Test
268     {
269     public:
270     }; // class loginUserOnFileServer
271 
272     TEST_F(loginUserOnFileServer, loginUserOnFileServer_001)
273     {
274         rtl::OUString suUserName;
275         rtl::OUString suPassword;
276         rtl::OUString suFileServer;
277         ::osl::Security aSec;
278         oslSecurity pSec = aSec.getHandle();
279 
280         oslSecurityError erg = osl_loginUserOnFileServer(suUserName.pData, suPassword.pData, suFileServer.pData, &pSec);
281 
282         ASSERT_TRUE(erg == osl_Security_E_UserUnknown) << "empty function.";
283     }
284 
285 } // namespace osl_Security
286 
287 
288 // -----------------------------------------------------------------------------
289 
290 /** to do some initialized work, we replace the NOADDITIONAL macro with the initialize work which
291       get current user name, .
292 */
293 
294 int main(int argc, char **argv)
295 {
296 	/// start message
297 	printf("#Initializing ...\n" );
298 	printf("#\n#logonUser function need root/Administrator account to test.\n" );
299 	printf("#You can test by login with root/Administrator, and excute:\n" );
300 	printf("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
301 	printf("#      where username and password are forwarded account info.\n" );
302 	printf("#if no text forwarded, this function will be skipped.\n" );
303 
304 	/// get system information
305 #if ( defined UNX ) || ( defined OS2 )
306 	/// some initialization work for UNIX OS
307 
308 
309 	struct passwd* pw;
310 	EXPECT_TRUE(( pw = getpwuid( getuid() ) ) != NULL) << "getpwuid: no password entry\n";
311 
312 	/// get user ID;
313 	strUserID = ::rtl::OUString::valueOf( ( sal_Int32 )getuid( ) );
314 
315 	/// get user Name;
316 	strUserName = ::rtl::OUString::createFromAscii( pw->pw_name );
317 
318 	/// get home directory;
319 	EXPECT_TRUE(::osl::File::E_None == ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( pw->pw_dir ), strHomeDirectory )) << "#Convert from system path to URL failed.";
320 
321 	/// get config directory;
322 	strConfigDirectory = strHomeDirectory.copy(0);
323 
324 	/// is administrator;
325 	if( !getuid( ) )
326 		isAdmin = sal_True;
327 
328 #endif
329 #if defined ( WNT )
330 	/// some initialization work for Windows OS
331 
332 
333 	/// Get the user name, computer name, user home directory.
334 	LPTSTR lpszSystemInfo;      // pointer to system information string
335 	DWORD cchBuff = BUFSIZE;    // size of computer or user name
336 	TCHAR tchBuffer[BUFSIZE];   // buffer for string
337 
338 	lpszSystemInfo = tchBuffer;
339 	cchBuff = BUFSIZE;
340 	if( GetUserNameA(lpszSystemInfo, &cchBuff) )
341 		strUserName = ::rtl::OUString::createFromAscii( lpszSystemInfo );
342 
343 	if( GetComputerName(lpszSystemInfo, &cchBuff) )
344 		strComputerName = ::rtl::OUString::createFromAscii( lpszSystemInfo );
345 
346 	/// Get user home directory.
347 	HKEY hRegKey;
348 	sal_Char PathA[_MAX_PATH];
349 	::rtl::OUString strHome;
350 	if (RegOpenKey(HKEY_CURRENT_USER,  "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",  &hRegKey) == ERROR_SUCCESS)
351 	{
352 		LONG lRet, lSize = sizeof(PathA);
353 		DWORD Type;
354 
355 		lRet = RegQueryValueEx(hRegKey, "AppData", NULL, &Type, ( unsigned char * )PathA, ( unsigned long * )&lSize);
356 		if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) &&  ( _access( PathA, 0 ) == 0 ) )
357 		{
358 			EXPECT_TRUE(::osl::File::E_None == ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA ), strConfigDirectory )) << "#Convert from system path to URL failed.";
359 		}
360 
361 		lRet = RegQueryValueEx(hRegKey, "Personal", NULL, &Type, ( unsigned char * )PathA, ( unsigned long * )&lSize);
362 		if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) &&  ( _access( PathA, 0 ) == 0 ) )
363 		{
364 			EXPECT_TRUE(::osl::File::E_None == ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA ), strHomeDirectory )) << "#Convert from system path to URL failed.";
365 		}
366 
367 		RegCloseKey(hRegKey);
368 	}
369 
370 
371 	/// Get user Security ID:
372 
373 	// Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
374  	const DWORD INITIAL_SIZE = 32;
375 	DWORD cbSid = 0;
376 	DWORD dwSidBufferSize = INITIAL_SIZE;
377 	DWORD cchDomainName = 0;
378 	DWORD dwDomainBufferSize = INITIAL_SIZE;
379 	WCHAR * wszDomainName = NULL;
380 	SID_NAME_USE eSidType;
381 	DWORD dwErrorCode = 0;
382 
383 	LPCWSTR wszAccName = ( LPWSTR ) strUserName.getStr( );
384 
385 	// Create buffers for the SID and the domain name.
386 	PSID pSid = (PSID) new WIN_BYTE[dwSidBufferSize];
387 	EXPECT_TRUE(pSid!= NULL) << "# creating SID buffer failed.\n";
388 	memset( pSid, 0, dwSidBufferSize);
389 
390 	wszDomainName = new WCHAR[dwDomainBufferSize];
391 	EXPECT_TRUE(wszDomainName != NULL) << "# creating Domain name buffer failed.\n";
392 	memset(wszDomainName, 0, dwDomainBufferSize*sizeof(WCHAR));
393 
394 	// Obtain the SID for the account name passed.
395 	for ( ; ; )
396 	{
397 		// Set the count variables to the buffer sizes and retrieve the SID.
398 		cbSid = dwSidBufferSize;
399 		cchDomainName = dwDomainBufferSize;
400 		if (LookupAccountNameW(
401 		                   NULL,            // Computer name. NULL for the local computer
402 		                   wszAccName,
403 		                   pSid,          // Pointer to the SID buffer. Use NULL to get the size needed,
404 		                   &cbSid,          // Size of the SID buffer needed.
405 		                   wszDomainName,   // wszDomainName,
406 		                   &cchDomainName,
407 		                   &eSidType
408 		                   ))
409 		{
410 			if (IsValidSid( pSid) == FALSE)
411 				wprintf(L"# The SID for %s is invalid.\n", wszAccName);
412 			break;
413 		}
414 		dwErrorCode = GetLastError();
415 
416 		// Check if one of the buffers was too small.
417 		if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
418 		{
419 			if (cbSid > dwSidBufferSize)
420 			{
421 				// Reallocate memory for the SID buffer.
422 				wprintf(L"# The SID buffer was too small. It will be reallocated.\n");
423 				FreeSid( pSid);
424 				pSid = (PSID) new WIN_BYTE[cbSid];
425 				EXPECT_TRUE(pSid!= NULL) << "# re-creating SID buffer failed.\n";
426 				memset( pSid, 0, cbSid);
427 				dwSidBufferSize = cbSid;
428 			}
429 			if (cchDomainName > dwDomainBufferSize)
430 			{
431 				// Reallocate memory for the domain name buffer.
432 				wprintf(L"# The domain name buffer was too small. It will be reallocated.\n");
433 				delete [] wszDomainName;
434 				wszDomainName = new WCHAR[cchDomainName];
435 				EXPECT_TRUE(wszDomainName!= NULL) << "# re-creating domain name buffer failed.\n";
436 				memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));
437 				dwDomainBufferSize = cchDomainName;
438 			}
439 		}
440 		else
441 		{
442 			wprintf(L"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
443 			break;
444 		}
445 	}
446 
447 	// now got SID successfully, only need to compare SID, so I copied the rest lines from source to convert SID to OUString.
448 	PSID_IDENTIFIER_AUTHORITY psia;
449 	DWORD dwSubAuthorities;
450 	DWORD dwSidRev=SID_REVISION;
451 	DWORD dwCounter;
452 	DWORD dwSidSize;
453 	sal_Char	*Ident;
454 
455 	/* obtain SidIdentifierAuthority */
456 	psia=GetSidIdentifierAuthority(pSid);
457 
458 	/* obtain sidsubauthority count */
459 	dwSubAuthorities=*GetSidSubAuthorityCount(pSid)<=5?*GetSidSubAuthorityCount(pSid):5;
460 
461 	/* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
462 	Ident=(sal_Char * )malloc(88*sizeof(sal_Char));
463 
464 	/* prepare S-SID_REVISION- */
465 	dwSidSize=wsprintf(Ident, TEXT("S-%lu-"), dwSidRev);
466 
467 	/* prepare SidIdentifierAuthority */
468 	if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
469 	{
470 	    dwSidSize+=wsprintf(Ident + strlen(Ident),
471 	                TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
472 	                (USHORT)psia->Value[0],
473 	                (USHORT)psia->Value[1],
474 	                (USHORT)psia->Value[2],
475 	                (USHORT)psia->Value[3],
476 	                (USHORT)psia->Value[4],
477 	                (USHORT)psia->Value[5]);
478 	}
479 	else
480 	{
481 	    dwSidSize+=wsprintf(Ident + strlen(Ident),
482 	                TEXT("%lu"),
483 	                (ULONG)(psia->Value[5]      )   +
484 	                (ULONG)(psia->Value[4] <<  8)   +
485 	                (ULONG)(psia->Value[3] << 16)   +
486 	                (ULONG)(psia->Value[2] << 24)   );
487 	}
488 
489 	/* loop through SidSubAuthorities */
490 	for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++)
491 	{
492 		dwSidSize+=wsprintf(Ident + dwSidSize, TEXT("-%lu"),
493 		            *GetSidSubAuthority(pSid, dwCounter) );
494 	}
495 
496 	strUserID = ::rtl::OUString::createFromAscii( Ident );
497 
498 	free(Ident);
499  	delete pSid;
500 	delete [] wszDomainName;
501 
502 
503 	/// check if logged in user is administrator:
504 
505 	WIN_BOOL b;
506 	SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
507 	PSID AdministratorsGroup;
508 	b = AllocateAndInitializeSid(
509 		&NtAuthority,
510 		2,
511 		SECURITY_BUILTIN_DOMAIN_RID,
512 		DOMAIN_ALIAS_RID_ADMINS,
513 		0, 0, 0, 0, 0, 0,
514 		&AdministratorsGroup);
515 	if(b)
516 	{
517 		if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
518 		{
519 			 b = FALSE;
520 		}
521 		FreeSid(AdministratorsGroup);
522 	}
523 
524 	isAdmin = ( sal_Bool )b;
525 
526 #endif
527 
528 	/// print the information.
529 	printf("#\n#Retrived system information is below:\n");
530 
531 	printf("Computer Name:              ");
532 	if ( strComputerName == aNullURL )
533 		printf(" Not retrived\n" );
534 	else
535 		printUString( strComputerName );
536 
537 	printf("Current User Name:          ");
538 	if ( strUserName == aNullURL )
539 		printf(" Not retrived\n" );
540 	else
541 		printUString( strUserName );
542 
543 	printf("Current User Home Directory:");
544 	if ( strHomeDirectory == aNullURL )
545 		printf(" Not retrived\n" );
546 	else
547 		printUString( strHomeDirectory );
548 
549 	printf("Current Config Directory:   ");
550 	if ( strConfigDirectory == aNullURL )
551 		printf(" Not retrived\n" );
552 	else
553 		printUString( strConfigDirectory );
554 
555 	printf("Current UserID:             ");
556 	if ( strUserID == aNullURL )
557 		printf(" Not retrived\n" );
558 	else
559 		printUString( strUserID );
560 
561 	printf("Current User is");
562 	if ( isAdmin == sal_False )
563 		printf(" NOT Administrator.\n" );
564 	else
565 		printf(" Administrator.\n" );
566 
567 
568 	/// get and display forwarded text if available.
569 	aStringForward = ::rtl::OUString::createFromAscii( getForwardString() );
570 	if ( !aStringForward.equals( aNullURL ) && aStringForward.indexOf( (sal_Unicode)' ' ) != -1 )
571 	{
572 		sal_Int32 nFirstSpacePoint = aStringForward.indexOf( (sal_Unicode)' ' );;
573 		sal_Int32 nLastSpacePoint = aStringForward.lastIndexOf( (sal_Unicode)' ' );;
574 		if ( nFirstSpacePoint == nLastSpacePoint )
575 		/// only forwarded two parameters, username and password.
576 		{
577 			aLogonUser = aStringForward.copy( 0, nFirstSpacePoint );
578 			printf("\n#Forwarded username: ");
579 			printUString( aLogonUser);
580 
581 			aLogonPasswd = aStringForward.copy( nFirstSpacePoint +1, aStringForward.getLength( ) - 1 );
582 			printf("#Forwarded password: ");
583 			for ( int i = nFirstSpacePoint +1; i <= aStringForward.getLength( ) - 1; i++, printf("*") );
584 			printf("\n" );
585 		}
586 		else
587 		/// forwarded three parameters, username, password and fileserver.
588 		{
589 			aLogonUser = aStringForward.copy( 0, nFirstSpacePoint );
590 			printf("#Forwarded username: ");
591 			printUString( aLogonUser);
592 
593 			aLogonPasswd = aStringForward.copy( nFirstSpacePoint +1, nLastSpacePoint );
594 			printf("#Forwarded password: ");
595 			for ( int i = nFirstSpacePoint +1; i <= nLastSpacePoint; i++, printf("*") );
596 			printf("\n" );
597 
598 			aFileServer = aStringForward.copy( nLastSpacePoint +1, aStringForward.getLength( ) - 1 );
599 			printf("#Forwarded FileServer: ");
600 			printUString( aFileServer );
601 
602 		}
603 	}
604 
605 	printf("#\n#Initialization Done.\n" );
606 
607 	::testing::InitGoogleTest(&argc, argv);
608 	return RUN_ALL_TESTS();
609 }
610