<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Domenik Pavletic</string-name>
          <email>pavletic@itemis.com</email>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Syed Aoun Raza</string-name>
          <email>aoun.raza@gmail.com</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Kolja Dummann</string-name>
          <email>dummann@itemis.com</email>
          <xref ref-type="aff" rid="aff1">1</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Kim Haßlbauer</string-name>
          <email>kim.hasslbauer@gmail.com</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Stuttgart</institution>
          ,
          <country country="DE">Germany</country>
        </aff>
        <aff id="aff1">
          <label>1</label>
          <institution>itemis AG</institution>
          ,
          <addr-line>Stuttgart</addr-line>
          ,
          <country country="DE">Germany</country>
        </aff>
      </contrib-group>
      <fpage>34</fpage>
      <lpage>40</lpage>
      <abstract>
        <p>-Extensible languages allow incremental extensions of a host language with domain specific abstractions. Debuggers for such languages must be extensible as well to support debugging of different language extensions at their corresponding abstraction level. As such languages evolve over time, it is essential to constantly verify their debugging behavior. For this purpose, a General Purpose Language (GPL) can be used, however this increases the complexity and decreases the readability of tests. To reduce continuous verification effort, in this paper, we introduce DeTeL, an extensible Domain-Specific Language (DSL) for testing extensible language debuggers. Index Terms-Formal languages, Software debugging, Software testing.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>I. INTRODUCTION</title>
      <p>
        Software development faces the challenge that GPLs do
not provide the appropriate abstractions for domain-specific
problems. Traditionally there are two approaches to overcome
this issue. One is to use frameworks that provide
domainspecific abstractions expressed with a GPL. This approach has
very limited support for static semantics, e. g., no support for
modifying constraints or type system. The second approach
is to use external DSLs for expressing solutions to domain
problems. This approach has some other drawbacks: these
DSLs are not inherently extensible. Extensible languages solve
these problems. Instead of having a single monolithic DSL,
extensible languages enable modular and incremental extensions
of a host language with domain specific abstractions [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ].
      </p>
      <p>To make debugging extensible languages useful to the
language user, it is not enough to debug programs after
extensions have been translated back to the host language
(using an existing debugger for the base language). A debugger
for an extensible language must be extensible as well, to
support debugging of modular language extensions at the same
abstraction level (extension-level). Minimally, this means users
can step through constructs provided by the extension and see
watch expressions (e. g., variables) related to the extensions.</p>
      <p>Because language extensions can be based on other
extensions and languages evolve over time, it is essential to
constantly test if debugger behavior matches the expected
behavior. To test debugging behavior, a GPL can be used,
however this raises the same issues discussed above. We
therefore propose in this paper DeTeL (Debugger Testing
Language), an extensible DSL for testing debuggers.</p>
      <p>
        II. MBEDDR
mbeddr [
        <xref ref-type="bibr" rid="ref2">2</xref>
        ] is an extensible version of C that can be
extended with modular, domain-specific extensions. It is built
on top of JetBrains Meta Programming System (MPS) [
        <xref ref-type="bibr" rid="ref3">3</xref>
        ] and
ships with a set of language extensions dedicated to embedded
software development. mbeddr includes an extensible C99
implementation. Further, it also includes a set of predefined
language extensions on top of C. These extensions include
state machines, components and physical units.
      </p>
      <p>In MPS, language implementations are separated into
aspects. The major aspects are Structure, Type System,
Constraints, Generator and Editor. However, for
building debugging support, the Editor aspect is irrelevant.</p>
    </sec>
    <sec id="sec-2">
      <title>III. LANGUAGE EXTENSION FOR UNIT TESTING</title>
      <p>To give an idea of building language and debugger
extensions, we first build MUnit, a language for writing unit
tests, and a corresponding debugger extension. Later, we will
describe how to test this debugger extension with a DSL.</p>
      <sec id="sec-2-1">
        <title>A. Structure</title>
        <p>Fig. 1 shows the language structure: AssertStatement is
derived from Statement and can therefore be used where
Statements are expected. It contains an Expression for
the condition. Testcase holds a StatementList that
contains the Statements that make up the test. Further, to
have the same scope as Function, Testcase implements
IModuleContent. ExecuteTestExpression contains a list
of TestcaseRef, which refer to Testcases to be executed.</p>
        <p>AssertStatement requires a constraint and a type system
rule. It restricts the usages only inside Testcases, meaning
an AssertStatement can only be used in a Testcase:
parentNode.ancestor&lt;concept = Testcase, +&gt;.isNotNull</p>
        <p>It also restricts the type of its child expr (condition) to
