35 // - Test sharing a chunk between threads, verify results are as expected. |
35 // - Test sharing a chunk between threads, verify results are as expected. |
36 // - Create a thread to watch for notification of changes in free memory and |
36 // - Create a thread to watch for notification of changes in free memory and |
37 // changes in out of memory status. Verify adjusting an RChunk generates |
37 // changes in out of memory status. Verify adjusting an RChunk generates |
38 // the expected notifications. |
38 // the expected notifications. |
39 // - Test finding a global chunk by name and verify results are as expected. |
39 // - Test finding a global chunk by name and verify results are as expected. |
|
40 // - Check read-only global chunks cannot be written to by other processes. |
40 // Platforms/Drives/Compatibility: |
41 // Platforms/Drives/Compatibility: |
41 // All. |
42 // All. |
42 // Assumptions/Requirement/Pre-requisites: |
43 // Assumptions/Requirement/Pre-requisites: |
43 // Failures and causes: |
44 // Failures and causes: |
44 // Base Port information: |
45 // Base Port information: |
1147 // kernel memory leaks. |
1148 // kernel memory leaks. |
1148 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); |
1149 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); |
1149 } |
1150 } |
1150 |
1151 |
1151 |
1152 |
1152 /**Returns true if 'extended' is found in the command line*/ |
1153 /**Returns true if argument is found in the command line*/ |
1153 TBool GetExtended() |
1154 TBool IsInCommandLine(const TDesC& aArg) |
1154 { |
1155 { |
1155 _LIT(KExtended,"extended"); |
|
1156 TBuf<64> c; |
1156 TBuf<64> c; |
1157 User::CommandLine(c); |
1157 User::CommandLine(c); |
1158 if (c.FindF(KExtended) >= 0) |
1158 if (c.FindF(aArg) >= 0) |
1159 return ETrue; |
1159 return ETrue; |
1160 return EFalse; |
1160 return EFalse; |
1161 } |
1161 } |
1162 |
1162 |
|
1163 _LIT(KTestChunkReadOnly, "TestReadOnlyChunk"); |
|
1164 _LIT(KTestSemaphoreReadOnly, "TestReadOnlySemaphore"); |
|
1165 _LIT(KTestParamRo, "restro"); |
|
1166 _LIT(KTestParamRw, "restrw"); |
|
1167 _LIT(KTestParamWait, "restwait"); |
|
1168 _LIT(KTestParamWritableChunk, "restwritable"); |
|
1169 |
|
1170 enum TTestProcessParameters |
|
1171 { |
|
1172 ETestRw = 0x1, |
|
1173 ETestWait = 0x2, |
|
1174 ETestWritableChunk = 0x4, |
|
1175 }; |
|
1176 |
|
1177 void TestReadOnlyProcess(TUint aParams) |
|
1178 { |
|
1179 TInt r; |
|
1180 RChunk chunk; |
|
1181 RSemaphore sem; |
|
1182 |
|
1183 test.Start(_L("Open global chunk")); |
|
1184 r = chunk.OpenGlobal(KTestChunkReadOnly, EFalse); |
|
1185 test_KErrNone(r); |
|
1186 |
|
1187 test(chunk.IsReadable()); |
|
1188 r = chunk.Adjust(1); |
|
1189 if (aParams & ETestWritableChunk) |
|
1190 { |
|
1191 test(chunk.IsWritable()); |
|
1192 test_KErrNone(r); |
|
1193 } |
|
1194 else |
|
1195 { |
|
1196 test(!chunk.IsWritable()); |
|
1197 test_Equal(KErrAccessDenied, r); |
|
1198 } |
|
1199 |
|
1200 if (aParams & ETestWait) |
|
1201 { |
|
1202 RProcess::Rendezvous(KErrNone); |
|
1203 test.Next(_L("Wait on semaphore")); |
|
1204 r = sem.OpenGlobal(KTestSemaphoreReadOnly); |
|
1205 test_KErrNone(r); |
|
1206 sem.Wait(); |
|
1207 } |
|
1208 |
|
1209 test.Next(_L("Read")); |
|
1210 TUint8 read = *(volatile TUint8*) chunk.Base(); |
|
1211 (void) read; |
|
1212 |
|
1213 if (aParams & ETestRw) |
|
1214 { |
|
1215 test.Next(_L("Write")); |
|
1216 TUint8* write = chunk.Base(); |
|
1217 *write = 0x3d; |
|
1218 } |
|
1219 |
|
1220 chunk.Close(); |
|
1221 if (aParams & ETestWait) |
|
1222 { |
|
1223 sem.Close(); |
|
1224 } |
|
1225 test.End(); |
|
1226 } |
|
1227 |
|
1228 void TestReadOnly() |
|
1229 { |
|
1230 TInt r; |
|
1231 RChunk chunk; |
|
1232 RProcess process1; |
|
1233 RProcess process2; |
|
1234 RSemaphore sem; |
|
1235 TRequestStatus rs; |
|
1236 TRequestStatus rv; |
|
1237 |
|
1238 // Assumption is made that any memory model from Flexible onwards that supports |
|
1239 // read-only memory also supports read-only chunks |
|
1240 if (MemModelType() < EMemModelTypeFlexible || !HaveWriteProt()) |
|
1241 { |
|
1242 test.Printf(_L("Memory model is not expected to support Read-Only Chunks\n")); |
|
1243 return; |
|
1244 } |
|
1245 |
|
1246 TBool jit = User::JustInTime(); |
|
1247 User::SetJustInTime(EFalse); |
|
1248 |
|
1249 test.Start(_L("Create writable global chunk")); |
|
1250 TChunkCreateInfo info; |
|
1251 info.SetNormal(0, 1234567); |
|
1252 info.SetGlobal(KTestChunkReadOnly); |
|
1253 r = chunk.Create(info); |
|
1254 test_KErrNone(r); |
|
1255 test(chunk.IsReadable()); |
|
1256 test(chunk.IsWritable()); |
|
1257 |
|
1258 test.Next(_L("Adjust size")); |
|
1259 r = chunk.Adjust(1); // add one page |
|
1260 test_KErrNone(r); |
|
1261 |
|
1262 test.Next(_L("Attempt read/write 1")); |
|
1263 r = process1.Create(RProcess().FileName(), KTestParamWritableChunk); |
|
1264 test_KErrNone(r); |
|
1265 process1.Logon(rs); |
|
1266 process1.Resume(); |
|
1267 User::WaitForRequest(rs); |
|
1268 test_Equal(EExitKill, process1.ExitType()); |
|
1269 test_KErrNone(process1.ExitReason()); |
|
1270 CLOSE_AND_WAIT(process1); |
|
1271 CLOSE_AND_WAIT(chunk); |
|
1272 |
|
1273 test.Next(_L("Create read-only global chunk")); |
|
1274 info.SetReadOnly(); |
|
1275 r = chunk.Create(info); |
|
1276 test_KErrNone(r); |
|
1277 test(chunk.IsReadable()); |
|
1278 test(chunk.IsWritable()); |
|
1279 // To keep in sync with the 'process2' process |
|
1280 r = sem.CreateGlobal(KTestSemaphoreReadOnly, 0); |
|
1281 test_KErrNone(r); |
|
1282 |
|
1283 test.Next(_L("Attempt read 1")); |
|
1284 r = process1.Create(RProcess().FileName(), KTestParamRo); |
|
1285 test_KErrNone(r); |
|
1286 process1.Logon(rs); |
|
1287 process1.Resume(); |
|
1288 User::WaitForRequest(rs); |
|
1289 test_Equal(EExitPanic, process1.ExitType()); |
|
1290 test_Equal(3, process1.ExitReason()); // KERN-EXEC 3 assumed |
|
1291 CLOSE_AND_WAIT(process1); |
|
1292 // Create second process before commiting memory and make it wait |
|
1293 r = process2.Create(RProcess().FileName(), KTestParamWait); |
|
1294 test_KErrNone(r) |
|
1295 process2.Rendezvous(rv); |
|
1296 process2.Resume(); |
|
1297 User::WaitForRequest(rv); |
|
1298 |
|
1299 test.Next(_L("Adjust size")); |
|
1300 r = chunk.Adjust(1); // add one page |
|
1301 test_KErrNone(r); |
|
1302 |
|
1303 test.Next(_L("Attempt read 2")); |
|
1304 r = process1.Create(RProcess().FileName(), KTestParamRo); |
|
1305 test_KErrNone(r); |
|
1306 process1.Logon(rs); |
|
1307 process1.Resume(); |
|
1308 User::WaitForRequest(rs); |
|
1309 test_Equal(EExitKill, process1.ExitType()); |
|
1310 test_KErrNone(process1.ExitReason()); |
|
1311 CLOSE_AND_WAIT(process1); |
|
1312 |
|
1313 test.Next(_L("Attempt read/write 1")); |
|
1314 r = process1.Create(RProcess().FileName(), KTestParamRw); |
|
1315 test_KErrNone(r); |
|
1316 process1.Logon(rs); |
|
1317 process1.Resume(); |
|
1318 User::WaitForRequest(rs); |
|
1319 test_Equal(EExitPanic, process1.ExitType()); |
|
1320 test_Equal(3, process1.ExitReason()); // KERN-EXEC 3 assumed |
|
1321 CLOSE_AND_WAIT(process1); |
|
1322 // Controlling process is not affected |
|
1323 TUint8* write = chunk.Base(); |
|
1324 *write = 0x77; |
|
1325 |
|
1326 test.Next(_L("Attempt read/write 2")); |
|
1327 test_Equal(EExitPending, process2.ExitType()); |
|
1328 process2.Logon(rs); |
|
1329 sem.Signal(); |
|
1330 User::WaitForRequest(rs); |
|
1331 test_Equal(EExitPanic, process2.ExitType()); |
|
1332 test_Equal(3, process2.ExitReason()); // KERN-EXEC 3 assumed |
|
1333 CLOSE_AND_WAIT(process2); |
|
1334 |
|
1335 chunk.Close(); |
|
1336 sem.Close(); |
|
1337 test.End(); |
|
1338 User::SetJustInTime(jit); |
|
1339 } |
1163 |
1340 |
1164 TInt E32Main() |
1341 TInt E32Main() |
1165 // |
1342 // |
1166 // Test RChunk class |
1343 // Test RChunk class |
1167 // |
1344 // |
1178 RLoader l; |
1355 RLoader l; |
1179 test(l.Connect()==KErrNone); |
1356 test(l.Connect()==KErrNone); |
1180 test(l.CancelLazyDllUnload()==KErrNone); |
1357 test(l.CancelLazyDllUnload()==KErrNone); |
1181 l.Close(); |
1358 l.Close(); |
1182 |
1359 |
1183 __KHEAP_MARK; |
1360 _LIT(KExtended,"extended"); |
1184 |
1361 |
1185 if (GetExtended() ) |
1362 if (IsInCommandLine(KExtended)) |
1186 { |
1363 { |
|
1364 __KHEAP_MARK; |
1187 test.Printf(_L("t_chunk extended was called. Ready to call TestFullAddressSpace(Etrue) \n")); |
1365 test.Printf(_L("t_chunk extended was called. Ready to call TestFullAddressSpace(Etrue) \n")); |
1188 TestFullAddressSpace(ETrue); |
1366 TestFullAddressSpace(ETrue); |
1189 } |
1367 __KHEAP_MARKEND; |
|
1368 } |
|
1369 else if (IsInCommandLine(KTestParamRo)) |
|
1370 { |
|
1371 test_KErrNone(User::RenameProcess(KTestParamRo)); |
|
1372 TestReadOnlyProcess(0); |
|
1373 } |
|
1374 else if (IsInCommandLine(KTestParamRw)) |
|
1375 { |
|
1376 test_KErrNone(User::RenameProcess(KTestParamRw)); |
|
1377 TestReadOnlyProcess(ETestRw); |
|
1378 } |
|
1379 else if (IsInCommandLine(KTestParamWait)) |
|
1380 { |
|
1381 test_KErrNone(User::RenameProcess(KTestParamWait)); |
|
1382 TestReadOnlyProcess(ETestRw | ETestWait); |
|
1383 } |
|
1384 else if (IsInCommandLine(KTestParamWritableChunk)) |
|
1385 { |
|
1386 test_KErrNone(User::RenameProcess(KTestParamWritableChunk)); |
|
1387 TestReadOnlyProcess(ETestWritableChunk | ETestRw); |
|
1388 } |
1190 else |
1389 else |
1191 { |
1390 { |
|
1391 __KHEAP_MARK; |
1192 test.Start(_L("Testing..")); |
1392 test.Start(_L("Testing..")); |
1193 testAdjustChunk(); |
1393 testAdjustChunk(); |
1194 test.Next(_L("Test1")); |
1394 test.Next(_L("Test1")); |
1195 test1(); |
1395 test1(); |
1196 test.Next(_L("Test2")); |
1396 test.Next(_L("Test2")); |