1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/system/t_chnot.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,523 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\system\t_chnot.cpp
1.18 +// Tests RChangeNotifier class
1.19 +// Overview:
1.20 +// Tests RChangeNotifier class
1.21 +// API Information:
1.22 +// RChangeNotifier
1.23 +// Details:
1.24 +// - Create a RChangeNotifier object and verify the logon status is
1.25 +// as expected.
1.26 +// - Call the Logon and LogonCancel methods, verify results are as
1.27 +// expected.
1.28 +// - Test for the correct midnight crossover notifier results in a
1.29 +// variety of situations: DST On, DST Off, various time offsets
1.30 +// and various dates.
1.31 +// - Test various locale changes and verify that the notifier response
1.32 +// is as expected.
1.33 +// - Test the notification of the death of a thread and check that
1.34 +// results are as expected. Check for normal exit, kill exit,
1.35 +// terminate exit and panic exit.
1.36 +// Platforms/Drives/Compatibility:
1.37 +// All.
1.38 +// Assumptions/Requirement/Pre-requisites:
1.39 +// Failures and causes:
1.40 +// Base Port information:
1.41 +//
1.42 +//
1.43 +
1.44 +#define __E32TEST_EXTENSION__
1.45 +#include <e32test.h>
1.46 +#include <e32hal.h>
1.47 +#include <e32svr.h>
1.48 +#include <u32hal.h>
1.49 +#include <e32def.h>
1.50 +#include <e32def_private.h>
1.51 +
1.52 +RTest test(_L("T_CHNOT"));
1.53 +
1.54 +RChangeNotifier notifier;
1.55 +
1.56 +void TestStat(const TRequestStatus& aStat, TInt aValue)
1.57 + {
1.58 + if (aStat.Int()!=aValue)
1.59 + {
1.60 + test.Printf(_L("Got %08x Expected %08x\n"),aStat.Int(),aValue);
1.61 + test(0);
1.62 + }
1.63 + }
1.64 +
1.65 +void TestCreate()
1.66 + {
1.67 + notifier.Create();
1.68 + TRequestStatus stat;
1.69 + notifier.Logon(stat);
1.70 +
1.71 + // Expect all except EChangesLowMemory
1.72 + TUint expected =
1.73 + EChangesLocale |
1.74 + EChangesMidnightCrossover |
1.75 + EChangesThreadDeath |
1.76 + EChangesPowerStatus |
1.77 + EChangesSystemTime |
1.78 + EChangesFreeMemory |
1.79 + EChangesOutOfMemory |
1.80 + EChangesThrashLevel;
1.81 +
1.82 + test(stat==expected);
1.83 + }
1.84 +
1.85 +void TestLogonLogoff()
1.86 + {
1.87 + TRequestStatus stat;
1.88 + notifier.LogonCancel();
1.89 + notifier.Logon(stat);
1.90 + TestStat(stat,KRequestPending);
1.91 + notifier.LogonCancel();
1.92 + TestStat(stat,KErrCancel);
1.93 + notifier.LogonCancel();
1.94 + TestStat(stat,KErrCancel);
1.95 + }
1.96 +
1.97 +void DoTestMidnight()
1.98 + {
1.99 + TTime time;
1.100 + time.HomeTime();
1.101 + TDateTime dateTime=time.DateTime();
1.102 + dateTime.SetHour(23);
1.103 + dateTime.SetMinute(59);
1.104 + dateTime.SetSecond(58);
1.105 + dateTime.SetMicroSecond(700000);
1.106 + time=dateTime;
1.107 + TRequestStatus stat;
1.108 + TInt r=notifier.Logon(stat);
1.109 + test(r==KErrNone);
1.110 + TestStat(stat,KRequestPending);
1.111 + test(User::SetHomeTime(time)==KErrNone);
1.112 + time.HomeTime();
1.113 + TDateTime dateTime2=time.DateTime();
1.114 + User::WaitForRequest(stat);
1.115 + TestStat(stat,EChangesSystemTime);
1.116 + r=notifier.Logon(stat);
1.117 + test(r==KErrNone);
1.118 + User::WaitForRequest(stat);
1.119 + time.HomeTime();
1.120 + TestStat(stat,EChangesMidnightCrossover);
1.121 + dateTime2=time.DateTime();
1.122 + test(dateTime2.Second()==0);
1.123 + test(dateTime2.Minute()==0);
1.124 + test(dateTime2.Hour()==0);
1.125 + if (dateTime2.Month()==dateTime.Month())
1.126 + test(dateTime2.Day()==dateTime.Day()+1);
1.127 + else
1.128 + test(dateTime2.Day()==0);
1.129 + time=dateTime;
1.130 + r=notifier.Logon(stat);
1.131 + test(r==KErrNone);
1.132 + TestStat(stat,KRequestPending);
1.133 + test(User::SetHomeTime(time)==KErrNone);
1.134 + User::WaitForRequest(stat);
1.135 + TestStat(stat,(EChangesSystemTime|EChangesMidnightCrossover));
1.136 + time=dateTime2;
1.137 + r=notifier.Logon(stat);
1.138 + test(r==KErrNone);
1.139 + TestStat(stat,KRequestPending);
1.140 + test(User::SetHomeTime(time)==KErrNone);
1.141 + User::WaitForRequest(stat);
1.142 + TestStat(stat,(EChangesSystemTime|EChangesMidnightCrossover));
1.143 +
1.144 + // Check that a change of secure time also triggers notification, even though the user time is unchanged
1.145 + r = notifier.Logon(stat);
1.146 + test(r == KErrNone);
1.147 + TestStat(stat, KRequestPending);
1.148 + if ((r = time.HomeTimeSecure()) == KErrNone)
1.149 + r = User::SetHomeTimeSecure(time+TTimeIntervalSeconds(60));
1.150 + if (r == KErrNone)
1.151 + {
1.152 + test(User::SetHomeTimeSecure(time) == KErrNone);
1.153 + r = EChangesSystemTime;
1.154 + }
1.155 + else
1.156 + {
1.157 + RDebug::Printf("WARNING: Secure clock change test skipped because secure time could not be changed!");
1.158 + notifier.LogonCancel();
1.159 + r = KErrCancel;
1.160 + }
1.161 + User::WaitForRequest(stat);
1.162 + TestStat(stat, r);
1.163 + }
1.164 +
1.165 +void SetOffsetForMidnight(TTime time,TTimeIntervalSeconds offset)
1.166 + {
1.167 + test(User::SetHomeTime(time)==KErrNone);
1.168 + User::SetUTCOffset(offset);
1.169 +// No longer need next line, as we now only get one notification
1.170 +// User::After(999999);//So, if time has gone backwards, midnight crossover has been noticed
1.171 + TRequestStatus stat;
1.172 + notifier.Logon(stat);
1.173 + User::WaitForRequest(stat);
1.174 + test(stat.Int()&(EChangesSystemTime|EChangesLocale));
1.175 + }
1.176 +
1.177 +void TestMidnightCrossover()
1.178 + {
1.179 + TTimeIntervalSeconds offset=User::UTCOffset();
1.180 + TTime time;
1.181 + time.HomeTime();
1.182 + test.Start(_L("Normal"));
1.183 + DoTestMidnight();
1.184 + test.Next(_L("Now offset 0"));
1.185 + SetOffsetForMidnight(time,0);
1.186 + DoTestMidnight();
1.187 + test.Next(_L("Now offset +30"));
1.188 + SetOffsetForMidnight(time,30);
1.189 + DoTestMidnight();
1.190 + test.Next(_L("Now offset -30"));
1.191 + SetOffsetForMidnight(time,-30);
1.192 + DoTestMidnight();
1.193 + test.Next(_L("Now offset +60"));
1.194 + SetOffsetForMidnight(time,60);
1.195 + DoTestMidnight();
1.196 + test.Next(_L("Now offset -60"));
1.197 + SetOffsetForMidnight(time,-60);
1.198 + DoTestMidnight();
1.199 + test.Next(_L("Now offset +120"));
1.200 + SetOffsetForMidnight(time,120);
1.201 + DoTestMidnight();
1.202 + test.Next(_L("Now offset -120"));
1.203 + SetOffsetForMidnight(time,-120);
1.204 + DoTestMidnight();
1.205 +//
1.206 + TTime time1998=TDateTime(1998,EFebruary,2,3,4,5,6);
1.207 + test.Next(_L("1998 offset 0"));
1.208 + SetOffsetForMidnight(time1998,0);
1.209 + DoTestMidnight();
1.210 + test.Next(_L("1998 offset +30"));
1.211 + SetOffsetForMidnight(time1998,30);
1.212 + DoTestMidnight();
1.213 + test.Next(_L("1998 offset -30"));
1.214 + SetOffsetForMidnight(time1998,-30);
1.215 + DoTestMidnight();
1.216 + test.Next(_L("1998 offset +60"));
1.217 + SetOffsetForMidnight(time1998,60);
1.218 + DoTestMidnight();
1.219 + test.Next(_L("1998 offset -60"));
1.220 + SetOffsetForMidnight(time1998,-60);
1.221 + DoTestMidnight();
1.222 + test.Next(_L("1998 offset +120"));
1.223 + SetOffsetForMidnight(time1998,120);
1.224 + DoTestMidnight();
1.225 + test.Next(_L("1998 offset -120"));
1.226 + SetOffsetForMidnight(time1998,-120);
1.227 + DoTestMidnight();
1.228 +//
1.229 + TTime time1999=TDateTime(1999,EDecember,30,3,4,5,6);
1.230 + test.Next(_L("1999 offset 0"));
1.231 + SetOffsetForMidnight(time1999,0);
1.232 + DoTestMidnight();
1.233 + TTime now;
1.234 + now.HomeTime();
1.235 + test(now.DateTime().Year()==2000);
1.236 + test(now.DateTime().Month()==EJanuary);
1.237 + test.Next(_L("1999 offset +30"));
1.238 + SetOffsetForMidnight(time1999,30);
1.239 + DoTestMidnight();
1.240 + now.HomeTime();
1.241 + test(now.DateTime().Year()==2000);
1.242 + test(now.DateTime().Month()==EJanuary);
1.243 + test.Next(_L("1999 offset -30"));
1.244 + SetOffsetForMidnight(time1999,-30);
1.245 + DoTestMidnight();
1.246 + now.HomeTime();
1.247 + test(now.DateTime().Year()==2000);
1.248 + test(now.DateTime().Month()==EJanuary);
1.249 + test.Next(_L("1999 offset +60"));
1.250 + SetOffsetForMidnight(time1999,60);
1.251 + DoTestMidnight();
1.252 + now.HomeTime();
1.253 + test(now.DateTime().Year()==2000);
1.254 + test(now.DateTime().Month()==EJanuary);
1.255 + test.Next(_L("1999 offset -60"));
1.256 + SetOffsetForMidnight(time1999,-60);
1.257 + DoTestMidnight();
1.258 + now.HomeTime();
1.259 + test(now.DateTime().Year()==2000);
1.260 + test(now.DateTime().Month()==EJanuary);
1.261 + test.Next(_L("1999 offset +120"));
1.262 + SetOffsetForMidnight(time1999,120);
1.263 + DoTestMidnight();
1.264 + now.HomeTime();
1.265 + test(now.DateTime().Year()==2000);
1.266 + test(now.DateTime().Month()==EJanuary);
1.267 + test.Next(_L("1999 offset -120"));
1.268 + SetOffsetForMidnight(time1999,-120);
1.269 + DoTestMidnight();
1.270 + now.HomeTime();
1.271 + test(now.DateTime().Year()==2000);
1.272 + test(now.DateTime().Month()==EJanuary);
1.273 +//
1.274 + TTime time2002=TDateTime(2002,EAugust,30,3,4,5,6);
1.275 + test.Next(_L("2002 offset 0"));
1.276 + SetOffsetForMidnight(time2002,0);
1.277 + DoTestMidnight();
1.278 + test.Next(_L("2002 offset +30"));
1.279 + SetOffsetForMidnight(time2002,30);
1.280 + DoTestMidnight();
1.281 + test.Next(_L("2002 offset -30"));
1.282 + SetOffsetForMidnight(time2002,-30);
1.283 + DoTestMidnight();
1.284 + test.Next(_L("2002 offset +60"));
1.285 + SetOffsetForMidnight(time2002,60);
1.286 + DoTestMidnight();
1.287 + test.Next(_L("2002 offset -60"));
1.288 + SetOffsetForMidnight(time2002,-60);
1.289 + DoTestMidnight();
1.290 + test.Next(_L("2002 offset +120"));
1.291 + SetOffsetForMidnight(time2002,120);
1.292 + DoTestMidnight();
1.293 + test.Next(_L("2002 offset -120"));
1.294 + SetOffsetForMidnight(time2002,-120);
1.295 + DoTestMidnight();
1.296 +//
1.297 + SetOffsetForMidnight(time,offset);
1.298 + test.End();
1.299 + }
1.300 +
1.301 +void TestLocaleChanges()
1.302 + {
1.303 + TRequestStatus stat;
1.304 + notifier.Logon(stat);
1.305 + TestStat(stat,KRequestPending);
1.306 + TLocale locale;
1.307 + locale.Set();
1.308 + User::WaitForRequest(stat);
1.309 + TestStat(stat,EChangesLocale);
1.310 + }
1.311 +
1.312 +void TestOffsetChanges()
1.313 + {
1.314 + TTimeIntervalSeconds oldOffset = User::UTCOffset();
1.315 + User::SetUTCOffset(0);
1.316 +
1.317 + TRequestStatus stat;
1.318 + TTime time;
1.319 + time.HomeTime();
1.320 + TDateTime dateTime=time.DateTime();
1.321 + dateTime.SetHour(23);
1.322 + dateTime.SetMinute(30);
1.323 + dateTime.SetSecond(0);
1.324 + dateTime.SetMicroSecond(0);
1.325 + time=dateTime;
1.326 + test(User::SetHomeTime(time)==KErrNone);
1.327 + notifier.Logon(stat);
1.328 + User::WaitForRequest(stat);
1.329 + TestStat(stat,(EChangesSystemTime));
1.330 +
1.331 + notifier.Logon(stat);
1.332 + TestStat(stat,KRequestPending);
1.333 + User::SetUTCOffset(3600);
1.334 + User::WaitForRequest(stat);
1.335 + TestStat(stat,(EChangesSystemTime|EChangesLocale|EChangesMidnightCrossover));
1.336 + User::SetUTCOffset(oldOffset);
1.337 + notifier.Logon(stat);
1.338 + User::WaitForRequest(stat);
1.339 + }
1.340 +
1.341 +const TInt retValue=65432;
1.342 +const TInt killValue=2081953;
1.343 +const TInt terminateValue=512123;
1.344 +const TInt panicValue=1257671;
1.345 +const TInt KHeapSize=0x200;
1.346 +
1.347 +TInt ThreadCode(TAny* aReturnImmetiateFlag)
1.348 + {
1.349 + if(!aReturnImmetiateFlag)
1.350 + User::After(60000000); // wait a minute, (effectively forever as far as the test goes).
1.351 + return retValue;
1.352 + }
1.353 +
1.354 +void TestThreadDeath()
1.355 + {
1.356 + test.Start(_L("Normal Exit"));
1.357 + RThread thread;
1.358 + TInt r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETrue);
1.359 + test(r==KErrNone);
1.360 + __KHEAP_MARK;
1.361 + TRequestStatus threadStat;
1.362 + thread.Logon(threadStat);
1.363 + TRequestStatus stat;
1.364 + notifier.Logon(stat);
1.365 + TestStat(stat,KRequestPending);
1.366 + thread.Resume();
1.367 + User::WaitForRequest(stat);
1.368 + TestStat(stat,EChangesThreadDeath);
1.369 + test(threadStat==retValue);
1.370 + test(thread.ExitReason()==retValue);
1.371 + test(thread.ExitType()==EExitKill);
1.372 + test(thread.ExitCategory()==_L("Kill"));
1.373 + CLOSE_AND_WAIT(thread);
1.374 + __KHEAP_MARKEND;
1.375 +
1.376 + test.Next(_L("Kill"));
1.377 + r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.378 + test(r==KErrNone);
1.379 + thread.Logon(threadStat);
1.380 + notifier.Logon(stat);
1.381 + TestStat(stat,KRequestPending);
1.382 + thread.Resume();
1.383 + thread.Kill(killValue);
1.384 + User::WaitForRequest(stat);
1.385 + TestStat(stat,EChangesThreadDeath);
1.386 + test(threadStat==killValue);
1.387 + test(thread.ExitReason()==killValue);
1.388 + test(thread.ExitType()==EExitKill);
1.389 + test(thread.ExitCategory()==_L("Kill"));
1.390 + CLOSE_AND_WAIT(thread);
1.391 +
1.392 + test.Next(_L("Terminate"));
1.393 + r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.394 + test(r==KErrNone);
1.395 + thread.Logon(threadStat);
1.396 + notifier.Logon(stat);
1.397 + TestStat(stat,KRequestPending);
1.398 + thread.Resume();
1.399 + thread.Terminate(terminateValue);
1.400 + User::WaitForRequest(stat);
1.401 + TestStat(stat,EChangesThreadDeath);
1.402 + test(threadStat==terminateValue);
1.403 + test(thread.ExitReason()==terminateValue);
1.404 + test(thread.ExitType()==EExitTerminate);
1.405 + test(thread.ExitCategory()==_L("Terminate"));
1.406 + CLOSE_AND_WAIT(thread);
1.407 +
1.408 + test.Next(_L("Panic"));
1.409 + r=thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1.410 + test(r==KErrNone);
1.411 + thread.Logon(threadStat);
1.412 + notifier.Logon(stat);
1.413 + TestStat(stat,KRequestPending);
1.414 + TBool justInTime=User::JustInTime();
1.415 + User::SetJustInTime(EFalse);
1.416 + thread.Resume();
1.417 + thread.Panic(_L("Testing panic"),panicValue);
1.418 + User::WaitForRequest(stat);
1.419 + User::SetJustInTime(justInTime);
1.420 + TestStat(stat,EChangesThreadDeath);
1.421 + test(threadStat==panicValue);
1.422 + test(thread.ExitReason()==panicValue);
1.423 + test(thread.ExitType()==EExitPanic);
1.424 + test(thread.ExitCategory()==_L("Testing panic"));
1.425 + CLOSE_AND_WAIT(thread);
1.426 + test.End();
1.427 + }
1.428 +
1.429 +void TestCloseWhilstPending()
1.430 + {
1.431 + test_KErrNone(notifier.Create());
1.432 + TRequestStatus stat;
1.433 + test_KErrNone(notifier.Logon(stat));
1.434 + User::WaitForRequest(stat);
1.435 + test_KErrNone(notifier.Logon(stat));
1.436 + notifier.Close();
1.437 + test_Equal(KErrGeneral,stat.Int());
1.438 + }
1.439 +
1.440 +void TestCloseAndCompleteRace()
1.441 + {
1.442 + RThread().SetPriority(EPriorityRealTime);
1.443 +
1.444 + // setup notifier2
1.445 + RChangeNotifier notifier2;
1.446 + test_KErrNone(notifier2.Create());
1.447 + TRequestStatus stat2;
1.448 + test_KErrNone(notifier2.Logon(stat2));
1.449 + User::WaitForRequest(stat2);
1.450 + test_KErrNone(notifier2.Logon(stat2));
1.451 +
1.452 + // setup notifier
1.453 + test_KErrNone(notifier.Create());
1.454 + TRequestStatus stat;
1.455 + test_KErrNone(notifier.Logon(stat));
1.456 + User::WaitForRequest(stat);
1.457 + test_KErrNone(notifier.Logon(stat));
1.458 +
1.459 + // create and kill a thread so notifiers get signaled
1.460 + RThread thread;
1.461 + test_KErrNone(thread.Create(_L("T_CHNOT ThreadCode"),ThreadCode,KDefaultStackSize,KHeapSize,KHeapSize,NULL));
1.462 + thread.Kill(0);
1.463 +
1.464 + // wait for notifier2
1.465 + User::WaitForRequest(stat2);
1.466 +
1.467 + // as this thread is realtime priority, then (on unicore systems) it has preempted
1.468 + // kernel supervisor thread after it completed 'notifier2' but before it completed
1.469 + // 'notifier'. if we close both notifiers now we trigger a race conidition which
1.470 + // previousely caused a null pointer dereference in the kernel...
1.471 + notifier.Close();
1.472 + notifier2.Close();
1.473 +
1.474 + User::WaitForRequest(stat);
1.475 + TInt result = stat.Int();
1.476 +
1.477 + // expect KErrGeneral from closing notifier, or on SMP probably EChangesThreadDeath as
1.478 + // the notifier had time to complete
1.479 + const TInt numCpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
1.480 + if(numCpus==1 || result!=EChangesThreadDeath)
1.481 + test_Equal(KErrGeneral,result);
1.482 +
1.483 + RThread().SetPriority(EPriorityNormal);
1.484 + thread.Close();
1.485 + }
1.486 +
1.487 +TInt E32Main()
1.488 + {
1.489 +
1.490 + User::After(1000000);//So WINS doesn't give an instant power-status change;
1.491 + test.Start(_L("Create"));
1.492 + TestCreate();
1.493 +
1.494 + test.Next(_L("Close"));
1.495 + notifier.Close();
1.496 +
1.497 + test.Next(_L("Create"));
1.498 + TestCreate();
1.499 +
1.500 + test.Next(_L("Logon/Logoff"));
1.501 + TestLogonLogoff();
1.502 +
1.503 + test.Next(_L("Midnight crossover"));
1.504 + TestMidnightCrossover();
1.505 +
1.506 + test.Next(_L("Locale changes"));
1.507 + TestLocaleChanges();
1.508 +
1.509 + test.Next(_L("Offset changes"));
1.510 + TestOffsetChanges();
1.511 +
1.512 + test.Next(_L("Thread death"));
1.513 + TestThreadDeath();
1.514 +
1.515 + test.Next(_L("Close"));
1.516 + notifier.Close();
1.517 +
1.518 + test.Next(_L("Close whilst pending"));
1.519 + TestCloseWhilstPending();
1.520 +
1.521 + test.Next(_L("Race between Close and complete"));
1.522 + TestCloseAndCompleteRace();
1.523 +
1.524 + test.End();
1.525 + return KErrNone;
1.526 + }