BooleanType, so only valid conditions can be entered:
check(typeof(assertStatement.expr) :&lt;=: &lt;BooleanType()&gt;);
ExecuteTestExpression returns the number of failed unit
tests, hence we specify Int32tType as its type (see rule
below). Later, the same type is used in the generator.
check(typeof(executeTestExpression) :==: &lt;Int32tType()&gt;);</p>
      </sec>
      <sec id="sec-2-2">
        <title>C. Generator</title>
        <p>The MUnit generator consists of many different
transformation rules, which translate code written with the language
directly to mbeddr C. Listing 1 shows on the left hand side
an example program, written with mbeddr C and MUnit. The
right hand side shows the C program generated from it. While
regular mbeddr C code is not colored, the boxes indicate how
Abstract Syntax Tree (AST) nodes from the left are translated
to C code on the right.
Listing 1. Example mbeddr program using the unit test language on the left
and the C code that has been generated from it on the right</p>
        <p>
          IV. MBEDDR DEBUGGER FRAMEWORK
mbeddr comes with a debugger, which allows users to
debug their mbeddr code on the abstraction levels of the used
languages. For that, each language contributes a debugger
extension, which is built with a framework also provided by
mbeddr [
          <xref ref-type="bibr" rid="ref4">4</xref>
          ]. Those extensions are always language-specific in
contrast to domain-specific debuggers (e. g., the moldable
debugger [
          <xref ref-type="bibr" rid="ref5">5</xref>
          ]), which provide application-specific debug actions
and views on the program state. Hence, debugging support is
implemented specifically for the language by lifting the call
stack/program state from the base-level to the extension-level
(see Fig. 2) and stepping/breakpoints vice versa.
The debugger framework can be separated into two different
parts: First, a DSL and a set of interfaces (shown in Fig. 3)
for specifying the debugging semantics of language concepts.
Second, a runtime for executing those specifications and thus
achieving the mapping described in Fig. 2.
        </p>
        <p>
          In this section, we provide an overview of the specification
part (see Fig. 3) that is required for understanding how
the debugger extension for MUnit is built. While this paper
concentrates on testing debuggers for extensible languages, we
have published another paper [
          <xref ref-type="bibr" rid="ref4">4</xref>
          ] describing details about the
debugger framework and its implementation with MPS.
        </p>
      </sec>
      <sec id="sec-2-3">
        <title>A. Breakpoints</title>
      </sec>
      <sec id="sec-2-4">
        <title>B. Watches</title>
        <p>Breakables are concepts (e. g., Statements) on which we
can set breakpoints to suspend the program execution.</p>
        <p>WatchProviders are translated to low-level watches
(e. g., Argument) or represent watches on the
extensionlevel. They are declared inside WatchProviderScopes (e. g.,
StatementList), which is a nestable context.</p>
      </sec>
      <sec id="sec-2-5">
        <title>C. Stepping</title>
        <p>Steppables define where program execution must suspend
next, after the user steps over an instance of Steppable (e. g.,
Statement). If a Steppable contains a StepIntoable (e. g.,
FunctionCall), then the Steppable also supports step into.
StepIntoables are concepts that branch execution into a
SteppableComposite (e. g., Function).</p>
        <p>
          All stepping is implemented by setting low-level
breakpoints and then resuming execution until one of these
breakpoints is hit (approach is based on [
          <xref ref-type="bibr" rid="ref6">6</xref>
          ]). The particular stepping
behavior is realized through stepping-related concepts by
utilizing DebugStrategies.
        </p>
      </sec>
      <sec id="sec-2-6">
        <title>D. Call Stack</title>
        <p>StackFrameContributors are concepts that have callable
semantics on the extension-level or are translated to low-level
callables (e. g., Functions). While the latter do not contribute
any StackFrames to the high level call stack, the former
contribute at least one StackFrame.</p>
        <p>To enable breakpoints on AssertStatements, an
implementation of the Breakable interface is required.
AssertStatement is derived from Statement that already
implements this interface, thus breakpoints are already supported.</p>
        <p>Since ExecuteTestExpression’s stack frame is not
shown in the high-level call stack, none of its watches are
mapped. In contrast, stack frames for Testcases are visible
thus we need to consider its watches. In case of Testcase,
the LocalVariableDeclaration _f has no corresponding
representation on the extension-level, and is therefore not
shown (specified in listing below).</p>
        <p>The mbeddr debugger framework uses a pessimistic
approach for lifting watches: those that should not be shown in
the UI are marked as hidden. Otherwise, the debugger shows
the low-level watch (in this case the C local variable _f) with
its respective value.
hide local variable with identifier "_f";</p>
        <p>AssertStatement is a Statement, which already provides
step over behavior. However, to be able to step into the
condition we overwrite Statement’s step into behavior:
break on nodes to step-into: this.expr;</p>
        <p>break on nodes searches in condition for instances of
StepIntoable and contributes their step into strategies.</p>
        <p>ExecuteTestExpression implements StepIntoable to
