os/ossrv/genericopenlibs/cstdlib/TSTLIB/STDLIB2K.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description:
sl@0
    15
* Year 2000 compliance tests for STDLIB
sl@0
    16
* 
sl@0
    17
*
sl@0
    18
*/
sl@0
    19
sl@0
    20
sl@0
    21
sl@0
    22
#include <stdlib.h>	/* definition of exit() */
sl@0
    23
#include <stdio.h>
sl@0
    24
#include <errno.h>
sl@0
    25
#include <string.h>
sl@0
    26
#include <time.h>
sl@0
    27
#include <fcntl.h>
sl@0
    28
#include <unistd.h>
sl@0
    29
#include <sys/time.h>	/* timeval, gettimeofday */
sl@0
    30
sl@0
    31
int failures=0;
sl@0
    32
void failed(char* reason)
sl@0
    33
	{
sl@0
    34
	printf("\nFAILURE >>>%s\n", reason);
sl@0
    35
	failures++;
sl@0
    36
	}
sl@0
    37
sl@0
    38
sl@0
    39
sl@0
    40
typedef struct {
sl@0
    41
	int day;	/* 1-31 */
sl@0
    42
	int month;	/* 1-12 */
sl@0
    43
	int year;	/* 1970-2050 */
sl@0
    44
	} testdate;
sl@0
    45
sl@0
    46
char* testmonths[14] = {
sl@0
    47
	"invalid_0",
sl@0
    48
	"Jan", "Feb", "March", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec",
sl@0
    49
	"invalid_13"
sl@0
    50
	};
sl@0
    51
sl@0
    52
char* tmdaynames[8] = {
sl@0
    53
	"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
sl@0
    54
	"invalid_7"
sl@0
    55
	};
sl@0
    56
sl@0
    57
/* Format a testdate to match the Y2K document
sl@0
    58
 */
sl@0
    59
void format_testdate(testdate* aDate, char* aBuffer)
sl@0
    60
	{
sl@0
    61
	char* th="th";
sl@0
    62
	if (aDate->day==1 || aDate->day==21 || aDate->day==31)
sl@0
    63
		th="st";
sl@0
    64
	if (aDate->day==2 || aDate->day==22)
sl@0
    65
		th="nd";
sl@0
    66
sl@0
    67
	sprintf(aBuffer, "%d%s %s %d", aDate->day, th, testmonths[aDate->month], aDate->year);
sl@0
    68
	}
sl@0
    69
sl@0
    70
typedef struct {
sl@0
    71
	testdate	input;		/* for conversion to seconds */
sl@0
    72
	testdate	result;		/* correct value */
sl@0
    73
	} testpair;
sl@0
    74
sl@0
    75
typedef struct {
sl@0
    76
	testdate	input;		/* for conversion to seconds */
sl@0
    77
	int		result;		/* correct value */
sl@0
    78
	} testint;
sl@0
    79
sl@0
    80
/* MAJOR TEST FUNCTIONALITY - READ THIS CAREFULLY
sl@0
    81
 *
sl@0
    82
 * STDLIB date handling is done in terms of seconds since the "epoch", which was
sl@0
    83
 * 00:00 on 1st January, 1970. The Y2K significant functionality consists solely of the
sl@0
    84
 * routines which manipulate the struct tm data structure.
sl@0
    85
 *
sl@0
    86
 *   time_t mktime (struct tm *brokentime)
sl@0
    87
 *
sl@0
    88
 *   struct tm * gmtime (const time_t *time)
sl@0
    89
 *   struct tm * localtime (const time_t *time)
sl@0
    90
 *
sl@0
    91
 * The mktime conversion is always using a GMT date, so we'll ignore the localtime function for Y2K
sl@0
    92
 * purposes. We also know that gmtime and localtime use the same underlying conversion function,
sl@0
    93
 * one applying the relevant GMT offset on the way in.
sl@0
    94
 *
sl@0
    95
 * Y2K is only concerned with dates, so we will always use 12:00:00 ("High Noon") as the time
sl@0
    96
 * of day.
sl@0
    97
 */
sl@0
    98
sl@0
    99
