/******************************************************************************* * Copyright (c) 2012, 2014 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.debug.test; import java.math.BigInteger; import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualItem; import org.eclipse.tcf.debug.test.services.RunControlCM.ContextState; import org.eclipse.tcf.debug.test.util.Transaction; import org.eclipse.tcf.services.ILineNumbers.CodeArea; import org.eclipse.tcf.services.IRunControl; import org.eclipse.tcf.services.ISymbols; import org.eclipse.tcf.services.ISymbols.Symbol; import org.eclipse.test.performance.Performance; import org.eclipse.test.performance.PerformanceMeter; import org.junit.Assert; @SuppressWarnings("restriction") public class SampleTest extends AbstractTcfUITest { public void testDebugViewContent() throws Exception { TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); VirtualItem launchItem = fDebugViewListener.findElement(new Pattern[] { Pattern.compile(".*" + fLaunch.getLaunchConfiguration().getName() + ".*") } ); Assert.assertTrue(launchItem != null); VirtualItem processItem = fDebugViewListener.findElement(launchItem, new Pattern[] { Pattern.compile(".*agent.*") } ); if (processItem == null) { /* Windows? */ processItem = fDebugViewListener.findElement(launchItem, new Pattern[] { Pattern.compile("P[0-9]*") } ); } Assert.assertTrue(processItem != null); VirtualItem threadItem = fDebugViewListener.findElement(processItem, new Pattern[] { Pattern.compile(".*" + processInfo.fThreadId + ".*") } ); Assert.assertTrue(threadItem != null); VirtualItem frameItem = fDebugViewListener.findElement(threadItem, new Pattern[] { Pattern.compile(".*tcf_test_func0.*")}); Assert.assertTrue(frameItem != null); } public void testSteppingDebugViewOnly() throws Exception { final TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); // Execute step loop String previousThreadLabel = null; for (int stepNum = 0; stepNum < 100; stepNum++) { fDebugViewListener.reset(); resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_INTO_LINE); fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE | CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING); VirtualItem topFrameItem = fDebugViewListener.findElement( new Pattern[] { Pattern.compile(".*"), Pattern.compile(".*"), Pattern.compile(".*" + processInfo.fProcessId + ".*\\(Step.*"), Pattern.compile(".*")}); if (topFrameItem == null) { Assert.fail("Top stack frame not found. \n\nDebug view dump: \n:" + fDebugViewViewer.toString()); } String topFrameLabel = ((String[])topFrameItem.getData(VirtualItem.LABEL_KEY))[0]; Assert.assertTrue(!topFrameLabel.equals(previousThreadLabel)); previousThreadLabel = topFrameLabel; } } public void testSteppingWithVariablesAndRegisters() throws Exception { fVariablesViewViewer.setActive(true); fRegistersViewViewer.setActive(true); TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); // Execute step loop String previousThreadLabel = null; for (int stepNum = 0; stepNum < 100; stepNum++) { fDebugViewListener.reset(); fVariablesViewListener.reset(); fRegistersViewListener.reset(); resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_INTO_LINE); fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE | CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING); fVariablesViewListener.waitTillFinished(CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING); fRegistersViewListener.waitTillFinished(CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING); VirtualItem topFrameItem = fDebugViewListener.findElement( new Pattern[] { Pattern.compile(".*"), Pattern.compile(".*"), Pattern.compile(".*" + processInfo.fProcessId + ".*\\(Step.*"), Pattern.compile(".*")}); Assert.assertTrue(topFrameItem != null); String topFrameLabel = ((String[])topFrameItem.getData(VirtualItem.LABEL_KEY))[0]; Assert.assertTrue(!topFrameLabel.equals(previousThreadLabel)); previousThreadLabel = topFrameLabel; } } public void testSteppingPerformanceWithSourceDisplay() throws Exception { final TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); final Number sym_func0_address = new Transaction<Number>() { @Override protected Number process() throws Transaction.InvalidCacheException ,ExecutionException { return validate( fDiagnosticsCM.getSymbol(processInfo.fProcessId, "tcf_test_func0") ).getValue(); }; }.get(); final Number sym_func3_address = new Transaction<Number>() { @Override protected Number process() throws Transaction.InvalidCacheException ,ExecutionException { return validate( fDiagnosticsCM.getSymbol(processInfo.fProcessId, "tcf_test_func3") ).getValue(); }; }.get(); Performance perf = Performance.getDefault(); PerformanceMeter meter = perf.createPerformanceMeter(perf.getDefaultScenarioId(this)); try { // Execute step loop for (int stepNum = 0; stepNum < 100; stepNum++) { fDebugViewListener.reset(); fSourceDisplayListener.reset(); meter.start(); ContextState state = resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_INTO_LINE); CodeArea area = calcPCCodeArea(processInfo); if (area != null) { fSourceDisplayListener.setCodeArea(calcPCCodeArea(processInfo)); } fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE | CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES_RUNNING); if (area != null) { fSourceDisplayListener.waitTillFinished(); } meter.stop(); if (new BigInteger(state.pc).equals(new BigInteger(sym_func3_address.toString()))) { moveToLocation(processInfo.fThreadId, sym_func0_address); } } meter.commit(); perf.assertPerformance(meter); } finally { meter.dispose(); } } private CodeArea calcPCCodeArea(final TestProcessInfo processInfo) throws ExecutionException, InterruptedException { return new Transaction<CodeArea>() { @Override protected CodeArea process() throws Transaction.InvalidCacheException ,ExecutionException { String pc = validate(fRunControlCM.getState(processInfo.fThreadId)).pc; BigInteger pcNumber = new BigInteger(pc); BigInteger pcNumberPlusOne = pcNumber.add(BigInteger.valueOf(1)); CodeArea[] areas = validate(fLineNumbersCM.mapToSource(processInfo.fThreadId, pcNumber, pcNumberPlusOne)); if (areas != null && areas.length >= 1) { return areas[0]; } return null; } }.get(); } public void testSymbolsCMResetOnContextRemove() throws Exception { final TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); // Retrieve the current PC for use later final String pc = new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { return validate(fRunControlCM.getState(processInfo.fThreadId)).pc; } }.get(); // Find symbol by name and valide the cache. final String symbolId = new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { String symId = validate( fSymbolsCM.find(processInfo.fProcessId, new BigInteger(pc), "tcf_test_func0") ); Symbol sym = validate( fSymbolsCM.getContext(symId) ); Assert.assertEquals(ISymbols.UPDATE_ON_MEMORY_MAP_CHANGES, sym.getUpdatePolicy()); return symId; } }.get(); // Find symbol by address and validate its context. Save address for later. final Number symAddr = new Transaction<Number>() { @Override protected Number process() throws InvalidCacheException, ExecutionException { Symbol sym = validate( fSymbolsCM.getContext(symbolId) ); String symId2 = validate( fSymbolsCM.findByAddr(processInfo.fProcessId, sym.getAddress()) ); Symbol sym2 = validate( fSymbolsCM.getContext(symId2) ); Assert.assertEquals(sym.getAddress(), sym2.getAddress()); return sym.getAddress(); } }.get(); // End test, check that all caches were reset and now return an error. new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) ); validate( fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this) ); try { validate( fSymbolsCM.getContext(symbolId) ); Assert.fail("Expected error"); } catch (ExecutionException e) {} try { validate( fSymbolsCM.find(processInfo.fProcessId, new BigInteger(pc), "tcf_test_func0") ); Assert.fail("Expected error"); } catch (ExecutionException e) {} try { validate( fSymbolsCM.findByAddr(processInfo.fProcessId, symAddr) ); Assert.fail("Expected error"); } catch (ExecutionException e) {} return null; } }.get(); } public void testSymbolsCMResetOnContextStateChange() throws Exception { final TestProcessInfo processInfo = initProcessModel("tcf_test_func2"); // Retrieve the current PC and top frame for use later final String pc = new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { return validate(fRunControlCM.getState(processInfo.fThreadId)).pc; } }.get(); final String topFrameId = new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) ); return frameIds[frameIds.length - 1]; } }.get(); // Find symbol by name and valide the cache. final String symbolId = new Transaction<String>() { @Override protected String process() throws InvalidCacheException, ExecutionException { String symId = validate( fSymbolsCM.find(topFrameId, new BigInteger(pc), "func2_local1") ); Symbol sym = validate( fSymbolsCM.getContext(symId) ); Assert.assertEquals(ISymbols.UPDATE_ON_EXE_STATE_CHANGES, sym.getUpdatePolicy()); return symId; } }.get(); // Note: findByAddr doesn't seem to work on a local var. // // Find symbol by address and validate its context. Save address for later. // final Number symAddr = new Transaction<Number>() { // @Override // protected Number process() throws InvalidCacheException, ExecutionException { // Symbol sym = validate( fSymbolsCM.getContext(symbolId) ); // String symId2 = validate( fSymbolsCM.findByAddr(topFrameId, sym.getAddress()) ); // Symbol sym2 = validate( fSymbolsCM.getContext(symId2) ); // Assert.assertEquals(sym.getAddress(), sym2.getAddress()); // return sym.getAddress(); // } // }.get(); // Execute a step. resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_OUT); // End test, check that all caches were reset and now return an error. new Transaction<Object>() { @Override protected Object process() throws InvalidCacheException, ExecutionException { Assert.assertFalse( "Expected cache to be reset", fSymbolsCM.getContext(symbolId).isValid()); Assert.assertFalse( "Expected cache to be reset", fSymbolsCM.find(topFrameId, new BigInteger(pc), "func2_local1").isValid() ); return null; } }.get(); } }