allow step into the referenced Testcases. A minimal
implementation puts a breakpoint in each Testcase:
foreach testRef in this.tests {</p>
        <p>break on node: testRef.test.body.statements.first;
}</p>
      </sec>
      <sec id="sec-2-7">
        <title>D. Call Stack</title>
        <p>Testcase and ExecuteTestExpression are translated to
base-level callables and therefore implement
StackFrameContributor. They contribute StackFrames, each is linked
to a base-level stack frame and states whether it is visible in
the extension-level call stack or not.</p>
        <p>The implementation of ExecuteTestExpression links the
low-level stack frame to the respective instance (see listing
below). Further, it hides the frame from the high-level call stack,
since ExecuteTestExpression has no callable semantics.
contribute frame mapping for frames.select(name=getName());</p>
        <p>Similarly the mapping for Testcase also requires linking
the low-level stack frame to the respective instance. However,
it declares to show the stack frame in the high-level call stack:
String frameName = "test_" + this.name;
contribute frame mapping for frames.select(name=frameName);
Further, we provide the name of the actual Testcase, which
is represented in the call stack view: Consider Listing 1, where
we would show the name forTest instead of test_forTest.</p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>VI. REQUIREMENTS</title>
      <p>The debugger testing DSL must allow us to verify at
least four aspects: call stack, program state, breakpoints and
stepping. To cover these requirements in DeTeL we delineate
in this section requirements. While we consider some of those
requirements as required (R), others are either context (CS)
or mbeddr specific (MS).</p>
      <sec id="sec-3-1">
        <title>A. Required</title>
        <p>R1 Debug state validation: Changes in generators can
modify names of generated procedures or variables and this
way, e. g., invalidate program state lifting in the debugger. For
being able to identify those problems, we need a mechanism to
validate the call stack, and for each of its frames the program
state and the location where execution is suspended. For the
call stack, a specification of expected stack frames with their
respective names is required. In terms of program state, we
need to verify the names of watches and their respective
values, which can either be simple or complex. Further, a
location specifies where program execution is expected to
suspend and tests can be written for a specific platform.</p>
        <p>R2 Debug control: Similarly as in R1, generator changes
also affect the stepping behavior. Consider changing the
FunctionCall generator to inline the body of called functions
instead of calling them. This change would require
modifications in the implementation of step into as well. For being
able to identify those problems, we need the ability to execute
stepping commands (in, over and out) and specify locations
where to break.</p>
        <p>R3 Language integration: The DSL must integrate with
language extensions. This integration is required for specifying
in programs under test locations where to break (see R2) and
for validating where program execution is suspended (see R1).</p>
      </sec>
      <sec id="sec-3-2">
        <title>B. Context Specific</title>
        <p>CS1 Reusability: For writing debugger tests in an efficient
way, we expect from DeTeL the ability to provide reuse: (1)
test data, (2) validation rules and (3) the structure of tests. The
first covers the ability to have one mbeddr program as test data
for multiple test cases. The second refers to single definition
and multiple usage of validation rules among different test
cases. Finally, the third refers to extending test cases and
having the possibility to specialize them.</p>
        <p>
          CS2 Extensibility: Languages should provide support for
contributing new validation rules thus achieving extensibility.
Those new rules can be used for testing further debugger
functionality not covered by DeTeL (e. g., mbeddr’s upcoming
support for multi-level debugging [
          <xref ref-type="bibr" rid="ref7">7</xref>
          ]) or for writing tests more
efficiently.
        </p>
        <p>CS3 Automated test execution: For fast feedback about
newly introduced debugger bugs, we require the ability to
integrate our tests into an automatic execution environment
(e. g., an IDE or a build server).</p>
        <p>An extending CallStack inherits all StackFrames from the
extended CallStack in the form of StackFrameExtensions,
with the possibility of specializing inherited properties (CS1),
and can declare additional StackFrames.</p>
      </sec>
      <sec id="sec-3-3">
        <title>C. Mbeddr Specific</title>
        <p>MS1 Exchangeable debugger backends: mbeddr targets
the embedded domain where platform vendors require
different compilers and debuggers. Hence, we require the ability
to run our tests against different debugger backends and on
different platforms.</p>
      </sec>
    </sec>
    <sec id="sec-4">
      <title>VII. DEBUGGER TESTING DSL</title>
      <p>
        DeTeL is open-source and is shipped as part of mbeddr [
        <xref ref-type="bibr" rid="ref8">8</xref>
        ].
      </p>
      <p>It is integrated in MPS and interacts with the mbeddr debugger
API. DeTeL is currently tightly coupled to mbeddr, however
it could interact with a generic debugger API and could be
implemented independent of MPS. This section describes the
structure of DeTeL and the implementation of requirements
discussed in Section VI. The language syntax is not
documented, but can easily be derived by looking at its editor
definitions in MPS.
A. DebuggerTest IStackFrame has three parts, each with two different</p>
      <p>
        Fig. 4 shows the structure of DebuggerTest, which is implementations: a name (IName), a location where program