void tm_from_testdate(struct tm* aTm, testdate* aDate)
sl@0
   100
	{
sl@0
   101
	time_t seconds;
sl@0
   102
	struct tm setup;
sl@0
   103
	struct tm* res;
sl@0
   104
sl@0
   105
	setup.tm_hour = 12;
sl@0
   106
	setup.tm_min  = 0;
sl@0
   107
	setup.tm_sec  = 0;
sl@0
   108
sl@0
   109
	setup.tm_mday = aDate->day;
sl@0
   110
	setup.tm_mon  = aDate->month - 1;	/* struct tm uses 0-11 */
sl@0
   111
	setup.tm_year = aDate->year - 1900;	/* struct tm uses years since 1900 */
sl@0
   112
sl@0
   113
	seconds = mktime(&setup);
sl@0
   114
	if (seconds != (time_t)(-1))
sl@0
   115
		{
sl@0
   116
		res = gmtime(&seconds);
sl@0
   117
		*aTm = *res;
sl@0
   118
		return;
sl@0
   119
		}
sl@0
   120
sl@0
   121
	/* unable to convert date */
sl@0
   122
	failed("tm_from_testdate: mktime failed");
sl@0
   123
	}
sl@0
   124
sl@0
   125
void normalize_tm(struct tm* aTm)
sl@0
   126
	{
sl@0
   127
	time_t seconds = mktime(aTm);
sl@0
   128
	if (seconds == (time_t)(-1))
sl@0
   129
		{
sl@0
   130
		/* unable to convert date */
sl@0
   131
		failed("normalize_tm: mktime failed");
sl@0
   132
		}
sl@0
   133
	return;
sl@0
   134
	}
sl@0
   135
sl@0
   136
int compare_testdate_tm(testdate* aDate, struct tm* aTm)
sl@0
   137
	{
sl@0
   138
	if (aDate->year-1900 != aTm->tm_year)
sl@0
   139
		return (aDate->year-1900-aTm->tm_year);
sl@0
   140
	if (aDate->month-1 != aTm->tm_mon)
sl@0
   141
		return (aDate->month-1-aTm->tm_mon);
sl@0
   142
	return (aDate->day - aTm->tm_mday);
sl@0
   143
	}
sl@0
   144
sl@0
   145
/*
sl@0
   146
 *   4.1 Rule 1 Tests
sl@0
   147
 *
sl@0
   148
 * "No valid value for current date will cause any interruption in operation"
sl@0
   149
 *
sl@0
   150
 */
sl@0
   151
sl@0
   152
testpair data_4_1[14] = {
sl@0
   153
	{{ 31,12,1998 } , {  1, 1, 1999 } },
sl@0
   154
	{{ 27, 2,1999 } , { 28, 2, 1999 } },
sl@0
   155
	{{ 28, 2,1999 } , {  1, 3, 1999 } },
sl@0
   156
	{{ 31, 8,1999 } , {  1, 9, 1999 } },
sl@0
   157
	{{  8, 9,1999 } , {  9, 9, 1999 } },
sl@0
   158
	{{  9, 9,1999 } , { 10, 9, 1999 } },
sl@0
   159
	{{ 31,12,1999 } , {  1, 1, 2000 } },
sl@0
   160
	{{ 27, 2,2000 } , { 28, 2, 2000 } },
sl@0
   161
	{{ 28, 2,2000 } , { 29, 2, 2000 } },
sl@0
   162
	{{ 29, 2,2000 } , {  1, 3, 2000 } },
sl@0
   163
	{{ 31,12,2000 } , {  1, 1, 2001 } },
sl@0
   164
	{{ 28, 2,2001 } , {  1, 3, 2001 } },
sl@0
   165
	{{ 28, 2,2004 } , { 29, 2, 2004 } },
sl@0
   166
	{{ 29, 2,2004 } , {  1, 3, 2004 } }
sl@0
   167
	};
sl@0
   168
sl@0
   169
/**
sl@0
   170
@SYMTestCaseID          SYSLIB-STDLIB-CT-1043
sl@0
   171
@SYMTestCaseDesc	    Tests for standard date boundaries
sl@0
   172
@SYMTestPriority 	    High
sl@0
   173
@SYMTestActions  	    Tests for standard date format
sl@0
   174
@SYMTestExpectedResults Test must not fail
sl@0
   175
@SYMREQ                 REQ0000
sl@0
   176
*/		
sl@0
   177
