Go to single file .html
[fw/sdcc] / doc / test_suite_spec.tex
1 % ``Test Suite Design''
2 % $Id$
3 \documentclass{widearticle}
4 \usepackage{url}
5
6 \begin{document}
7 \title{Proposed Test Suite Design}
8 \author{Michael Hope (michaelh@juju.net.nz)}
9 \date{\today}
10 \maketitle
11
12 \begin{abstract}
13 This article describes the goals, requirements, and suggested
14 specification for a test suite for the output of the Small Device C
15 Compiler (sdcc).  Also included is a short list of existing works.
16 \end{abstract}
17
18 \section{Goals}
19 The main goals of a test suite for sdcc are
20 \begin{enumerate}
21     \item To allow developers to run regression tests to check that
22 core changes do not break any of the many ports.
23     \item To verify the core.
24     \item To allow developers to verify individual ports.
25     \item To allow developers to test port changes.
26 \end{enumerate}
27
28 This design only covers the generated code.  It does not cover a
29 test/unit test framework for the sdcc application itself, which may be
30 useful.
31
32 One side effect of (1) is that it requires that the individual ports
33 pass the tests originally.  This may be too hard.  See the section on
34 Exceptions below.
35
36 \section{Requirements}
37 \subsection{Coverage}
38 The suite is intended to cover language features only.  Hardware
39 specific libraries are explicitly not covered.
40
41 \subsection{Permutations}
42 The ports often generate different code for handling different types
43 (Byte, Word, DWord, and the signed forms).  Meta information
44 could be used to permute the different test cases across the different
45 types.
46
47 \subsection{Exceptions}
48 The different ports are all at different levels of development.  Test
49 cases must be able to be disabled on a per port basis.  Permutations
50 also must be able to be disabled on a port level for unsupported
51 cases.  Disabling, as opposed to enabling, on a per port basis seems
52 more maintainable.
53
54 \subsection{Running}
55 The tests must be able to run unaided.  The test suite must run on all
56 platforms that sdcc runs on.  A good minimum may be a subset of Unix
57 command set and common tools, provided by default on a Unix host and
58 provided through cygwin on a Windows host.
59
60 The tests suits should be able to be sub-divided, so that the failing
61 or interesting tests may be run separately.
62
63 \subsection{Artifcats}
64 The test code within the test cases should not generate artifacts.  An
65 artifact occurs when the test code itself interferes with the test and
66 generates an erroneous result.
67
68 \subsection{Emulators}
69 sdcc is a cross compiling compiler.  As such, an emulator is needed
70 for each port to run the tests.
71
72 \section{Existing works}
73 \subsection{DejaGnu}
74 DejaGnu is a toolkit written in Expect designed to test an interactive
75 program.  It provides a way of specifying an interface to the program,
76 and given that interface a way of stimulating the program and
77 interpreting the results.  It was originally written by Cygnus
78 Solutions for running against development boards.  I believe the gcc
79 test suite is written against DejaGnu, perhaps partly to test the
80 Cygnus ports of gcc on target systems.
81
82 \subsection{gcc test suite}
83 I don't know much about the gcc test suite.  It was recently removed
84 from the gcc distribution due to issues with copyright ownership.  The
85 code I saw from older distributions seemed more concerned with
86 esoteric features of the language.
87
88 \subsection{xUnit}
89 The xUnit family, in particular JUnit, is a library of in test
90 assertions, test wrappers, and test suite wrappers designed mainly for
91 unit testing.  PENDING: More.
92
93 \subsection{CoreLinux++ Assertion framework}
94 While not a test suite system, the assertion framework is an
95 interesting model for the types of assertions that could be used.
96 They include pre-condition, post-condition, invariants, conditional
97 assertions, unconditional assertions, and methods for checking
98 conditions.
99
100 \section{Specification}
101 This specification borrows from the JUnit style of unit testing and
102 the CoreLinux++ style of assertions.  The emphasis is on
103 maintainability and ease of writing the test cases.
104
105 \subsection{Terms}
106 PENDING: Align these terms with the rest of the world.
107
108 \begin{itemize}
109     \item An \emph{assertion} is a statement of how things should be.
110 PENDING: Better description, an example.
111     \item A \emph{test point} is the smallest unit of a test suite,
112 and consists of a single assertion that passes if the test passes.
113     \item A \emph{test case} is a set of test points that test a
114 certain feature.
115     \item A \emph{test suite} is a set of test cases that test a
116 certain set of features.
117 \end{itemize}
118
119 \subsection{Test cases}
120 Test cases shall be contained in their own C file, along with the meta
121 data on the test.  Test cases shall be contained within functions
122 whose names start with 'test' and which are descriptive of the test
123 case.  Any function that starts with 'test' will be automatically run in
124 the test suite.
125
126 To make the automatic code generation easier, the C code shall have
127 this format
128 \begin{itemize}
129     \item Test functions shall start with 'test' to allow
130 automatic detection.
131     \item Test functions shall follow the K\&R intention style for ease
132 of detection.  i.e. the function name shall start in the left
133 column on a new line below the return specification.
134 \end{itemize}
135
136 \subsection{Assertions}
137 All assertions shall log the line number, function name, and test
138 case file when they fail.  Most assertions can have a more descriptive
139 message attached to them.  Assertions will be implemented through
140 macros to get at the line information.  This may cause trouble with
141 artifacts.
142
143 The following definitions use C++ style default arguments where
144 optional messages may be inserted.  All assertions use double opening
145 and closing brackets in the macros to allow them to be compiled out
146 without any side effects.  While this is not required for a test
147 suite, they are there in case any of this code is incorporated into the
148 main product.
149
150 Borrowing from JUnit, the assertions shall include
151 \begin{itemize}
152     \item FAIL((String msg = ``Failed'')).  Used when execution should
153 not get here.
154     \item ASSERT((Boolean cond, String msg = ``Assertion failed'').
155 Fails if cond is false.  Parent to REQUIRE and ENSURE.
156 \end{itemize}
157
158 JUnit also includes may sub-cases of ASSERT, such as assertNotNull,
159 assertEquals, and assertSame.
160
161 CoreLinux++ includes the extra assertions
162 \begin{itemize}
163     \item REQUIRE((Boolean cond, String msg = ``Precondition
164 failed'').  Checks preconditions.
165     \item ENSURE((Boolean cond, String msg = ``Postcondition
166 failed'').  Checks post conditions.
167     \item CHECK((Boolean cond, String msg = ``Check failed'')).  Used
168 to call a function and to check that the return value is as expected.
169 i.e.  CHECK((fread(in, buf, 10) != -1)).  Very similar to ASSERT, but
170 the function still gets called in a release build.
171     \item FORALL and EXISTS.  Used to check conditions within part of
172 the code.  For example, can be used to check that a list is still
173 sorted inside each loop of a sort routine.
174 \end{itemize}
175
176 All of FAIL, ASSERT, REQUIRE, ENSURE, and CHECK shall be available.
177
178 \subsection{Meta data}
179 PENDING:  It's not really meta data.
180
181 Meta data includes permutation information, exception information, and
182 permutation exceptions.
183
184 Meta data shall be global to the file.  Meta data names consist of the
185 lower case alphanumerics.  Test case specific meta data (fields) shall
186 be stored in a comment block at the start of the file.  This is only
187 due to style.  
188
189 A field definition shall consist of
190 \begin{itemize}
191     \item The field name
192     \item A colon.
193     \item A comma separated list of values.
194 \end{itemize}
195
196 The values shall be stripped of leading and trailing white space.
197
198 Permutation exceptions are by port only.  Exceptions to a field are
199 specified by a modified field definition.  An exception definition
200 consists of 
201
202 \begin{itemize}
203     \item The field name.
204     \item An opening square bracket.
205     \item A comma separated list of ports the exception applies for.
206     \item A closing square bracket.
207     \item A colon.
208     \item The values to use for this field for these ports.
209 \end{itemize}
210
211 An instance of the test case shall be generated for each permutation
212 of the test case specific meta data fields.
213
214 The runtime meta fields are
215 \begin{itemize}
216     \item port - The port this test is running on.
217     \item testcase - The name of this test case.
218     \item function - The name of the current function.
219 \end{itemize}
220
221 Most of the runtime fields are not very usable.  They are there for
222 completeness.
223
224 Meta fields may be accessed inside the test case by enclosing them in
225 curly brackets.  The curly brackets will be interpreted anywhere
226 inside the test case, including inside quoted strings.  Field names that
227 are not recognised will be passed through including the brackets.
228 Note that it is therefore impossible to use some strings within the
229 test case.
230
231 Test case function names should include the permuted fields in the
232 name to reduce name collisions.
233
234 \subsection{An example}
235 I don't know how to do pre-formatted text in \LaTeX.  Sigh.
236
237 The following code generates a simple increment test for all combinations of the
238 storage classes and all combinations of the data sizes.  This is a
239 bad example as the optimiser will often remove most of this code.
240
241 \tt{
242 /** Test for increment. 
243  
244     type: char, int, long
245
246     Z80 port does not fully support longs (4 byte)
247
248     type[z80]: char, int   
249
250
251     class: ``'', register, static
252 */
253
254 static void
255
256 testInc\{class\}\{types\}(void)
257
258 \{
259
260     \{class\} \{type\} i = 0;
261     
262     i = i + 1;
263
264     ASSERT((i == 1));
265
266 \}
267
268 }
269
270 \end{document}