a module that contains IDebuggerTestContents, currently execution should suspend (ILocation) and visible watches
implemented by DebuggerTestcase and CallStack (de- (IWatches).
scribed later). This interface facilitates extensibility inside IName implementations: SpecificName verifies the
specDebuggerTest (CS2). Further, DebuggerTest refers to a ified name matches the actual and AnyName ignores it
comBinary, which is a concept from mbeddr representing the pletely. ILocation implementations: AnyLocation that does
compiled mbeddr program under test (R3), the imports of not perform any validation and ProgramMarkerRef that refers
IDebuggerTestContents from other DebuggerTests (CS1) via ProgramMarker to a specific location in a program under
and an IDebuggerBackend that specifies the debugger back- test (R3). These markers just annotate nodes in the AST and
end (CS2, MS1). The later is implemented by GdbBackend have no influence on code generation. IWatch
implementaand allows this way to run debugger tests with the GNU tions: AnyWatches performs no validations and WatchList
Debugger (GDB) [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ]. contains a list of Watches, each specifies a name/value
(IValue) pair. The value can be either PrimitiveValue
(e. g., numbers) or ComplexValue (e. g., arrays).
      </p>
      <p>MPS already contains the language mps.lang.test for
writing type system and editor tests. This allows (1) automatic
execution of tests on the command-line and (2) visualization of
test results in a table view inside MPS. All of that functionality
is built for future implementations of ITestcase - an interface
from mps.lang.test. By implementing this interface in
DebuggerTest (our container for DebuggerTestcases), we
benefit from available features (CS3).</p>
      <sec id="sec-4-1">
        <title>C. DebuggerTestcase</title>
        <p>Fig. 6 shows the structure of DebuggerTestcase:
it can extend other DebuggerTestcases (CS1), has a
name, and can be abstract. Further it contains the
following parts: SuspendConfig, SteppingConfig and
ValidationConfig. Concrete DebuggerTestcases require
a SuspendConfig and a ValidationConfig (can be
inherited), while an abstract DebuggerTestcase requires none
of these.
location (R2). This interface is implemented by StepInto,
1 call stack csInMainFunction {
StepOver, and StepOut (each performs the respective com- 2 0:main
mand n times). 3 location: onReturnInMain
4 watches: {argc, argv}</p>
        <p>ValidationConfig contains a list of IValidations 5 }
(CS2, R1), implemented by CallStack, CallStackRef and 67 call stack csInTestcase extends csInMainFunction {
OnPlatform. CallStackRef refers to a CallStack that can- 8 1:forTest
not be modified. Finally, OnPlatform specifies a Platform 109 wlaotccahteiso:n:{&lt;saunmy,&gt;nums}
(Mac, Unix or Windows) and contains validations, which are 11 0:main
only executed on the specific platform (R1). 12 }</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>VIII. WRITING DEBUGGER TESTS</title>
      <p>In this section, we describe an application scenario where
we apply DeTeL to test the debugger extension of MUnit.</p>
      <p>Before writing debugger tests, we first take the program
using MUnit from Listing 1 and annotate it in Listing 2
with ProgramMarkers. Those markers are later used by
DebuggerTestcases for specification and verification of code
locations where program execution should suspend.
1 int32 main(int32 argc, string[ ] argv) {
2 [return test[forTest];] onReturnInMain
3 }
4 int32 add(int32 a, int32 b) {
5 [return a+b;] inAdd
6 }
7 testcase forTest {
8 [int32 sum = 0;] onSumDeclaration
9 [assert: sum == 0;] firstAssert
10 [int32[ ] nums = {1, 2, 3};] onArrayDecl
11 for(int32_t i=0;i&lt;3;i++) { sum += nums[i]; }
12 [assert: sum == 6;] secondAssert
13 }</p>
      <p>Listing 2. Annotated program</p>
      <p>Next, in the Listing 3 a stub of DebuggerTest UnitTesting
