Vser
Vser

Reputation: 763

Breaking Ada privacy for Test functions

Say I have two packages:

with Ada.Streams; use Ada.Streams;
package P is
   type SEA is new Stream_Element_Array (1..4);
   function foo (Input : in SEA) return Natural;
private
   type PRecord is record
      Bar : Natural := 0;
   end record;
   function To_PRecord is new Ada.Unchecked_Conversion
     (Source => SEA,
      Target => PRecord);
end P;
------
package body P is
   function foo (Input : in SEA) return Natural
   is
      Tmp : constant PRecord := To_PRecord (Input);
   begin
      return Tmp.Bar;
   end foo;
end P;

And

-- Say SEA was defined in a third package and is accessible
package Q is
   function foo (Input : SEA) return Natural;
end P;
-----
with P;
package body Q is
   function foo (Input : SEA) return Natural
   is
   begin
      return P.foo(Input);
   end foo;
end Q;

The Package P is easily testable with:

with AUnit.Assertions; use AUnit.Assertions;
package body P.Tests is
   function To_SEA is new Ada.Unchecked_Conversion
     (Source => PRecord,
      Target => SEA);

   procedure Test_Foo
   is
      Input : PRecord := (Bar => 42);
   begin
      Assert (foo(To_SEA (Input)) = 42, "foo failed miserably");
   end Test_Foo;
end P.Tests;

But how may I test Q? PRecord is not accessible. As such, I do not see how Q is testable without changing much the code I am testing. In C++ I would define the package Q.Tests as a friend of P and get access.

I guess I could define PRecord in a package that would be withed by P and Q.Tests but is there a solution that do not require to change P or Q (because I do not really like when I need to change production code for the sake of testing).

Upvotes: 3

Views: 203

Answers (2)

Vser
Vser

Reputation: 763

Based on Simon Wright answer, one can define the P.Spy package as follows:

package P.Spy is
   function Create (Bar : in Natural) return SEA;
private
   function To_SEA is new Ada.Unchecked_Conversion (Source => PRecord,Target => SEA);
end P.Spy;
---
package body P.Spy is
   function Create (Bar : in Natural) return SEA
   is
      Result : PRecord;
   begin 
      Result.Bar := Bar;
      return To_SEA (Result);
   end Create;
end P.Spy;

Which allows to give Q.Tests ability to test its public interface.

Upvotes: 0

Simon Wright
Simon Wright

Reputation: 25491

A child package P.Spy has visibility of the whole of P’s spec; Q.Tests could call it to do validation checks.

Upvotes: 4

Related Questions