diff --git a/plugins/org.eclipse.dd.tests.dsf/.classpath b/plugins/org.eclipse.dd.tests.dsf/.classpath
new file mode 100644
index 00000000000..304e86186aa
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.tests.dsf/.cvsignore b/plugins/org.eclipse.dd.tests.dsf/.cvsignore
new file mode 100644
index 00000000000..ba077a4031a
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/plugins/org.eclipse.dd.tests.dsf/.project b/plugins/org.eclipse.dd.tests.dsf/.project
new file mode 100644
index 00000000000..a662c11dc13
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.dd.tests.dsf
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..8241d8c455d
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,65 @@
+#Thu Jun 07 11:08:23 PDT 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.ui.prefs b/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 00000000000..28984618f01
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+#Thu Oct 12 11:27:35 PDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
diff --git a/plugins/org.eclipse.dd.tests.dsf/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.tests.dsf/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..2e88859313d
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/META-INF/MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Debug Services Framework Unit Tests
+Bundle-Vendor: Eclipse.org
+Bundle-SymbolicName: org.eclipse.dd.tests.dsf;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.dd.tests.dsf.DsfTestPlugin
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.debug.core,
+ org.eclipse.debug.ui,
+ org.eclipse.dd.dsf,
+ org.junit4,
+ org.eclipse.ui,
+ org.eclipse.dd.dsf.ui
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.dd.tests.dsf/about.html b/plugins/org.eclipse.dd.tests.dsf/about.html
new file mode 100644
index 00000000000..cb740ae8bc8
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/about.html
@@ -0,0 +1,24 @@
+
+
+
+
+About
+About This Content
+
+June 5, 2007
+License
+
+The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html.
+For purposes of the EPL, "Program" will mean the Content.
+
+If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org.
+
+
\ No newline at end of file
diff --git a/plugins/org.eclipse.dd.tests.dsf/build.properties b/plugins/org.eclipse.dd.tests.dsf/build.properties
new file mode 100644
index 00000000000..786b1df9364
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ about.html
diff --git a/plugins/org.eclipse.dd.tests.dsf/plugin.properties b/plugins/org.eclipse.dd.tests.dsf/plugin.properties
new file mode 100644
index 00000000000..8dc99b1d8eb
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/plugin.properties
@@ -0,0 +1,13 @@
+###############################################################################
+# Copyright (c) 2006 Wind River Systems 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
+###############################################################################
+pluginName=DSDP/DD Debugger Services Framework (DSF) Test Plugin
+providerName=Eclipse.org
+
diff --git a/plugins/org.eclipse.dd.tests.dsf/plugin.xml b/plugins/org.eclipse.dd.tests.dsf/plugin.xml
new file mode 100644
index 00000000000..aa2732002b6
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/plugin.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/MultiInstanceTestService.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/MultiInstanceTestService.java
new file mode 100644
index 00000000000..2b70cf6bed1
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/MultiInstanceTestService.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.dsf.tests.service;
+
+import java.util.Hashtable;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.service.AbstractDsfService;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.osgi.framework.BundleContext;
+
+public class MultiInstanceTestService extends AbstractDsfService {
+
+ public static String PROP_INSTANCE_ID = "org.eclipse.dd.dsf.tests.service.MultiInstanceTestService.id"; //$NON-NLS-1$
+ String fInstanceId;
+
+ public MultiInstanceTestService(DsfSession session, String instanceId) {
+ super(session);
+ fInstanceId = instanceId;
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return DsfTestPlugin.getBundleContext();
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ Hashtable properties = new Hashtable();
+ properties.put(PROP_INSTANCE_ID, fInstanceId);
+ register(new String[]{MultiInstanceTestService.class.getName()}, properties);
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/ServiceTests.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/ServiceTests.java
new file mode 100644
index 00000000000..102c72e8b09
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/ServiceTests.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.dsf.tests.service;
+
+import java.lang.reflect.Constructor;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.service.IDsfService;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.eclipse.dd.tests.dsf.TestDsfExecutor;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class ServiceTests {
+ TestDsfExecutor fExecutor;
+
+ @Before public void startExecutor() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+ }
+
+ @After public void shutdownExecutor() throws ExecutionException, InterruptedException {
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fExecutor.shutdown();
+ }}).get();
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fExecutor = null;
+ }
+
+ private class CreateSessionStep extends Sequence.Step {
+ private DsfSession fSession;
+ @Override public void execute(RequestMonitor requestMonitor) {
+ fSession = DsfSession.startSession(fExecutor, "org.eclipse.dd.dsf.tests"); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+
+ DsfSession getSession() { return fSession; }
+ }
+
+ private class ShutdownSessionStep extends Sequence.Step {
+ private CreateSessionStep fCreateSessionStep;
+
+ ShutdownSessionStep(CreateSessionStep createSessionStep) {
+ fCreateSessionStep = createSessionStep;
+ }
+
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ DsfSession.endSession(fCreateSessionStep.getSession());
+ requestMonitor.done();
+ }
+ }
+
+ private class InitializeServiceStep extends Sequence.Step {
+ CreateSessionStep fCreateSessionStep;
+ Class extends IDsfService> fServiceClass;
+ IDsfService fService;
+
+ InitializeServiceStep(CreateSessionStep createSessionStep, Class extends IDsfService> serviceClass) {
+ fCreateSessionStep = createSessionStep;
+ fServiceClass = serviceClass;
+ }
+ IDsfService getService() { return fService; }
+
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ try {
+ Constructor extends IDsfService> c = fServiceClass.getConstructor(new Class[] {DsfSession.class});
+ fService = c.newInstance(new Object[] {fCreateSessionStep.getSession()});
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception"); //$NON-NLS-1$
+ }
+ fService.initialize(requestMonitor);
+ }
+ }
+
+ private class InitializeMultiInstanceServiceStep extends InitializeServiceStep {
+ String fServiceId;
+
+ InitializeMultiInstanceServiceStep(CreateSessionStep createSessionStep, Class extends IDsfService> serviceClass, String serviceId) {
+ super(createSessionStep, serviceClass);
+ fServiceId = serviceId;
+ }
+ @Override
+ IDsfService getService() { return fService; }
+
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ try {
+ Constructor extends IDsfService> c =
+ fServiceClass.getConstructor(new Class[] {DsfSession.class, String.class});
+ fService = c.newInstance(new Object[] {fCreateSessionStep.getSession(), fServiceId});
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception"); //$NON-NLS-1$
+ }
+ fService.initialize(requestMonitor);
+ }
+ }
+
+ private class ShutdownServiceStep extends Sequence.Step {
+ InitializeServiceStep fInitializeServiceStep;
+ ShutdownServiceStep(InitializeServiceStep initStep) {
+ fInitializeServiceStep = initStep;
+ }
+
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fInitializeServiceStep.getService().shutdown(requestMonitor);
+ }
+ }
+
+
+ abstract private class TestRetrievingReferenceStep extends Sequence.Step {
+ String fClass;
+ boolean fShouldSucceed;
+
+ TestRetrievingReferenceStep(Class> clazz, boolean shouldSucceed) {
+ fClass = clazz.getName();
+ fShouldSucceed = shouldSucceed;
+ }
+
+ abstract String getFilter();
+
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ ServiceReference[] refs = null;
+ try {
+ refs = DsfTestPlugin.getBundleContext().getServiceReferences(fClass, getFilter());
+ } catch (InvalidSyntaxException e) {
+ Assert.fail("Unexpected exception"); //$NON-NLS-1$
+ }
+ if (fShouldSucceed) {
+ Assert.assertTrue(refs != null);
+ Assert.assertTrue(refs.length == 1);
+ IDsfService service = (IDsfService)DsfTestPlugin.getBundleContext().getService(refs[0]);
+ Assert.assertTrue(service != null);
+ DsfTestPlugin.getBundleContext().ungetService(refs[0]);
+ } else {
+ Assert.assertTrue(refs == null);
+ }
+ requestMonitor.done();
+ }
+ }
+
+ private class TestRetrievingSimpleServiceReferenceStep extends TestRetrievingReferenceStep {
+ CreateSessionStep fCreateSessionStep;
+ TestRetrievingSimpleServiceReferenceStep(Class> clazz, boolean shouldSucceed, CreateSessionStep createSessionStep) {
+ super(clazz, shouldSucceed);
+ fCreateSessionStep = createSessionStep;
+ }
+ @Override
+ String getFilter() {
+ return "(" + IDsfService.PROP_SESSION_ID + "=" + fCreateSessionStep.getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ private class TestRetrievingMultiSessionServiceReferenceStep extends TestRetrievingSimpleServiceReferenceStep {
+ String fServiceId;
+ TestRetrievingMultiSessionServiceReferenceStep(Class> clazz, boolean shouldSucceed, CreateSessionStep createSessionStep,
+ String serviceId) {
+ super(clazz, shouldSucceed, createSessionStep);
+ fServiceId = serviceId;
+ }
+ @Override
+ String getFilter() {
+ return "(&" + //$NON-NLS-1$
+ "(" + IDsfService.PROP_SESSION_ID + "=" + fCreateSessionStep.getSession().getId() + ")" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "(" + MultiInstanceTestService.PROP_INSTANCE_ID + "=" + fServiceId + ")" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ")"; //$NON-NLS-1$
+ }
+ }
+
+ @Test
+ public void singleServiceTest() throws InterruptedException, ExecutionException {
+ Sequence seq = new Sequence(fExecutor) {
+ CreateSessionStep fSessionStep;
+ InitializeServiceStep fServiceStep;
+
+ @Override
+ public Step[] getSteps() { return fSteps; }
+
+ final private Step[] fSteps = new Step[]
+ {
+ fSessionStep = new CreateSessionStep(),
+ fServiceStep = new InitializeServiceStep(fSessionStep, SimpleTestService.class),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, true, fSessionStep),
+ new ShutdownServiceStep(fServiceStep),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, false, fSessionStep),
+ new ShutdownSessionStep(fSessionStep)
+ };
+ };
+ fExecutor.execute(seq);
+ seq.get();
+ }
+
+ /**
+ * Creates two sessions and starts a single service within each session.
+ * Then it tests retrieving the reference to the service.
+ */
+ @Test
+ public void singleServiceMultiSessionTest() throws InterruptedException, ExecutionException {
+ Sequence seq = new Sequence(fExecutor) {
+ CreateSessionStep fSession1Step;
+ CreateSessionStep fSession2Step;
+ InitializeServiceStep fSession1ServiceStep;
+ InitializeServiceStep fSession2ServiceStep;
+
+ @Override
+ public Step[] getSteps() { return fSteps; }
+
+ final private Step[] fSteps = new Step[]
+ {
+ fSession1Step = new CreateSessionStep(),
+ fSession2Step = new CreateSessionStep(),
+ fSession1ServiceStep = new InitializeServiceStep(fSession1Step, SimpleTestService.class),
+ fSession2ServiceStep = new InitializeServiceStep(fSession2Step, SimpleTestService.class),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, true, fSession1Step),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, true, fSession2Step),
+ new ShutdownServiceStep(fSession1ServiceStep),
+ new ShutdownServiceStep(fSession2ServiceStep),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, false, fSession1Step),
+ new TestRetrievingSimpleServiceReferenceStep(SimpleTestService.class, false, fSession2Step),
+ new ShutdownSessionStep(fSession1Step),
+ new ShutdownSessionStep(fSession2Step)
+ };
+ };
+ fExecutor.execute(seq);
+ seq.get();
+ }
+
+ @Test
+ public void multiServiceServiceTest() throws InterruptedException, ExecutionException {
+ Sequence seq = new Sequence(fExecutor) {
+ CreateSessionStep fSessionStep;
+ InitializeServiceStep fService1Step;
+ InitializeServiceStep fService2Step;
+
+ @Override
+ public Step[] getSteps() { return fSteps; }
+
+ final private Step[] fSteps = new Step[]
+ {
+ fSessionStep = new CreateSessionStep(),
+ fService1Step = new InitializeMultiInstanceServiceStep(fSessionStep, MultiInstanceTestService.class, "1"), //$NON-NLS-1$
+ fService2Step = new InitializeMultiInstanceServiceStep(fSessionStep, MultiInstanceTestService.class, "2"), //$NON-NLS-1$
+ new TestRetrievingMultiSessionServiceReferenceStep(MultiInstanceTestService.class, true, fSessionStep, "1"), //$NON-NLS-1$
+ new TestRetrievingMultiSessionServiceReferenceStep(MultiInstanceTestService.class, true, fSessionStep, "2"), //$NON-NLS-1$
+ new ShutdownServiceStep(fService1Step),
+ new ShutdownServiceStep(fService2Step),
+ new TestRetrievingMultiSessionServiceReferenceStep(MultiInstanceTestService.class, false, fSessionStep, "1"), //$NON-NLS-1$
+ new TestRetrievingMultiSessionServiceReferenceStep(MultiInstanceTestService.class, false, fSessionStep, "2"), //$NON-NLS-1$
+ new ShutdownSessionStep(fSessionStep)
+ };
+ };
+ fExecutor.execute(seq);
+ seq.get();
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/SimpleTestService.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/SimpleTestService.java
new file mode 100644
index 00000000000..902bf0885cb
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/dsf/tests/service/SimpleTestService.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.dsf.tests.service;
+
+import java.util.Hashtable;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.service.AbstractDsfService;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.osgi.framework.BundleContext;
+
+public class SimpleTestService extends AbstractDsfService {
+
+ public SimpleTestService(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return DsfTestPlugin.getBundleContext();
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ register(new String[]{SimpleTestService.class.getName()}, new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/DsfTestPlugin.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/DsfTestPlugin.java
new file mode 100644
index 00000000000..cd4e0288f17
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/DsfTestPlugin.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class DsfTestPlugin extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.dd.tests.dsf"; //$NON-NLS-1$
+
+ // The shared instance
+ private static DsfTestPlugin fgPlugin;
+ private static BundleContext fgBundleContext;
+
+ /**
+ * The constructor
+ */
+ public DsfTestPlugin() {
+ fgPlugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ fgBundleContext = context;
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ fgBundleContext = null;
+ fgPlugin = null;
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static DsfTestPlugin getDefault() {
+ return fgPlugin;
+ }
+
+ public static BundleContext getBundleContext() {
+ return fgBundleContext;
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/TestDsfExecutor.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/TestDsfExecutor.java
new file mode 100644
index 00000000000..37fe241a8bb
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/TestDsfExecutor.java
@@ -0,0 +1,50 @@
+package org.eclipse.dd.tests.dsf;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
+
+/**
+ * DsfExecutor for use with unit tests. It records the exceptions that were
+ * thrown in the executor thread so that they can be re-thrown by the test.
+ *
+ */
+public class TestDsfExecutor extends DefaultDsfExecutor {
+ private List fExceptions = Collections.synchronizedList(new ArrayList());
+
+ @Override
+ protected void afterExecute(Runnable r, Throwable t) {
+ super.afterExecute(r, t);
+ if (r instanceof Future>) {
+ Future> future = (Future>)r;
+ try {
+ if (future.isDone()) {
+ future.get();
+ }
+ future.get();
+ } catch (InterruptedException e) { // Ignore
+ } catch (CancellationException e) { // Ignore also
+ } catch (ExecutionException e) {
+ if (e.getCause() != null) {
+ fExceptions.add(e.getCause());
+ }
+ }
+ }
+ }
+
+ public boolean exceptionsCaught() {
+ return fExceptions.size() != 0;
+ }
+
+ public Throwable[] getExceptions() {
+ synchronized (fExceptions) {
+ return fExceptions.toArray(new Throwable[fExceptions.size()]);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/ValueHolder.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/ValueHolder.java
new file mode 100644
index 00000000000..c3b087dcc12
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/ValueHolder.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf;
+
+/**
+ * Utility class to hold a value retrieved in a runnable.
+ * Usage in a test is as follows:
+ *
+ * final ValueHolder value = new ValueHolder();
+ * fExecutor.execute(new Runnable() {
+ * public void run() {
+ * value.fValue = 1;
+ * }
+ * });
+ * Assert.assertTrue(value.fValue == 1);
+ *
+ */
+public class ValueHolder {
+ public V fValue;
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfQueryTests.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfQueryTests.java
new file mode 100644
index 00000000000..e4015eba8ae
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfQueryTests.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.concurrent;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import junit.framework.Assert;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.concurrent.Query;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.eclipse.dd.tests.dsf.TestDsfExecutor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that excercise the Query object.
+ */
+public class DsfQueryTests {
+ TestDsfExecutor fExecutor;
+
+ @Before
+ public void startServices() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+ }
+
+ @After
+ public void shutdownServices() throws ExecutionException, InterruptedException {
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fExecutor.shutdown();
+ }}).get();
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fExecutor = null;
+ }
+
+ @Test
+ public void simpleGetTest() throws InterruptedException, ExecutionException {
+ Query q = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ rm.setData(1);
+ rm.done();
+ }
+ };
+ // Check initial state
+ Assert.assertTrue(!q.isDone());
+ Assert.assertTrue(!q.isCancelled());
+
+ fExecutor.execute(q);
+ Assert.assertEquals(1, (int)q.get());
+
+ // Check final state
+ Assert.assertTrue(q.isDone());
+ Assert.assertTrue(!q.isCancelled());
+
+ }
+
+ @Test
+ public void getWithMultipleDispatchesTest() throws InterruptedException, ExecutionException {
+ Query q = new Query() {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ fExecutor.execute(new DsfRunnable() {
+ public void run() {
+ rm.setData(1);
+ rm.done();
+ }
+ @Override
+ public String toString() { return super.toString() + "\n getWithMultipleDispatchesTest() second runnable"; } //$NON-NLS-1$
+ });
+ }
+ @Override
+ public String toString() { return super.toString() + "\n getWithMultipleDispatchesTest() first runnable (query)"; } //$NON-NLS-1$
+ };
+ fExecutor.execute(q);
+ Assert.assertEquals(1, (int)q.get());
+ }
+
+ @Test (expected = ExecutionException.class)
+ public void exceptionOnGetTest() throws InterruptedException, ExecutionException {
+ Query q = new Query() {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, -1, "", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ };
+
+ fExecutor.execute(q);
+
+ try {
+ q.get();
+ } finally {
+ Assert.assertTrue(q.isDone());
+ Assert.assertTrue(!q.isCancelled());
+ }
+ }
+
+ @Test
+ public void cancelWhileWaitingTest() throws InterruptedException, ExecutionException {
+ final Query q = new Query() {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ // Call done with a delay of 1 second, to avoid stalling the tests.
+ fExecutor.schedule(
+ new DsfRunnable() {
+ public void run() { rm.done(); }
+ },
+ 1, TimeUnit.SECONDS);
+ }
+ };
+
+ fExecutor.execute(q);
+
+ // Note: no point in checking isDone() and isCancelled() here, because
+ // the value could change on timing.
+
+ // This does not really guarantee that the cancel will be called after
+ // the call to Fugure.get(), but the 1ms delay in call to schedule should
+ // help.
+ new Job("DsfQueryTests cancel job") { @Override public IStatus run(IProgressMonitor monitor) { //$NON-NLS-1$
+ q.cancel(false);
+ return Status.OK_STATUS;
+ }}.schedule(1);
+
+ try {
+ q.get();
+ } catch (CancellationException e) {
+ return; // Success
+ } finally {
+ Assert.assertTrue(q.isDone());
+ Assert.assertTrue(q.isCancelled());
+ }
+ Assert.assertTrue("CancellationException should have been thrown", false); //$NON-NLS-1$
+ }
+
+ @Test
+ public void cancelBeforeWaitingTest() throws InterruptedException, ExecutionException {
+ final Query q = new Query() {
+ @Override protected void execute(final DataRequestMonitor rm) {
+ Assert.fail("Query was cancelled, it should not be called."); //$NON-NLS-1$
+ rm.done();
+ }
+ };
+
+ // Cancel before invoking the query.
+ q.cancel(false);
+
+ Assert.assertTrue(q.isDone());
+ Assert.assertTrue(q.isCancelled());
+
+ // Start the query.
+ fExecutor.execute(q);
+
+ // Block to retrieve data
+ try {
+ q.get();
+ } catch (CancellationException e) {
+ return; // Success
+ } finally {
+ Assert.assertTrue(q.isDone());
+ Assert.assertTrue(q.isCancelled());
+ }
+ Assert.assertTrue("CancellationException should have been thrown", false); //$NON-NLS-1$
+ }
+
+ @Test
+ public void getTimeoutTest() throws InterruptedException, ExecutionException {
+ final Query q = new Query() {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ // Call done with a delay of 1 second, to avoid stalling the tests.
+ fExecutor.schedule(
+ new DsfRunnable() {
+ public void run() { rm.done(); }
+ },
+ 1, TimeUnit.SECONDS);
+ }
+ };
+
+ fExecutor.execute(q);
+
+ // Note: no point in checking isDone() and isCancelled() here, because
+ // the value could change on timing.
+
+ try {
+ q.get(1, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ return; // Success
+ } finally {
+ Assert.assertFalse("Query should not be done yet, it should have timed out first.", q.isDone()); //$NON-NLS-1$
+ }
+ Assert.assertTrue("TimeoutException should have been thrown", false); //$NON-NLS-1$
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfSequenceTests.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfSequenceTests.java
new file mode 100644
index 00000000000..0f1985acd73
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/concurrent/DsfSequenceTests.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.concurrent;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.eclipse.dd.tests.dsf.TestDsfExecutor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that excercise the Sequence object.
+ */
+public class DsfSequenceTests {
+ TestDsfExecutor fExecutor;
+
+ @Before
+ public void startExecutor() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+ }
+
+ @After
+ public void shutdownExecutor() throws ExecutionException, InterruptedException {
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fExecutor.shutdown();
+ }}).get();
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fExecutor = null;
+ }
+
+ @Test
+ public void simpleTest() throws InterruptedException, ExecutionException {
+ // Create a counter for tracking number of steps performed.
+ class IntegerHolder { int fInteger; }
+ final IntegerHolder stepCounter = new IntegerHolder();
+
+ // Create the steps of the sequence
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+ requestMonitor.done();
+ }
+ },
+ new Sequence.Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+ requestMonitor.done();
+ }
+ }
+ };
+
+ // Create, start, and wait for the sequence.
+ Sequence sequence = new Sequence(fExecutor) {
+ @Override public Step[] getSteps() { return steps; }
+ };
+ Assert.assertTrue(!sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+
+ fExecutor.execute(sequence);
+ sequence.get();
+
+ // Check the count
+ Assert.assertTrue(stepCounter.fInteger == 2);
+
+ // Check post conditions
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+
+ @Test (expected = ExecutionException.class)
+ public void rollbackTest() throws InterruptedException, ExecutionException {
+ // Create a counter for tracking number of steps performed and steps
+ // rolled back.
+ class IntegerHolder { int fInteger; }
+ final IntegerHolder stepCounter = new IntegerHolder();
+ final IntegerHolder rollBackCounter = new IntegerHolder();
+
+ // Create the steps of the sequence
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+ requestMonitor.done();
+ }
+ @Override public void rollBack(RequestMonitor requestMonitor) {
+ rollBackCounter.fInteger++;
+ requestMonitor.done();
+ }
+ },
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+ requestMonitor.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, -1, "", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ @Override public void rollBack(RequestMonitor requestMonitor) {
+ rollBackCounter.fInteger++;
+ requestMonitor.done();
+ }
+ }
+ };
+
+ // Create and start.
+ Sequence sequence = new Sequence(fExecutor) {
+ @Override public Step[] getSteps() { return steps; }
+ };
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to bomplete.
+ try {
+ sequence.get();
+ } finally {
+ // Both steps should be performed
+ Assert.assertTrue(stepCounter.fInteger == 2);
+ // Only one step is rolled back, the first one.
+ Assert.assertTrue(rollBackCounter.fInteger == 1);
+
+ // Check state from Future interface
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+ Assert.assertTrue("Exception should have been thrown", false); //$NON-NLS-1$
+ }
+
+ /**
+ * The goal of this test it to check that if an exception is thrown within
+ * the Step.execute(), the step will return from the Future.get() method.
+ */
+ @Test (expected = ExecutionException.class)
+ public void exceptionTest() throws InterruptedException, ExecutionException {
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ throw new Error("Exception part of unit test."); //$NON-NLS-1$
+ }
+ }
+ };
+
+ // Create and start.
+ Sequence sequence = new Sequence(fExecutor) {
+ @Override public Step[] getSteps() { return steps; }
+ };
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to bomplete.
+ try {
+ sequence.get();
+ } finally {
+ // Check state from Future interface
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(!sequence.isCancelled());
+ }
+ Assert.assertTrue("Exception should have been thrown", false); //$NON-NLS-1$
+ }
+
+
+ @Test (expected = CancellationException.class)
+ public void cancelBeforeWaitingTest() throws InterruptedException, ExecutionException {
+ // Create the sequence
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ Assert.assertTrue("Sequence was cancelled, it should not be called.", false); //$NON-NLS-1$
+ }
+ }
+ };
+ Sequence sequence = new Sequence(fExecutor) {
+ @Override public Step[] getSteps() { return steps; }
+ };
+
+ // Cancel before invoking the sequence.
+ sequence.cancel(false);
+
+ Assert.assertTrue(!sequence.isDone());
+ Assert.assertTrue(sequence.isCancelled());
+
+ // Start the sequence
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to bomplete.
+ try {
+ sequence.get();
+ } finally {
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(sequence.isCancelled());
+ }
+ Assert.assertTrue("CancellationException should have been thrown", false); //$NON-NLS-1$
+ }
+
+
+ @Test (expected = CancellationException.class)
+ public void cancelFromStepTest() throws InterruptedException, ExecutionException {
+ // Create a counter for tracking number of steps performed and steps
+ // rolled back.
+ class IntegerHolder { int fInteger; }
+ final IntegerHolder stepCounter = new IntegerHolder();
+ final IntegerHolder rollBackCounter = new IntegerHolder();
+
+ // Create the steps of the sequence
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+ requestMonitor.done();
+ }
+ @Override public void rollBack(RequestMonitor requestMonitor) {
+ rollBackCounter.fInteger++;
+ requestMonitor.done();
+ }
+ },
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ stepCounter.fInteger++;
+
+ // Perform the cancel!
+ getSequence().cancel(false);
+
+ requestMonitor.done();
+ }
+ @Override public void rollBack(RequestMonitor requestMonitor) {
+ rollBackCounter.fInteger++;
+ requestMonitor.done();
+ }
+ }
+ };
+
+ // Create and start sequence with a delay. Delay so that we call get() before
+ // cancel is called.
+ final Sequence sequence = new Sequence(fExecutor) {
+ @Override public Step[] getSteps() { return steps; }
+ };
+ fExecutor.schedule(sequence, 1, TimeUnit.MILLISECONDS);
+
+ // Block to retrieve data
+ try {
+ sequence.get();
+ } finally {
+ // Both steps should be performed
+ Assert.assertTrue(stepCounter.fInteger == 2);
+ // Both roll-backs should be performed since cancel does not take effect until
+ // after the step is completed.
+ Assert.assertTrue(rollBackCounter.fInteger == 2);
+
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(sequence.isCancelled());
+ }
+ Assert.assertTrue("CancellationException should have been thrown", false); //$NON-NLS-1$
+ }
+
+ @Test (expected = CancellationException.class)
+ public void cancelBeforeWithProgressManagerTest() throws InterruptedException, ExecutionException {
+ // Create the sequence
+ final Sequence.Step[] steps = new Sequence.Step[] {
+ new Sequence.Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ Assert.assertTrue("Sequence was cancelled, it should not be called.", false); //$NON-NLS-1$
+ }
+ }
+ };
+
+ // Create the progress monitor that we will cancel.
+ IProgressMonitor pm = new NullProgressMonitor();
+
+ // Create the seqeunce with our steps.
+ Sequence sequence = new Sequence(fExecutor, pm, "", "", null) { //$NON-NLS-1$ //$NON-NLS-2$
+ @Override public Step[] getSteps() { return steps; }
+ };
+
+ // Cancel the progress monitor before invoking the sequence. Note
+ // that the state of the sequence doesn't change yet, because the
+ // sequence does not check the progress monitor until it is executed.
+ pm.setCanceled(true);
+
+ // Start the sequence
+ fExecutor.execute(sequence);
+
+ // Block and wait for sequence to bomplete. Exception is thrown,
+ // which is expected.
+ try {
+ sequence.get();
+ } finally {
+ Assert.assertTrue(sequence.isDone());
+ Assert.assertTrue(sequence.isCancelled());
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/AbstractService.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/AbstractService.java
new file mode 100644
index 00000000000..94a5fdc9de2
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/AbstractService.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.dd.dsf.service.AbstractDsfService;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Test service class used to test event behavior. It has three types of events
+ * and three methods to receive the events.
+ *
+ */
+abstract public class AbstractService extends AbstractDsfService
+{
+ AbstractService(DsfSession session) {
+ super(session);
+ }
+
+ @Override protected BundleContext getBundleContext() {
+ return DsfTestPlugin.getBundleContext();
+ }
+
+ @Override public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ getSession().addServiceEventListener(this, null);
+ requestMonitor.done();
+ }
+
+ @Override public void shutdown(RequestMonitor requestMonitor) {
+ getSession().removeServiceEventListener(this);
+ super.shutdown(requestMonitor);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Test API
+ /** Records the number in the event 1 object when this service received the event. */
+ int fEvent1RecipientNumber;
+
+ /** Records the number in the event 2 object when this service received the event. */
+ int fEvent2RecipientNumber;
+
+ /** Records the number in the event 3 object when this service received the event. */
+ int fEvent3RecipientNumber;
+
+ /** Simple event class 1 */
+ public class Event1 {
+ // 1-based counter for the recipient of the event.
+ int fRecipientNumberCounter = 1;
+ }
+
+ /** Simple event class 2. Note it doesn't have any relation to event 1 */
+ public class Event2 {
+ int fRecipientNumberCounter = 1;
+ }
+
+ /** Simple event class 3. Note it does sub-class event 1 */
+ public class Event3 extends Event1 {}
+
+ @ThreadSafe
+ public void dispatchEvent1() {
+ getSession().dispatchEvent(new Event1(), getProperties());
+ }
+
+ @ThreadSafe
+ public void dispatchEvent2() {
+ getSession().dispatchEvent(new Event2(), getProperties());
+ }
+
+ @ThreadSafe
+ public void dispatchEvent3() {
+ getSession().dispatchEvent(new Event3(), getProperties());
+ }
+
+ /** Handles event 1 (and event 3 which derives from event 1) */
+ @DsfServiceEventHandler public void eventDispatched(Event1 e) {
+ fEvent1RecipientNumber = e.fRecipientNumberCounter++;
+ }
+
+ /** Handles event 2 only */
+ @DsfServiceEventHandler public void eventDispatched(Event2 e) {
+ fEvent2RecipientNumber = e.fRecipientNumberCounter++;
+ }
+
+ /** Handles event 3 only */
+ @DsfServiceEventHandler public void eventDispatched(Event3 e) {
+ fEvent3RecipientNumber = e.fRecipientNumberCounter++;
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event1.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event1.java
new file mode 100644
index 00000000000..def8159ea60
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event1.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+
+public class Event1 {
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event2.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event2.java
new file mode 100644
index 00000000000..cc7bdbe70df
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Event2.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+public class Event2 extends Event1 {
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/EventTest.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/EventTest.java
new file mode 100644
index 00000000000..102be68b751
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/EventTest.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.eclipse.dd.tests.dsf.TestDsfExecutor;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class EventTest {
+
+ DsfSession fSession;
+ TestDsfExecutor fExecutor;
+ DsfServicesTracker fTracker;
+ Service1 fService1;
+ Service2 fService2;
+ Service3 fService3;
+
+ @Before public void startServices() throws ExecutionException, InterruptedException {
+ fExecutor = new TestDsfExecutor();
+
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fSession = DsfSession.startSession(fExecutor, "org.eclipse.dd.dsf.tests"); //$NON-NLS-1$
+ }}).get();
+
+ StartupSequence startupSeq = new StartupSequence(fSession);
+ fExecutor.execute(startupSeq);
+ startupSeq.get();
+
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fTracker = new DsfServicesTracker(DsfTestPlugin.getBundleContext(), fSession.getId());
+ fService1 = fTracker.getService(Service1.class);
+ fService2 = fTracker.getService(Service2.class);
+ fService3 = fTracker.getService(Service3.class);
+ }}).get();
+ Assert.assertNotNull(fService1);
+ Assert.assertNotNull(fService2);
+ Assert.assertNotNull(fService3);
+ }
+
+ @After public void shutdownServices() throws ExecutionException, InterruptedException {
+ ShutdownSequence shutdownSeq = new ShutdownSequence(fSession);
+ fExecutor.execute(shutdownSeq);
+ shutdownSeq.get();
+
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ fService1 = null;
+ fService2 = null;
+ fService3 = null;
+ fTracker.dispose();
+ fTracker = null;
+ DsfSession.endSession(fSession);
+ fSession = null;
+ fExecutor.shutdown();
+ }}).get();
+
+ if (fExecutor.exceptionsCaught()) {
+ Throwable[] exceptions = fExecutor.getExceptions();
+ throw new ExecutionException(exceptions[0]);
+ }
+ fExecutor = null;
+ }
+
+ /**
+ * Test only the startup and shutdown sequences.
+ */
+ @Test public void startStopTest() {
+ }
+
+ /**
+ * Tests dispatching event 1. The goal of the test is to make sure that
+ * recipients are called in the correct order.
+ */
+ @Test public void event1Test() throws ExecutionException, InterruptedException {
+ fService1.dispatchEvent1();
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ Assert.assertTrue(1 == fService1.fEvent1RecipientNumber);
+ Assert.assertTrue(2 == fService2.fEvent1RecipientNumber);
+ Assert.assertTrue(3 == fService3.fEvent1RecipientNumber);
+ Assert.assertTrue(0 == fService1.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService2.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService3.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService1.fEvent3RecipientNumber);
+ Assert.assertTrue(0 == fService2.fEvent3RecipientNumber);
+ Assert.assertTrue(0 == fService3.fEvent3RecipientNumber);
+ }}).get();
+ }
+
+ /**
+ * Tests dispatching event 2. The goal of the test is to make sure that
+ * recipients are called in the correct order, and that the other events
+ * are not registered.
+ */
+ @Test public void event2Test() throws ExecutionException, InterruptedException {
+ fService1.dispatchEvent2();
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ Assert.assertTrue(0 == fService1.fEvent1RecipientNumber);
+ Assert.assertTrue(0 == fService2.fEvent1RecipientNumber);
+ Assert.assertTrue(0 == fService3.fEvent1RecipientNumber);
+ Assert.assertTrue(1 == fService1.fEvent2RecipientNumber);
+ Assert.assertTrue(2 == fService2.fEvent2RecipientNumber);
+ Assert.assertTrue(3 == fService3.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService1.fEvent3RecipientNumber);
+ Assert.assertTrue(0 == fService2.fEvent3RecipientNumber);
+ Assert.assertTrue(0 == fService3.fEvent3RecipientNumber);
+ }}).get();
+ }
+
+ /**
+ * Tests dispatching event 2. The goal of the test is to make sure that
+ * both event 2 and even 3 recipients are called for this event.
+ *
+ * Note: When a single listener object has more than one method that that
+ * matches the event, both methods will be called. But there is currently
+ * no guaranteed order in which they should be called.
+ */
+ @Test public void event3Test() throws ExecutionException, InterruptedException {
+ fService1.dispatchEvent3();
+ fExecutor.submit(new DsfRunnable() { public void run() {
+ Assert.assertTrue(1 == fService1.fEvent1RecipientNumber || 2 == fService1.fEvent1RecipientNumber);
+ Assert.assertTrue(3 == fService2.fEvent1RecipientNumber || 4 == fService2.fEvent1RecipientNumber);
+ Assert.assertTrue(5 == fService3.fEvent1RecipientNumber || 6 == fService3.fEvent1RecipientNumber);
+ Assert.assertTrue(0 == fService1.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService2.fEvent2RecipientNumber);
+ Assert.assertTrue(0 == fService3.fEvent2RecipientNumber);
+ Assert.assertTrue(1 == fService1.fEvent3RecipientNumber || 2 == fService1.fEvent3RecipientNumber);
+ Assert.assertTrue(3 == fService2.fEvent3RecipientNumber || 4 == fService2.fEvent3RecipientNumber);
+ Assert.assertTrue(5 == fService3.fEvent3RecipientNumber || 6 == fService3.fEvent3RecipientNumber);
+ }}).get();
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service1.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service1.java
new file mode 100644
index 00000000000..34e3cd72bb2
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service1.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import java.util.Hashtable;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.service.DsfSession;
+
+public class Service1 extends AbstractService {
+ Service1(DsfSession session) {
+ super(session);
+ }
+
+ @Override public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ register(new String[]{Service1.class.getName()}, new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service2.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service2.java
new file mode 100644
index 00000000000..a466c03e295
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service2.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import java.util.Hashtable;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.service.DsfSession;
+
+public class Service2 extends AbstractService {
+ Service2(DsfSession session) {
+ super(session);
+ }
+
+ @Override public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ getServicesTracker().getService(Service1.class);
+ register(new String[]{Service2.class.getName()}, new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service3.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service3.java
new file mode 100644
index 00000000000..5069157e8d0
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/Service3.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import java.util.Hashtable;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+import org.osgi.framework.BundleContext;
+
+public class Service3 extends AbstractService {
+ Service3(DsfSession session) {
+ super(session);
+ }
+
+ @Override protected BundleContext getBundleContext() {
+ return DsfTestPlugin.getBundleContext();
+ }
+
+ @Override public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleOK() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(RequestMonitor requestMonitor) {
+ getServicesTracker().getService(Service1.class);
+ getServicesTracker().getService(Service2.class);
+ register(new String[]{Service3.class.getName()}, new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/ShutdownSequence.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/ShutdownSequence.java
new file mode 100644
index 00000000000..84112677e85
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/ShutdownSequence.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.service.IDsfService;
+import org.eclipse.dd.tests.dsf.DsfTestPlugin;
+
+class ShutdownSequence extends Sequence {
+
+ DsfSession fSession;
+ DsfServicesTracker fTracker;
+
+ ShutdownSequence(DsfSession session) {
+ super(session.getExecutor());
+ fSession = session;
+ }
+
+ @Override
+ public Step[] getSteps() { return fSteps; }
+
+ final Step[] fSteps = new Step[] {
+ new Step() {
+ @Override public void execute(RequestMonitor requestMonitor) {
+ fTracker = new DsfServicesTracker(DsfTestPlugin.getBundleContext(), fSession.getId());
+ requestMonitor.done();
+ }
+
+ @Override public void rollBack(RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
+ },
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ shutdownService(Service3.class, requestMonitor);
+ }},
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ shutdownService(Service2.class, requestMonitor);
+ }},
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ shutdownService(Service1.class, requestMonitor);
+ }},
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }}
+ };
+
+ private void shutdownService(Class extends IDsfService> clazz, RequestMonitor requestMonitor) {
+ IDsfService service = fTracker.getService(clazz);
+ if (service != null) {
+ service.shutdown(requestMonitor);
+ }
+ else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, -1, "Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$
+ requestMonitor.done();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/StartupSequence.java b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/StartupSequence.java
new file mode 100644
index 00000000000..85d3c5dbef3
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.dsf/src/org/eclipse/dd/tests/dsf/events/StartupSequence.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems 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.dd.tests.dsf.events;
+
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.service.DsfSession;
+
+class StartupSequence extends Sequence {
+ DsfSession fSession;
+
+ StartupSequence(DsfSession session) {
+ super(session.getExecutor());
+ fSession = session;
+ }
+
+ @Override
+ public Step[] getSteps() { return fSteps; }
+
+ final Step[] fSteps = new Step[] {
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ new Service1(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ new Service2(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override public void execute(RequestMonitor requestMonitor) {
+ new Service3(fSession).initialize(requestMonitor);
+ }}
+ };
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/.classpath b/plugins/org.eclipse.dd.tests.gdb/.classpath
new file mode 100644
index 00000000000..304e86186aa
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/.externalToolBuilders/TestAppBuilder.launch b/plugins/org.eclipse.dd.tests.gdb/.externalToolBuilders/TestAppBuilder.launch
new file mode 100644
index 00000000000..5c664b7c490
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/.externalToolBuilders/TestAppBuilder.launch
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/.project b/plugins/org.eclipse.dd.tests.gdb/.project
new file mode 100644
index 00000000000..7eaa1391123
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/.project
@@ -0,0 +1,38 @@
+
+
+ org.eclipse.dd.tests.gdb
+
+
+
+
+
+ org.eclipse.ui.externaltools.ExternalToolBuilder
+ clean,full,incremental,
+
+
+ LaunchConfigHandle
+ <project>/.externalToolBuilders/TestAppBuilder.launch
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.dd.tests.gdb/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..e598bffe12f
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,65 @@
+#Thu Jun 07 11:08:01 PDT 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/plugins/org.eclipse.dd.tests.gdb/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.tests.gdb/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..326dfb185e7
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GDB/MI reference application tests
+Bundle-SymbolicName: org.eclipse.dd.tests.gdb;singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.dd.tests.gdb.launching.TestsPlugin
+Bundle-Vendor: Ericsson
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.dd.dsf,
+ org.eclipse.dd.dsf.debug,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.launch,
+ org.eclipse.cdt.debug.core,
+ org.eclipse.dd.mi,
+ org.junit4,
+ org.eclipse.debug.core,
+ org.eclipse.cdt.debug.mi.core,
+ org.eclipse.swt,
+ org.eclipse.dd.gdb
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ClassPath: .
diff --git a/plugins/org.eclipse.dd.tests.gdb/TestAppBuilder.xml b/plugins/org.eclipse.dd.tests.gdb/TestAppBuilder.xml
new file mode 100644
index 00000000000..3f8e9f07fed
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/TestAppBuilder.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/build.properties b/plugins/org.eclipse.dd.tests.gdb/build.properties
new file mode 100644
index 00000000000..aba8ab478f4
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/build.properties
@@ -0,0 +1,5 @@
+output.tests.jar = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .
+source.. = src/
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/BreakpointTestApp.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/BreakpointTestApp.exe
new file mode 100755
index 00000000000..6eb8b78a5b9
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/BreakpointTestApp.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/ExpressionTestApp.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/ExpressionTestApp.exe
new file mode 100755
index 00000000000..9051861f97e
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/ExpressionTestApp.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/GDBMIGenericTestApp.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/GDBMIGenericTestApp.exe
new file mode 100755
index 00000000000..6f604184d78
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/GDBMIGenericTestApp.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MemoryTestApp.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MemoryTestApp.exe
new file mode 100755
index 00000000000..390d47e29a8
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MemoryTestApp.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MultiThread.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MultiThread.exe
new file mode 100755
index 00000000000..e89bc956e7f
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MultiThread.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/SpecialTestApp.exe b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/SpecialTestApp.exe
new file mode 100755
index 00000000000..cbe79e76c9b
Binary files /dev/null and b/plugins/org.eclipse.dd.tests.gdb/data/launch/bin/SpecialTestApp.exe differ
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/BreakpointTestApp.cc b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/BreakpointTestApp.cc
new file mode 100644
index 00000000000..5474e540718
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/BreakpointTestApp.cc
@@ -0,0 +1,47 @@
+//============================================================================
+// Name : BreakpointTestApp.cpp
+// Author : Francois Chouinard
+// Version : 1.0
+// Copyright : Ericsson AB
+// Description : Breakpoint test application
+//============================================================================
+
+#include
+using namespace std;
+
+const int ARRAY_SIZE = 256;
+
+char charBlock[ARRAY_SIZE];
+int integerBlock[ARRAY_SIZE];
+
+void zeroBlocks(int abc)
+{
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ charBlock[i] = '\0';
+ integerBlock[i] = 0;
+ }
+}
+
+void setBlocks()
+{
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ charBlock[i] = (char) i;
+ integerBlock[i] = i;
+ }
+}
+
+void loop()
+{
+ int j;
+
+ for (int i = 0; i < ARRAY_SIZE; i++)
+ j = i;
+}
+
+int main()
+{
+ zeroBlocks(1);
+ loop();
+ setBlocks();
+ return 0;
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/ExpressionTestApp.cc b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/ExpressionTestApp.cc
new file mode 100644
index 00000000000..269b5bcf2d7
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/ExpressionTestApp.cc
@@ -0,0 +1,298 @@
+#include
+
+int gIntVar = 543;
+double gDoubleVar = 543.543;
+char gCharVar = 'g';
+bool gBoolVar = false;
+
+int gIntArray[2] = {987, 654};
+double gDoubleArray[2] = {987.654, 654.321};
+char gCharArray[2] = {'g', 'd'};
+bool gBoolArray[2] = {true, false};
+
+int *gIntPtr = &gIntVar;
+double *gDoublePtr = &gDoubleVar;
+char *gCharPtr = &gCharVar;
+bool *gBoolPtr = &gBoolVar;
+
+int *gIntPtr2 = (int*)0x8;
+double *gDoublePtr2 = (double*)0x5432;
+char *gCharPtr2 = (char*)0x4321;
+bool *gBoolPtr2 = (bool*)0x12ABCDEF;
+
+class bar {
+public:
+ int d;
+private:
+ int e[2];
+};
+
+class bar2 {
+public:
+ int f;
+private:
+ int g[2];
+};
+
+class foo: public bar, bar2 {
+public:
+ int a[2];
+ bar b;
+private:
+ int c;
+};
+
+struct Z {
+public:
+ int x;
+ int y;
+};
+struct childStruct {
+public:
+ Z z;
+};
+void locals2() {
+ // Check that we get the content of local variables with
+ // the same name as the calling method
+ int lIntVar = 6789;
+ double lDoubleArray[2] = {123.456, 6789.6789};
+ char lCharVar = 'i';
+ char *lCharPtr = &lCharVar;
+ bool *lBoolPtr2 = (bool*)0xABCDE123;
+
+ return;
+}
+
+void testLocals() {
+
+ int lIntVar = 12345;
+ double lDoubleVar = 12345.12345;
+ char lCharVar = 'm';
+ bool lBoolVar = false;
+
+ int lIntArray[2] = {6789, 12345};
+ double lDoubleArray[2] = {456.789, 12345.12345};
+ char lCharArray[2] = {'i', 'm'};
+ bool lBoolArray[2] = {true, false};
+
+ int *lIntPtr = &lIntVar;
+ double *lDoublePtr = &lDoubleVar;
+ char *lCharPtr = &lCharVar;
+ bool *lBoolPtr = &gBoolVar;
+
+ int *lIntPtr2 = (int*)0x1;
+ double *lDoublePtr2 = (double*)0x2345;
+ char *lCharPtr2 = (char*)0x1234;
+ bool *lBoolPtr2 = (bool*)0x123ABCDE;
+
+ locals2();
+
+ return;
+}
+
+int testChildren() {
+ foo f;
+
+ f.d = 1;
+
+ return 0;
+}
+
+int testWrite() {
+ int a[2] = {3, 456};
+
+ return 0;
+}
+
+int testName1(int newVal) {
+ int a = newVal;
+ return a;
+}
+
+int testName2(int newVal) {
+ int a = newVal;
+ return a;
+}
+
+int testSameName1(int newVal) {
+ int a = newVal;
+ Z z;
+ z.x = newVal;
+ return a;
+}
+int testSameName1(int newVal, int ignore) {
+ int a = newVal;
+ Z z;
+ z.x = newVal;
+ return a;
+}
+
+
+int testSameName() {
+ testSameName1(1);
+ testSameName1(2, 0);
+ testSameName1(3);
+
+ return 0;
+}
+
+int testConcurrent() {
+ int a[2] = {28, 32};
+ return a[0];
+}
+
+int testSubblock() {
+ int a = 8;
+ int b = 1;
+ if (a) {
+ int a = 12;
+ b = a;
+ }
+ return b;
+}
+
+int testAddress() {
+ int a = 8;
+ int* a_ptr = &a;
+
+ return a;
+}
+
+
+
+int testUpdateChildren(int val) {
+ childStruct a;
+ a.z.x = val + 10;
+ a.z.y = val + 11;
+
+ a.z.x = val + 20;
+ a.z.y = val + 21;
+
+ return a.z.x;
+}
+int testUpdateChildren2(int val) {
+ childStruct a;
+ a.z.x = val + 10;
+ a.z.y = val + 11;
+
+ a.z.x = val + 20;
+ a.z.y = val + 21;
+
+ return a.z.x;
+}
+
+int testDeleteChildren() {
+ foo f;
+ int a[1111];
+
+ return 1;
+}
+
+int testUpdateGDBBug() {
+ // GDB 6.7 has a bug which will cause var-update not to show
+ // the new value of 'a' if we switch the format to binary,
+ // since binary of 3 is 11 which is the same as the old value
+ // in natural format
+ int a = 11;
+ a = 3;
+ return 0;
+}
+
+int testUpdateIssue() {
+ double a = 1.99;
+ a = 1.22;
+}
+
+int testUpdateIssue2() {
+ struct {
+ double d;
+ } z;
+
+ z.d = 1.0;
+ z.d = 1.22;
+}
+
+int testConcurrentReadAndUpdateChild() {
+ struct {
+ int d;
+ }z;
+
+ z.d = 1;
+ z.d = 2;
+}
+
+int testConcurrentUpdateOutOfScopeChildThenParent1() {
+ struct {
+ int d;
+ }z;
+
+ z.d = 1;
+}
+
+int testConcurrentUpdateOutOfScopeChildThenParent2() {
+ struct {
+ int d;
+ }z;
+
+ z.d = 2;
+}
+
+int testConcurrentUpdateOutOfScopeChildThenParent() {
+ testConcurrentUpdateOutOfScopeChildThenParent1();
+ testConcurrentUpdateOutOfScopeChildThenParent2();
+}
+
+int testUpdateOfPointer() {
+ struct {
+ int a;
+ int* b;
+ }z;
+
+ int c = 3;
+
+ z.b = &(z.a);
+ z.a = 1;
+
+ z.b = &c;
+ z.a = 2;
+}
+
+int testCanWrite() {
+ int a;
+ int* b;
+ struct {
+ int in;
+ } c;
+ int d[2];
+
+ return 1;
+}
+
+int main() {
+ printf("Running ExpressionTest App\n");
+
+ testLocals();
+ testChildren();
+ testWrite();
+ testName1(1);
+ testName2(2);
+ testName1(3);
+ testSameName();
+ testConcurrent();
+ testSubblock();
+ testAddress();
+ testUpdateChildren(0);
+ testUpdateChildren(100);
+ testUpdateChildren2(200);
+ testDeleteChildren();
+ testUpdateGDBBug();
+ testUpdateIssue();
+ testUpdateIssue2();
+ testConcurrentReadAndUpdateChild();
+ testConcurrentUpdateOutOfScopeChildThenParent();
+ testUpdateOfPointer();
+ testCanWrite();
+
+ return 0;
+}
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/GDBMIGenericTestApp.cc b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/GDBMIGenericTestApp.cc
new file mode 100644
index 00000000000..e4007b95427
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/GDBMIGenericTestApp.cc
@@ -0,0 +1,15 @@
+#include
+
+int main() {
+ printf("Running Generic App\n");
+
+ const char *path = "/tmp/dsftest.txt";
+ const char *mode = "a";
+ FILE* fd = fopen(path, mode);
+ fprintf(fd, "Running Generic App\n");
+ fclose(fd);
+
+
+ return 0;
+}
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/Makefile b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/Makefile
new file mode 100644
index 00000000000..777b8b828b3
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/Makefile
@@ -0,0 +1,14 @@
+src = $(wildcard *.cc *.c)
+destDir = ../bin
+GCCFLAGS = -g -pthread
+
+all:
+ @mkdir -p $(destDir)
+# Name the target with an .exe extension so that CVS does not
+# include it when making a patch
+ @for file in $(src) ; \
+ do \
+ target=`basename $$file .c` ; \
+ target=`basename $$target .cc` ; \
+ g++ $(GCCFLAGS) $$file -o $(destDir)/$$target.exe ; \
+ done
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MemoryTestApp.cc b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MemoryTestApp.cc
new file mode 100644
index 00000000000..bef0b930e0e
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MemoryTestApp.cc
@@ -0,0 +1,38 @@
+//============================================================================
+// Name : MemoryTestApp.cpp
+// Author : Francois Chouinard
+// Version : 1.0
+// Copyright : Ericsson AB
+// Description : Memory test application
+//============================================================================
+
+#include
+using namespace std;
+
+const int ARRAY_SIZE = 256;
+
+char charBlock[ARRAY_SIZE];
+int integerBlock[ARRAY_SIZE];
+
+void zeroBlocks()
+{
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ charBlock[i] = '\0';
+ integerBlock[i] = 0;
+ }
+}
+
+void setBlocks()
+{
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ charBlock[i] = (char) i;
+ integerBlock[i] = i;
+ }
+}
+
+int main()
+{
+ zeroBlocks();
+ setBlocks();
+ return 0;
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MultiThread.cc b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MultiThread.cc
new file mode 100644
index 00000000000..80f99fea6aa
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/data/launch/src/MultiThread.cc
@@ -0,0 +1,29 @@
+#include
+#include
+#include
+#include
+#define NUM_THREADS 5
+
+void *PrintHello(void *threadid)
+{
+ int tid;
+ tid = (int)threadid;
+ printf("Hello World! It's me, thread #%d!\n", tid);
+ pthread_exit(NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t threads[NUM_THREADS];
+ int rc, t;
+ for(t=0;t
+
+int main() {
+ printf("Running SpecialTestApp\n");
+
+ const char *path = "/tmp/dsftest.txt";
+ const char *mode = "a";
+ FILE* fd = fopen(path, mode);
+ fprintf(fd, "Running SpecialTestApp\n");
+ fclose(fd);
+
+
+ return 0;
+}
+
diff --git a/plugins/org.eclipse.dd.tests.gdb/plugin.xml b/plugins/org.eclipse.dd.tests.gdb/plugin.xml
new file mode 100644
index 00000000000..e2b5a7c5bfd
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/plugin.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/mi/service/ClassAccessor.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/mi/service/ClassAccessor.java
new file mode 100644
index 00000000000..3d4bd45fdd3
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/mi/service/ClassAccessor.java
@@ -0,0 +1,38 @@
+package org.eclipse.dd.mi.service;
+
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.dd.mi.service.ExpressionService.MIExpressionDMC;
+
+public class ClassAccessor {
+
+ public static class MIExpressionDMCAccessor {
+ private MIExpressionDMC miExprDmc;
+
+ public MIExpressionDMCAccessor(IExpressionDMContext dmc) {
+ miExprDmc = (MIExpressionDMC) dmc;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return miExprDmc.equals(other);
+ }
+
+ @Override
+ public int hashCode() {
+ return miExprDmc.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return miExprDmc.toString();
+ }
+
+ public String getExpression() {
+ return miExprDmc.getExpression();
+ }
+
+ public String getRelativeExpression() {
+ return miExprDmc.getRelativeExpression();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/AllTests.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/AllTests.java
new file mode 100644
index 00000000000..94f304e8140
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/AllTests.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Ericsson 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:
+ * Ericsson - Initial Implementation
+ *******************************************************************************/
+package org.eclipse.dd.tests.gdb;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/*
+ * This class is meant to be empty. It enables us to define
+ * the annotations which list all the different JUnit class we
+ * want to run. When creating a new test class, it should be
+ * added to the list below.
+ */
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ MIRegistersTest.class,
+ MIRunControlTest.class,
+ ExpressionServiceTest.class,
+ MIMemoryTest.class,
+ MIBreakpointsTest.class,
+
+ /* Add your test class here */
+ })
+
+public class AllTests {}
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExampleTest.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExampleTest.java
new file mode 100644
index 00000000000..4604d9046ad
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExampleTest.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Ericsson 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:
+ * Ericsson - Initial Implementation
+ *******************************************************************************/
+package org.eclipse.dd.tests.gdb;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileNotFoundException;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.dd.tests.gdb.framework.BackgroundRunner;
+import org.eclipse.dd.tests.gdb.framework.BaseTestCase;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/*
+ * This is an example of how to write new JUnit test cases
+ * for services of DSF.
+ *
+ * Each test class should extend BaseTestCase
+ * so as to automatically launch the application before
+ * each testcase and tear it down after.
+ *
+ * Also, each new test class must be added to the list within AllTest.
+ *
+ * Finally, each testcase should be @RunWith(BackgroundRunner.class)
+ * so as to release the UI thread and allow things such as
+ * timeouts to work in JUnit
+ */
+
+// Each test must run with the BackgroundRunner so as
+// to release the UI thread
+@RunWith(BackgroundRunner.class)
+
+public class ExampleTest extends BaseTestCase {
+
+ @BeforeClass
+ public static void beforeClassMethod() {
+ // Things to run once specifically for this class,
+ // before starting this set of tests.
+ // Any method name can be used
+
+ // To choose your own test application, use the following form
+ // You must make sure the compiled binary is available in the
+ // specified location.
+ // If this method call is not made, the default GDBMIGenericTestApp
+ // will be used
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
+ "data/launch/bin/SpecialTestApp.exe");
+
+ // Other attributes can be changed here
+ }
+
+ @AfterClass
+ public static void afterClassMethod() {
+ // Things to run once specifically for this class,
+ // after the launch has been performed
+ // Any method name can be used
+ }
+
+ @Before
+ public void beforeMethod() {
+ // Things to run specifically for this class,
+ // before each test but after the launch has been performed
+ // The Launched used is for the default test application
+ // Any method name can be used
+ }
+
+ @After
+ public void afterMethod() {
+ // Things to run specifically for this class
+ // after each test but before the launch has been torn down
+ // Any method name can be used
+ }
+
+// @Override
+// public void baseBeforeMethod() {
+// // Can be used to override and prevent the baseSetup from being run
+// // The name baseBeforeMethod must be used
+// }
+
+// @Override
+// public void baseAfterMethod() {
+// // Can be used to override and prevent the baseTeardown from being run
+// // The name baseAfterMethod must be used
+// }
+
+ @Test
+ public void basicTest() {
+ // First test to run
+ assertTrue("", true);
+ }
+
+ @Test(timeout=5000)
+ public void timeoutTest() {
+ // Second test to run, which will timeout if not finished on time
+ assertTrue("", true);
+ }
+
+ @Test(expected=FileNotFoundException.class)
+ public void exceptionTest() throws FileNotFoundException {
+ // Third test to run which expects an exception
+ throw new FileNotFoundException("Just testing");
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExpressionServiceTest.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExpressionServiceTest.java
new file mode 100644
index 00000000000..33ccdf3ae6b
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/ExpressionServiceTest.java
@@ -0,0 +1,2960 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Ericsson 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:
+ * Ericsson - Initial Implementation
+ *******************************************************************************/
+package org.eclipse.dd.tests.gdb;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.core.IAddress;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.Addr32;
+import org.eclipse.cdt.utils.Addr64;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
+import org.eclipse.dd.dsf.debug.service.IExpressions;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionChangedDMEvent;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMAddress;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData;
+import org.eclipse.dd.dsf.debug.service.IRunControl.StepType;
+import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.ClassAccessor.MIExpressionDMCAccessor;
+import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
+import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
+import org.eclipse.dd.tests.gdb.framework.BackgroundRunner;
+import org.eclipse.dd.tests.gdb.framework.BaseTestCase;
+import org.eclipse.dd.tests.gdb.framework.SyncUtil;
+import org.eclipse.dd.tests.gdb.launching.TestsPlugin;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(BackgroundRunner.class)
+public class ExpressionServiceTest extends BaseTestCase {
+
+ private DsfSession fSession;
+
+ private DsfServicesTracker fServicesTracker;
+
+ private GDBControl fGdbControl;
+
+ private IExpressions fExpService;
+
+ private int fExprChangedEventCount = 0;
+
+ private IExpressionDMContext fExprChangedCtx = null;
+
+ private IExpressionDMContext globalExpressionCtx1 = null;
+ private IExpressionDMContext globalExpressionCtx2 = null;
+
+
+ @BeforeClass
+ public static void beforeClassMethod() {
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, "data/launch/bin/ExpressionTestApp.exe");
+ }
+
+ @Before
+ public void init() {
+ fSession = getGDBLaunch().getSession();
+ fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
+
+ fExpService = fServicesTracker.getService(IExpressions.class);
+ fGdbControl = fServicesTracker.getService(GDBControl.class);
+ fSession.addServiceEventListener(this, null);
+ clearExprChangedData();
+ }
+
+ @After
+ public void shutdown() {
+ fSession.removeServiceEventListener(this);
+ fExpService = null;
+ fServicesTracker.dispose();
+ }
+
+ // Handles ExpressionChangedEvent
+ @DsfServiceEventHandler
+ public void eventDispatched(IExpressionChangedDMEvent e) {
+ fExprChangedEventCount++;
+ fExprChangedCtx = e.getDMContext();
+ }
+
+ // Clears the counters
+ private void clearExprChangedData() {
+ fExprChangedEventCount = 0;
+ fExprChangedCtx = null;
+ }
+
+ // Returns the total number of events received
+ private int getExprChangedCount() {
+ return fExprChangedEventCount;
+ }
+
+ private IExpressionDMContext getExprChangedContext() {
+ return fExprChangedCtx;
+ }
+
+ // *********************************************************************
+ // Below are the tests for the expression service.
+ // *********************************************************************
+
+ /**
+ * Test that we can correctly evaluate integer expressions.
+ */
+ @Test
+ public void testLiteralIntegerExpressions() throws Throwable {
+ // Create a map of expressions and their expected values.
+ Map tests = new HashMap();
+
+ tests.put("0 + 0 - 0", new String[] { "0x0", "0", "0", "0", "0" });
+ tests.put("3 + 4", new String[] { "0x7", "07", "111", "7", "7" });
+ tests.put("3 + 4 * 5", new String[] { "0x17", "027", "10111", "23", "23" });
+ tests.put("5 * 3 + 4", new String[] { "0x13", "023", "10011", "19", "19" });
+ tests.put("5 * (3 + 4)", new String[] { "0x23", "043", "100011", "35", "35" });
+ tests.put("10 - 15", new String[] { "0xFFFFFFFB", "037777777773", "11111111111111111111111111111011", "-5",
+ "-5" });
+ tests.put("10 + -15", new String[] { "0xFFFFFFFB", "037777777773", "11111111111111111111111111111011", "-5",
+ "-5" });
+
+ executeExpressionSubTests(tests, fGdbControl.getControlDMContext());
+ }
+
+ /**
+ * Test that we can correctly evaluate floating-point expressions.
+ */
+ @Test
+ public void testLiteralFloatingPointExpressions() throws Throwable {
+ // Create a map of expressions and their expected values.
+ Map tests = new HashMap();
+
+ tests.put("3.1415 + 1.1111", new String[] { "0x4", "04", "100", "4", "4.2526000000000002" });
+ tests.put("100.0 / 3.0", new String[] { "0x21", "041", "100001", "33", "33.333333333333336" });
+ tests.put("-100.0 / 3.0", new String[] { "0xffffffffffffffdf", "01777777777777777777737",
+ "1111111111111111111111111111111111111111111111111111111111011111", "-33", "-33.333333333333336" });
+ tests.put("-100.0 / -3.0", new String[] { "0x21", "041", "100001", "33", "33.333333333333336" });
+ tests.put("100.0 / 0.5", new String[] { "0xc8", "0310", "11001000", "200", "200" });
+
+ executeExpressionSubTests(tests, fGdbControl.getControlDMContext());
+ }
+
+ /**
+ * Test that we can correctly evaluate C expressions involving local
+ * variables.
+ */
+ @Test
+ public void testLocalVariables() throws Throwable {
+ // Run to the point where all local variables are initialized
+ SyncUtil.SyncRunToLocation("testLocals");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 16);
+
+ // Create a map of expressions to expected values.
+ Map tests1 = new HashMap();
+
+ tests1.put("lIntVar", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345" });
+ tests1.put("lDoubleVar", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999" });
+ tests1.put("lCharVar", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'" });
+ tests1.put("lBoolVar", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests1.put("lIntArray[1]", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345" });
+ tests1.put("lDoubleArray[1]", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999" });
+ tests1.put("lCharArray[1]", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'" });
+ tests1.put("lBoolArray[1]", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests1.put("*lIntPtr", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345" });
+ tests1.put("*lDoublePtr", new String[] { "0x3039", "030071", "11000000111001", "12345", "12345.123449999999" });
+ tests1.put("*lCharPtr", new String[] { "0x6d", "0155", "1101101", "109", "109 'm'" });
+ tests1.put("*lBoolPtr", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests1.put("lIntPtr2", new String[] { "0x1", "01", "1", "1", "0x1" });
+ tests1.put("lDoublePtr2", new String[] { "0x2345", "021505", "10001101000101", "9029", "0x2345" });
+ // GDB says a char* is out of bounds, but not the other pointers???
+ // tests1.put("CharPtr2", new String[] { "0x1234", "011064",
+ // "1001000110100", "4660", "0x1234" });
+ tests1.put("lBoolPtr2", new String[] { "0x123ABCDE", "02216536336", "10010001110101011110011011110", "305839326", "0x123ABCDE" });
+
+ executeExpressionSubTests(tests1, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0));
+
+ // Step into the method and stop until all new local variables are
+ // initialized
+ SyncUtil.SyncStep(StepType.STEP_INTO);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 5);
+
+ // Create a map of expressions to expected values.
+ Map tests2 = new HashMap();
+
+ tests2.put("lIntVar", new String[] { "0x1a85", "015205", "1101010000101", "6789", "6789" });
+ tests2.put("lDoubleArray[1]",
+ new String[] { "0x1a85", "015205", "1101010000101", "6789", "6789.6788999999999" });
+ tests2.put("lCharVar", new String[] { "0x69", "0151", "1101001", "105", "105 'i'" });
+ tests2.put("*lCharPtr", new String[] { "0x69", "0151", "1101001", "105", "105 'i'" });
+ tests2.put("lBoolPtr2", new String[] { "0xABCDE123", "025363360443", "10101011110011011110000100100011",
+ "2882396451", "0xABCDE123" });
+
+ // check variables at current stack frame
+ executeExpressionSubTests(tests2, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0));
+ // check previous stack frame
+ executeExpressionSubTests(tests1, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 1));
+
+ // Now return from the method and check that we see the
+ // original variables
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_RETURN);
+
+ executeExpressionSubTests(tests1, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0));
+ }
+
+ /**
+ * This tests verifies that we can deal with variables in a subblock hiding
+ * variables with the same name in the outer block.
+ */
+ @Ignore("Sublocks do not work with GDB")
+ @Test
+ public void testSubBlock() throws Throwable {
+ SyncUtil.SyncRunToLocation("testSubblock");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ Map tests = new HashMap();
+
+ tests.put("a", new String[] { "0x8", "010", "1000", "8", "8" });
+ tests.put("b", new String[] { "0x1", "01", "1", "1", "1" });
+
+ executeExpressionSubTests(tests, frameDmc);
+
+ // Now enter a subblock with the same variable names
+ SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+
+ tests = new HashMap();
+
+ tests.put("a", new String[] { "0xc", "014", "1100", "12", "12" });
+ tests.put("b", new String[] { "0x1", "01", "1", "1", "1" });
+
+ executeExpressionSubTests(tests, frameDmc);
+
+ // Now step to change the b variable
+ SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ tests = new HashMap();
+
+ tests.put("a", new String[] { "0xc", "014", "1100", "12", "12" });
+ tests.put("b", new String[] { "0xc", "014", "1100", "12", "12" });
+
+ executeExpressionSubTests(tests, frameDmc);
+
+ // Now exit the sub-block and check that we see the original a but the
+ // same b
+ SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ tests = new HashMap();
+
+ tests.put("a", new String[] { "0x8", "010", "1000", "8", "8" });
+ tests.put("b", new String[] { "0xc", "014", "1100", "12", "12" });
+
+ executeExpressionSubTests(tests, frameDmc);
+ }
+
+ /**
+ * This tests verifies that we can obtain children properly.
+ */
+ @Test
+ public void testChildren() throws Throwable {
+
+ // Get the children of some variables
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncRunToLocation("testChildren");
+ doTestChildren(stoppedEvent);
+
+ // Now do a step and get the children again, to test the internal cache
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ doTestChildren(stoppedEvent);
+ }
+
+ /**
+ * This test verifies that the ExpressionService can write to a variable.
+ */
+ @Test
+ public void testWriteVariable() throws Throwable {
+ SyncUtil.SyncRunToLocation("testWrite");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ final IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a[1]");
+
+ writeAndCheck(exprDmc, "987", IFormattedValues.DECIMAL_FORMAT, "987");
+ writeAndCheck(exprDmc, "16", IFormattedValues.HEX_FORMAT, "22");
+ writeAndCheck(exprDmc, "0x2e", IFormattedValues.HEX_FORMAT, "46");
+ writeAndCheck(exprDmc, "16", IFormattedValues.OCTAL_FORMAT, "14");
+ writeAndCheck(exprDmc, "022", IFormattedValues.OCTAL_FORMAT, "18");
+ writeAndCheck(exprDmc, "1011", IFormattedValues.BINARY_FORMAT, "11");
+ writeAndCheck(exprDmc, "0b1001", IFormattedValues.BINARY_FORMAT, "9");
+ writeAndCheck(exprDmc, "456", IFormattedValues.NATURAL_FORMAT, "456");
+
+ }
+
+ /*
+ * This method does a write and then a read to make sure the new value was
+ * properly written.
+ */
+ private void writeAndCheck(final IExpressionDMContext exprDmc, final String newValueFormatted, final String format,
+ final String newValueInDecimal) throws Throwable {
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // Write the new value using its formatted value
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.writeExpression(
+ exprDmc,
+ newValueFormatted,
+ format,
+ new RequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ assertTrue("ExprChangedEvent problem: expected 1, received " + getExprChangedCount(),
+ getExprChangedCount() == 1);
+
+ clearExprChangedData();
+
+ wait.waitReset();
+
+ // Read the new value in decimal and check that it is what we expected
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.DECIMAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ String actualDecimalValue = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();
+
+ assertTrue("Failed to correctly evaluate '" + exprDmc.getExpression() + "': expected '" + newValueInDecimal
+ + "', got '" + actualDecimalValue + "'", actualDecimalValue.equalsIgnoreCase(newValueInDecimal));
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+ /**
+ * This tests verifies that we handle invalid formats properly for a write.
+ */
+ @Test
+ public void testWriteErrorFormat() throws Throwable {
+ SyncUtil.SyncRunToLocation("testWrite");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a[1]");
+
+ writeAndCheckError(exprDmc, "goodbye", IFormattedValues.DECIMAL_FORMAT);
+ writeAndCheckError(exprDmc, "abggg", IFormattedValues.HEX_FORMAT);
+ writeAndCheckError(exprDmc, "99", IFormattedValues.OCTAL_FORMAT);
+ writeAndCheckError(exprDmc, "234", IFormattedValues.BINARY_FORMAT);
+ writeAndCheckError(exprDmc, "hello", IFormattedValues.NATURAL_FORMAT);
+ writeAndCheckError(exprDmc, "1", "ThisFormatDoesNotExist");
+
+ IExpressionDMContext notWritableExprDmc = SyncUtil.SyncCreateExpression(frameDmc, "10+5");
+ writeAndCheckError(notWritableExprDmc, "1", IFormattedValues.NATURAL_FORMAT);
+ }
+
+ /*
+ * This method does a write that should use an invalid value or format, and
+ * verifies that the operation fails
+ */
+ private void writeAndCheckError(final IExpressionDMContext exprDmc, final String invalidValueFormatted,
+ final String format) throws Throwable {
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // Write the new value using its formatted value
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.writeExpression(exprDmc, invalidValueFormatted, format, new RequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue("Got an OK status for an error test case. Should not be able to write value "
+ + invalidValueFormatted + " in " + format, !wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+ /**
+ * This test tries multiple format reads during the same executor cycle, to
+ * make sure the internal MI commands are sequenced properly.
+ */
+ @Test
+ public void testConcurrentReads() throws Throwable {
+ // Next we test that we can read the value more than once
+ // of the same variable object at the exact same time
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a[0]");
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("28")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.HEX_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equalsIgnoreCase("0x1c")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+
+ }
+
+ /**
+ * This test tries reads and listChildren during the same executor cycle, to
+ * make sure the internal MI commands are sequenced properly.
+ */
+ @Test
+ public void testConcurrentReadChildren() throws Throwable {
+ // Next we test that we can retrieve children while reading the value
+ // and vice-versa
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // First we get the expected value of the array pointer.
+ final IExpressionDMContext addrDmc = SyncUtil.SyncCreateExpression(frameDmc, "&a");
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(addrDmc, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ final String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();
+
+ wait.waitReset();
+
+ // Now perform the test
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals(actualAddrStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getSubExpressions(exprDmc, new DataRequestMonitor(
+ fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ IExpressionDMContext[] children = getData();
+ int failedIndex = -1;
+ for (int i = 0; i < 2; i++) {
+ if (!children[i].getExpression().equals("a[" + i + "]")) {
+ failedIndex = i;
+ }
+ }
+
+ if (failedIndex != -1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting child number: " + failedIndex, null));
+ } else {
+ wait.waitFinished();
+ }
+ }
+ }
+ });
+
+ // Use different format to avoid triggering the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.HEX_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals(actualAddrStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+ /**
+ * This test tries reads and getChildrenCount during the same executor
+ * cycle, to make sure the internal MI commands are sequenced properly.
+ */
+ @Test
+ public void testConcurrentReadChildrenCount() throws Throwable {
+ // Next we test that we can retrieve children count while reading the
+ // value and vice-versa
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // First we get the expected value of the array pointer.
+ final IExpressionDMContext addrDmc = SyncUtil.SyncCreateExpression(frameDmc, "&a");
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(addrDmc, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ final String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();
+
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ wait.increment();
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");
+
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals(actualAddrStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getSubExpressionCount(exprDmc, new DataRequestMonitor(fExpService.getExecutor(),
+ null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ int count = getData();
+ if (count != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting count for children. Got" + count + "instead of 2", null));
+ } else {
+ wait.waitFinished();
+ }
+ }
+ }
+ });
+
+ // Use different format to avoid triggering the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.HEX_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals(actualAddrStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+ /**
+ * This test tries reads and writes during the same executor cycle, to make
+ * sure the internal MI commands are sequenced properly.
+ */
+ @Test
+ public void testConcurrentReadWrite() throws Throwable {
+ // Next we test that we can deal with a write request and read request
+ // at
+ // the same time and vice-versa
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a[1]");
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("32")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, got " + getData().getFormattedValue()
+ + " instead of 32", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.writeExpression(exprDmc, "56", IFormattedValues.NATURAL_FORMAT, new RequestMonitor(
+ fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ wait.waitFinished();
+ }
+ }
+ });
+
+ // Use different format to avoid triggering the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.HEX_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("0x38")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format, got " + getData().getFormattedValue()
+ + " instead of 0x38", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 1, received " + getExprChangedCount(),
+ getExprChangedCount() == 1);
+ exprDmc.equals(getExprChangedContext());
+ clearExprChangedData();
+ }
+
+ /**
+ * This test tries many different operations during the same executor cycle,
+ * to make sure the internal MI commands are sequenced properly.
+ */
+ @Test
+ public void testConcurrentReadWriteChildren() throws Throwable {
+ // Finally, we go nuts and request two reads, while requesting
+ // a get children and get children count.
+ // Note that we don't request a write, because a write is allowed to
+ // go through at any time and we don't exactly know when it will
+ // change the value we are reading.
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a[1]");
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("32")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, got " + getData().getFormattedValue()
+ + " instead of 32", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.HEX_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("0x20")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format, got " + getData().getFormattedValue()
+ + " instead of 0x20", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getSubExpressionCount(exprDmc, new DataRequestMonitor(fExpService.getExecutor(),
+ null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData() != 0) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting child count; expecting 0 got " + getData(), null));
+ } else {
+ wait.waitFinished();
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getSubExpressions(exprDmc, new DataRequestMonitor(
+ fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().length != 0) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 0 got " + getData().length, null));
+ } else {
+ wait.waitFinished();
+ }
+ }
+ }
+ });
+
+ // Must use a different format or else the cache will be triggered
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.OCTAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("040")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format, got " + getData().getFormattedValue()
+ + " instead of 040", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ exprDmc.equals(getExprChangedContext());
+ clearExprChangedData();
+ }
+
+ /**
+ * This test verifies that the ExpressionService caches the evaluation of an
+ * expression in a specific format. It verifies this by: 1- reading a
+ * variable 2- writing to that variable 3- reading the variable in a new
+ * format and seeing the new value 4- reading the variable in the same
+ * format as step 1 and seeing the old value cached Note that all above
+ * steps must be done within the same Runnable submitted to the executor.
+ * This allows the cache to be triggered before it is invalidated by a write
+ * command, since the write command will need an new executor cycle to send
+ * an MI command to the back-end
+ */
+ @Test
+ public void testWriteCache() throws Throwable {
+ // Test the cache by changing a value but triggering a read before the
+ // write clears the cache
+
+ SyncUtil.SyncRunToLocation("testConcurrent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a[1]");
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("32")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, got " + getData().getFormattedValue()
+ + " instead of 32", null));
+ }
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.writeExpression(exprDmc, "56", IFormattedValues.NATURAL_FORMAT, new RequestMonitor(
+ fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ wait.waitFinished();
+ }
+ }
+ });
+
+ // Must use a different format or else the cache will be
+ // triggered
+ // This will prove that the write has changed the backend
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.OCTAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("070")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating hex format, got " + getData().getFormattedValue()
+ + " instead of 070", null));
+ }
+ }
+ }
+ });
+
+ // Test that the cache is triggered, giving us the old value
+ // This happens because we are calling this operation on the
+ // same executor run call.
+ // NOTE that this is not a problem, because the writeExpression
+ // will eventually
+ // reset the cache (we'll test this below).
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("32")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, got " + getData().getFormattedValue()
+ + " instead of 32", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ // Now that we know the writeExpressions completed and the cache was
+ // reset, do a similar
+ // request as above to see that the cache has indeed been reset
+ wait.waitReset();
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("56")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, got " + getData().getFormattedValue()
+ + " instead of 56", null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ assertTrue("ExprChangedEvent problem: expected 1, received " + getExprChangedCount(),
+ getExprChangedCount() == 1);
+ exprDmc.equals(getExprChangedContext());
+ clearExprChangedData();
+ }
+
+ /**
+ * Test that we can correctly retrieve the address and type size of an
+ * expression
+ */
+ @Test
+ public void testExprAddress() throws Throwable {
+
+ SyncUtil.SyncRunToLocation("testAddress");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final IExpressionDMContext exprDmc = SyncUtil.SyncCreateExpression(frameDmc, "a");
+
+ final IExpressionDMContext exprDmc2 = SyncUtil.SyncCreateExpression(frameDmc, "a_ptr");
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // First get the address of 'a' through 'a_ptr'
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getFormattedExpressionValue(fExpService.getFormattedValueContext(exprDmc2,
+ IFormattedValues.NATURAL_FORMAT), new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ String actualAddrStr = ((FormattedValueDMData) wait.getReturnInfo()).getFormattedValue();
+ wait.waitReset();
+
+ // Now check the address through our getAddressData
+ checkAddressData(exprDmc, actualAddrStr, 4);
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+
+ /**
+ * Test that we can correctly evaluate C expressions involving global
+ * variables.
+ *
+ * @return void
+ */
+ // @Test
+ public void testGlobalVariables() throws Throwable {
+
+ // Step to a stack level of 2 to be able to test differen stack frames
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncRunToLocation("locals2");
+
+ // Create a map of expressions to expected values.
+ Map tests = new HashMap();
+
+ // Global variables
+ tests.put("gIntVar", new String[] { "0x21F", "01037", "1000011111", "543", "543" });
+ tests.put("gDoubleVar", new String[] { "0x21F", "01037", "1000011111", "543", "543.54300000000001" });
+ tests.put("gCharVar", new String[] { "0x67", "0147", "1100111", "103", "103 'g'" });
+ tests.put("gBoolVar", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests.put("gIntArray[1]", new String[] { "0x28E", "01216", "1010001110", "654", "654" });
+ tests.put("gDoubleArray[1]", new String[] { "0x28E", "01216", "1010001110", "654", "654.32100000000003" });
+ tests.put("gCharArray[1]", new String[] { "0x64", "0144", "1100100", "100", "100 'd'" });
+ tests.put("gBoolArray[1]", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests.put("*gIntPtr", new String[] { "0x21F", "01037", "1000011111", "543", "543" });
+ tests.put("*gDoublePtr", new String[] { "0x21F", "01037", "1000011111", "543", "543.54300000000001" });
+ tests.put("*gCharPtr", new String[] { "0x67", "0147", "1100111", "103", "103 'g'" });
+ tests.put("*gBoolPtr", new String[] { "0x0", "0", "0", "0", "false" });
+
+ tests.put("gIntPtr2", new String[] { "0x8", "010", "1000", "8", "0x8" });
+ tests.put("gDoublePtr2", new String[] { "0x5432", "052062", "101010000110010", "21554", "0x5432" });
+ // GDB says a char* is out of bounds, but not the other pointers???
+ // tests.put("gCharPtr2", new String[] { "0x4321", "041441",
+ // "100001100100001", "17185", "0x4321" });
+ tests.put("gBoolPtr2", new String[] { "0x12ABCDEF", "02252746757", "10010101010111100110111101111",
+ "313249263", "0x12ABCDEF" });
+
+ // Try different stack frames
+ executeExpressionSubTests(tests, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0));
+ executeExpressionSubTests(tests, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 1));
+ executeExpressionSubTests(tests, SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 2));
+ }
+
+ /**
+ * This test verifies that the ExpressionService can handle having a
+ * variable with the same name in two different methods but at the same
+ * stack depth.
+ */
+ @Test
+ public void testNamingSameDepth() throws Throwable {
+ SyncUtil.SyncRunToLocation("testName1");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ Map tests = new HashMap();
+ tests.put("a", new String[] { "0x1", "01", "1", "1", "1" });
+ executeExpressionSubTests(tests, frameDmc);
+
+ SyncUtil.SyncRunToLocation("testName2");
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 1);
+ frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ tests = new HashMap();
+ tests.put("a", new String[] { "0x2", "02", "10", "2", "2" });
+ executeExpressionSubTests(tests, frameDmc);
+
+ SyncUtil.SyncRunToLocation("testName1");
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 1);
+ frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ tests = new HashMap();
+ tests.put("a", new String[] { "0x3", "03", "11", "3", "3" });
+ executeExpressionSubTests(tests, frameDmc);
+ }
+
+ /**
+ * This test verifies that the ExpressionService can handle having a
+ * variable with the same name in two methods that also have the same name
+ */
+ @Test
+ public void testNamingSameMethod() throws Throwable {
+ SyncUtil.SyncRunToLocation("testSameName");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 2);
+ IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ Map tests = new HashMap();
+ tests.put("a", new String[] { "0x1", "01", "1", "1", "1" });
+ executeExpressionSubTests(tests, frameDmc);
+
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 2);
+ frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ tests = new HashMap();
+ tests.put("a", new String[] { "0x2", "02", "10", "2", "2" });
+ executeExpressionSubTests(tests, frameDmc);
+
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 2);
+ frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ tests = new HashMap();
+ tests.put("a", new String[] { "0x3", "03", "11", "3", "3" });
+ executeExpressionSubTests(tests, frameDmc);
+ }
+
+ /**
+ * This test verifies that the ExpressionService can handle having a
+ * child variable with the same name in two methods that also have the same name
+ */
+ @Test
+ public void testChildNamingSameMethod() throws Throwable {
+ SyncUtil.SyncRunToLocation("testSameName");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 4);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ // now get the value of the child
+ final String valueStr = "1";
+ final IExpressionDMContext child = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+
+
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 4);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ // now get the value of the child
+ final String valueStr = "2";
+ final IExpressionDMContext child = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+
+
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 4);
+ final IFrameDMContext frameDmc3 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc3, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ // now get the value of the child
+ final String valueStr = "3";
+ final IExpressionDMContext child = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(child, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + child.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+
+
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ }
+
+ /**
+ * This test verifies that the ExpressionService properly updates
+ * children variables, when we do not update the parent explicitly
+ */
+ @Test
+ public void testUpdatingChildren() throws Throwable {
+ SyncUtil.SyncRunToLocation("testUpdateChildren");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ doUpdateTest(frameDmc, 0);
+
+ // Re-run the test to test out-of-scope update again
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 3);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ doUpdateTest(frameDmc2, 100);
+
+ // Re-run the test within a different method test out-of-scope updates
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 3);
+ final IFrameDMContext frameDmc3 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+ doUpdateTest(frameDmc3, 200);
+
+ }
+
+
+ public void doUpdateTest(final IFrameDMContext frameDmc, final int baseValue) throws Throwable {
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "a");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // Now list the children of this child
+ fExpService.getSubExpressions(
+ getData()[0],
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final IExpressionDMContext[] childDmcs = getData();
+
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (childDmcs.length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + childDmcs.length, null));
+ } else {
+ // now get the value of the two children
+ for (int i =0; i<2; i++) {
+ final String valueStr = Integer.toString(baseValue + i + 10);
+ final int finali = i;
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(childDmcs[i], IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + childDmcs[finali].getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+ }
+ }
+ });
+ }
+
+
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now step to change the value of a.z.x and a.z.y and verify the changed values.
+ // This will confirm that the parent "a" will have been properly updated
+ // It is a better test to do it for two children because it tests concurrent update requests
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "a");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // Now list the children of this child
+ fExpService.getSubExpressions(
+ getData()[0],
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final IExpressionDMContext[] childDmcs = getData();
+
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (childDmcs.length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + childDmcs.length, null));
+ } else {
+ // now get the value of the two children
+ for (int i =0; i<2; i++) {
+ final String valueStr = Integer.toString(baseValue + i + 20);
+ final int finali = i;
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(childDmcs[i], IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + childDmcs[finali].getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+ }
+ }
+ });
+ }
+
+
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * This test creates a variable object with children (not an array) and then gets these children
+ * to be deleted because of a large number of other variable objects being created.
+ * We then check that the expression service can handle a request for one of those deleted children,
+ * which has a complex path.
+ */
+ @Test
+ public void testDeleteChildren() throws Throwable {
+ SyncUtil.SyncRunToLocation("testDeleteChildren");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "f");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().length != 5) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 5 got " + getData().length, null));
+ } else {
+ String childStr = "((bar) f)";
+ if (!getData()[0].getExpression().equals(childStr)) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Got child " + getData()[0].getExpression() + " instead of " + childStr, null));
+ } else {
+ // Now list the children of the first element
+ fExpService.getSubExpressions(
+ getData()[0],
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ String childStr = "((((bar) f)).d)";
+ if (!getData()[0].getExpression().equals(childStr)) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Got child " + getData()[0].getExpression() + " instead of " + childStr, null));
+ } else {
+ wait.setReturnInfo(getData()[0]);
+ wait.waitFinished();
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ final IExpressionDMContext deletedChildDmc = (IExpressionDMContext)wait.getReturnInfo();
+
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // Now create more than 1000 expressions to trigger the deletion of the children
+ // that were created above
+ for (int i=0; i<1100; i++) {
+ IExpressionDMContext dmc = fExpService.createExpression(frameDmc, "a[" + i + "]");
+
+ wait.increment();
+ fExpService.getExpressionData(
+ dmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ wait.waitFinished();
+ }
+ }
+ });
+ }
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // Evaluate the expression of a child that we know is deleted to make sure
+ // the expression service can handle that
+ fExpService.getExpressionData(
+ deletedChildDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ wait.waitFinished();
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ }
+
+ /**
+ * GDB 6.7 has a bug which will cause var-update not to show
+ * the new value of 'a' if we switch the format to binary,
+ * since binary of 3 is 11 which is the same as the old value
+ * in natural format. Our expression service should work around this.
+ *
+ * int main() {
+ * int a = 11;
+ * a = 3;
+ * return 0;
+ * }
+ */
+ @Test
+ public void testUpdateGDBBug() throws Throwable {
+ SyncUtil.SyncRunToLocation("testUpdateGDBBug");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and all its children
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");
+
+ // This call will create the variable object in natural format and then change
+ // it to binary to fetch the value
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(exprDmc, IFormattedValues.BINARY_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("1011")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating binary format, expected 1011 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now step to change the value of "a" and ask for it again
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and all its children
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc2, "a");
+
+ // This call will create the variable object in natural format and then change
+ // it to binary to fetch the value
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(exprDmc, IFormattedValues.BINARY_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("11")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating binary format, expected 11 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * var-update will not show a change if eval-expression is the same
+ * in the current format. This is a problem for us because we don't
+ * know if another format changed:
+ *
+ * int main() {
+ * double a = 1.99;
+ * a = 1.11;
+ * }
+ *
+ * If a is displayed in anything but natural, both values of a are the same
+ * and we won't know it changed in the natural format.
+ *
+ * The test below is in case GDB fixes var-update to keep track of the last
+ * printed value through eval-expression. Until they do that, we do not have
+ * a problem because of our caching: where, if we change formats since the last
+ * var-update, it is impossible for us to set the format back
+ * to the one of the last -var-update, since we already have that value in our cache.
+ * So, the -var-update will show a change because of the new current format.
+ * But if GDB has eval-expression reset their stored printed_value, this test
+ * will fail and we'll know we have to fix something.
+ */
+ @Test
+ public void testUpdateIssue() throws Throwable {
+ SyncUtil.SyncRunToLocation("testUpdateIssue");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and all its children
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc, "a");
+
+ // check that we have the proper value
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(exprDmc, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("1.99")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating a, expected 1.99 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+
+ // ask for hex to set the format to hex
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(exprDmc, IFormattedValues.HEX_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("0x1")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating a, expected 0x1 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now step to change the value of "a" and ask for it again but in the natural format
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and all its children
+ IExpressionDMContext exprDmc = fExpService.createExpression(frameDmc2, "a");
+
+ // trigger the var-update in the last format (hex)
+ // then request the actual value in natural which should not be taken from the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(exprDmc, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("1.22")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, expected 1.22 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * var-update will not show a change if eval-expression is the same
+ * in the current format. This is a problem for us because we don't
+ * know if another format changed:
+ *
+ * int main() {
+ * struct {
+ * double d;
+ * } z;
+ *
+ * z.d = 1.0;
+ * z.d = 1.22;
+ * }
+ *
+ * If a is displayed in anything but natural, both values of a are the same
+ * and we won't know it changed in the natural format.
+ * This test uses a child to increase the value of the test.
+ * Also, it avoids the cache saving us since we start with the 1.0 value
+ * which is the same in natural and decimal
+ */
+ @Test
+ public void testUpdateIssue2() throws Throwable {
+ SyncUtil.SyncRunToLocation("testUpdateIssue2");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // check that we have the proper value
+ // This will cache the value 1 in the natural format cache
+ final String valueStr = "1";
+ globalExpressionCtx1 = getData()[0];
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+
+ // ask for decimal to set the format to decimal
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.DECIMAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ }
+ });
+
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now step to change the value of "a" in natural but it remains the same in decimal
+ SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // trigger the var-update in the last format (decimal)
+ // then request the actual value in natural which should not be taken from the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ if (getData().getFormattedValue().equals("1.22")) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating natural format, expected 1.22 but got " +
+ getData().getFormattedValue(), null));
+ }
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * This test verifies the state handling of a child variable object
+ * to make sure that our locking scheme works even though we must deal
+ * with an update call, internally
+ */
+ @Test
+ public void testConcurrentReadAndUpdateChild() throws Throwable {
+ SyncUtil.SyncRunToLocation("testConcurrentReadAndUpdateChild");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 1);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // Ask for one value to create the var object
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and all its children
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");
+
+ wait.increment();
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // now get the value of the child
+ final String valueStr = "01";
+ globalExpressionCtx1 = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.OCTAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now do two reads in two different formats
+ // We need to make sure that the locking properly works although we are calling
+ // the internal update method, which does affect the state of the object
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.BINARY_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final String valueStr = "1";
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.HEX_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final String valueStr = "0x1";
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * This test verifies some of the logic of dealing with out-of-scope variables.
+ * This particular scenario is that we create a parent with a child and then
+ * have them go out of scope. Then we request the child which will update the parent
+ * and mark it as out-of-scope and recreate the child. The parent is not re-created.
+ * We then ask twice for the parent which is already known to be out-of-scope and we need
+ * to make sure that the parent is re-created once and only once.
+ * We had a bug where we would enter an infinite loop in this case.
+ */
+ @Test(timeout=5000)
+ public void testConcurrentUpdateOutOfScopeChildThenParent() throws Throwable {
+ SyncUtil.SyncRunToLocation("testConcurrentUpdateOutOfScopeChildThenParent");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 2);
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ // First create the var object and its child
+ globalExpressionCtx1 = fExpService.createExpression(frameDmc, "z");
+
+ wait.increment();
+ fExpService.getSubExpressions(
+ globalExpressionCtx1,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // now get the value of the child
+ final String valueStr = "1";
+ globalExpressionCtx2 = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ SyncUtil.SyncStep(StepType.STEP_RETURN);
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_INTO, 2);
+
+ // Now step to another method to make the previous variable objects out-of-scope
+ // then first request the child and then the parent. We want to test this order
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final String valueStr = "2";
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final String valueStr = "{...}";
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+
+ // Ask a second time but in a different format, to avoid the cache
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.DECIMAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ final String valueStr = "{...}";
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(valueStr)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + valueStr, null));
+ }
+ }
+ });
+
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ //TODO although this test passes, the variable z is created twice, without being
+ // deleted in GDB. We should fix this
+ }
+
+ /**
+ * This test verifies that we properly update a pointer and its child since they can both
+ * change and be reported by var-update
+ */
+ @Test
+ public void testUpdateOfPointer() throws Throwable {
+ SyncUtil.SyncRunToLocation("testUpdateOfPointer");
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 3);
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final String firstValue = "1";
+ final String secondValue = "2";
+ final String thirdValue = "3";
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ // check that we have the proper value for both children
+ globalExpressionCtx1 = getData()[0];
+ globalExpressionCtx2 = getData()[1];
+
+ // Get the value of the first child
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(firstValue)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + firstValue, null));
+ }
+ }
+ });
+
+ // Get the value of the second child
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ wait.setReturnInfo(getData().getFormattedValue());
+ wait.waitFinished();
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ final String pointerValue = (String)wait.getReturnInfo();
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // also get the child of the pointer
+ fExpService.getSubExpressions(
+ globalExpressionCtx2,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // Get the value of the child of the pointer
+ globalExpressionCtx2 = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(firstValue)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + firstValue, null));
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ // Now step to change the values of all the children
+ stoppedEvent = SyncUtil.SyncStep(StepType.STEP_OVER, 2);
+ final IFrameDMContext frameDmc2 = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ IExpressionDMContext parentDmc = fExpService.createExpression(frameDmc2, "z");
+
+ fExpService.getSubExpressions(
+ parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 2) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 2 got " + getData().length, null));
+ } else {
+ // check that we have the proper value for both children
+ globalExpressionCtx1 = getData()[0];
+ globalExpressionCtx2 = getData()[1];
+
+ // Get the value of the first child
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx1, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(secondValue)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx1.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + secondValue, null));
+ }
+ }
+ });
+
+ // Get the value of the second child
+ wait.increment();
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (!getData().getFormattedValue().equals(pointerValue)) {
+ // The value should have changed
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of some other value", null));
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ // also get the child of the pointer
+ fExpService.getSubExpressions(
+ globalExpressionCtx2,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().length != 1) {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed getting children; expecting 1 got " + getData().length, null));
+ } else {
+ // Get the value of the child of the pointer
+ globalExpressionCtx2 = getData()[0];
+ fExpService.getFormattedExpressionValue(
+ fExpService.getFormattedValueContext(globalExpressionCtx2, IFormattedValues.NATURAL_FORMAT),
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData().getFormattedValue().equals(thirdValue)) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed evaluating " + globalExpressionCtx2.getExpression() + ", got " + getData().getFormattedValue()
+ + " instead of " + thirdValue, null));
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * This test verifies that we properly return if we can write to different expressions
+ */
+ @Test
+ public void testCanWrite() throws Throwable {
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncRunToLocation("testCanWrite");
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ final int exprCount = 5;
+ final IExpressionDMContext dmcs[] = new IExpressionDMContext[exprCount];
+ final boolean expectedValues[] = new boolean[exprCount];
+
+ int exprIndex = 0;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "a");
+ expectedValues[exprIndex] = true;
+ exprIndex++;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "b");
+ expectedValues[exprIndex] = true;
+ exprIndex++;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "c");
+ expectedValues[exprIndex] = false;
+ exprIndex++;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "d");
+ expectedValues[exprIndex] = false;
+ exprIndex++;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "d[1]");
+ expectedValues[exprIndex] = true;
+ exprIndex++;
+
+ for (int index = 0; index < exprCount; index++) {
+ final int finalIndex = index;
+ wait.increment();
+ fExpService.canWriteExpression(
+ dmcs[finalIndex],
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData() == expectedValues[finalIndex]) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed establishing proper canWrite for " + dmcs[finalIndex].getExpression() +
+ ", got " + getData() + " instead of " + expectedValues[finalIndex], null));
+ }
+
+
+ }
+ });
+ }
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * This test verifies that we properly return if we can write to an expression
+ * that is an L-Value or a Constant
+ */
+ @Ignore("Only works in versions later than GDB6.7")
+ @Test
+ public void testCanWriteLValue() throws Throwable {
+ MIStoppedEvent stoppedEvent = SyncUtil.SyncRunToLocation("testCanWrite"); // Re-use test
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ final int exprCount = 2;
+ final IExpressionDMContext dmcs[] = new IExpressionDMContext[exprCount];
+ final boolean expectedValues[] = new boolean[exprCount];
+
+ int exprIndex = 0;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "&a");
+ expectedValues[exprIndex] = false;
+ exprIndex++;
+ dmcs[exprIndex] = fExpService.createExpression(frameDmc, "1");
+ expectedValues[exprIndex] = false;
+ exprIndex++;
+
+ for (int index = 0; index < exprCount; index++) {
+ final int finalIndex = index;
+ wait.increment();
+ fExpService.canWriteExpression(
+ dmcs[finalIndex],
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else if (getData() == expectedValues[finalIndex]) {
+ wait.waitFinished();
+ } else {
+ wait.waitFinished(new Status(IStatus.ERROR, TestsPlugin.PLUGIN_ID,
+ "Failed establishing proper canWrite for " + dmcs[finalIndex].getExpression() +
+ ", got " + getData() + " instead of " + expectedValues[finalIndex], null));
+ }
+
+
+ }
+ });
+ }
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ wait.waitReset();
+ }
+
+ /**
+ * Executes a group of sub-tests.
+ *
+ * @param tests:
+ * A Map in which the key is an expression to evaluate and the
+ * value is an array of expected values, one for each of the
+ * formats supported by the Expressions service (hex, octal,
+ * binary, decimal, natural).
+ */
+ private void executeExpressionSubTests(final Map tests, IDMContext dmc)
+ throws Throwable
+ {
+
+ // Now evaluate each of the above expressions and compare the actual
+ // value against
+ // the expected value.
+ for (final String expressionToEvaluate : tests.keySet()) {
+
+ // Get an IExpressionDMContext object representing the expression to
+ // be evaluated.
+ final IExpressionDMContext exprDMC = SyncUtil.SyncCreateExpression(dmc, expressionToEvaluate);
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ // Get the list of available format IDs for this expression and for
+ // each one,
+ // get the value of the expression
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getAvailableFormats(exprDMC, new DataRequestMonitor(
+ fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+ final String[] formatIds = getData();
+
+ // Now run the current sub-test using each of
+ // the formats available for the type of
+ // the expression in the sub-test.
+
+ for (final String formatId : formatIds) {
+ // Get a FormattedValueCMContext object for
+ // the expression-formatID pair.
+ final FormattedValueDMContext valueDmc = fExpService.getFormattedValueContext(
+ exprDMC, formatId);
+
+ // Increment the number of completed
+ // requests to wait for, since we will send
+ // multiple concurrent requests
+ wait.increment();
+
+ // Evaluate the expression represented by
+ // the FormattedValueDMContext object
+ // This actually evaluates the expression.
+ fExpService.getFormattedExpressionValue(valueDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ wait.waitFinished(getStatus());
+ } else {
+
+ // Get the
+ // FormattedValueDMData
+ // object from the waiter.
+ FormattedValueDMData exprValueDMData = getData();
+
+ final String[] expectedValues = tests.get(expressionToEvaluate);
+
+ // Check the value of the
+ // expression for
+ // correctness.
+ String actualValue = exprValueDMData.getFormattedValue();
+ String expectedValue;
+
+ if (formatId.equals(IFormattedValues.HEX_FORMAT))
+ expectedValue = expectedValues[0];
+ else if (formatId.equals(IFormattedValues.OCTAL_FORMAT))
+ expectedValue = expectedValues[1];
+ else if (formatId.equals(IFormattedValues.BINARY_FORMAT))
+ expectedValue = expectedValues[2];
+ else if (formatId.equals(IFormattedValues.DECIMAL_FORMAT))
+ expectedValue = expectedValues[3];
+ else if (formatId.equals(IFormattedValues.NATURAL_FORMAT))
+ expectedValue = expectedValues[4];
+ else
+ expectedValue = "[Unrecognized format ID: " + formatId + "]";
+
+ if (actualValue.equalsIgnoreCase(expectedValue)) {
+ wait.waitFinished();
+ } else {
+ String errorMsg = "Failed to correctly evalutate '"
+ + expressionToEvaluate + "': expected '" + expectedValue
+ + "', got '" + actualValue + "'";
+ wait.waitFinished(new Status(IStatus.ERROR,
+ TestsPlugin.PLUGIN_ID, errorMsg, null));
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+ });
+ }
+ });
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+ }
+
+ private boolean addressesEqual(IExpressionDMAddress addrToTest, String addrStr, int size) {
+ IAddress addr;
+ if (addrStr.length() <= 10) {
+ addr = new Addr32(addrStr);
+ } else {
+ addr = new Addr64(addrStr);
+ }
+ return addrToTest.getAddress().equals(addr) && addrToTest.getSize() == size;
+ }
+
+ private void checkAddressData(final IExpressionDMContext dmc, String actualAddrStr, int actualAddrSize) throws Throwable {
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpService.getExpressionAddressData(dmc, new DataRequestMonitor(fExpService
+ .getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ IExpressionDMAddress addr = (IExpressionDMAddress)wait.getReturnInfo();
+
+ assertTrue("Unable to get address", addr != null);
+ assertTrue("Received wrong address of " + addr.toString() + " instead of (" +
+ actualAddrStr + ", " + actualAddrSize + ")",
+ addressesEqual(addr, actualAddrStr, actualAddrSize));
+ }
+
+ private void doTestChildren(MIStoppedEvent stoppedEvent) throws Throwable {
+
+ final IFrameDMContext frameDmc = SyncUtil.SyncGetStackFrame(stoppedEvent.getDMContext(), 0);
+
+ final IExpressionDMContext exprDMC = SyncUtil.SyncCreateExpression(frameDmc, "f");
+
+ IExpressionDMContext[] children =
+ getChildren(exprDMC, new String[] {"bar", "bar2", "a", "b", "c"});
+
+ // f.bar
+ IExpressionDMContext[] children1 =
+ getChildren(children[0], new String[] {"d", "e"});
+ // f.bar.d
+ getChildren(children1[0], new String[0]);
+ // f.bar.e
+ IExpressionDMContext[] children2 =
+ getChildren(children1[1], new String[] {"e[0]", "e[1]"});
+ // f.bar.e[0]
+ getChildren(children2[0], new String[0]);
+ // f.bar.e[1]
+ getChildren(children2[1], new String[0]);
+
+ // f.bar2
+ children1 = getChildren(children[1], new String[] {"f", "g"});
+ // f.bar2.f
+ getChildren(children1[0], new String[0]);
+ // f.bar2.g
+ children2 = getChildren(children1[1], new String[] {"g[0]", "g[1]"});
+ // f.bar2.g[0]
+ getChildren(children2[0], new String[0]);
+ // f.bar2.g[1]
+ getChildren(children2[1], new String[0]);
+
+ // f.a
+ children1 = getChildren(children[2], new String[] {"a[0]", "a[1]"});
+ // f.a[0]
+ getChildren(children1[0], new String[0]);
+ // f.a[1]
+ getChildren(children1[1], new String[0]);
+
+ // f.b
+ children1 = getChildren(children[3], new String[] {"d", "e"});
+ // f.b.d
+ getChildren(children1[0], new String[0]);
+ // f.b.e
+ children2 = getChildren(children1[1], new String[] {"e[0]", "e[1]"});
+ // f.b.e[0]
+ getChildren(children2[0], new String[0]);
+ // f.b.e[1]
+ getChildren(children2[1], new String[0]);
+
+ // f.c
+ getChildren(children[4], new String[0]);
+
+ assertTrue("ExprChangedEvent problem: expected 0, received " + getExprChangedCount(),
+ getExprChangedCount() == 0);
+ }
+
+ private IExpressionDMContext[] getChildren(
+ final IExpressionDMContext parentDmc,
+ String[] expectedValues) throws Throwable {
+
+ final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
+
+ fExpService.getExecutor().submit(new Runnable() {
+ public void run() {
+
+ fExpService.getSubExpressions(parentDmc,
+ new DataRequestMonitor(fExpService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ wait.setReturnInfo(getData());
+ }
+ wait.waitFinished(getStatus());
+ }
+ });
+ }
+ });
+
+ wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(wait.getMessage(), wait.isOK());
+
+ IExpressionDMContext[] childDmcs =
+ (IExpressionDMContext[]) wait.getReturnInfo();
+
+ String[] childExpressions = new String[childDmcs.length];
+ MIExpressionDMCAccessor[] childDmcsAccessor = new MIExpressionDMCAccessor[childDmcs.length];
+
+ // Convert to a MIExpressionDMCAccessor to be able to call getRelativeExpression
+ // Also convert to String[] to be able to use Arrays.toString()
+ for (int i = 0; i < childExpressions.length; i++) {
+ childDmcsAccessor[i] = new MIExpressionDMCAccessor(childDmcs[i]);
+ childExpressions[i] = childDmcsAccessor[i].getRelativeExpression();
+ }
+ assertTrue("Expected " + Arrays.toString(expectedValues) + " but got " + Arrays.toString(childExpressions),
+ expectedValues.length == childExpressions.length);
+
+ for (int i = 0; i < childDmcsAccessor.length; i++) {
+ assertTrue("Expected: " + expectedValues[i] + " got: " + childDmcsAccessor[i].getRelativeExpression(),
+ childDmcsAccessor[i].getRelativeExpression().equals(expectedValues[i]));
+ }
+
+ return childDmcs;
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/GDBProcessesTest.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/GDBProcessesTest.java
new file mode 100644
index 00000000000..1f8fe3aba88
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/GDBProcessesTest.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Ericsson 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:
+ * Ericsson AB - Initial implementation of Test cases
+ *******************************************************************************/
+package org.eclipse.dd.tests.gdb;
+
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.gdb.service.GDBRunControl;
+import org.eclipse.dd.gdb.service.GDBRunControl.GDBProcessData;
+import org.eclipse.dd.gdb.service.GDBRunControl.GDBThreadData;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.IMIExecutionDMContext;
+import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
+import org.eclipse.dd.tests.gdb.framework.BaseTestCase;
+import org.eclipse.dd.tests.gdb.launching.TestsPlugin;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class GDBProcessesTest extends BaseTestCase {
+ /*
+ * Path to executable
+ */
+ private static final String EXEC_PATH = "data/launch/bin/";
+ /*
+ * Name of the executable
+ */
+ private static final String EXEC_NAME = "MultiThread.exe";
+
+
+ private DsfSession fSession;
+ private DsfServicesTracker fServicesTracker;
+
+ private GDBControl fGdbCtrl;
+ private GDBRunControl fRunCtrl;
+
+ /*
+ * Create a waiter and a generic completion object. They will be used to
+ * wait for asynchronous call completion.
+ */
+ private final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
+
+ @Before
+ public void init() throws Exception {
+ fSession = getGDBLaunch().getSession();
+ fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
+ /*
+ * Get the GDBProcesses & MIRunControl service.
+ */
+ fRunCtrl = fServicesTracker.getService(GDBRunControl.class);
+ fGdbCtrl = fServicesTracker.getService(GDBControl.class);
+ }
+
+ @After
+ public void tearDown() {
+ fRunCtrl = null;
+ fServicesTracker.dispose();
+ }
+
+ @BeforeClass
+ public static void beforeClassMethod() {
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
+ EXEC_PATH + EXEC_NAME);
+ }
+
+ @Test
+ /*
+ * Get the process data for the current program. Process is executable name in case of GDB back end
+ */
+ public void getProcessData() throws InterruptedException{
+ /*
+ * Create a request monitor
+ */
+ final DataRequestMonitor rm =
+ new DataRequestMonitor(fSession.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ fWait.setReturnInfo(getData());
+ }
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ /*
+ * Ask the service to get model data for the process.
+ * There is only one process in case of GDB back end.
+ */
+ fSession.getExecutor().submit(new Runnable() {
+ public void run() {
+ fRunCtrl.getProcessData(fGdbCtrl.getGDBDMContext(), rm);
+ }
+ });
+ /*
+ * Wait for the operation to get over
+ */
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ /*
+ * Assert false if status is not OK
+ */
+ Assert.assertTrue(fWait.getMessage(), fWait.isOK());
+
+ /*
+ * Get process data
+ */
+ GDBProcessData processData = rm.getData();
+
+ if(processData == null)
+ Assert.fail("No process data is returned for Process DMC");
+ else{
+ /*
+ * Name of the process is the executable name in case of GDB back-end.
+ */
+ assertEquals("Process data should be executable name " + EXEC_NAME, EXEC_NAME, processData.getName());
+ }
+ }
+
+ /*
+ * getThreadData() for multiple threads
+ */
+ @Test
+ public void getThreadData() throws InterruptedException{
+ final DataRequestMonitor rm =
+ new DataRequestMonitor(fSession.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ fWait.setReturnInfo(getData());
+ }
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ /*
+ * Create an execution DMC
+ */
+ final IMIExecutionDMContext dmc = fRunCtrl.createMIExecutionContext(fGdbCtrl.getGDBDMContext(), 1);
+
+ /*
+ * getModelData for Execution DMC
+ */
+ fRunCtrl.getExecutor().submit(new Runnable() {
+ public void run() {
+ fRunCtrl.getThreadData(dmc, rm);
+ }
+ });
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ GDBThreadData threadData = rm.getData();
+ if(threadData == null)
+ fail("Thread data not returned for thread id = " + dmc.getThreadId());
+ else{
+ // Thread id is only a series of numbers
+ Pattern pattern = Pattern.compile("\\d*", Pattern.MULTILINE); //$NON-NLS-1$
+ Matcher matcher = pattern.matcher(threadData.getId());
+ assertTrue("Thread ID is a series of number", matcher.find());
+ // Name is blank in case of GDB back end
+ assertEquals("Thread name is blank for GDB Back end", "", threadData.getName());
+ }
+ fWait.waitReset();
+ }
+}
diff --git a/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/MIBreakpointsTest.java b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/MIBreakpointsTest.java
new file mode 100644
index 00000000000..b54c70b9c04
--- /dev/null
+++ b/plugins/org.eclipse.dd.tests.gdb/src/org/eclipse/dd/tests/gdb/MIBreakpointsTest.java
@@ -0,0 +1,2762 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Ericsson 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:
+ * Ericsson - Initial Implementation
+ *******************************************************************************/
+package org.eclipse.dd.tests.gdb;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints;
+import org.eclipse.dd.dsf.debug.service.IExpressions;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointDMData;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsAddedEvent;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsRemovedEvent;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsUpdatedEvent;
+import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
+import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.gdb.service.command.GDBControlDMContext;
+import org.eclipse.dd.mi.service.MIBreakpointDMData;
+import org.eclipse.dd.mi.service.MIBreakpoints;
+import org.eclipse.dd.mi.service.MIRunControl;
+import org.eclipse.dd.mi.service.MIBreakpoints.MIBreakpointDMContext;
+import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
+import org.eclipse.dd.mi.service.command.events.MIWatchpointScopeEvent;
+import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
+import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
+import org.eclipse.dd.tests.gdb.framework.BackgroundRunner;
+import org.eclipse.dd.tests.gdb.framework.BaseTestCase;
+import org.eclipse.dd.tests.gdb.framework.SyncUtil;
+import org.eclipse.dd.tests.gdb.launching.TestsPlugin;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/*
+ * This is the Breakpoint Service test suite.
+ *
+ * It is meant to be a regression suite to be executed automatically against
+ * the DSF nightly builds.
+ *
+ * It is also meant to be augmented with a proper test case(s) every time a
+ * feature is added or in the event (unlikely :-) that a bug is found in the
+ * Breakpoint Service.
+ *
+ * Refer to the JUnit4 documentation for an explanation of the annotations.
+ */
+
+@RunWith(BackgroundRunner.class)
+public class MIBreakpointsTest extends BaseTestCase {
+
+ // Global constants
+ public static final String PLUGIN_ID = "org.eclipse.cdt.debug.core" ; //$NON-NLS-1$
+ public static final String TEST_APPL = "data/launch/bin/BreakpointTestApp.exe"; //$NON-NLS-1$
+ public static final String SOURCE_PATH = "data/launch/src"; //$NON-NLS-1$
+
+ public static final String SOURCE_PROJECT = "MIBreakpointsTest";
+ public static final String SOURCE_FOLDER = "src";
+ public static final String SOURCE_FILE = "BreakpointTestApp.cc"; //$NON-NLS-1$
+
+ // Asynchronous Completion
+ private final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
+
+ // Services references
+ private DsfSession fSession;
+ private GDBControlDMContext fGdbControlDmc;
+ private DsfServicesTracker fServicesTracker;
+ private MIRunControl fRunControl;
+ private IBreakpoints fBreakpointService;
+
+ // Event Management
+ private static Boolean lock = true;
+ enum Events { BP_ADDED, BP_UPDATED, BP_REMOVED, BP_HIT, WP_HIT, WP_OOS }
+ final int BP_ADDED = Events.BP_ADDED.ordinal();
+ final int BP_UPDATED = Events.BP_UPDATED.ordinal();
+ final int BP_REMOVED = Events.BP_REMOVED.ordinal();
+ final int BP_HIT = Events.BP_HIT.ordinal();
+ final int WP_HIT = Events.WP_HIT.ordinal();
+ final int WP_OOS = Events.WP_OOS.ordinal();
+ private int[] fBreakpointEvents = new int[Events.values().length];
+ private boolean fBreakpointEvent;
+ private int fBreakpointEventCount;
+ private int fBreakpointRef;
+
+ // Some useful constants
+ final String BREAKPOINT_TYPE_TAG = MIBreakpoints.BREAKPOINT_TYPE;
+ final String BREAKPOINT_TAG = MIBreakpoints.BREAKPOINT;
+ final String WATCHPOINT_TAG = MIBreakpoints.WATCHPOINT;
+
+ final String FILE_NAME_TAG = MIBreakpoints.FILE_NAME;
+ final String LINE_NUMBER_TAG = MIBreakpoints.LINE_NUMBER;
+ final String FUNCTION_TAG = MIBreakpoints.FUNCTION;
+ final String ADDRESS_TAG = MIBreakpoints.ADDRESS;
+ final String CONDITION_TAG = MIBreakpoints.CONDITION;
+ final String IGNORE_COUNT_TAG = MIBreakpoints.IGNORE_COUNT;
+ final String IS_ENABLED_TAG = MIBreakpoints.IS_ENABLED;
+ final String THREAD_ID_TAG = MIBreakpointDMData.THREAD_ID;
+ final String NUMBER_TAG = MIBreakpointDMData.NUMBER;
+
+ final String EXPRESSION_TAG = MIBreakpoints.EXPRESSION;
+ final String READ_TAG = MIBreakpoints.READ;
+ final String WRITE_TAG = MIBreakpoints.WRITE;
+
+ // Target application 'special' locations
+ private final int LINE_NUMBER_1 = 20;
+ private final int LINE_NUMBER_2 = 21;
+ private final int LINE_NUMBER_3 = 27;
+ private final int LINE_NUMBER_4 = 35;
+ private final String FUNCTION = "zeroBlocks";
+ private final String SIGNED_FUNCTION = "zeroBlocks(int)";
+ private final String NO_CONDITION = "";
+
+ // NOTE: The back-end can reformat the condition. In order for the
+ // comparison to work, better specify the condition as the back-end
+ // would have it.
+ private final String CONDITION_1 = "i == 128";
+ private final String CONDITION_2 = "i == 64";
+ private final String CONDITION_3 = "j == 20";
+ private final int IGNORE_COUNT_1 = 128;
+ private final int IGNORE_COUNT_2 = 20;
+
+ private final String EXPRESSION_1 = "charBlock[20]";
+ private final String EXPRESSION_2 = "j";
+
+ // Error messages
+ final String UNKNOWN_EXECUTION_CONTEXT = "Unknown execution context";
+ final String INVALID_BREAKPOINT_LOCATION = "Invalid breakpoint location";
+ final String BREAKPOINT_INSERTION_FAILURE = "Breakpoint insertion failure";
+ final String UNKNOWN_BREAKPOINT = "Unknown breakpoint";
+
+ // ========================================================================
+ // Housekeeping stuff
+ // ========================================================================
+
+ @BeforeClass
+ public static void testSuiteInitialization() {
+ // Select the binary to run the tests against
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, TEST_APPL);
+ setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, SOURCE_PATH);
+ }
+
+ @AfterClass
+ public static void testSuiteCleanup() {
+ }
+
+ @Before
+ public void testCaseInitialization() {
+
+ // Get a reference to the breakpoint service
+ fSession = getGDBLaunch().getSession();
+ fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
+ assert(fServicesTracker != null);
+
+ GDBControl gdbControl = fServicesTracker.getService(GDBControl.class);
+ fGdbControlDmc = gdbControl.getGDBDMContext();
+ assert(fGdbControlDmc != null);
+
+ fRunControl = fServicesTracker.getService(MIRunControl.class);
+ assert(fRunControl != null);
+
+ fBreakpointService = fServicesTracker.getService(IBreakpoints.class);
+ assert(fBreakpointService != null);
+
+ // Register to breakpoint events
+ fRunControl.getSession().addServiceEventListener(MIBreakpointsTest.this, null);
+
+ clearEventCounters();
+ }
+
+ @After
+ public void testCaseCleanup() {
+
+ // Clear the references (not strictly necessary)
+ fRunControl.getSession().removeServiceEventListener(MIBreakpointsTest.this);
+ fBreakpointService = null;
+ fRunControl = null;
+ fServicesTracker = null;
+
+ clearEventCounters();
+ }
+
+ // ========================================================================
+ // Event Management Functions
+ // ========================================================================
+
+ /* -----------------------------------------------------------------------
+ * eventDispatched
+ * ------------------------------------------------------------------------
+ * Processes BreakpointHitEvent.
+ * ------------------------------------------------------------------------
+ * @param e The BreakpointEvent
+ * ------------------------------------------------------------------------
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(IBreakpointsAddedEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[BP_ADDED]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = ((MIBreakpointDMContext) e.getBreakpoints()[0]).getReference();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IBreakpointsUpdatedEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[BP_UPDATED]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = ((MIBreakpointDMContext) e.getBreakpoints()[0]).getReference();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IBreakpointsRemovedEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[BP_REMOVED]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = ((MIBreakpointDMContext) e.getBreakpoints()[0]).getReference();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(MIBreakpointHitEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[BP_HIT]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = e.getNumber();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(MIWatchpointTriggerEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[WP_HIT]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = e.getNumber();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(MIWatchpointScopeEvent e) {
+ synchronized (lock) {
+ fBreakpointEvents[WP_OOS]++;
+ fBreakpointEventCount++;
+ fBreakpointRef = e.getNumber();
+ fBreakpointEvent = true;
+ lock.notifyAll();
+ }
+ }
+
+ // Clears the counters
+ private void clearEventCounters() {
+ synchronized (lock) {
+ for (int i = 0; i < fBreakpointEvents.length; i++) {
+ fBreakpointEvents[i] = 0;
+ }
+ fBreakpointEvent = false;
+ fBreakpointEventCount = 0;
+ }
+ }
+
+ // Get the breakpoint hit count
+ private int getBreakpointEventCount(int event) {
+ int count = 0;
+ synchronized (lock) {
+ count = fBreakpointEvents[event];
+ }
+ return count;
+ }
+
+ // Suspends the thread until an event is flagged
+ // NOTE: too simple for real life but good enough for this test suite
+ private void waitForBreakpointEvent() {
+ synchronized (lock) {
+ while (!fBreakpointEvent) {
+ try {
+ lock.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ fBreakpointEvent = false;
+ }
+ }
+
+ // ========================================================================
+ // Helper Functions
+ // ========================================================================
+
+ /* ------------------------------------------------------------------------
+ * evaluateExpression
+ * ------------------------------------------------------------------------
+ * Invokes the ExpressionService to evaluate an expression. In theory,
+ * we shouldn't rely on another service to test this one but we need a
+ * way to access a variable from the test application in order verify
+ * that the memory operations (read/write) are working properly.
+ * ------------------------------------------------------------------------
+ * @param expression Expression to resolve @return Resolved expression
+ * @throws InterruptedException
+ * ------------------------------------------------------------------------
+ */
+ private BigInteger evaluateExpression(String expression) throws Throwable {
+
+ final IExpressions fExpressionService = fServicesTracker.getService(IExpressions.class);
+ assert (fExpressionService != null);
+
+ // Get a stack context (temporary - should be an MIcontainerDMC)
+ final IExpressionDMContext expressionDMC = SyncUtil.SyncCreateExpression(fGdbControlDmc, expression);
+ final FormattedValueDMContext formattedValueDMC = SyncUtil.SyncGetFormattedValue(fExpressionService,
+ expressionDMC, IFormattedValues.DECIMAL_FORMAT);
+
+ // Create the DataRequestMonitor which will store the operation result in the wait object
+ final DataRequestMonitor drm =
+ new DataRequestMonitor(fSession.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (getStatus().isOK()) {
+ fWait.setReturnInfo(getData());
+ }
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Evaluate the expression (asynchronously)
+ fWait.waitReset();
+ fSession.getExecutor().submit(new Runnable() {
+ public void run() {
+ fExpressionService.getFormattedExpressionValue(formattedValueDMC, drm);
+ }
+ });
+
+ // Wait for completion
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Return the string formatted by the back-end
+ String result = "";
+ Object returnInfo = fWait.getReturnInfo();
+ if (returnInfo instanceof FormattedValueDMData)
+ result = ((FormattedValueDMData) returnInfo).getFormattedValue();
+ return new BigInteger(result);
+ }
+
+ /* ------------------------------------------------------------------------
+ * getBreakpoints
+ * ------------------------------------------------------------------------
+ * Retrieves the installed breakpoints list
+ * ------------------------------------------------------------------------
+ * Typical usage:
+ * IBreakpointDMContext[] breakpoints = getBreakpoints(context);
+ * ------------------------------------------------------------------------
+ * @param context the execution context
+ * ------------------------------------------------------------------------
+ */
+ private IBreakpointDMContext[] getBreakpoints(final IBreakpointsTargetDMContext context) throws InterruptedException
+ {
+ // Clear the completion waiter
+ fWait.waitReset();
+
+ // Set the Request Monitor
+ final DataRequestMonitor drm =
+ new DataRequestMonitor(fBreakpointService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Issue the breakpoint request
+ fWait.waitReset();
+ fBreakpointService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fBreakpointService.getBreakpoints(context, drm);
+ }
+ });
+
+ // Wait for completion
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Return the string formatted by the back-end
+ return drm.getData();
+ }
+
+ /* ------------------------------------------------------------------------
+ * getBreakpoint
+ * ------------------------------------------------------------------------
+ * Retrieves the installed breakpoint
+ * ------------------------------------------------------------------------
+ * Typical usage:
+ * IBreakpointDMContext breakpoint = ...;
+ * IBreakpointDMData bp = getBreakpoint(breakpoint);
+ * ------------------------------------------------------------------------
+ * @param breakpoint the breakpoint to retrieve
+ * ------------------------------------------------------------------------
+ */
+ private IBreakpointDMData getBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException
+ {
+ // Clear the completion waiter
+ fWait.waitReset();
+
+ // Set the Request Monitor
+ final DataRequestMonitor drm =
+ new DataRequestMonitor(fBreakpointService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Issue the breakpoint request
+ fWait.waitReset();
+ fBreakpointService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fBreakpointService.getBreakpointDMData(breakpoint, drm);
+ }
+ });
+
+ // Wait for completion
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Return the string formatted by the back-end
+ return drm.getData();
+ }
+
+ /* ------------------------------------------------------------------------
+ * insertBreakpoint
+ * ------------------------------------------------------------------------
+ * Issues an add breakpoint request.
+ * ------------------------------------------------------------------------
+ * Typical usage:
+ * bp = insertBreakpoint(context, attributes);
+ * assertTrue(fWait.getMessage(), fWait.isOK());
+ * ------------------------------------------------------------------------
+ * @param context the execution context
+ * @param attributes the breakpoint attributes
+ * ------------------------------------------------------------------------
+ */
+ private IBreakpointDMContext insertBreakpoint(final IBreakpointsTargetDMContext context,
+ final Map attributes) throws InterruptedException
+ {
+ // Clear the completion waiter
+ fWait.waitReset();
+
+ // Set the Request Monitor
+ final DataRequestMonitor drm =
+ new DataRequestMonitor(fBreakpointService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Issue the remove breakpoint request
+ fBreakpointService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fBreakpointService.insertBreakpoint(context, attributes, drm);
+ }
+ });
+
+ // Wait for the result and return the breakpoint id
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ return drm.getData();
+ }
+
+ /* ------------------------------------------------------------------------
+ * removeBreakpoint
+ * ------------------------------------------------------------------------
+ * Issues a remove breakpoint request.
+ * ------------------------------------------------------------------------
+ * Typical usage:
+ * IBreakpointDMContext breakpoint = ...;
+ * removeBreakpoint(context, breakpoint);
+ * assertTrue(fWait.getMessage(), fWait.isOK());
+ * ------------------------------------------------------------------------
+ * @param breakpoint the breakpoint to remove
+ * ------------------------------------------------------------------------
+ */
+ private void removeBreakpoint(final IBreakpointDMContext breakpoint) throws InterruptedException
+ {
+ // Clear the completion waiter
+ fWait.waitReset();
+
+ // Set the Request Monitor
+ final RequestMonitor rm =
+ new RequestMonitor(fBreakpointService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Issue the add breakpoint request
+ fBreakpointService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fBreakpointService.removeBreakpoint(breakpoint, rm);
+ }
+ });
+
+ // Wait for the result
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ }
+
+ /* ------------------------------------------------------------------------
+ * updateBreakpoint
+ * ------------------------------------------------------------------------
+ * Issues an update breakpoint request.
+ * ------------------------------------------------------------------------
+ * Typical usage:
+ * updateBreakpoint(context, breakpoint, properties);
+ * assertTrue(fWait.getMessage(), fWait.isOK());
+ * ------------------------------------------------------------------------
+ * @param breakpoint the breakpoint to update
+ * @param delta the delta properties
+ * ------------------------------------------------------------------------
+ */
+ private void updateBreakpoint(final IBreakpointDMContext breakpoint,
+ final Map delta) throws InterruptedException
+ {
+ // Clear the completion waiter
+ fWait.waitReset();
+
+ // Set the Request Monitor
+ final RequestMonitor rm =
+ new RequestMonitor(fBreakpointService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fWait.waitFinished(getStatus());
+ }
+ };
+
+ // Issue the update breakpoint request
+ fBreakpointService.getExecutor().submit(new Runnable() {
+ public void run() {
+ fBreakpointService.updateBreakpoint(breakpoint, delta, rm);
+ }
+ });
+
+ // Wait for the result
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ }
+
+ // ========================================================================
+ // Test Cases
+ // ------------------------------------------------------------------------
+ // Templates:
+ // ------------------------------------------------------------------------
+ // @Test
+ // public void basicTest() {
+ // // First test to run
+ // assertTrue("", true);
+ // }
+ // ------------------------------------------------------------------------
+ // @Test(timeout=5000)
+ // public void timeoutTest() {
+ // // Second test to run, which will timeout if not finished on time
+ // assertTrue("", true);
+ // }
+ // ------------------------------------------------------------------------
+ // @Test(expected=FileNotFoundException.class)
+ // public void exceptionTest() throws FileNotFoundException {
+ // // Third test to run which expects an exception
+ // throw new FileNotFoundException("Just testing");
+ // }
+ // ========================================================================
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Add Breakpoint tests
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_InvalidContext
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_InvalidContext() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Perform the test
+ String expected = UNKNOWN_EXECUTION_CONTEXT;
+ insertBreakpoint(null, breakpoint);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_InvalidFileName
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_InvalidFileName() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE + "_bad");
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Perform the test
+ String expected = BREAKPOINT_INSERTION_FAILURE;
+ insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_InvalidLineNumber
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_InvalidLineNumber() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, 0);
+
+ // Perform the test
+ String expected = BREAKPOINT_INSERTION_FAILURE;
+ insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_InvalidFunctionName
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_InvalidFunctionName() throws Throwable {
+
+ // Create a function breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(FUNCTION_TAG, "invalid-function-name");
+
+ // Perform the test
+ String expected = BREAKPOINT_INSERTION_FAILURE;
+ insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_InvalidAddress
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_InvalidAddress() throws Throwable {
+
+ // Create an address breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(ADDRESS_TAG, "0x0");
+
+ // Perform the test
+ String expected = BREAKPOINT_INSERTION_FAILURE;
+ insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_LineNumber
+ // Set a breakpoint on a line number.
+ // Ensure that it is set correctly at the back-end.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_LineNumber() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)",
+ breakpoint1.isEnabled());
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_Disabled
+ // Set a disabled breakpoint on a line number.
+ // Ensure that it is set correctly at the back-end.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_Disabled() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(IS_ENABLED_TAG, false);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong state)",
+ !breakpoint1.isEnabled());
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_FunctionName
+ // Set a breakpoint on a function name.
+ // Ensure that it is set correctly at the back-end.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_FunctionName() throws Throwable {
+
+ // Create a function breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(FUNCTION_TAG, FUNCTION);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong function)",
+ breakpoint1.getFunctionName().equals(SIGNED_FUNCTION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_Condition
+ // Set a conditional breakpoint.
+ // Ensure that it is set correctly at the back-end.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_Condition() throws Throwable {
+
+ // Create a conditional line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(CONDITION_1));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_IgnoreCnt
+ // Set a breakpoint with an ignore count.
+ // Ensure that it is set correctly at the back-end.
+ // ------------------------------------------------------------------------
+ @Test
+ public void insertBreakpoint_IgnoreCnt() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(IGNORE_COUNT_TAG, IGNORE_COUNT_1);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == IGNORE_COUNT_1);
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_MultipleBreakpoints
+ // Set multiple distinct breakpoints.
+ // Ensure that the state is kosher.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_MultipleBreakpoints() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+
+ // Create a function breakpoint
+ breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(FUNCTION_TAG, FUNCTION);
+
+ // Perform the test
+ ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint2.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong function)",
+ breakpoint2.getFunctionName().equals(SIGNED_FUNCTION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint2.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint2.getIgnoreCount() == 0);
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 2 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 2);
+ MIBreakpointDMData svc_bp1 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ MIBreakpointDMData svc_bp2 = (MIBreakpointDMData) getBreakpoint(breakpoints[1]);
+
+ // The breakpoint references are not necessarily retrieved in the order the
+ // breakpoints were initially set...
+ int ref1 = breakpoint1.getNumber();
+ int ref2 = svc_bp1.getNumber();
+ if (ref1 == ref2) {
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp1.equals(breakpoint1));
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp2.equals(breakpoint2));
+ } else {
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp1.equals(breakpoint2));
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp2.equals(breakpoint1));
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // insertBreakpoint_Duplicate
+ // Set 2 identical breakpoints.
+ // For GDB, no problem...
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertBreakpoint_Duplicate() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint1.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint1.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint1.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint1.getIgnoreCount() == 0);
+
+ // Create a second line breakpoint, same attributes...
+ ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the breakpoint was correctly installed
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong file name)",
+ breakpoint2.getFileName().equals(SOURCE_FILE));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong line number)",
+ breakpoint2.getLineNumber() == LINE_NUMBER_1);
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong condition)",
+ breakpoint2.getCondition().equals(NO_CONDITION));
+ assertTrue("BreakpointService problem: breakpoint mismatch (wrong ignore count)",
+ breakpoint2.getIgnoreCount() == 0);
+
+ // Ensure the BreakpointService holds only the right breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 2 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 2);
+ MIBreakpointDMData svc_bp1 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ MIBreakpointDMData svc_bp2 = (MIBreakpointDMData) getBreakpoint(breakpoints[1]);
+
+ // The breakpoint references are not necessarily retrieved in the order the
+ // breakpoints were initially set...
+ int ref1 = breakpoint1.getNumber();
+ int ref2 = svc_bp1.getNumber();
+ if (ref1 == ref2) {
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp1.equals(breakpoint1));
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp2.equals(breakpoint2));
+ } else {
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp1.equals(breakpoint2));
+ assertTrue("BreakpointService problem: breakpoint mismatch", svc_bp2.equals(breakpoint1));
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Add Watchpoint tests
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // insertWatchpoint_Write
+ // Set a write watchpoint.
+ // Ensure that the state is kosher.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertWatchpoint_Write() throws Throwable {
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(WRITE_TAG, true);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the watchpoint was correctly installed
+ MIBreakpointDMData watchpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong expression)",
+ watchpoint1.getExpression().equals(EXPRESSION_1));
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong read state)",
+ !watchpoint1.isReadWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong write state)",
+ watchpoint1.isWriteWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)",
+ !watchpoint1.isAccessWatchpoint());
+
+ // Ensure the BreakpointService holds only the right watchpoints
+ IBreakpointDMContext[] watchpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " watchpoints(s), received "
+ + watchpoints.length, watchpoints.length == 1);
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(watchpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ watchpoint1.equals(watchpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertWatchpoint_Read
+ // Set a read watchpoint.
+ // Ensure that the state is kosher.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertWatchpoint_Read() throws Throwable {
+
+ // Create a read watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(READ_TAG, true);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the watchpoint was correctly installed
+ MIBreakpointDMData watchpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong expression)",
+ watchpoint1.getExpression().equals(EXPRESSION_1));
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong read state)",
+ watchpoint1.isReadWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong write state)",
+ !watchpoint1.isWriteWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)",
+ !watchpoint1.isAccessWatchpoint());
+
+ // Ensure the BreakpointService holds only the right watchpoints
+ IBreakpointDMContext[] watchpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " watchpoints(s), received "
+ + watchpoints.length, watchpoints.length == 1);
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(watchpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ watchpoint1.equals(watchpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // insertWatchpoint_Access
+ // Set an access watchpoint.
+ // Ensure that the state is kosher.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void insertWatchpoint_Access() throws Throwable {
+
+ // Create an access watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(READ_TAG, true);
+ watchpoint.put(WRITE_TAG, true);
+
+ // Perform the test
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure that the watchpoint was correctly installed
+ MIBreakpointDMData watchpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong expression)",
+ watchpoint1.getExpression().equals(EXPRESSION_1));
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong read state)",
+ !watchpoint1.isReadWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong write state)",
+ !watchpoint1.isWriteWatchpoint());
+ assertTrue("BreakpointService problem: watchpoint mismatch (wrong access state)",
+ watchpoint1.isAccessWatchpoint());
+
+ // Ensure the BreakpointService holds only the right watchpoints
+ IBreakpointDMContext[] watchpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " watchpoints(s), received "
+ + watchpoints.length, watchpoints.length == 1);
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(watchpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ watchpoint1.equals(watchpoint2));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Remove Breakpoint tests
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // removeBreakpoint_SimpleCase
+ // Set a breakpoint and then remove it.
+ // Ensure that the state is kosher.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void removeBreakpoint_SimpleCase() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Remove the installed breakpoint
+ removeBreakpoint(ref);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_REMOVED event(s), received "
+ + getBreakpointEventCount(BP_REMOVED), getBreakpointEventCount(BP_REMOVED) == 1);
+ clearEventCounters();
+
+ // Ensure the breakpoint was effectively removed
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 0 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // removeBreakpoint_InvalidBreakpoint
+ // Try removing a non-existing breakpoint.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void removeBreakpoint_InvalidBreakpoint() throws Throwable {
+
+ // Create an invalid breakpoint reference
+ IBreakpointDMContext invalid_ref =
+ new MIBreakpointDMContext((MIBreakpoints) fBreakpointService, new IDMContext[] { fGdbControlDmc }, 0);
+
+ // Remove the invalid breakpoint
+ String expected = UNKNOWN_BREAKPOINT;
+ removeBreakpoint(invalid_ref);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that right BreakpointEvents were received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ IBreakpointDMContext saved_ref = ref;
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Ensure the breakpoint list is OK
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+
+ // Remove the installed breakpoint
+ removeBreakpoint(ref);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_REMOVED event(s), received "
+ + getBreakpointEventCount(BP_REMOVED), getBreakpointEventCount(BP_REMOVED) == 1);
+ clearEventCounters();
+
+ // Ensure the breakpoint list is OK
+ breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 0 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 0);
+
+ // Remove the un-installed breakpoint
+ removeBreakpoint(saved_ref);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that right BreakpointEvents were received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+
+ // Ensure the breakpoint list is OK
+ breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 0 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 0);
+
+ // Re-install the breakpoint
+ ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Remove an un-installed breakpoint (again)
+ removeBreakpoint(saved_ref);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that right BreakpointEvents were received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+
+ // Ensure that the existing breakpoint is unaffected
+ breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 1 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(breakpoints[0]);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ breakpoint1.equals(breakpoint2));
+ }
+
+ // ------------------------------------------------------------------------
+ // removeBreakpoint_MixedCase
+ // Set a number of breakpoints and then remove them in disorder.
+ // Ensure that the right breakpoints are left after each iteration.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void removeBreakpoint_MixedCase() throws Throwable {
+
+ // Create a line breakpoint
+ for (int i = 0; i < 4; i++) {
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1 + i);
+ insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ int expected = i + 1;
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + expected + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == expected);
+ assertTrue("BreakpointEvent problem: expected " + expected + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == expected);
+ }
+ clearEventCounters();
+
+ // Get the list of breakpoints
+ IBreakpointDMContext[] breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + 4 + " breakpoint(s), received "
+ + breakpoints.length, breakpoints.length == 4);
+
+ // Remove the breakpoint one at a time in the following order: 1, 3, 2, 4
+ int[] indices = { 0, 2, 1, 3 };
+ int breakpoints_left = 4;
+ for (int i = 0; i < breakpoints_left; i++) {
+
+ // Remove the selected breakpoint
+ IBreakpointDMContext index = breakpoints[indices[i]];
+ removeBreakpoint(index);
+ fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+ breakpoints_left--;
+
+ // Ensure that right BreakpointEvents were received
+ int expected = i + 1;
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + expected + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == expected);
+ assertTrue("BreakpointEvent problem: expected " + expected + " BREAKPOINT_REMOVED event(s), received "
+ + getBreakpointEventCount(BP_REMOVED), getBreakpointEventCount(BP_REMOVED) == expected);
+
+ // Ensure the breakpoint was effectively removed
+ IBreakpointDMContext[] remaining_breakpoints = getBreakpoints(fGdbControlDmc);
+ assertTrue("BreakpointService problem: expected " + breakpoints_left + " breakpoint(s), received "
+ + remaining_breakpoints.length, remaining_breakpoints.length == breakpoints_left);
+ for (int j = 0; i < breakpoints_left; i++) {
+ assertTrue("BreakpointService problem: removed breakpoint still present (" + index + ")",
+ remaining_breakpoints[j] != index);
+ }
+ }
+ clearEventCounters();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Breakpoint Update tests
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_InvalidBreakpoint
+ // Updates a non-existing breakpoint.
+ // For GDB, no problem...
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_InvalidBreakpoint() throws Throwable {
+
+ // Create an invalid breakpoint reference
+ IBreakpointDMContext invalid_ref =
+ new MIBreakpointDMContext((MIBreakpoints) fBreakpointService, new IDMContext[] { fGdbControlDmc }, 0);
+
+ // Update the invalid breakpoint
+ String expected = UNKNOWN_BREAKPOINT;
+ Map properties = new HashMap();
+ properties.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ properties.put(FILE_NAME_TAG, SOURCE_FILE);
+ properties.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ updateBreakpoint(invalid_ref, properties);
+ assertFalse(fWait.getMessage(), fWait.isOK());
+ assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
+ fWait.getMessage().contains(expected));
+
+ // Ensure that no BreakpointEvent was received
+ assertTrue("BreakpointEvent problem: expected " + 0 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_AddCondition
+ // Set a breakpoint and then add a condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_AddCondition() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Modify the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, CONDITION_1);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ breakpoint2.getCondition().equals(CONDITION_1));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_RemoveCondition
+ // Set a conditional breakpoint and then remove the condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_RemoveCondition() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Remove the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, null);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ breakpoint2.getCondition().equals(""));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_ModifyCondition
+ // Set a conditional breakpoint and then modify the condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_ModifyCondition() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Update the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, CONDITION_2);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ breakpoint2.getCondition().equals(CONDITION_2));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateWatchpoint_AddCondition
+ // Set a watchpoint and then add a condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateWatchpoint_AddCondition() throws Throwable {
+
+ // Run to the point where the variable is initialized
+ SyncUtil.SyncAddBreakpoint(SOURCE_FILE + ":" + LINE_NUMBER_1, true);
+ SyncUtil.SyncResumeUntilStopped();
+ clearEventCounters();
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(WRITE_TAG, true);
+
+ // Install the watchpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Add the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, CONDITION_1);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the watchpoint
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ watchpoint2.getCondition().equals(CONDITION_1));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateWatchpoint_RemoveCondition
+ // Set a conditional watchpoint and then remove the condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateWatchpoint_RemoveCondition() throws Throwable {
+
+ // Run to the point where the variable is initialized
+ SyncUtil.SyncAddBreakpoint(SOURCE_FILE + ":" + LINE_NUMBER_1, true);
+ SyncUtil.SyncResumeUntilStopped();
+ clearEventCounters();
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(WRITE_TAG, true);
+ watchpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Install the watchpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Remove the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, null);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the watchpoint
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ watchpoint2.getCondition().equals(""));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateWatchpoint_ModifyCondition
+ // Set a conditional watchpoint and then modify the condition.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateWatchpoint_ModifyCondition() throws Throwable {
+
+ // Run to the point where the variable is initialized
+ SyncUtil.SyncAddBreakpoint(SOURCE_FILE + ":" + LINE_NUMBER_1, true);
+ SyncUtil.SyncResumeUntilStopped();
+ clearEventCounters();
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(WRITE_TAG, true);
+ watchpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Install the watchpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Update the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, CONDITION_2);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData watchpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)",
+ watchpoint2.getCondition().equals(CONDITION_2));
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_AddCount
+ // Set a breakpoint and then add an ignore count.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_AddCount() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Add a count
+ Map delta = new HashMap();
+ delta.put(IGNORE_COUNT_TAG, IGNORE_COUNT_2);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong count)",
+ breakpoint2.getIgnoreCount() == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_RemoveCount
+ // Set a conditional breakpoint and then remove the count..
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_RemoveCount() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(IGNORE_COUNT_TAG, IGNORE_COUNT_2);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Remove the count
+ Map delta = new HashMap();
+ delta.put(IGNORE_COUNT_TAG, null);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong count)",
+ breakpoint2.getIgnoreCount() == 0);
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_ModifyCount
+ // Set a conditional breakpoint and then modify the count.
+ // Ensure that the new breakpoint reflects the changes
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_ModifyCount() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(IGNORE_COUNT_TAG, IGNORE_COUNT_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Update the count
+ Map delta = new HashMap();
+ delta.put(IGNORE_COUNT_TAG, IGNORE_COUNT_2);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoint
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong count)",
+ breakpoint2.getIgnoreCount() == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_Disable
+ // Set 2 breakpoints and disable the first one.
+ // Ensure that we stop on the second one.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_Disable() throws Throwable {
+
+ // Create a first line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref1 = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Create a second line breakpoint
+ breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_2);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref2 = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 2);
+ assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 2);
+ clearEventCounters();
+
+ // Verify the state of the breakpoints
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref2);
+ assertTrue("BreakpointService problem: breakpoint state error",
+ breakpoint1.isEnabled() && breakpoint2.isEnabled());
+
+ // Disable the first breakpoint
+ Map delta = new HashMap();
+ delta.put(IS_ENABLED_TAG, false);
+ updateBreakpoint(ref1, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoints
+ breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref1);
+ breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref2);
+ assertTrue("BreakpointService problem: breakpoint state error",
+ !breakpoint1.isEnabled() && breakpoint2.isEnabled());
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the BreakpointEvent was received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint2.getNumber());
+ clearEventCounters();
+ }
+
+ // ------------------------------------------------------------------------
+ // updateBreakpoint_Enable
+ // In a loop, set 2 breakpoints and disable the first one. After hitting
+ // the second one, enable the first one again.
+ // Ensure that we stop on the first one on the next iteration.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void updateBreakpoint_Enable() throws Throwable {
+
+ // Create a first line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref1 = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Create a second line breakpoint
+ breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_2);
+
+ // Install the breakpoint
+ IBreakpointDMContext ref2 = insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 2);
+ assertTrue("BreakpointEvent problem: expected " + 2 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 2);
+ clearEventCounters();
+
+ // Verify the state of the breakpoints
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref1);
+ MIBreakpointDMData breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref2);
+ assertTrue("BreakpointService problem: breakpoint state error",
+ breakpoint1.isEnabled() && breakpoint2.isEnabled());
+
+ // Disable the first breakpoint
+ Map delta = new HashMap();
+ delta.put(IS_ENABLED_TAG, false);
+ updateBreakpoint(ref1, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoints
+ breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref1);
+ breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref2);
+ assertTrue("BreakpointService problem: breakpoint state error",
+ !breakpoint1.isEnabled() && breakpoint2.isEnabled());
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the BreakpointEvent was received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint2.getNumber());
+ clearEventCounters();
+
+ // Enable the first breakpoint
+ delta = new HashMap();
+ delta.put(IS_ENABLED_TAG, true);
+ updateBreakpoint(ref1, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Verify the state of the breakpoints
+ breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref1);
+ breakpoint2 = (MIBreakpointDMData) getBreakpoint(ref2);
+ assertTrue("BreakpointService problem: breakpoint state error",
+ breakpoint1.isEnabled() && breakpoint2.isEnabled());
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the BreakpointEvent was received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Breakpoint Hit tests
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_LineNumber
+ // Set a breakpoint on a line number.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_LineNumber() throws Throwable {
+
+ // Create a line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_Function
+ // Set a breakpoint on a function name.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_Function() throws Throwable {
+
+ // Create a function breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(FUNCTION_TAG, FUNCTION);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_Condition
+ // Set a breakpoint on a line where a variable being increased (loop).
+ // Set a condition so that the break occurs only after variable == count.
+ // Ensure that the variable was increased 'count' times.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_Condition() throws Throwable {
+
+ // Create a conditional line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(CONDITION_TAG, CONDITION_1);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == 128);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_UpdatedCondition
+ // Set a breakpoint on a line where a variable being increased (loop).
+ // Set a condition so that the break occurs only after variable == count.
+ // Ensure that the variable was increased 'count' times.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_UpdatedCondition() throws Throwable {
+
+ // Create a conditional line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Add the condition
+ Map delta = new HashMap();
+ delta.put(CONDITION_TAG, CONDITION_1);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == 128);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_Count
+ // Set a breakpoint on a line where a variable being increased (loop).
+ // Set an ignore count != 0.
+ // Ensure that the variable was increased 'ignoreCount' times.
+ // ------------------------------------------------------------------------
+ @Test
+ public void breakpointHit_Count() throws Throwable {
+
+ // Create a conditional line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+ breakpoint.put(IGNORE_COUNT_TAG, IGNORE_COUNT_2);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_UpdatedCount
+ // Set a breakpoint on a line where a variable being increased (loop).
+ // Set an ignore count != 0.
+ // Ensure that the variable was increased 'ignoreCount' times.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_UpdatedCount() throws Throwable {
+
+ // Create a conditional line breakpoint
+ Map breakpoint = new HashMap();
+ breakpoint.put(BREAKPOINT_TYPE_TAG, BREAKPOINT_TAG);
+ breakpoint.put(FILE_NAME_TAG, SOURCE_FILE);
+ breakpoint.put(LINE_NUMBER_TAG, LINE_NUMBER_1);
+
+ // Install the breakpoint
+ MIBreakpointDMContext ref = (MIBreakpointDMContext) insertBreakpoint(fGdbControlDmc, breakpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Add a count
+ Map delta = new HashMap();
+ delta.put(IGNORE_COUNT_TAG, IGNORE_COUNT_2);
+ updateBreakpoint(ref, delta);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_UPDATED event(s), received "
+ + getBreakpointEventCount(BP_UPDATED), getBreakpointEventCount(BP_UPDATED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData breakpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_HIT event(s), received "
+ + getBreakpointEventCount(BP_HIT), getBreakpointEventCount(BP_HIT) == 1);
+ assertTrue("BreakpointService problem: breakpoint mismatch",
+ fBreakpointRef == breakpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_WriteWatchpoint
+ // Set a write watchpoint and go.
+ // Ensure that the correct event is received.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_WriteWatchpoint() throws Throwable {
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(WRITE_TAG, true);
+
+ // Install the watchpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData watchpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " WATCHPOINT_HIT event(s), received "
+ + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1);
+ assertTrue("BreakpointService problem: watchpoint mismatch",
+ fBreakpointRef == watchpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_ReadWatchpoint
+ // Set a read watchpoint and go.
+ // Ensure that the correct event is received.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_ReadWatchpoint() throws Throwable {
+
+ // Create a write watchpoint
+ Map watchpoint = new HashMap();
+ watchpoint.put(BREAKPOINT_TYPE_TAG, WATCHPOINT_TAG);
+ watchpoint.put(EXPRESSION_TAG, EXPRESSION_1);
+ watchpoint.put(READ_TAG, true);
+
+ // Install the watchpoint
+ IBreakpointDMContext ref = insertBreakpoint(fGdbControlDmc, watchpoint);
+ assertTrue(fWait.getMessage(), fWait.isOK());
+
+ // Ensure that right BreakpointEvents were received
+ waitForBreakpointEvent();
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT_ADDED event(s), received "
+ + getBreakpointEventCount(BP_ADDED), getBreakpointEventCount(BP_ADDED) == 1);
+ clearEventCounters();
+
+ // Run until the breakpoint is hit and the event generated
+ SyncUtil.SyncResumeUntilStopped();
+
+ // Ensure the correct BreakpointEvent was received
+ waitForBreakpointEvent();
+ MIBreakpointDMData watchpoint1 = (MIBreakpointDMData) getBreakpoint(ref);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " BREAKPOINT event(s), received "
+ + fBreakpointEventCount, fBreakpointEventCount == 1);
+ assertTrue("BreakpointEvent problem: expected " + 1 + " WATCHPOINT_HIT event(s), received "
+ + getBreakpointEventCount(WP_HIT), getBreakpointEventCount(WP_HIT) == 1);
+ assertTrue("BreakpointService problem: watchpoint mismatch",
+ fBreakpointRef == watchpoint1.getNumber());
+ clearEventCounters();
+
+ // Verify that the condition is met
+ int i = evaluateExpression("i").intValue();
+ assertTrue("BreakpointEvent problem: breakpoint mismatch (wrong condition)", i == IGNORE_COUNT_2);
+ }
+
+ // ------------------------------------------------------------------------
+ // breakpointHit_AccessWatchpoint
+ // Set an access watchpoint and go.
+ // Ensure that the correct event is received.
+ // ------------------------------------------------------------------------
+ // @Test
+ public void breakpointHit_AccessWatchpoint() throws Throwable {
+
+ // Create an access watchpoint
+ Map