is created that will later contain all DebuggerTestcases
described in this section. UnitTesting tests against the Binary
UnitTestingBinary, which is compiled from Listing 2.
Additionally, it instructs the debugger runtime to execute tests with
the GdbBackend.
1 DebuggerTest UnitTesting
2
3 }
tests binary: UnitTestingBinary {
uses debugger: gdb</p>
      <sec id="sec-5-1">
        <title>Listing 3. DebuggerTest stub</title>
        <sec id="sec-5-1-1">
          <title>A. Step Into ExecuteTestExpression</title>
        </sec>
      </sec>
      <sec id="sec-5-2">
        <title>Listing 4. CallStack declarations</title>
        <p>Listing 5 contains the DebuggerTestcase
stepIntoTestcase, which uses the CallStack csInTestcase to verify step
into for instances of ExecuteTestExpression. As a first
step, program execution is suspended at onReturnInMain, next,
a single StepInto is performed before the actual call stack
is validated against a custom CallStack derived from
csInTestcase. This custom declaration specializes the StackFrame
forTest i. e., program execution is expected to suspend at
onSumDeclaration.
1 testcase stepIntoTestcase {
2 suspend at:
3 onReturnInMain
4 then perform:
5 step into 1 times
6 finally validate:
7 call stack csOnSumDeclInTestcase extends csInTestcase {
8 1:forTest
9 overwrite location: onSumDeclaration
10 watches: fsum, numsg
11 0:main
12 }
13 }</p>
        <p>Listing 5. Step into ExecuteTestExpression</p>
        <sec id="sec-5-2-1">
          <title>B. Step into/over AssertStatement</title>
          <p>After verifying step into for ExecuteTestExpression in
the previous section, we now test step into and over for
AssertStatement. Both stepping commands have the same
result when performed at firstAssert, hence common test
behavior is extracted into the abstract DebuggerTestcase
stepOnAssert as shown in Listing 6: (1) program execution
suspends at firstAssert, (2) a custom CallStack verifies
program execution suspended in forTest on onArrayDecl and
(3) the Watch num holds the PrimitiveValue zero.</p>
          <p>For testing step into on instances of Execute- 1 abstract testcase stepOnAssert {
TestExpression, in the Listing 4, we create a CallStack 2 suspend at:
that specifies the stack organization after performing step 34 finaflilrystvAaslsiedratte:
into on onReturnInMain. To reuse information and minimize 5 call stack csOnArrayDeclInTestcase extends csInTestcase {
redundancy in subsequent DebuggerTestcases, two separate 76 1:foorvTeerswtrite location: onArrayDecl
CallStacks are created: First, csInMainFunction contains 8 overwrite watches: {sum=0,nums}
a single StackFrame that expects (1) program execution 109 } 0:main
to suspend at onReturnInMain and (2) two Watches (argc 11 }
and argv). Second, csInTestcase extends csInMainFunction Listing 6. Abstract DebuggerTestcase
by adding an additional StackFrame forTest on top of
the StackFrameExtension main (colored in gray). This
StackFrame specifies two Watches (sum and nums) and no
specific location (AnyLocation).</p>
          <p>The DebuggerTestcase stepIntoAssert extending
stepOnAssert performs a StepInto command and
stepOver</p>
          <p>Assert performs a StepOver:
1 testcase stepIntoAssert extends stepOnAssert {
2 then perform:
3 step into 1 times
4 }
5 testcase stepOverAssert extends stepOnAssert {
6 then perform:
7 step over 1 times
8 }</p>
        </sec>
      </sec>
      <sec id="sec-5-3">
        <title>Listing 7. Extending DebuggerTestcases</title>
        <sec id="sec-5-3-1">
          <title>C. Step on last Statement in Testcase</title>
          <p>The last testing scenario verifies that stepping on the last
Statement (secondAssert) inside a Testcase suspends
execution on the ExecuteTestExpression (onReturnInMain).
Again, we create an abstract DebuggerTestcase
steppingOnLastStmnt that suspends execution on secondAssert and
verifies that the actual call stack has the same structure as
CallStack csInMainFunction:
1 abstract testcase steppingOnLastStmnt {
2 suspend at:
3 secondAssert
4 finally validate:
5 call stack csInMainFunction
6 }</p>
          <p>Listing 8. Assumptions after suspending program execution in main
Next, separate DebuggerTestcases are created, each for
step over, into and out, which extend steppingOnLastStmnt
and specify only the respective ISteppingCommand:
1 testcase stepOverLastStmnt extends steppingOnLastStmnt {
2 then perform:
3 step over 1 times
4 }
5
6 testcase stepIntoLastStmnt extends steppingOnLastStmnt {
7 then perform:
8 step into 1 times
9 }
10
11 testcase stepOutFromLastStmnt extends steppingOnLastStmnt {
12 then perform:
13 step out 1 times
14 }</p>
          <p>Listing 9. Test stepping commands on last Statement in Testcase
In each DebuggerTestcase from the listing above
execution suspends on the same Statement (OnReturnInMain),
although different stepping commands are performed.
Remember, since secondAssert does not contain any children of type
StepIntoable (e. g., FunctionCall), performing a step into
on the Statement has the same effect as a step over.</p>
        </sec>
      </sec>
    </sec>
    <sec id="sec-6">
      <title>IX. EXECUTING DEBUGGER TESTS</title>
      <p>Our test cases from the previous section are generated
to plain Java code and can be executed in MPS with an
action from the context menu. This functionality is
obtained by implementing ITestcase in DebuggerTest (see
Section VII-A). By executing this action, test results are
visualized in a table view, provided by MPS: for each
DebuggerTestcase, the result (success or fail) is indicated
with a colored bubble and a text field shows the process output.</p>
      <p>As indicated by a green bubble on the left side of Fig. 7, all
of our previously written DebuggerTestcases pass. We show
in the next section how language evolution will invalidate the
debugger definition and this way cause all of our tests to fail.</p>
      <p>The previous sections have shown how to build a language
extension for mbeddr in MPS, define a debugger for this
extension and use DeTeL to test its debugging behavior. This
section demonstrates how DeTeL is used to identify invalid
definitions in debugger extensions after evolving the language.</p>
      <sec id="sec-6-1">
        <title>A. Evolving MUnit</title>
        <p>In this section we modify the MUnit generator to
demonstrate how this affects the debugger. Currently, the generator
reduces a Testcase to a Function: its name is prefixed with
test_, followed by the Testcase name (see Listing 1). We
now change this generator, so the Function name is prefixed
with testcase_, instead of test_. The listing below shows how
our example program from Listing 1 is now generated to C.
int32_t main(int32_t argc,
char *(argv[])) {
return blockexpr_2() ;
}</p>
        <p>|
int32_t blockexpr_2(void) {
int32_t _f = 0;
_f += testcase_forTest();
return _f;
int32_t testcase_forTest() {
int32_t _f = 0;
int32_t sum = 0;
if(!( sum == 0 )) { _f++; }
int32_t[] nums = {1, 2, 3};
for(int32_t i=0;i&lt;3;i++){</p>
        <p>sum += nums[i];
}
if(!( sum == 6 )) { _f++; }
return _f;
} }
Listing 10. C code that has been generated with the modified Testcase
generator for the example program from Listing 1</p>
        <p>Because of our generator modification, Testcases are
now generated to Functions with a different identifier as
before. However, we have not updated the debugger extension,
therefore, the call stack construction for all Testcases fails
and this way all of our DebuggerTests fail as well (see
Fig. 8). Although those debugger tests fail, they are still valid,
since they are written on the abstraction level of the languages,
not the generator. The next section shows how we update the
debugger extension to solve the call stack construction.</p>
      </sec>
      <sec id="sec-6-2">
        <title>B. Updating the Debugger Extension</title>
        <p>The MUnit debugger extension tries to lift for each
Testcase a stack frame whose name is prefixed with test_,
followed by the name of the respective Testcase (see
Section V-D). However, due to our generator modification,
this frame is not present and therefore the whole call stack
construction fails with an error. To solve this problem, we
update the name used for matching the stack frame name:
String frameName = "testcase_" + this.name;
contribute frame mapping for frames.select(name=frameName);</p>
        <p>Other aspects, such as stepping, breakpoints or watches are
not affected by the generator modification and hence do not
need to be changed. Therefore, after fixing the call stack lifting
for Testcase our debugger tests pass again.</p>
      </sec>
    </sec>
    <sec id="sec-7">
      <title>XI. RELATED WORK</title>
      <p>
        Wu et al. describe a unit testing framework for DSLs [
        <xref ref-type="bibr" rid="ref10">10</xref>
        ]
with focus on testing the semantics of the language. However,
from our perspective, it is necessary to have testing DSLs for
all aspects of the language definition, e. g., editor (concrete
syntax), type system, scoping, transformation rules, and finally
the debugger.1 mbeddr contains tests for the editor, type
system, scoping and transformation rules, our work contributes
the language for testing the debugger aspect.
      </p>
      <p>
        The Low Level Virtual Machine (LLVM) project [
        <xref ref-type="bibr" rid="ref11">11</xref>
        ] comes
with a C debugger named Low Level Debugger (LLDB). Test
cases for this debugger are written in Python and the unit test
framework of Python. While those tests verify the command
line interface and the scripting Application Programming
Interface (API) of the debugger, they also test other functionality,
such as using the help menu or changing the debugger settings.
Further, some of the LLDB tests verify the debugging behavior
on different platforms, such as Darwin or Linux. In contrast,
we only concentrate on testing the debugging behavior, but
also support writing tests for specific platforms. Our approach
for testing the debugging behavior is derived from the LLDB
project: write a program in the source-language (mbeddr),
compile it to an executable and debug it through test cases,
which verify the debugging behavior.
      </p>
      <p>
        The GDB debugger takes a similar approach as the LLDB:
tests cover different aspects of the debugger functionality and
are written in a scripting language [
        <xref ref-type="bibr" rid="ref9">9</xref>
        ]. Contrarily, to our
approach of testing debugging for one extensible language, the
GDB project tests debugging behavior for all of its supported
languages, such as C, C++, Java, Ada etc. Further, those tests
run on different platforms and target configurations. Our work
supports writing tests against different platforms, but does not
allow users to change the target configuration via the DSL.
      </p>
    </sec>
    <sec id="sec-8">
      <title>XII. SUMMARY AND FUTURE WORK</title>
      <p>The mbeddr extensible language comes with an extensible
debugger. To test this debugger, we have introduced in this
paper a generic and extensible testing DSL. The language is
implemented in MPS with focus on mbeddr, but the underlying
1Specific language workbenches might require testing of additional aspects
approach is applicable for testing any imperative language
debugger. Further, we have shown in this paper (1) the
implementation of a language extension, (2) how debugging
support is build for it and (3) how the debugger is tested with
use of our DSL. The language is designed for extensibility,
so others can contribute their own context-specific validation
rules. In addition, we concentrated on reuse, so test data, test
structures and validation rules can be shared among tests.</p>
      <p>
        In the future, we plan to investigate ways for integrating
the debugger specification DSL with the DSL for testing the
debugger extension. From this integration we expect to (1)
gain advances in validating debugger test cases and (2) the
possibility to automatically generate test cases from formal
debugger specifications (based on work from [
        <xref ref-type="bibr" rid="ref12">12</xref>
        ], [
        <xref ref-type="bibr" rid="ref13">13</xref>
        ] and
[
        <xref ref-type="bibr" rid="ref14">14</xref>
        ]). In addition, we will continue researching on languages
for testing non-functional aspects, such as testing the
performance of stepping commands and lifting of program state.
      </p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>M.</given-names>
            <surname>Voelter</surname>
          </string-name>
          , “
          <article-title>Language and IDE Development, Modularization and Composition with MPS,” in Generative and Transformational Techniques in Software Engineering, ser</article-title>
          .
          <source>Lecture Notes in Computer Science</source>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>M.</given-names>
            <surname>Voelter</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Ratiu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>B.</given-names>
            <surname>Schaetz</surname>
          </string-name>
          , and
          <string-name>
            <given-names>B.</given-names>
            <surname>Kolb</surname>
          </string-name>
          , “
          <article-title>Mbeddr: An extensible c-based programming language and ide for embedded systems</article-title>
          ,”
          <source>in Proceedings of the 3rd Annual Conference on Systems, Programming</source>
          , and
          <article-title>Applications: Software for Humanity, ser</article-title>
          .
          <source>SPLASH '12</source>
          . New York, NY, USA: ACM,
          <year>2012</year>
          , pp.
          <fpage>121</fpage>
          -
          <lpage>140</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3] JetBrains, “
          <article-title>Meta Programming System</article-title>
          ,”
          <year>2015</year>
          . [Online]. Available: http://www.jetbrains.com/mps
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>D.</given-names>
            <surname>Pavletic</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Voelter</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S. A.</given-names>
            <surname>Raza</surname>
          </string-name>
          ,
          <string-name>
            <given-names>B.</given-names>
            <surname>Kolb</surname>
          </string-name>
          , and T. Kehrer, “
          <article-title>Extensible debugger framework for extensible languages</article-title>
          ,
          <source>” in Reliable Software Technologies - Ada-Europe 2015 - 20th Ada-Europe International Conference on Reliable Software Technologies</source>
          , Madrid Spain, June 22-26,
          <year>2015</year>
          , Proceedings, ser. Lecture Notes in Computer Science, J. A.
          <string-name>
            <surname>de la Puente</surname>
          </string-name>
          and T. Vardanega, Eds., vol.
          <volume>9111</volume>
          . Springer,
          <year>2015</year>
          , pp.
          <fpage>33</fpage>
          -
          <lpage>49</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>A.</given-names>
            <surname>Chis</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Gîrba</surname>
          </string-name>
          , and
          <string-name>
            <given-names>O.</given-names>
            <surname>Nierstrasz</surname>
          </string-name>
          , “
          <article-title>The moldable debugger: A framework for developing domain-specific debuggers,” in Software Language Engineering -</article-title>
          7th International Conference, SLE 2014, Västerås, Sweden,
          <source>September 15-16</source>
          ,
          <year>2014</year>
          . Proceedings,
          <year>2014</year>
          , pp.
          <fpage>102</fpage>
          -
          <lpage>121</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>H.</given-names>
            <surname>Wu</surname>
          </string-name>
          , “
          <article-title>Grammar-driven Generation of Domain-specific Language Testing Tools,” in 20th Annual ACM Special Interest Group on Programming Languages (SIGPLAN) Conference on Object-oriented Programming, Systems</article-title>
          , Languages, and
          <string-name>
            <surname>Applications</surname>
          </string-name>
          . San Diego, CA, USA: ACM,
          <year>2005</year>
          , pp.
          <fpage>210</fpage>
          -
          <lpage>211</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>D.</given-names>
            <surname>Pavletic</surname>
          </string-name>
          and
          <string-name>
            <given-names>S. A.</given-names>
            <surname>Raza</surname>
          </string-name>
          ,
          <article-title>“Multi-Level Debugging for Extensible Languages,” Softwaretechnik-Trends</article-title>
          , vol.
          <volume>35</volume>
          , no.
          <issue>1</issue>
          ,
          <year>2015</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>B.</given-names>
            <surname>Kolb</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Voelter</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Ratiu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Pavletic</surname>
          </string-name>
          ,
          <string-name>
            <given-names>Z.</given-names>
            <surname>Molotnikov</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Dummann</surname>
          </string-name>
          ,
          <string-name>
            <given-names>N.</given-names>
            <surname>Stotz</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Lisson</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Eberle</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Szabo</surname>
          </string-name>
          ,
          <string-name>
            <given-names>A.</given-names>
            <surname>Shatalin</surname>
          </string-name>
          ,
          <string-name>
            <given-names>K.</given-names>
            <surname>Miyamoto</surname>
          </string-name>
          , and S. Kaufmann, “mbeddr.core - An
          <string-name>
            <surname>extensible</surname>
            <given-names>C</given-names>
          </string-name>
          ,” https://github.com/ mbeddr/mbeddr.core, GitHub repository,
          <year>2015</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>Free</given-names>
            <surname>Software</surname>
          </string-name>
          <string-name>
            <surname>Foundation</surname>
          </string-name>
          , “The GNU Project Debugger,”
          <year>2015</year>
          . [Online]. Available: https://www.gnu.org/software/gdb/
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>H.</given-names>
            <surname>Wu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J. G.</given-names>
            <surname>Gray</surname>
          </string-name>
          , and
          <string-name>
            <given-names>M.</given-names>
            <surname>Mernik</surname>
          </string-name>
          , “
          <article-title>Unit testing for domain-specific languages,” in Domain-Specific Languages</article-title>
          ,
          <source>IFIP TC 2 Working Conference, DSL 2009</source>
          , Oxford, UK,
          <source>July 15-17</source>
          ,
          <year>2009</year>
          , Proceedings, ser. Lecture Notes in Computer Science, W. M. Taha, Ed., vol.
          <volume>5658</volume>
          . Springer,
          <year>2009</year>
          , pp.
          <fpage>125</fpage>
          -
          <lpage>147</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref11">
        <mixed-citation>
          [11]
          <string-name>
            <given-names>LLVM</given-names>
            <surname>Compiler Infrastructure</surname>
          </string-name>
          , “The LLDB Debugger,”
          <year>2015</year>
          . [Online]. Available: http://lldb.llvm.org
        </mixed-citation>
      </ref>
      <ref id="ref12">
        <mixed-citation>
          [12]
          <string-name>
            <given-names>H.</given-names>
            <surname>Wu</surname>
          </string-name>
          and
          <string-name>
            <given-names>J.</given-names>
            <surname>Gray</surname>
          </string-name>
          , “
          <article-title>Automated generation of testing tools for domainspecific languages</article-title>
          .” in ASE,
          <string-name>
            <given-names>D. F.</given-names>
            <surname>Redmiles</surname>
          </string-name>
          ,
          <string-name>
            <given-names>T.</given-names>
            <surname>Ellman</surname>
          </string-name>
          ,
          <article-title>and</article-title>
          <string-name>
            <surname>A</surname>
          </string-name>
          . Zisman, Eds. ACM,
          <year>2005</year>
          , pp.
          <fpage>436</fpage>
          -
          <lpage>439</lpage>
          .
        </mixed-citation>
      </ref>
      <ref id="ref13">
        <mixed-citation>
          [13]
          <string-name>
            <given-names>P. R.</given-names>
            <surname>Henriques</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M. J. V.</given-names>
            <surname>Pereira</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Mernik</surname>
          </string-name>
          ,
          <string-name>
            <given-names>M.</given-names>
            <surname>Lenic</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Gray</surname>
          </string-name>
          , and H. Wu, “
          <article-title>Automatic generation of language-based tools using the LISA system,” Software, IEE Proceedings -</article-title>
          , vol.
          <volume>152</volume>
          , no.
          <issue>2</issue>
          , pp.
          <fpage>54</fpage>
          -
          <lpage>69</lpage>
          ,
          <year>2005</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref14">
        <mixed-citation>
          [14]
          <string-name>
            <given-names>H.</given-names>
            <surname>Wu</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Gray</surname>
          </string-name>
          , and
          <string-name>
            <given-names>M.</given-names>
            <surname>Mernik</surname>
          </string-name>
          , “
          <article-title>Grammar-driven generation of domain-specific language debuggers</article-title>
          .
          <source>” Software: Practice and Experience</source>
          , vol.
          <volume>38</volume>
          , no.
          <issue>10</issue>
          , pp.
          <fpage>1073</fpage>
          -
          <lpage>1103</lpage>
          ,
          <year>2008</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>