void tests_4_1()
sl@0
   178
	{
sl@0
   179
	int i;
sl@0
   180
	testdate* from_dp;
sl@0
   181
	testdate* to_dp;
sl@0
   182
	char frombuf[80];
sl@0
   183
	char tobuf[80];
sl@0
   184
	struct tm workdate;
sl@0
   185
sl@0
   186
	printf("\n4.1 Rule 1 Tests\n\n");
sl@0
   187
	printf("4.1.1.1 Standard Date Boundaries\n\n");
sl@0
   188
	for (i=0; i<14; i++)
sl@0
   189
		{
sl@0
   190
		from_dp=&data_4_1[i].input;
sl@0
   191
		to_dp=&data_4_1[i].result;
sl@0
   192
sl@0
   193
		format_testdate(from_dp, frombuf); 
sl@0
   194
		format_testdate(to_dp, tobuf); 
sl@0
   195
		printf("%-2d  From %-14s to %-14s ", i+1, frombuf, tobuf);
sl@0
   196
sl@0
   197
		tm_from_testdate(&workdate, from_dp);
sl@0
   198
		if (compare_testdate_tm(from_dp, &workdate) != 0)
sl@0
   199
			failed("test_4_1: invalid from date");
sl@0
   200
sl@0
   201
		workdate.tm_mday += 1;	/* move the time on by one day */
sl@0
   202
sl@0
   203
		normalize_tm(&workdate);
sl@0
   204
		if (compare_testdate_tm(to_dp, &workdate) != 0)
sl@0
   205
			{
sl@0
   206
			printf("*** FAILED\n");
sl@0
   207
			failures++;
sl@0
   208
			}
sl@0
   209
		else
sl@0
   210
			printf("PASSED\n");
sl@0
   211
		}
sl@0
   212
sl@0
   213
	}
sl@0
   214
sl@0
   215
/*
sl@0
   216
 *   4.2 Rule 2 Tests (incorporating Rule 4 Tests)
sl@0
   217
 *
sl@0
   218
 * "All manipulations of date or time related data will produce the required results for
sl@0
   219
 *  all valid date values prior to, during and after Year 2000"
sl@0
   220
 *
sl@0
   221
 * "Year 2000 must be recognised as a leap year"
sl@0
   222
 *
sl@0
   223
 */
sl@0
   224
sl@0
   225
testdate data_4_2_1[19] = {
sl@0
   226
	{ 31, 12, 1998 },
sl@0
   227
	{  1,  3, 1999 },
sl@0
   228
	{ 27,  2, 2000 },
sl@0
   229
	{ 31, 12, 2000 },
sl@0
   230
	{ 28,  2, 2004 },
sl@0
   231
	{  1,  1, 1999 },
sl@0
   232
	{  9,  9, 1999 },
sl@0
   233
	{ 28,  2, 2000 },
sl@0
   234
	{  1,  1, 2001 },
sl@0
   235
	{ 29,  2, 2004 },
sl@0
   236
	{ 27,  2, 1999 },
sl@0
   237
	{ 31, 12, 1999 },
sl@0
   238
	{ 29,  2, 2000 },
sl@0
   239
	{ 28,  2, 2000 },
sl@0
   240
	{  1,  3, 2004 },
sl@0
   241
	{ 28,  2, 1999 },
sl@0
   242
	{  1,  1, 2000 },
sl@0
   243
	{  1,  3, 2000 },
sl@0
   244
	{  1,  3, 2001 }
sl@0
   245
	};
sl@0
   246
sl@0
   247
void tests_4_2_1()
sl@0
   248
	{
sl@0
   249
	int i;
sl@0
   250
	testdate* from_dp;
sl@0
   251
	char frombuf[80];
sl@0
   252
	struct tm workdate;
sl@0
   253
sl@0
   254
	printf("\n4.2 Rule 2 Tests (incorporating Rule 4 Tests)\n\n");
sl@0
   255
	printf("4.2.1 Valid Dates\n\n");
sl@0
   256
	for (i=0; i<19; i++)
sl@0
   257
		{
sl@0
   258
		from_dp=&data_4_2_1[i];
sl@0
   259
sl@0
   260
		format_testdate(from_dp, frombuf); 
sl@0
   261
		printf("%-2d  Valid date %-14s  ", i+1, frombuf);
sl@0
   262
sl@0
   263
		tm_from_testdate(&workdate, from_dp);
sl@0
   264
		if (compare_testdate_tm(from_dp, &workdate) != 0)
sl@0
   265
			{
sl@0
   266
			printf("*** FAILED\n");
sl@0
   267
			failures++;
sl@0
   268
			}
sl@0
   269
		else
sl@0
   270
			printf("PASSED\n");
sl@0
   271
		}
sl@0
   272
	}
