sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // Simple STDLIB tests.
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32test.h>
sl@0: #include <e32svr.h>
sl@0: #include <ctype.h>
sl@0: #include <math.h>
sl@0: #include <errno.h>
sl@0: #include "ESTLIB.H"
sl@0: 
sl@0: //CPP file is used for C tests, because by default any console opened from a C file
sl@0: //expects a key to be pressed when it is about to be closed. That makes impossible
sl@0: //the creation of automated C tests.
sl@0: 
sl@0: //
sl@0: // Globals
sl@0: 
sl@0: static RTest TheTest(_L("TMisc3"));
sl@0: const double KPi = 3.14159265358979323846;
sl@0: 
sl@0: //
sl@0: //
sl@0: //Test macroses and functions
sl@0: 
sl@0: static void Check(TInt aValue, TInt aLine)
sl@0: 	{
sl@0: 	if(!aValue)
sl@0: 		{
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: static  void Check(TInt aValue, TInt aExpected, TInt aLine)
sl@0: 	{
sl@0: 	if(aValue != aExpected)
sl@0: 		{
sl@0: 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: #define TEST(arg) ::Check((arg), __LINE__)
sl@0: #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
sl@0: 
sl@0: #define TEST_NAN (0.0/0.0)
sl@0: #define TEST_POS_INFINITY (1.0/0.0)
sl@0: #define TEST_NEG_INFINITY (-1.0/0.0)
sl@0: 
sl@0: //
sl@0: // Tests
sl@0: 
sl@0: static void TestCType()
sl@0: 	{
sl@0: 	char c;
sl@0: 	for(c='a';c<='z';++c)
sl@0: 		{
sl@0: 		TEST(isalnum(c));
sl@0: 		TEST(isalpha(c));
sl@0: 		TEST(!iscntrl(c));
sl@0: 		TEST(!isdigit(c));
sl@0: 		TEST(isgraph(c));
sl@0: 		TEST(islower(c));
sl@0: 		TEST(isprint(c));
sl@0: 		TEST(!ispunct(c));
sl@0: 		TEST(!isspace(c));
sl@0: 		TEST(!isupper(c));
sl@0: 		TEST(c >= 'a' && c <= 'f' ? isxdigit(c) : !isxdigit(c));
sl@0: 		}
sl@0: 	for(c='A';c<='Z';++c)
sl@0: 		{
sl@0: 		TEST(isalnum(c));
sl@0: 		TEST(isalpha(c));
sl@0: 		TEST(!iscntrl(c));
sl@0: 		TEST(!isdigit(c));
sl@0: 		TEST(isgraph(c));
sl@0: 		TEST(!islower(c));
sl@0: 		TEST(isprint(c));
sl@0: 		TEST(!ispunct(c));
sl@0: 		TEST(!isspace(c));
sl@0: 		TEST(isupper(c));
sl@0: 		TEST(c >= 'A' && c <= 'F' ? isxdigit(c) : !isxdigit(c));
sl@0: 		}
sl@0: 	for(c='0';c<='9';++c)
sl@0: 		{
sl@0: 		TEST(isalnum(c));
sl@0: 		TEST(!isalpha(c));
sl@0: 		TEST(!iscntrl(c));
sl@0: 		TEST(isdigit(c));
sl@0: 		TEST(isgraph(c));
sl@0: 		TEST(!islower(c));
sl@0: 		TEST(isprint(c));
sl@0: 		TEST(!ispunct(c));
sl@0: 		TEST(!isspace(c));
sl@0: 		TEST(!isupper(c));
sl@0: 		TEST(isxdigit(c));
sl@0: 		}
sl@0: 	for(c=0;c<' ';++c)
sl@0: 		{
sl@0: 		TEST(!isalnum(c));
sl@0: 		TEST(!isalpha(c));
sl@0: 		TEST(iscntrl(c));
sl@0: 		TEST(!isdigit(c));
sl@0: 		TEST(!isgraph(c));
sl@0: 		TEST(!islower(c));
sl@0: 		TEST(!isprint(c));
sl@0: 		TEST(!ispunct(c));
sl@0: 		if(c != '\t' && c != '\n' && c != '\r' && c != '\v' && c != '\f')
sl@0: 			{
sl@0: 			TEST(!isspace(c));
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TEST(isspace(c));
sl@0: 			}
sl@0: 		TEST(!isupper(c));
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: static void TestMath()
sl@0: 	{
sl@0: 	double eps = 0.000001;
sl@0: 
sl@0: 	double res = fabs(21.091);
sl@0: 	TEST((21.091 - res) < eps);
sl@0: 	res = fabs(-1.91);
sl@0: 	TEST((res - 1.91) < eps);
sl@0: 
sl@0: 	res = atan(0.0);
sl@0: 	TEST(fabs(res) < eps);
sl@0: 	// 90 degrees
sl@0: 	res = tan(KPi/2);
sl@0: 	TEST(res > 1000000000.0);
sl@0: 	res = atan(res);
sl@0: 	TEST(fabs(res - KPi/2) < eps);
sl@0: 	// 45 degrees
sl@0: 	res = tan(KPi/4);
sl@0: 	TEST(fabs(res - 1.0) < eps);
sl@0: 	res = atan(res);
sl@0: 	TEST(fabs(res - KPi/4) < eps);
sl@0: 	// 135 degrees
sl@0: 	res = tan((3 * KPi) / 4);
sl@0: 	TEST(fabs(res + 1.0) < eps);
sl@0: 	res = atan(res);
sl@0: 	TEST(fabs((KPi + res) - (3 * KPi) / 4) < eps);
sl@0: 
sl@0: 	// 0 degrees
sl@0: 	res = cos(0.0);
sl@0: 	TEST(fabs(res - 1) < eps);
sl@0: 	// 90 degrees
sl@0: 	res = cos(KPi/2);
sl@0: 	TEST(res < eps);
sl@0: 	// 180 degrees
sl@0: 	res = cos(KPi);
sl@0: 	TEST(fabs(res + 1.0) < eps);
sl@0: 
sl@0: 	// 0 degrees
sl@0: 	res = sin(0.0);
sl@0: 	TEST(res < eps);
sl@0: 	// 90 degrees
sl@0: 	res = sin(KPi/2);
sl@0: 	TEST(fabs(res - 1) < eps);
sl@0: 	// 180 degrees
sl@0: 	res = sin(KPi);
sl@0: 	TEST(res < eps);
sl@0: 
sl@0: 	res = tanh(1.0);
sl@0: 	TEST(fabs(res - 0.761594) < eps);
sl@0: 
sl@0: 	int exponent;
sl@0: 	res = frexp(0.51E+2, &exponent);
sl@0: 	TEST((0.51E+2 - res * pow(2.0, exponent)) < eps);
sl@0: 
sl@0: 	double integer;
sl@0: 	res = modf(34.567, &integer);
sl@0: 	TEST(fabs(res - 0.567) < eps);
sl@0: 	TEST(fabs(integer - 34.0) < eps);
sl@0: 	res = modf(-35.567, &integer);
sl@0: 	TEST(fabs(res + 0.567) < eps);
sl@0: 	TEST(fabs(integer + 35.0) < eps);
sl@0: 
sl@0: 	res = ceil(245.8903);
sl@0: 	TEST(fabs(res - 246.0) < eps);
sl@0: 	res = ceil(-11.91);
sl@0: 	TEST(fabs(res + 11.0) < eps);
sl@0: 
sl@0: 	res = floor(245.8903);
sl@0: 	TEST(fabs(res - 245.0) < eps);
sl@0: 	res = floor(-11.91);
sl@0: 	TEST(fabs(res + 12.0) < eps);
sl@0: 
sl@0: 	res = copysign(4.789, -9.001);
sl@0: 	TEST((res + 4.789) < eps);
sl@0: 	res = copysign(-4.789, 9.001);
sl@0: 	TEST((res - 4.789) < eps);
sl@0: 
sl@0: 	}
sl@0: 
sl@0: static void TestDef113884()
sl@0: 	{
sl@0: 	int exponent;
sl@0: 
sl@0: 	errno = 0;
sl@0: 	frexp(0.51E+2, &exponent);
sl@0: 	pow(2.0, exponent);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	pow(-1.0, 0.5);
sl@0: 	TEST2(errno, EDOM);
sl@0: 	errno = 0;
sl@0: 	// Added 'LL' as GCC needs to know these are explicitly 'long long'
sl@0: 	pow(34523543434234LL , 23423432234LL);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 	errno = 0;
sl@0: 	pow(-34523543434234LL , -23423432234LL);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	atan(0.0);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	cos(0.0);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	sin(0.5);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	tan(KPi/2);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	acos(0.5);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	acos(HUGE_VAL);
sl@0: 	TEST2(errno, EDOM);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	asin(0.5);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	exp(2);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	exp(HUGE_VAL);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 	errno = 0;
sl@0: 	exp(-1 * HUGE_VAL);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	log(2);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	log(-1);
sl@0: 	TEST2(errno, EDOM);
sl@0: 	errno = 0;
sl@0: 	log(0);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	log10(2);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	log10(-1);
sl@0: 	TEST2(errno, EDOM);
sl@0: 	errno = 0;
sl@0: 	log10(0);
sl@0: 	TEST2(errno, ERANGE);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	sqrt(2);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	sqrt(-1);
sl@0: 	TEST2(errno, EDOM);
sl@0: #ifdef __ARMCC__
sl@0: #pragma diag_suppress 222  //armv5 Warning #222-D is an echo of the following test.  We want to ensure that the test reports the error as well.
sl@0: #else
sl@0: #pragma warning (disable: 222)  //winscw Warning #222-D is an echo of the following test.  We want to ensure that the test reports the error as well.
sl@0: #endif
sl@0: 	errno = 0;
sl@0: 	sqrt(2.0 * HUGE_VAL);
sl@0: 	TEST2(errno, ERANGE);
sl@0: #ifdef __ARMCC__
sl@0: #pragma diag_default 222  //armv5 Warning #222-D turned back on.
sl@0: #else
sl@0: #pragma warning (default: 222)  //winscw Warning #222-D turned back on.
sl@0: #endif
sl@0: 
sl@0: 	errno = 0;
sl@0: 	atan2(2.0, 2.0);
sl@0: 	TEST2(errno, 0);
sl@0: #pragma warning (disable: 222)  //Warning #222-D is an echo of the following test.
sl@0: 	errno = 0;
sl@0: 	atan2(0.0, 0.0);
sl@0: 	TEST2(errno, EDOM);
sl@0: #pragma warning (default: 222)  //Warning #222-D is an echo of the following test.
sl@0: 
sl@0: 	errno = 0;
sl@0: 	fmod(2.0, 2.0);
sl@0: 	TEST2(errno, 0);
sl@0: 	errno = 0;
sl@0: 	fmod(1.0, 0.0);
sl@0: 	TEST2(errno, EDOM);
sl@0: 
sl@0: 	errno = 0;
sl@0: 	rint(2.129999);
sl@0: 	TEST2(errno, 0);
sl@0: 
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: //
sl@0: 
sl@0: static void MainL()
sl@0:     {
sl@0: 	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-STDLIB-LEGACY-TMISC3-0001 CTYPE tests "));
sl@0: 	::TestCType();
sl@0: 
sl@0: 	TheTest.Next(_L("MATH tests"));
sl@0: 	::TestMath();
sl@0: 
sl@0: 	TheTest.Next(_L("MATH DEF113884 tests"));
sl@0: 	::TestDef113884();
sl@0: 
sl@0: 	CloseSTDLIB();
sl@0: 	}
sl@0: 
sl@0: TInt E32Main()
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0: 	CTrapCleanup* tc = CTrapCleanup::New();
sl@0:     TEST(tc != NULL);
sl@0: 
sl@0: 	TheTest.Title();
sl@0:     TRAPD(err, ::MainL());
sl@0: 	TEST2(err, KErrNone);
sl@0: 
sl@0: 	TheTest.End();
sl@0: 	TheTest.Close();
sl@0: 
sl@0: 	delete tc;
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	User::Heap().Check();
sl@0: 	return KErrNone;
sl@0: 	}