os/kernelhwsrv/kerneltest/e32test/system/t_chnot.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\system\t_chnot.cpp
    15 // Tests RChangeNotifier class
    16 // Overview:
    17 // Tests RChangeNotifier class
    18 // API Information:
    19 // RChangeNotifier
    20 // Details:
    21 // - Create a RChangeNotifier object and verify the logon status is 
    22 // as expected.
    23 // - Call the Logon and LogonCancel methods, verify results are as
    24 // expected.
    25 // - Test for the correct midnight crossover notifier results in a 
    26 // variety of situations: DST On, DST Off, various time offsets
    27 // and various dates.
    28 // - Test various locale changes and verify that the notifier response
    29 // is as expected.
    30 // - Test the notification of the death of a thread and check that
    31 // results are as expected. Check for normal exit, kill exit, 
    32 // terminate exit and panic exit.
    33 // Platforms/Drives/Compatibility:
    34 // All.
    35 // Assumptions/Requirement/Pre-requisites:
    36 // Failures and causes:
    37 // Base Port information:
    38 // 
    39 //
    40 
    41 #define __E32TEST_EXTENSION__
    42 #include <e32test.h>
    43 #include <e32hal.h>
    44 #include <e32svr.h>
    45 #include <u32hal.h>
    46 #include <e32def.h>
    47 #include <e32def_private.h>
    48 
    49 RTest test(_L("T_CHNOT"));
    50 
    51 RChangeNotifier notifier;
    52 
    53 void TestStat(const TRequestStatus& aStat, TInt aValue)
    54 	{
    55 	if (aStat.Int()!=aValue)
    56 		{
    57 		test.Printf(_L("Got %08x Expected %08x\n"),aStat.Int(),aValue);
    58 		test(0);
    59 		}
    60 	}
    61 
    62 void TestCreate()
    63 	{
    64 	notifier.Create();
    65 	TRequestStatus stat;
    66 	notifier.Logon(stat);
    67 
    68 	// Expect all except EChangesLowMemory
    69 	TUint expected =
    70 		EChangesLocale |
    71 		EChangesMidnightCrossover |
    72 		EChangesThreadDeath |
    73 		EChangesPowerStatus |
    74 		EChangesSystemTime |
    75 		EChangesFreeMemory |
    76 		EChangesOutOfMemory |
    77 		EChangesThrashLevel;
    78 	
    79 	test(stat==expected);
    80 	}
    81 
    82 void TestLogonLogoff()
    83 	{
    84 	TRequestStatus stat;
    85 	notifier.LogonCancel();
    86 	notifier.Logon(stat);
    87 	TestStat(stat,KRequestPending);
    88 	notifier.LogonCancel();
    89 	TestStat(stat,KErrCancel);
    90 	notifier.LogonCancel();
    91 	TestStat(stat,KErrCancel);
    92 	}
    93 
    94 void DoTestMidnight()
    95 	{
    96 	TTime time;
    97 	time.HomeTime();
    98 	TDateTime dateTime=time.DateTime();
    99 	dateTime.SetHour(23);
   100 	dateTime.SetMinute(59);
   101 	dateTime.SetSecond(58);
   102 	dateTime.SetMicroSecond(700000);
   103 	time=dateTime;
   104 	TRequestStatus stat;
   105 	TInt r=notifier.Logon(stat);
   106 	test(r==KErrNone);
   107 	TestStat(stat,KRequestPending);
   108 	test(User::SetHomeTime(time)==KErrNone);
   109 	time.HomeTime();
   110 	TDateTime dateTime2=time.DateTime();
   111 	User::WaitForRequest(stat);
   112 	TestStat(stat,EChangesSystemTime);
   113 	r=notifier.Logon(stat);
   114 	test(r==KErrNone);
   115 	User::WaitForRequest(stat);
   116 	time.HomeTime();
   117 	TestStat(stat,EChangesMidnightCrossover);
   118 	dateTime2=time.DateTime();
   119 	test(dateTime2.Second()==0);
   120 	test(dateTime2.Minute()==0);
   121 	test(dateTime2.Hour()==0);
   122 	if (dateTime2.Month()==dateTime.Month())
   123 		test(dateTime2.Day()==dateTime.Day()+1);
   124 	else
   125 		test(dateTime2.Day()==0);
   126 	time=dateTime;
   127 	r=notifier.Logon(stat);
   128 	test(r==KErrNone);
   129 	TestStat(stat,KRequestPending);
   130 	test(User::SetHomeTime(time)==KErrNone);
   131 	User::WaitForRequest(stat);
   132 	TestStat(stat,(EChangesSystemTime|EChangesMidnightCrossover));
   133 	time=dateTime2;
   134 	r=notifier.Logon(stat);
   135 	test(r==KErrNone);
   136 	TestStat(stat,KRequestPending);
   137 	test(User::SetHomeTime(time)==KErrNone);
   138 	User::WaitForRequest(stat);
   139 	TestStat(stat,(EChangesSystemTime|EChangesMidnightCrossover));
   140 
   141 	// Check that a change of secure time also triggers notification, even though the user time is unchanged
   142 	r = notifier.Logon(stat);
   143 	test(r == KErrNone);
   144 	TestStat(stat, KRequestPending);
   145 	if ((r = time.HomeTimeSecure()) == KErrNone)
   146 		r = User::SetHomeTimeSecure(time+TTimeIntervalSeconds(60));
   147 	if (r == KErrNone)
   148 		{
   149 		test(User::SetHomeTimeSecure(time) == KErrNone);
   150 		r = EChangesSystemTime;
   151 		}
   152 	else
   153 		{
   154 		RDebug::Printf("WARNING: Secure clock change test skipped because secure time could not be changed!");
   155 		notifier.LogonCancel();
   156 		r = KErrCancel;
   157 		}
   158 	User::WaitForRequest(stat);
   159 	TestStat(stat, r);
   160 	}
   161 
   162 void SetOffsetForMidnight(TTime time,TTimeIntervalSeconds offset)
   163 	{
   164 	test(User::SetHomeTime(time)==KErrNone);
   165 	User::SetUTCOffset(offset);
   166 // No longer need next line, as we now only get one notification
   167 //	User::After(999999);//So, if time has gone backwards, midnight crossover has been noticed
   168 	TRequestStatus stat;
   169 	notifier.Logon(stat);
   170 	User::WaitForRequest(stat);
   171 	test(stat.Int()&(EChangesSystemTime|EChangesLocale));
   172 	}
   173 
   174 void TestMidnightCrossover()
   175 	{
   176 	TTimeIntervalSeconds offset=User::UTCOffset();
   177 	TTime time;
   178 	time.HomeTime();
   179 	test.Start(_L("Normal"));
   180 	DoTestMidnight();
   181 	test.Next(_L("Now  offset 0"));
   182 	SetOffsetForMidnight(time,0);
   183 	DoTestMidnight();
   184 	test.Next(_L("Now  offset +30"));
   185 	SetOffsetForMidnight(time,30);
   186 	DoTestMidnight();
   187 	test.Next(_L("Now  offset -30"));
   188 	SetOffsetForMidnight(time,-30);
   189 	DoTestMidnight();
   190 	test.Next(_L("Now  offset +60"));
   191 	SetOffsetForMidnight(time,60);
   192 	DoTestMidnight();
   193 	test.Next(_L("Now  offset -60"));
   194 	SetOffsetForMidnight(time,-60);
   195 	DoTestMidnight();
   196 	test.Next(_L("Now  offset +120"));
   197 	SetOffsetForMidnight(time,120);
   198 	DoTestMidnight();
   199 	test.Next(_L("Now  offset -120"));
   200 	SetOffsetForMidnight(time,-120);
   201 	DoTestMidnight();
   202 //
   203 	TTime time1998=TDateTime(1998,EFebruary,2,3,4,5,6);
   204 	test.Next(_L("1998 offset 0"));
   205 	SetOffsetForMidnight(time1998,0);
   206 	DoTestMidnight();
   207 	test.Next(_L("1998 offset +30"));
   208 	SetOffsetForMidnight(time1998,30);
   209 	DoTestMidnight();
   210 	test.Next(_L("1998 offset -30"));
   211 	SetOffsetForMidnight(time1998,-30);
   212 	DoTestMidnight();
   213 	test.Next(_L("1998 offset +60"));
   214 	SetOffsetForMidnight(time1998,60);
   215 	DoTestMidnight();
   216 	test.Next(_L("1998 offset -60"));
   217 	SetOffsetForMidnight(time1998,-60);
   218 	DoTestMidnight();
   219 	test.Next(_L("1998 offset +120"));
   220 	SetOffsetForMidnight(time1998,120);
   221 	DoTestMidnight();
   222 	test.Next(_L("1998 offset -120"));
   223 	SetOffsetForMidnight(time1998,-120);
   224 	DoTestMidnight();
   225 //
   226 	TTime time1999=TDateTime(1999,EDecember,30,3,4,5,6);
   227 	test.Next(_L("1999 offset 0"));
   228 	SetOffsetForMidnight(time1999,0);
   229 	DoTestMidnight();
   230 	TTime now;
   231 	now.HomeTime();
   232 	test(now.DateTime().Year()==2000);
   233 	test(now.DateTime().Month()==EJanuary);
   234 	test.Next(_L("1999 offset +30"));
   235 	SetOffsetForMidnight(time1999,30);
   236 	DoTestMidnight();
   237 	now.HomeTime();
   238 	test(now.DateTime().Year()==2000);
   239 	test(now.DateTime().Month()==EJanuary);
   240 	test.Next(_L("1999 offset -30"));
   241 	SetOffsetForMidnight(time1999,-30);
   242 	DoTestMidnight();
   243 	now.HomeTime();
   244 	test(now.DateTime().Year()==2000);
   245 	test(now.DateTime().Month()==EJanuary);
   246 	test.Next(_L("1999 offset +60"));
   247 	SetOffsetForMidnight(time1999,60);
   248 	DoTestMidnight();
   249 	now.HomeTime();
   250 	test(now.DateTime().Year()==2000);
   251 	test(now.DateTime().Month()==EJanuary);
   252 	test.Next(_L("1999 offset -60"));
   253 	SetOffsetForMidnight(time1999,-60);
   254 	DoTestMidnight();
   255 	now.HomeTime();
   256 	test(now.DateTime().Year()==2000);
   257 	test(now.DateTime().Month()==EJanuary);
   258 	test.Next(_L("1999 offset +120"));
   259 	SetOffsetForMidnight(time1999,120);
   260 	DoTestMidnight();
   261 	now.HomeTime();
   262 	test(now.DateTime().Year()==2000);
   263 	test(now.DateTime().Month()==EJanuary);
   264 	test.Next(_L("1999 offset -120"));
   265 	SetOffsetForMidnight(time1999,-120);
   266 	DoTestMidnight();
   267 	now.HomeTime();
   268 	test(now.DateTime().Year()==2000);
   269 	test(now.DateTime().Month()==EJanuary);
   270 //
   271 	TTime time2002=TDateTime(2002,EAugust,30,3,4,5,6);
   272 	test.Next(_L("2002 offset 0"));
   273 	SetOffsetForMidnight(time2002,0);
   274 	DoTestMidnight();
   275 	test.Next(_L("2002 offset +30"));
   276 	SetOffsetForMidnight(time2002,30);
   277 	DoTestMidnight();
   278 	test.Next(_L("2002 offset -30"));
   279 	SetOffsetForMidnight(time2002,-30);
   280 	DoTestMidnight();
   281 	test.Next(_L("2002 offset +60"));
   282 	SetOffsetForMidnight(time2002,60);
   283 	DoTestMidnight();
   284 	test.Next(_L("2002 offset -60"));
   285 	SetOffsetForMidnight(time2002,-60);
   286 	DoTestMidnight();
   287 	test.Next(_L("2002 offset +120"));
   288 	SetOffsetForMidnight(time2002,120);
   289 	DoTestMidnight();
   290 	test.Next(_L("2002 offset -120"));
   291 	SetOffsetForMidnight(time2002,-120);
   292 	DoTestMidnight();
   293 //
   294 	SetOffsetForMidnight(time,offset);
   295 	test.End();
   296 	}
   297 
   298 void TestLocaleChanges()
   299 	{
   300 	TRequestStatus stat;
   301 	notifier.Logon(stat);
   302 	TestStat(stat,KRequestPending);
   303 	TLocale	locale;
   304 	locale.Set();
   305 	User::WaitForRequest(stat);
   306 	TestStat(stat,EChangesLocale);
   307 	}
   308 
   309 void TestOffsetChanges()
   310 	{
   311 	TTimeIntervalSeconds oldOffset = User::UTCOffset();
   312 	User::SetUTCOffset(0);
   313 	
   314 	TRequestStatus stat;
   315 	TTime time;
   316 	time.HomeTime();
   317 	TDateTime dateTime=time.DateTime();
   318 	dateTime.SetHour(23);
   319 	dateTime.SetMinute(30);
   320 	dateTime.SetSecond(0);
   321 	dateTime.SetMicroSecond(0);
   322 	time=dateTime;
   323 	test(User::SetHomeTime(time)==KErrNone);
   324 	notifier.Logon(stat);
   325 	User::WaitForRequest(stat);
   326 	TestStat(stat,(EChangesSystemTime));
   327 
   328 	notifier.Logon(stat);
   329 	TestStat(stat,KRequestPending);
   330 	User::SetUTCOffset(3600);
   331 	User::WaitForRequest(stat);
   332 	TestStat(stat,(EChangesSystemTime|EChangesLocale|EChangesMidnightCrossover));
   333 	User::SetUTCOffset(oldOffset);
   334 	notifier.Logon(stat);
   335 	User::WaitForRequest(stat);
   336 	}
   337 
   338 const TInt retValue=65432;
   339 const TInt killValue=2081953;
   340 const TInt terminateValue=512123;
   341 const TInt panicValue=1257671;
   342 const TInt KHeapSize=0x200;
   343 
   344 TInt ThreadCode(TAny* aReturnImmetiateFlag)
   345 	{
   346 	if(!aReturnImmetiateFlag)
   347 		User::After(60000000); // wait a minute, (effectively forever as far as the test goes).
   348 	return retValue;
   349 	}
   350 
   351 void TestThreadDeath()
   352 	{
   353 	test.Start(_L("Normal Exit"));
   354 	RThread	thread;
   355 	TInt r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETrue);
   356 	test(r==KErrNone);
   357 	__KHEAP_MARK;
   358 	TRequestStatus threadStat;
   359 	thread.Logon(threadStat);
   360 	TRequestStatus stat;
   361 	notifier.Logon(stat);
   362 	TestStat(stat,KRequestPending);
   363 	thread.Resume();
   364 	User::WaitForRequest(stat);
   365 	TestStat(stat,EChangesThreadDeath);
   366 	test(threadStat==retValue);
   367 	test(thread.ExitReason()==retValue);
   368 	test(thread.ExitType()==EExitKill);
   369 	test(thread.ExitCategory()==_L("Kill"));
   370 	CLOSE_AND_WAIT(thread);
   371 	__KHEAP_MARKEND;
   372 
   373 	test.Next(_L("Kill"));
   374 	r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   375 	test(r==KErrNone);
   376 	thread.Logon(threadStat);
   377 	notifier.Logon(stat);
   378 	TestStat(stat,KRequestPending);
   379 	thread.Resume();
   380 	thread.Kill(killValue);
   381 	User::WaitForRequest(stat);
   382 	TestStat(stat,EChangesThreadDeath);
   383 	test(threadStat==killValue);
   384 	test(thread.ExitReason()==killValue);
   385 	test(thread.ExitType()==EExitKill);
   386 	test(thread.ExitCategory()==_L("Kill"));
   387 	CLOSE_AND_WAIT(thread);
   388 
   389 	test.Next(_L("Terminate"));
   390 	r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   391 	test(r==KErrNone);
   392 	thread.Logon(threadStat);
   393 	notifier.Logon(stat);
   394 	TestStat(stat,KRequestPending);
   395 	thread.Resume();
   396 	thread.Terminate(terminateValue);
   397 	User::WaitForRequest(stat);
   398 	TestStat(stat,EChangesThreadDeath);
   399 	test(threadStat==terminateValue);
   400 	test(thread.ExitReason()==terminateValue);
   401 	test(thread.ExitType()==EExitTerminate);
   402 	test(thread.ExitCategory()==_L("Terminate"));
   403 	CLOSE_AND_WAIT(thread);
   404 
   405 	test.Next(_L("Panic"));
   406 	r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   407 	test(r==KErrNone);
   408 	thread.Logon(threadStat);
   409 	notifier.Logon(stat);
   410 	TestStat(stat,KRequestPending);
   411 	TBool justInTime=User::JustInTime(); 
   412 	User::SetJustInTime(EFalse); 
   413 	thread.Resume();
   414 	thread.Panic(_L("Testing panic"),panicValue);
   415 	User::WaitForRequest(stat);
   416 	User::SetJustInTime(justInTime); 
   417 	TestStat(stat,EChangesThreadDeath);
   418 	test(threadStat==panicValue);
   419 	test(thread.ExitReason()==panicValue);
   420 	test(thread.ExitType()==EExitPanic);
   421 	test(thread.ExitCategory()==_L("Testing panic"));
   422 	CLOSE_AND_WAIT(thread);
   423 	test.End();
   424 	}
   425 
   426 void TestCloseWhilstPending()
   427 	{
   428 	test_KErrNone(notifier.Create());
   429 	TRequestStatus stat;
   430 	test_KErrNone(notifier.Logon(stat));
   431 	User::WaitForRequest(stat);
   432 	test_KErrNone(notifier.Logon(stat));
   433 	notifier.Close();
   434 	test_Equal(KErrGeneral,stat.Int());
   435 	}
   436 
   437 void TestCloseAndCompleteRace()
   438 	{
   439 	RThread().SetPriority(EPriorityRealTime);
   440 
   441 	// setup notifier2
   442 	RChangeNotifier notifier2;
   443 	test_KErrNone(notifier2.Create());
   444 	TRequestStatus stat2;
   445 	test_KErrNone(notifier2.Logon(stat2));
   446 	User::WaitForRequest(stat2);
   447 	test_KErrNone(notifier2.Logon(stat2));
   448 
   449 	// setup notifier
   450 	test_KErrNone(notifier.Create());
   451 	TRequestStatus stat;
   452 	test_KErrNone(notifier.Logon(stat));
   453 	User::WaitForRequest(stat);
   454 	test_KErrNone(notifier.Logon(stat));
   455 
   456 	// create and kill a thread so notifiers get signaled
   457 	RThread	thread;
   458 	test_KErrNone(thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL));
   459 	thread.Kill(0);
   460 
   461 	// wait for notifier2
   462 	User::WaitForRequest(stat2);
   463 
   464 	// as this thread is realtime priority, then (on unicore systems) it has preempted
   465 	// kernel supervisor thread after it completed 'notifier2' but before it completed
   466 	// 'notifier'. if we close both notifiers now we trigger a race conidition which
   467 	// previousely caused a null pointer dereference in the kernel...
   468 	notifier.Close();
   469 	notifier2.Close();
   470 
   471 	User::WaitForRequest(stat);
   472 	TInt result = stat.Int();
   473 
   474 	// expect KErrGeneral from closing notifier, or on SMP probably EChangesThreadDeath as
   475 	// the notifier had time to complete
   476 	const TInt numCpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
   477 	if(numCpus==1 || result!=EChangesThreadDeath)
   478 		test_Equal(KErrGeneral,result);
   479 
   480 	RThread().SetPriority(EPriorityNormal);
   481 	thread.Close();
   482 	}
   483 
   484 TInt E32Main()
   485 	{
   486 
   487 	User::After(1000000);//So WINS doesn't give an instant power-status change;
   488 	test.Start(_L("Create"));
   489 	TestCreate();
   490 
   491 	test.Next(_L("Close"));
   492 	notifier.Close();
   493 
   494 	test.Next(_L("Create"));
   495 	TestCreate();
   496 
   497 	test.Next(_L("Logon/Logoff"));
   498 	TestLogonLogoff();
   499 
   500 	test.Next(_L("Midnight crossover"));
   501 	TestMidnightCrossover();
   502 
   503 	test.Next(_L("Locale changes"));
   504 	TestLocaleChanges();
   505 
   506 	test.Next(_L("Offset changes"));
   507 	TestOffsetChanges();
   508 
   509 	test.Next(_L("Thread death"));
   510 	TestThreadDeath();
   511 
   512 	test.Next(_L("Close"));
   513 	notifier.Close();
   514 
   515 	test.Next(_L("Close whilst pending"));
   516 	TestCloseWhilstPending();
   517 
   518 	test.Next(_L("Race between Close and complete"));
   519 	TestCloseAndCompleteRace();
   520 
   521 	test.End();
   522 	return KErrNone;
   523 	}