sl@0
   273
sl@0
   274
testdate data_4_2_2[5] = {
sl@0
   275
	{ 31,  4, 1998 },
sl@0
   276
	{ 30,  2, 2000 },
sl@0
   277
	{ 29,  2, 2001 },
sl@0
   278
	{ 29,  2, 1999 },
sl@0
   279
	{ 30,  2, 2004 }
sl@0
   280
	};
sl@0
   281
sl@0
   282
void tests_4_2_2()
sl@0
   283
	{
sl@0
   284
	int i;
sl@0
   285
	testdate* from_dp;
sl@0
   286
	char frombuf[80];
sl@0
   287
	struct tm workdate;
sl@0
   288
sl@0
   289
	printf("\n4.2.2 Invalid Dates\n\n");
sl@0
   290
	for (i=0; i<5; i++)
sl@0
   291
		{
sl@0
   292
		from_dp=&data_4_2_2[i];
sl@0
   293
sl@0
   294
		format_testdate(from_dp, frombuf); 
sl@0
   295
		printf("%-2d  Invalid date %-14s  ", i+1, frombuf);
sl@0
   296
sl@0
   297
		tm_from_testdate(&workdate, from_dp);
sl@0
   298
		if (compare_testdate_tm(from_dp, &workdate) == 0)
sl@0
   299
			{
sl@0
   300
			printf("*** FAILED\n");
sl@0
   301
			failures++;
sl@0
   302
			}
sl@0
   303
		else
sl@0
   304
			printf("PASSED\n");
sl@0
   305
		}
sl@0
   306
	}
sl@0
   307
sl@0
   308
testint data_4_2_4[3] = {
sl@0
   309
	{ { 31, 12, 2000 }, 366 },
sl@0
   310
	{ { 31, 12, 1999 }, 365 },
sl@0
   311
	{ { 31, 12, 2004 }, 366 }
sl@0
   312
	};
sl@0
   313
sl@0
   314
void tests_4_2_4()
sl@0
   315
	{
sl@0
   316
	int i;
sl@0
   317
	testdate* from_dp;
sl@0
   318
	char frombuf[80];
sl@0
   319
	struct tm workdate;
sl@0
   320
sl@0
   321
	printf("\n4.2.4 Year Lengths\n\n");
sl@0
   322
	for (i=0; i<3; i++)
sl@0
   323
		{
sl@0
   324
		from_dp=&data_4_2_4[i].input;
sl@0
   325
sl@0
   326
		format_testdate(from_dp, frombuf); 
sl@0
   327
		printf("%-2d  Yearday of %-14s == %d ", i+1, frombuf, data_4_2_4[i].result);
sl@0
   328
sl@0
   329
		tm_from_testdate(&workdate, from_dp);
sl@0
   330
		if (workdate.tm_yday+1 != data_4_2_4[i].result)
sl@0
   331
			{
sl@0
   332
			printf("*** FAILED\n");
sl@0
   333
			failures++;
sl@0
   334
			}
sl@0
   335
		else
sl@0
   336
			printf("PASSED\n");
sl@0
   337
		}
sl@0
   338
	}
sl@0
   339
sl@0
   340
