| /******************************************************************************* |
| * Copyright (c) 2009, 2010 Nokia and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Nokia - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.edc.debugger.tests; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import org.eclipse.cdt.debug.edc.internal.HostOS; |
| import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC; |
| import org.eclipse.cdt.debug.edc.internal.snapshot.Album; |
| import org.eclipse.cdt.debug.edc.internal.snapshot.ISnapshotAlbumEventListener; |
| import org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot; |
| import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils; |
| import org.eclipse.cdt.debug.edc.launch.EDCLaunch; |
| import org.eclipse.cdt.debug.edc.services.IEDCExecutionDMC; |
| import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC; |
| import org.eclipse.cdt.debug.edc.tests.EDCTestPlugin; |
| import org.eclipse.cdt.debug.edc.tests.TestUtils; |
| import org.eclipse.cdt.debug.edc.tests.TestUtils.Condition; |
| import org.eclipse.cdt.dsf.concurrent.DsfRunnable; |
| import org.eclipse.cdt.dsf.service.DsfSession; |
| import org.eclipse.core.runtime.CoreException; |
| import org.junit.Assert; |
| import org.junit.Test; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| public class SnapshotTests extends BaseLaunchTest { |
| |
| private boolean testComplete; |
| |
| @Test |
| public void testSnapshot() throws Exception { |
| if (!HostOS.IS_WIN32) |
| return; |
| testComplete = false; |
| TestUtils.showDebugPerspective(); |
| EDCLaunch launch = createLaunch(); |
| assertNotNull(launch); |
| final DsfSession session = waitForSession(launch); |
| assertNotNull(session); |
| IEDCExecutionDMC executionDMC = waitForExecutionDMC(session); |
| assertNotNull(executionDMC); |
| ExecutionDMC threadDMC = TestUtils.waitForSuspendedThread(session); |
| Assert.assertNotNull(threadDMC); |
| |
| Album.addSnapshotAlbumEventListener(new ISnapshotAlbumEventListener() { |
| |
| public void snapshotSessionEnded(Album album, DsfSession session) {} |
| |
| public void snapshotOpened(Snapshot snapshot) {} |
| |
| public void snapshotCreated(Album album, Snapshot snapshot, |
| final DsfSession session, StackFrameDMC stackFrame) { |
| assertTrue(album.isRecording()); |
| assertEquals(1, album.getSnapshots().size()); |
| try { |
| assertAlbumStructureCorrect(album); |
| } catch (Exception e) { |
| EDCTestPlugin.logError(null, e); |
| } |
| final Snapshot snap = album.getSnapshots().get(0); |
| assertNotNull(snap); |
| |
| session.getExecutor().execute(new DsfRunnable() { |
| |
| public void run() { |
| snap.open(session); // parse snapshot data in album (.dsa) |
| try { |
| assertSnapshotStructureCorrect(snap); |
| } catch (Exception e) { |
| EDCTestPlugin.logError(null, e); |
| } |
| testComplete = true; |
| } |
| }); |
| } |
| }); |
| |
| Album.captureSnapshotForSession(session); |
| |
| TestUtils.wait(new Condition() { |
| |
| public boolean isConditionValid() { |
| return testComplete; |
| } |
| }); |
| |
| TestUtils.terminateLaunch(launch); |
| |
| } |
| |
| private void assertAlbumStructureCorrect(Album album) throws Exception { |
| Document document = (Document) album.getAdapter(Document.class); |
| |
| assertNotNull(document); |
| // find the snapshot meta data element |
| NodeList nodeList = document.getElementsByTagName(Album.METADATA); |
| assertEquals(1, nodeList.getLength()); |
| |
| assertTrue(album.getLocation().toOSString().endsWith(".dsa")); |
| assertEquals(0, album.getCurrentSnapshotIndex()); |
| |
| } |
| |
| private void assertSnapshotStructureCorrect(Snapshot snapshot) throws Exception { |
| |
| assertTrue(snapshot.getCreationDate().length() > 0); |
| assertTrue(snapshot.getSnapshotFileName().endsWith(".xml")); |
| |
| Document snapShotdocument = (Document) snapshot.getAdapter(Document.class); |
| assertNotNull(snapShotdocument); |
| |
| // find the snapshot element |
| NodeList nodeList = snapShotdocument.getElementsByTagName(Snapshot.SNAPSHOT); |
| assertEquals(1, nodeList.getLength()); |
| |
| Element snapshotElement = (Element) nodeList.item(0); |
| // check nested execution contexts as list |
| nodeList = snapshotElement.getElementsByTagName("execution_context"); |
| assertEquals(2, nodeList.getLength()); |
| // check properties of top-level execution context |
| // (BlackFlagMinGW.exe) |
| Element bfElement = (Element) nodeList.item(0); |
| assertNotNull(bfElement.getAttribute("ID")); |
| NodeList propsList = bfElement.getChildNodes(); |
| |
| assertTrue(propsList.getLength() > 0); |
| |
| Element propElement = (Element) bfElement.getElementsByTagName(SnapshotUtils.PROPERTIES) |
| .item(0); |
| |
| Properties properties = createPropertiesFromElement(propElement); |
| assertEquals("BlackFlagMinGW.exe", properties.get("Name")); |
| assertEquals("root", properties.get("ParentID")); |
| String mainExeContextID = (String) properties.get("ID"); |
| // TODO: CanResume is being set as a integer and not a boolean |
| // assertEquals("true", properties.get("CanResume")); |
| assertEquals(true, properties.get("CanSuspend")); |
| assertEquals(true, properties.get("CanTerminate")); |
| // check properties of second one (shared lib) |
| Element slElement = (Element) nodeList.item(1); |
| |
| propElement = (Element) bfElement.getElementsByTagName(SnapshotUtils.PROPERTIES) |
| .item(1); |
| |
| properties = createPropertiesFromElement(propElement); |
| assertTrue(properties.containsKey("Name")); |
| assertTrue(properties.containsKey("OSID")); |
| String subExecContextID = (String) properties.get("ID"); |
| assertEquals(mainExeContextID, properties.get("ParentID")); |
| // TODO: CanResume is being set as a integer and not a boolean |
| // assertEquals("true", properties.get("CanResume")); |
| assertEquals(true, properties.get("CanSuspend")); |
| assertEquals(true, properties.get("CanTerminate")); |
| // assertEquals("Exception", properties.get("Message")); // This is sometimes "Exception" and sometimes "Shared Library" |
| assertEquals(true, properties.get("State")); |
| |
| // check the registers |
| nodeList = slElement.getElementsByTagName("execution_context_registers"); |
| assertEquals(1, nodeList.getLength()); |
| Element regGroupElement = (Element) slElement.getElementsByTagName("register_group") |
| .item(0); |
| assertEquals("register_group", regGroupElement.getTagName()); |
| String regGroupID = regGroupElement.getAttribute("ID"); |
| assertTrue("Wrong register group ID: " + regGroupID, regGroupID.equals("GPX") || regGroupID.contains("Basic")); |
| |
| propElement = (Element) regGroupElement.getElementsByTagName(SnapshotUtils.PROPERTIES) |
| .item(0); |
| |
| properties = createPropertiesFromElement(propElement); |
| String name = (String)properties.get("Name"); |
| assertTrue("Wrong register group name: " + name, name.equals("General") || name.contains("Basic")); |
| assertEquals(subExecContextID, properties.get("Context_ID")); |
| assertX86RegisterValuesOk(regGroupElement, subExecContextID); |
| |
| // check the modules |
| nodeList = snapshotElement.getElementsByTagName("execution_context_modules"); |
| assertEquals(1, nodeList.getLength()); |
| Element moduleE = (Element) nodeList.item(0); |
| Element stackFrameElement = (Element) moduleE.getElementsByTagName(SnapshotUtils.PROPERTIES) |
| .item(0); |
| |
| properties = createPropertiesFromElement(stackFrameElement); |
| assertTrue(properties.containsKey("File")); |
| assertTrue(properties.containsKey("Loaded")); |
| assertTrue(properties.containsKey("ImageBaseAddress")); |
| assertTrue(properties.containsKey("CodeSize")); |
| |
| } |
| |
| private void assertX86RegisterValuesOk(Element regGroupElement, String execContextID) { |
| NodeList registerNodes = regGroupElement.getElementsByTagName("register"); |
| assertEquals(16, registerNodes.getLength()); |
| Set<String> registerNames = new HashSet<String>(); |
| for (int i = 0; i < registerNodes.getLength(); i++) { |
| Element register = (Element) registerNodes.item(i); |
| String id = register.getAttribute("ID"); |
| Node propertiesNode = register.getFirstChild(); |
| assertNotNull(propertiesNode); |
| |
| Element propElement = (Element) regGroupElement.getElementsByTagName(SnapshotUtils.PROPERTIES) |
| .item(i+1); |
| |
| Properties properties = createPropertiesFromElement(propElement); |
| String name = (String)properties.get("Name"); |
| assertEquals(id, properties.get("ID")); |
| assertEquals(execContextID, properties.get("Context_ID")); |
| registerNames.add(name); |
| } |
| String[] registerNameVals = new String[] { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "GS", "FS", |
| "ES", "DS", "EIP", "CS", "EFL", "SS" }; |
| Set<String> expectedRegisterIds = new HashSet<String>(Arrays.asList(registerNameVals)); |
| assertEquals(expectedRegisterIds, registerNames); |
| } |
| |
| private Properties createPropertiesFromElement(Element propertyElement) { |
| Properties properties = new Properties(); |
| HashMap<String, Object> propMap = new HashMap<String, Object>(); |
| try { |
| SnapshotUtils.initializeFromXML(propertyElement, propMap); |
| } catch (CoreException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| |
| Iterator<?> it = propMap.entrySet().iterator(); |
| while (it.hasNext()){ |
| Map.Entry<?,?> pairs = (Map.Entry<?,?>)it.next(); |
| //System.out.println(pairs.getKey() + " = " + pairs.getValue()); |
| properties.put(pairs.getKey(), pairs.getValue()); |
| } |
| |
| return properties; |
| } |
| |
| } |