kerneltest/e32test/system/t_chnot.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}