testint data_4_2_7[14] = {
sl@0
   341
	{ {  1,  1, 1900 }, 1 },	// not supported
sl@0
   342
	{ { 28,  2, 1900 }, 3 },	// not supported
sl@0
   343
	{ {  1,  3, 1900 }, 4 },	// not supported
sl@0
   344
	{ { 28,  2, 1999 }, 0 },
sl@0
   345
	{ {  1,  3, 1999 }, 1 },
sl@0
   346
	{ { 31, 12, 1999 }, 5 },
sl@0
   347
	{ {  1,  1, 2000 }, 6 },
sl@0
   348
	{ { 28,  2, 2000 }, 1 },
sl@0
   349
	{ { 29,  2, 2000 }, 2 },
sl@0
   350
	{ {  1,  3, 2000 }, 3 },
sl@0
   351
	{ {  1,  1, 2001 }, 1 },
sl@0
   352
	{ { 28,  2, 2004 }, 6 },
sl@0
   353
	{ { 29,  2, 2004 }, 0 },
sl@0
   354
	{ {  1,  3, 2004 }, 1 }
sl@0
   355
	};
sl@0
   356
sl@0
   357
void tests_4_2_7()
sl@0
   358
	{
sl@0
   359
	int i;
sl@0
   360
	testdate* from_dp;
sl@0
   361
	char frombuf[80];
sl@0
   362
	struct tm workdate;
sl@0
   363
sl@0
   364
	printf("\n4.2.7 Calculation of days of the week from dates\n\n");
sl@0
   365
	for (i=3; i<14; i++)
sl@0
   366
		{
sl@0
   367
		from_dp=&data_4_2_7[i].input;
sl@0
   368
sl@0
   369
		format_testdate(from_dp, frombuf); 
sl@0
   370
		printf("%-2d  %-14s == %-10s ", i+1, frombuf, tmdaynames[data_4_2_7[i].result]);
sl@0
   371
sl@0
   372
		tm_from_testdate(&workdate, from_dp);
sl@0
   373
		if (compare_testdate_tm(from_dp, &workdate) != 0)
sl@0
   374
			failed("test_4_2_7: invalid from date");
sl@0
   375
sl@0
   376
		if (workdate.tm_wday != data_4_2_7[i].result)
sl@0
   377
			{
sl@0
   378
			printf("*** FAILED  (%d %s)\n", workdate.tm_wday, tmdaynames[workdate.tm_wday]);
sl@0
   379
			failures++;
sl@0
   380
			}
sl@0
   381
		else
sl@0
   382
			printf("PASSED\n");
sl@0
   383
		}
sl@0
   384
	}
sl@0
   385
sl@0
   386
void do_all_tests()
sl@0
   387
	{
sl@0
   388
	time_t now = time(0);
sl@0
   389
	failures=0;
sl@0
   390
sl@0
   391
	tests_4_1();
sl@0
   392
	tests_4_2_1();
sl@0
   393
	tests_4_2_2();
sl@0
   394
	tests_4_2_4();
sl@0
   395
	tests_4_2_7();
sl@0
   396
sl@0
   397
	if (failures != 0)
sl@0
   398
		printf("\n\n NOT YEAR 2000 COMPLIANT\n\n");
sl@0
   399
	else
sl@0
   400
		printf("\n\n ALL TESTS PASSED - YEAR 2000 COMPLIANT\n\n");
sl@0
   401
sl@0
   402
	printf("Test run dated: %s", ctime(&now));
sl@0
   403
	}
sl@0
   404
sl@0
   405
int main()
sl@0
   406
	{
sl@0
   407
	int fd;
sl@0
   408
sl@0
   409
	do_all_tests();	
sl@0
   410
sl@0
   411
	/* Now repeat the tests into a log file */
sl@0
   412
sl@0
   413
	fd=open("c:/stdlib_y2k.txt", O_WRONLY+O_CREAT+O_TRUNC, 0);
sl@0
   414
	if (fd<0)
sl@0
   415
		{
sl@0
   416
		printf("unable to create test result file\n");
sl@0
   417
		return -1;
sl@0
   418
		}
sl@0
   419
sl@0
   420
	setbuf(stderr, NULL);
sl@0
   421
	dup2(fd, fileno(stderr));	/* redirect stderr */
sl@0
   422
	setbuf(stdout, NULL);
sl@0
   423
	dup2(fd, fileno(stdout));	/* redirect stdout */
sl@0
   424
	close(fd);
sl@0
   425
	fclose(stdin);
sl@0
   426
sl@0
   427
	do_all_tests();
sl@0
   428
sl@0
   429
	fflush(stdout);
sl@0
   430
	return 0;
sl@0
   431
	}