ANN: Ahven 1.8

20 views
Skip to first unread message

Tero Koskinen

unread,
Jun 2, 2010, 12:24:13 PM6/2/10
to
Hi,

I released Ahven 1.8 today. It can be downloaded from
http://sourceforge.net/projects/ahven/files/

Ahven is a unit testing library for Ada 95
programming language.

Version 1.8 is a bugfix release with following changes:

* Fix for double free when mixing dynamically
allocated test cases with statically allocated
test suites.

* Support for dynamic libraries was dropped.
It was too complex (for me) to maintain
Makefile/GPR-file logic which would work
in the same way on Fedora, Debian, OpenBSD,
and Windows.

If some packagers (like Debian people) want
to enable support they can apply Makefiles
and GNAT project files from Ahven 1.7 on
top of 1.8.

* Support for Janus/Ada 3.1.1d was dropped.
Janus/Ada 3.1.2beta or newer is required.

Janus/Ada 3.1.1d support required too many
work-arounds, so to make my life easier
I decided to drop the support.

If someone needs this, I welcome patches. :)

* TAP 1.3 test result format was dropped.
Version 1.2 is supported.

The release has been tested with following compilers:
* FSF GCC/GNAT 4.3.5 and 4.4.4
* GNAT GPL 2009
* Janus/Ada 3.1.2beta
* Irvine ICCAda

The code can be compiled either as plain Ada 95 or
as Ada 2005 code.

--
Tero Koskinen - http://iki.fi/tero.koskinen/

Stephen Leake

unread,
Jun 3, 2010, 8:08:12 AM6/3/10
to
Tero Koskinen <tero.k...@iki.fi> writes:

> Hi,
>
> I released Ahven 1.8 today. It can be downloaded from
> http://sourceforge.net/projects/ahven/files/
>
> Ahven is a unit testing library for Ada 95
> programming language.

Is this actually restricted to Ada 95? What prevents it from being used
with Ada 2005?

How does it compare to AUnit?

> The code can be compiled either as plain Ada 95 or
> as Ada 2005 code.

Ah; much better. Perhaps you should fix the intro statement to just say
"Ada"; no one will be surprised if it doesn't work with an Ada 83
compiler.

--
-- Stephe

Dan

unread,
Jun 3, 2010, 3:36:08 PM6/3/10
to
On Jun 3, 5:08 am, Stephen Leake <stephen_le...@stephe-leake.org>
wrote:

> How does it compare to AUnit?

I am able to use Ahven in a table-driven manner, as shown below.
But I don't see a way to use AUnit similarly (replacing the Ahven-
specific code below the line of dashes).


with text_io;
procedure p1 is begin text_io.put_line("in p1"); end;

with text_io;
procedure p2 is begin text_io.put_line("in p2"); end;

with text_io;
procedure p3 is begin text_io.put_line("in p3"); end;


with text_io;
procedure q1 is begin text_io.put_line("in q1"); end;

with text_io;
procedure q2 is begin text_io.put_line("in q2"); end;

with text_io;
procedure q3 is begin text_io.put_line("in q3"); end;


package test_suite is

type proc_access is access procedure;
type rec is record
proc: proc_access;
name: access string;
end record;
type suite_type is array(natural range <>) of rec;

generic
suite_name: string;
suite_arr: suite_type;
package suites is
end suites;

function "+"(s: string) return access string;
end test_suite;

package body test_suite is

function "+"(s: string) return access string is
begin
return new string'(s);
end;
end test_suite;


