| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> |
| <HTML |
| ><HEAD |
| ><TITLE |
| >Adding A New Tool</TITLE |
| ><META |
| NAME="GENERATOR" |
| CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+ |
| "><LINK |
| REL="HOME" |
| TITLE="DejaGnu" |
| HREF="book1.html"><LINK |
| REL="UP" |
| TITLE="Extending DejaGnu" |
| HREF="c1099.html"><LINK |
| REL="PREVIOUS" |
| TITLE="Extending DejaGnu" |
| HREF="c1099.html"><LINK |
| REL="NEXT" |
| TITLE="Adding A New Target" |
| HREF="x1195.html"></HEAD |
| ><BODY |
| CLASS="SECT1" |
| BGCOLOR="#FFFFFF" |
| TEXT="#000000" |
| LINK="#0000FF" |
| VLINK="#840084" |
| ALINK="#0000FF" |
| ><DIV |
| CLASS="NAVHEADER" |
| ><TABLE |
| SUMMARY="Header navigation table" |
| WIDTH="100%" |
| BORDER="0" |
| CELLPADDING="0" |
| CELLSPACING="0" |
| ><TR |
| ><TH |
| COLSPAN="3" |
| ALIGN="center" |
| >DejaGnu: The GNU Testing Framework</TH |
| ></TR |
| ><TR |
| ><TD |
| WIDTH="10%" |
| ALIGN="left" |
| VALIGN="bottom" |
| ><A |
| HREF="c1099.html" |
| ACCESSKEY="P" |
| ><<< Previous</A |
| ></TD |
| ><TD |
| WIDTH="80%" |
| ALIGN="center" |
| VALIGN="bottom" |
| >Extending DejaGnu</TD |
| ><TD |
| WIDTH="10%" |
| ALIGN="right" |
| VALIGN="bottom" |
| ><A |
| HREF="x1195.html" |
| ACCESSKEY="N" |
| >Next >>></A |
| ></TD |
| ></TR |
| ></TABLE |
| ><HR |
| ALIGN="LEFT" |
| WIDTH="100%"></DIV |
| ><DIV |
| CLASS="SECT1" |
| ><H1 |
| CLASS="SECT1" |
| ><A |
| NAME="ADDTOOL" |
| ></A |
| >Adding A New Tool</H1 |
| ><P |
| >In general, the best way to learn how to write (code or even prose) |
| is to read something similar. This principle applies to test cases and |
| to testsuites. Unfortunately, well-established testsuites have a way |
| of developing their own conventions: as test writers become more |
| experienced with DejaGnu and with Tcl, they accumulate more utilities, |
| and take advantage of more and more features of |
| <SPAN |
| CLASS="PRODUCTNAME" |
| >Expect</SPAN |
| > and <SPAN |
| CLASS="PRODUCTNAME" |
| >Tcl</SPAN |
| > in |
| general.</P |
| ><P |
| >Inspecting such established testsuites may make the prospect of |
| creating an entirely new testsuite appear overwhelming. Nevertheless, |
| it is quite straightforward to get a new testsuite going.</P |
| ><P |
| >There is one testsuite that is guaranteed not to grow more |
| elaborate over time: both it and the tool it tests were created expressly |
| to illustrate what it takes to get started with DejaGnu. The |
| <TT |
| CLASS="FILENAME" |
| >example/</TT |
| > directory of the DejaGnu distribution |
| contains both an interactive tool called <B |
| CLASS="COMMAND" |
| >calc</B |
| >, and a |
| testsuite for it. Reading this testsuite, and experimenting with it, |
| is a good way to supplement the information in this section. (Thanks to |
| Robert Lupton for creating calc and its testsuite---and also the first |
| version of this section of the manual!)</P |
| ><P |
| >To help orient you further in this task, here is an outline of the |
| steps to begin building a testsuite for a program example.</P |
| ><P |
| ></P |
| ><UL |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Create or select a directory to contain your new |
| collection of tests. Change into that directory (shown here as |
| <TT |
| CLASS="FILENAME" |
| >testsuite</TT |
| >):</P |
| ><P |
| >Create a <TT |
| CLASS="FILENAME" |
| >configure.in</TT |
| > file in this directory, |
| to control configuration-dependent choices for your tests. So far as |
| DejaGnu is concerned, the important thing is to set a value for the |
| variable <SPAN |
| CLASS="SYMBOL" |
| >target_abbrev</SPAN |
| >; this value is the link to the |
| init file you will write soon. (For simplicity, we assume the |
| environment is Unix, and use <I |
| CLASS="EMPHASIS" |
| >unix</I |
| > as the |
| value.)</P |
| ><P |
| >What else is needed in <TT |
| CLASS="FILENAME" |
| >configure.in</TT |
| > depends on |
| the requirements of your tool, your intended test environments, and which |
| configure system you use. This example is a minimal configure.in for use |
| with <SPAN |
| CLASS="PRODUCTNAME" |
| >GNU Autoconf</SPAN |
| >. </P |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Create <TT |
| CLASS="FILENAME" |
| >Makefile.in</TT |
| > (if you are using |
| Autoconf), or <TT |
| CLASS="FILENAME" |
| >Makefile.am</TT |
| >(if you are using |
| Automake), the source file used by configure to build your |
| <TT |
| CLASS="FILENAME" |
| >Makefile</TT |
| >. If you are using GNU Automake.just add the |
| keyword <I |
| CLASS="EMPHASIS" |
| >dejagnu</I |
| > to the |
| <I |
| CLASS="EMPHASIS" |
| >AUTOMAKE_OPTIONS</I |
| > variable in your |
| <TT |
| CLASS="FILENAME" |
| >Makefile.am</TT |
| > file. This will add all the Makefile |
| support needed to run DejaGnu, and support the <A |
| HREF="c401.html#MAKECHECK" |
| >Make Check</A |
| > |
| target.</P |
| ><P |
| >You also need to include two targets important to DejaGnu: |
| <I |
| CLASS="EMPHASIS" |
| >check</I |
| >, to run the tests, and |
| <I |
| CLASS="EMPHASIS" |
| >site.exp</I |
| >, to set up the Tcl copies of |
| configuration-dependent values. This is called the <A |
| HREF="c848.html#LOCAL" |
| >Local Config File</A |
| > |
| The check target must run the <B |
| CLASS="COMMAND" |
| >runtest</B |
| > program to |
| execute the tests.</P |
| ><P |
| >The <TT |
| CLASS="FILENAME" |
| >site.exp</TT |
| > target should usually set up |
| (among other things) the $tool variable for the name of your program. If |
| the local site.exp file is setup correctly, it is possible to execute the |
| tests by merely typing <B |
| CLASS="COMMAND" |
| >runtest</B |
| > on the command |
| line.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="AEN1145" |
| ></A |
| ><P |
| ><B |
| >Example 1. Sample Makefile.in Fragment</B |
| ></P |
| ><TABLE |
| BORDER="0" |
| BGCOLOR="#E0E0E0" |
| WIDTH="90%" |
| ><TR |
| ><TD |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > # Look for a local version of DejaGnu, otherwise use one in the path |
| RUNTEST = `if test -f $(top_srcdir)/../dejagnu/runtest; then \ |
| echo $(top_srcdir) ../dejagnu/runtest; \ |
| else \ |
| echo runtest; \ |
| fi` |
| |
| # The flags to pass to runtest |
| RUNTESTFLAGS = |
| |
| # Execute the tests |
| check: site.exp all |
| $(RUNTEST) $(RUNTESTFLAGS) \ |
| --tool <SPAN |
| CLASS="SYMBOL" |
| >${example}</SPAN |
| > --srcdir $(srcdir) |
| |
| # Make the local config file |
| site.exp: ./config.status Makefile |
| @echo "Making a new config file..." |
| -@rm -f ./tmp? |
| @touch site.exp |
| |
| -@mv site.exp site.bak |
| @echo "## these variables are automatically\ |
| generated by make ##" > ./tmp0 |
| @echo "# Do not edit here. If you wish to\ |
| override these values" >> ./tmp0 |
| @echo "# add them to the last section" >> ./tmp0 |
| @echo "set host_os ${host_os}" >> ./tmp0 |
| @echo "set host_alias ${host_alias}" >> ./tmp0 |
| @echo "set host_cpu ${host_cpu}" >> ./tmp0 |
| @echo "set host_vendor ${host_vendor}" >> ./tmp0 |
| @echo "set target_os ${target_os}" >> ./tmp0 |
| @echo "set target_alias ${target_alias}" >> ./tmp0 |
| @echo "set target_cpu ${target_cpu}" >> ./tmp0 |
| @echo "set target_vendor ${target_vendor}" >> ./tmp0 |
| @echo "set host_triplet ${host_canonical}" >> ./tmp0 |
| @echo "set target_triplet ${target_canonical}">>./tmp0 |
| @echo "set tool binutils" >> ./tmp0 |
| @echo "set srcdir ${srcdir}" >> ./tmp0 |
| @echo "set objdir `pwd`" >> ./tmp0 |
| @echo "set <SPAN |
| CLASS="SYMBOL" |
| >${examplename}</SPAN |
| > <SPAN |
| CLASS="SYMBOL" |
| >${example}</SPAN |
| >" >> ./tmp0 |
| @echo "## All variables above are generated by\ |
| configure. Do Not Edit ##" >> ./tmp0 |
| @cat ./tmp0 > site.exp |
| @sed < site.bak \ |
| -e '1,/^## All variables above are.*##/ d' \ |
| >> site.exp |
| -@rm -f ./tmp? |
| |
| </PRE |
| ></TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Create a directory (in <TT |
| CLASS="FILENAME" |
| >testsuite</TT |
| >) |
| called <TT |
| CLASS="FILENAME" |
| >config</TT |
| >. Make a <I |
| CLASS="EMPHASIS" |
| >Tool Init |
| File</I |
| > in this directory. Its name must start with the |
| <SPAN |
| CLASS="SYMBOL" |
| >target_abbrev</SPAN |
| > value, or be named |
| <TT |
| CLASS="FILENAME" |
| >default.exp</TT |
| > so call it |
| <TT |
| CLASS="FILENAME" |
| >config/unix.exp</TT |
| > for our Unix based example. This |
| is the file that contains the target-dependent procedures. |
| Fortunately, on Unix, most of them do not have to do very much in |
| order for <B |
| CLASS="COMMAND" |
| >runtest</B |
| > to run.</P |
| ><P |
| >If the program being tested is not interactive, you can get |
| away with this minimal <TT |
| CLASS="FILENAME" |
| >unix.exp</TT |
| > to begin |
| with:</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="AEN1162" |
| ></A |
| ><P |
| ><B |
| >Example 2. Simple Batch Program Tool Init File</B |
| ></P |
| ><TABLE |
| BORDER="0" |
| BGCOLOR="#E0E0E0" |
| WIDTH="90%" |
| ><TR |
| ><TD |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > proc foo_exit {} {} |
| proc foo_version {} {} |
| |
| </PRE |
| ></TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ><P |
| >If the program being tested is interactive, however, you might |
| as well define a <I |
| CLASS="EMPHASIS" |
| >start</I |
| > routine and invoke it by |
| using an init file like this:</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="AEN1167" |
| ></A |
| ><P |
| ><B |
| >Example 3. Simple Interactive Program Tool Init File</B |
| ></P |
| ><TABLE |
| BORDER="0" |
| BGCOLOR="#E0E0E0" |
| WIDTH="90%" |
| ><TR |
| ><TD |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > |
| proc foo_exit {} {} |
| proc foo_version {} {} |
| |
| proc foo_start {} { |
| global ${examplename} |
| spawn ${examplename} |
| expect { |
| -re "" {} |
| } |
| } |
| |
| # Start the program running we want to test |
| foo_start |
| |
| </PRE |
| ></TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Create a directory whose name begins with your tool's |
| name, to contain tests. For example, if your tool's name is |
| <I |
| CLASS="EMPHASIS" |
| >gcc</I |
| >, then the directories all need to start with |
| <I |
| CLASS="EMPHASIS" |
| >"gcc."</I |
| >.</P |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Create a sample test file. Its name must end with |
| <TT |
| CLASS="FILENAME" |
| >.exp</TT |
| >. You can use |
| <TT |
| CLASS="FILENAME" |
| >first-try.exp</TT |
| >. To begin with, just write there a |
| line of Tcl code to issue a message.</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="AEN1178" |
| ></A |
| ><P |
| ><B |
| >Example 4. Testing A New Tool Config</B |
| ></P |
| ><TABLE |
| BORDER="0" |
| BGCOLOR="#E0E0E0" |
| WIDTH="90%" |
| ><TR |
| ><TD |
| ><PRE |
| CLASS="PROGRAMLISTING" |
| > send_user "Testing: one, two...\n" |
| |
| </PRE |
| ></TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Back in the <TT |
| CLASS="FILENAME" |
| >testsuite</TT |
| > (top |
| level) directory, run <B |
| CLASS="COMMAND" |
| >configure</B |
| >. Typically you do |
| this while in the build directory. You may have to specify more of a |
| path, if a suitable configure is not available in your execution |
| path.</P |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >e now ready to triumphantly type <B |
| CLASS="COMMAND" |
| >make |
| check</B |
| > or <B |
| CLASS="COMMAND" |
| >runtest</B |
| >. You should see |
| something like this:</P |
| ><DIV |
| CLASS="EXAMPLE" |
| ><A |
| NAME="AEN1189" |
| ></A |
| ><P |
| ><B |
| >Example 5. Example Test Case Run</B |
| ></P |
| ><TABLE |
| BORDER="0" |
| BGCOLOR="#E0E0E0" |
| WIDTH="90%" |
| ><TR |
| ><TD |
| ><PRE |
| CLASS="SCREEN" |
| > Test Run By rhl on Fri Jan 29 16:25:44 EST 1993 |
| |
| === example tests === |
| |
| Running ./example.0/first-try.exp ... |
| Testing: one, two... |
| |
| === example Summary === |
| |
| </PRE |
| ></TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ><P |
| >There is no output in the summary, because so far the example |
| does not call any of the procedures that establish a test |
| outcome.</P |
| ></LI |
| ><LI |
| STYLE="list-style-type: disc" |
| ><P |
| >Write some real tests. For an interactive tool, you |
| should probably write a real exit routine in fairly short order. In |
| any case, you should also write a real version routine |
| soon. </P |
| ></LI |
| ></UL |
| ></DIV |
| ><DIV |
| CLASS="NAVFOOTER" |
| ><HR |
| ALIGN="LEFT" |
| WIDTH="100%"><TABLE |
| SUMMARY="Footer navigation table" |
| WIDTH="100%" |
| BORDER="0" |
| CELLPADDING="0" |
| CELLSPACING="0" |
| ><TR |
| ><TD |
| WIDTH="33%" |
| ALIGN="left" |
| VALIGN="top" |
| ><A |
| HREF="c1099.html" |
| ACCESSKEY="P" |
| ><<< Previous</A |
| ></TD |
| ><TD |
| WIDTH="34%" |
| ALIGN="center" |
| VALIGN="top" |
| ><A |
| HREF="book1.html" |
| ACCESSKEY="H" |
| >Home</A |
| ></TD |
| ><TD |
| WIDTH="33%" |
| ALIGN="right" |
| VALIGN="top" |
| ><A |
| HREF="x1195.html" |
| ACCESSKEY="N" |
| >Next >>></A |
| ></TD |
| ></TR |
| ><TR |
| ><TD |
| WIDTH="33%" |
| ALIGN="left" |
| VALIGN="top" |
| >Extending DejaGnu</TD |
| ><TD |
| WIDTH="34%" |
| ALIGN="center" |
| VALIGN="top" |
| ><A |
| HREF="c1099.html" |
| ACCESSKEY="U" |
| >Up</A |
| ></TD |
| ><TD |
| WIDTH="33%" |
| ALIGN="right" |
| VALIGN="top" |
| >Adding A New Target</TD |
| ></TR |
| ></TABLE |
| ></DIV |
| ></BODY |
| ></HTML |
| > |