with p1, p2, p3;
with test_suite; use test_suite;
package p_suite is new test_suite.suites(
suite_name => "p",
suite_arr => (
(p1'access, +"p1"),
(p2'access, +"p3"),
(p3'access, +"p3")));

with test_suite; use test_suite;
package q_suite is new test_suite.suites(
suite_name => "q",
suite_arr => (
(q1'access, +"q1"),
(q2'access, +"q3"),
(q3'access, +"q3")));

-------------------------------------------------------------------

with ahven.framework;
with test_suite;
generic
S : Ahven.Framework.Test_Suite_Access;
with package the_suite is new test_suite.suites(<>);
package one_suite is
type test is new ahven.framework.test_case with null record;
procedure initialize (T: in out test);
end;

package body one_suite is

procedure initialize (T: in out test) is
begin
set_name(T, the_suite.suite_name);
for i in the_suite.suite_arr'range loop
ahven.framework.add_test_routine (T,
ahven.framework.Simple_Test_Routine_Access(
the_suite.suite_arr(i).proc),
the_suite.suite_arr(i).name.all);
end loop;
end;

begin
Ahven.Framework.Add_Test (S.all, new Test);
end one_suite;


with p_suite;
with q_suite;
with one_suite;
with ahven.framework;
package all_suites is
S : Ahven.Framework.Test_Suite_Access :=
Ahven.Framework.Create_Suite ("acats C tests");

package suite_p is new one_suite(S, p_suite);
package suite_q is new one_suite(S, q_suite);
end all_suites;


with all_suites; use all_suites;
with Ahven.Text_Runner;
with Ahven.Framework;
procedure main is
begin
Ahven.Text_Runner.Run (S);
Ahven.Framework.Release_Suite (S);
end main;

Dan

unread,
Jun 3, 2010, 3:43:40 PM6/3/10
to
On Jun 3, 12:36 pm, Dan <d...@irvine.com> wrote:

with q1, q2, q3; -- oops, this line was missing!

Stephen Leake

unread,
Jun 4, 2010, 5:17:51 AM6/4/10
to
Dan <d...@irvine.com> writes:

> On Jun 3, 5:08 am, Stephen Leake <stephen_le...@stephe-leake.org>
> wrote:
>> How does it compare to AUnit?
>
> I am able to use Ahven in a table-driven manner, as shown below.
> But I don't see a way to use AUnit similarly (replacing the Ahven-
> specific code below the line of dashes).
>
>

> ...

> with p1, p2, p3;
> with test_suite; use test_suite;
> package p_suite is new test_suite.suites(
> suite_name => "p",
> suite_arr => (
> (p1'access, +"p1"),
> (p2'access, +"p3"),
> (p3'access, +"p3")));

In AUnit, tests are 'registered' in a test_case:

overriding procedure Register_Tests (T : in out Test_Case)
is
begin
Register_Routine (T, Nominal'Access, "Nominal");
Register_Routine (T, Commands'Access, "Commands");
Register_Routine (T, Glitches'Access, "Glitches");
Register_Routine (T, Multi_Cycle'Access, "Multi_Cycle");
end Register_Tests;

Then test_cases are added to suites:

Add_Test (Suite, new Test_Hardware.Analog_In_Out_Wrappers.Test_Case);
Add_Test (Suite, new Test_Hardware.Analog_In_Wrapper_Common.Test_Case);
Add_Test (Suite, new Test_Hardware.Analog_Out_Wrapper_Common.Test_Case);

This seems roughly equivalent to Ahven.

AUnit also has setup and teardown functions for initializing and finalizing
each test and/or each Test_Case; those are very helpful.

--
-- Stephe

Tero Koskinen

unread,
Jun 4, 2010, 11:37:08 AM6/4/10
to
On Fri, 04 Jun 2010 05:17:51 -0400 Stephen Leake wrote:

> Dan <d...@irvine.com> writes:
>
> > On Jun 3, 5:08 am, Stephen Leake <stephen_le...@stephe-leake.org>
> > wrote:
> >> How does it compare to AUnit?

Here a little summary:
* The basic API is similar in Ahven and AUnit 1 (and 3).
* In Ahven, I have the public API stuffed into two packages:
Ahven and Ahven.Framework while AUnit spreads it API into
larger amount of packages.

* AUnit is Ada 2005 code only and I think it can be compiled
only with GNAT (not 100% sure since I haven't tried it with
other Ada 2005 compilers)
* Ahven is Ada 95 code, but can be compiled as Ada 2005 code also.
I have seen some effort to make Ahven build out of the box
with several Ada 95 or Ada 2005 compilers. So far, GNAT,
Janus/Ada, ObjectAda, and ICCAda have been tested.
(Unix and Windows environments)

I don't know about IBM/Rational Apex, GHS AdaMulti, or PowerAda,
but I suspect that they should be okay also.

* Both are free or open-source software.
AUnit is distributed under GPL and Ahven under ISC
license (similar to BSD).

* Both libraries support XML results, but AUnit uses CppUnit's
XML format while Ahven uses JUnit's format.
In addition, Ahven can output test results in
Test-Anything-Protocol (TAP) format, which is my favorite
at the moment.

* AUnit's documentation is probably better. So far I have
concentrated on the code.

> In AUnit, tests are 'registered' in a test_case:
>
> overriding procedure Register_Tests (T : in out Test_Case)
> is
> begin
> Register_Routine (T, Nominal'Access, "Nominal");

Same works for Ahven. Dan's example was just somewhat exotic, so
one couldn't figure it out from that.

procedure Initialize (T: in out Test_Case) is
procedure Register_Routine
(T : in out Ahven.Framework.Test_Case'Class;
Routine : Simple_Test_Routine_Access;
Name : String) renames Ahven.Framework.Add_Test_Routine;


begin
Register_Routine (T, Nominal'Access, "Nominal");

...;

The difference is in the test routine signature.

AUnit accepts only form
procedure Nominal (T : in out AUnit.Test_Cases.Test_Case'Class);

while Ahven accepts
procedure Nominal (T : in out Ahven.Framework.Test_Case'Class);
and
procedure Nominal;

> Then test_cases are added to suites:
>
> Add_Test (Suite, new Test_Hardware.Analog_In_Out_Wrappers.Test_Case);
> Add_Test (Suite, new Test_Hardware.Analog_In_Wrapper_Common.Test_Case);
> Add_Test (Suite, new Test_Hardware.Analog_Out_Wrapper_Common.Test_Case);
>
> This seems roughly equivalent to Ahven.

Yes.

> AUnit also has setup and teardown functions for initializing and finalizing
> each test and/or each Test_Case; those are very helpful.

Ahven supports setup and teardown procedures for each test.

For each Test_Case you need to rely on Initialize and Finalize
procedures provided by Ada.Finalization.Controlled.

package body Simple_Tests is
type Test_Access is access all Test;

procedure Initialize (T : in out Test) is
begin
Set_Name (T, "Simple Tests");

Ahven.Framework.Add_Test_Routine
(T, Test_Assertion'Access, "Test Assertion");
Ahven.Framework.Add_Test_Routine
(T, Test_With_Object'Access, "Test With Object");
Ahven.Framework.Add_Test_Routine
(T, Test_Error'Access, "Test Error (exception)");

end Initialize;

procedure Set_Up (T : in out Test) is
begin
Put_Line ("Simple_Tests.Set_Up");
T.Value := 1;
end Set_Up;

procedure Tear_Down (T : in out Test) is
begin
Put_Line ("Simple_Tests.Tear_Down");
T.Value := -1;
end Tear_Down;

procedure Test_Assertion is
begin
Put_Line ("Test_Assertion");
Ahven.Assert (False, "assert(false)");
end Test_Assertion;

procedure Test_Error is
begin
raise Constraint_Error;
end Test_Error;

procedure Hello (T : Test) is
begin
Ahven.Assert (T.Value = 1, "T.Value = 1");
end Hello;

procedure Test_With_Object (T : in out Ahven.Framework.Test_Case'Class) is
begin
Put_Line ("Test_With_Object");
Hello (Test (T));
end Test_With_Object;
end Simple_Tests;


There are probably also other differences, but
I don't want to spoil too much. ;)

> --
> -- Stephe

Dan

unread,
Jun 4, 2010, 1:12:37 PM6/4/10
to
On Jun 4, 2:17 am, Stephen Leake <stephen_le...@stephe-leake.org>

There is a significant difference in registering tests between Ahven
and Aunit, which Tero mentions, but I will expand on.

Ahven accepts parameterless procedures as test routines,
such as the p1,p2,p3,q1,q2,q3 in my example. AUnit, in contrast,
requires test routines to have a parameter of type
AUnit.Test_Cases.Test_Case'Class. I have thousands of procedures that
I would like to test using a test driver, but unfortunately not a
single one of those comes in the form AUnit requires.

If you start with an array of parameterless test procedures, AUnit
requires that you traverse the array, creating a new test procedure
(containing the required parameter) for each parameterless test
procedure in the array. Then you can register the newly created test
procedures.

The problem is that Ada doesn't have a good way for one procedure to
create other procedures, that can then be registered (using 'access).
I tried using generics to instantiate the new test procedures, but ran
into accessiblity-level problems. I also tried using an allocator of
a protected type that contains a procedure, but that results in a
protected procedure, and AUnit only knows how to register normal
(unprotected) procedures.

I presume that it may be possible to modify AUnit to support
registering parameterless test procedures (or even better, an array of
them), which would be convenient for my purposes. It would also be
possible to write some sort of offline test-generator that creates the
kind of test procedures that AUnit expects.

Stephen Leake

unread,
Jun 5, 2010, 12:08:03 AM6/5/10
to
Dan <d...@irvine.com> writes:

> Ahven accepts parameterless procedures as test routines,
> such as the p1,p2,p3,q1,q2,q3 in my example. AUnit, in contrast,
> requires test routines to have a parameter of type
> AUnit.Test_Cases.Test_Case'Class. I have thousands of procedures that
> I would like to test using a test driver, but unfortunately not a
> single one of those comes in the form AUnit requires.

Ah. Adapting an existing test suite to use the framework is an issue.

You could write one AUnit test that calls all the thousands of tests,
but that would be silly.

You could probably write a tool to convert those tests to match AUnit,
but that would still be a lot of work.

> The problem is that Ada doesn't have a good way for one procedure to
> create other procedures, that can then be registered (using 'access).
> I tried using generics to instantiate the new test procedures, but ran
> into accessiblity-level problems. I also tried using an allocator of
> a protected type that contains a procedure, but that results in a
> protected procedure, and AUnit only knows how to register normal
> (unprotected) procedures.

You need to write new source code. Real software writes itself :) (a new
slogan I just made up :).

> I presume that it may be possible to modify AUnit to support
> registering parameterless test procedures (or even better, an array of
> them), which would be convenient for my purposes.

Not easy; the tests are called by the standard Ada dispatching call methods.

> It would also be possible to write some sort of offline test-generator
> that creates the kind of test procedures that AUnit expects.

Yes.

--
-- Stephe

Simon Wright

unread,
Jun 5, 2010, 8:41:15 AM6/5/10
to
Tero Koskinen <tero.k...@iki.fi> writes:

> * AUnit is Ada 2005 code only and I think it can be compiled
> only with GNAT (not 100% sure since I haven't tried it with
> other Ada 2005 compilers)

The 2005-ness occurs because AUnit uses a private copy of
Ada.Containers.Lists with some 05 constructs removed so that it can be
compiled with "an" Ada 95 compiler.

Unfortunately, what they mean is "with an Ada 95 compiler that
recognises pragma Ada_2005 to mean that some Ada 2005 constructs are
permitted even when compiling in Ada 95 mode".

This doesn't include older GNATs, and certainly won't include compilers
from other vendors.

These patches update the current SVN source of AUnit to work with older
GNATs. Ask me if you need a copy and the news system has mangled them or
I've failed to drive Emacs correctly ...

ada_95_only.diff

Ludovic Brenta

unread,
Jun 5, 2010, 3:17:19 PM6/5/10
to

Stephe, how about applying this patch to Debian's version of AUnit?

--
Ludovic Brenta.

Stephen Leake

unread,
Jun 6, 2010, 8:31:39 AM6/6/10
to
Ludovic Brenta <lud...@ludovic-brenta.org> writes:

I don't see why. Debian supports the current version of GNAT, which
supports the current Debian version (and newer AdaCore versions) of
AUnit.

--
-- Stephe

Ludovic Brenta

unread,
Jun 6, 2010, 12:20:46 PM6/6/10
to

The current version of GNAT (in Debian) allows compiling Ada 83, Ada 95
and Ada 2005 programs. I think that allowing Ada 95 programs to use
AUnit is better than forbidding this. So the main objection is that
this patch requires changing the aliversion; I would undertand that you
wouldn't want to do that.

--
Ludovic Brenta.

Simon Wright

unread,
Jun 6, 2010, 12:45:14 PM6/6/10
to
Ludovic Brenta <lud...@ludovic-brenta.org> writes:

Ludovic,

I think it's very likely that the current Debian GNAT supports AUnit 3's
use of this pragma, even in -gnat95 mode ... OK, just tried in a VM
running (sorry for my ignorance about the Debian release name) Debian 5,
GNAT 4.3.2, and it says ..

simon@nidhoggr-d:/mnt/hgfs/simon/AUnit-svn/aunit/containers$ gnatmake -gnat95 ada_containers-aunit_lists.adb -c -u -f -I../framework
gcc-4.3 -c -gnat95 -I../framework ada_containers-aunit_lists.adb
simon@nidhoggr-d:/mnt/hgfs/simon/AUnit-svn/aunit/containers$

which looks good to me. So no need for any change.

--S

Ludovic Brenta

unread,
Jun 6, 2010, 1:48:29 PM6/6/10
to
Simon Wright writes on comp.lang.ada:

OK, thanks a lot for checking this.

--
Ludovic Brenta.

Stephen Leake

unread,
Jun 7, 2010, 4:26:51 AM6/7/10
to
Ludovic Brenta <lud...@ludovic-brenta.org> writes:

True. I have no idea how many people use the old language. I should
think the only reason to do that is for compatibility with a different
compiler. And even then, the language version is not likely to be an issue.

For example, I used to program in DDC Ada for an embedded computer, but
GNAT for development and unit test. I used GNAT in Ada 95 mode, while
DDC was Ada 83. No problems.

> I think that allowing Ada 95 programs to use AUnit is better than
> forbidding this. So the main objection is that this patch requires
> changing the aliversion;

No, the main objection is that it is different than upstream. I don't
have access to the AUnit test suite. I don't want to fork.

--
-- Stephe

Simon Wright

unread,
Jun 7, 2010, 3:21:50 PM6/7/10
to
Stephen Leake <stephe...@stephe-leake.org> writes:

> No, the main objection is that it is different than upstream. I don't
> have access to the AUnit test suite. I don't want to fork.

I've reported the issue, it's been accepted but as ever may take some
time to trickle through!

Jérôme Haguet

unread,
Jun 8, 2010, 11:24:50 AM6/8/10
to
On 2 juin, 18:24, Tero Koskinen <tero.koski...@iki.fi> wrote:
> Hi,
>
> I released Ahven 1.8 today. It can be downloaded from
>  http://sourceforge.net/projects/ahven/files/
>
> Ahven is a unit testing library for Ada 95
> programming language.
>
> ...

> The release has been tested with following compilers:
>  * FSF GCC/GNAT 4.3.5 and 4.4.4
>  * GNAT GPL 2009
>  * Janus/Ada 3.1.2beta
>  * Irvine ICCAda
>

Hello Tero.

FYI, Ahven 1.8 works also fine with Atego/ObjectAda 8.4 + U5 on
Windows XP.

Regards.

Jérôme

Reply all
Reply to author
Forward
0 new messages