I am trying to write a test for a method with a simple Ada.Text_IO.Put
. For the sake of simplicity, this is a made up method that I want to test:
procedure Say_Something is
begin
Put("Something.");
end Say_Something;
In my AUnit test, I have:
procedure Test_Put (T : in out Test) is
pragma Unreferenced (T);
use Ada.Text_IO;
Stdout : constant File_Type := Standard_Output;
Put_File_Name : constant String := "say_something_test.txt";
Put_File : File_Type;
Expected : constant String := "Something.";
begin
-- Create the output file and redirect output
Create (Put_File, Append_File, Put_File_Name);
Set_Output (Put_File);
Say_Something;
-- Redirect output to stdout and close the file
Set_Output (Stdout);
Close (Put_File);
-- Read file
declare
File_Size : constant Natural :=
Natural (Ada.Directories.Size (Put_File_Name));
Actual : String (1 .. File_Size);
begin
Actual := Read_File (Put_File_Name, File_Size);
Ada.Directories.Delete_File (Put_File_Name);
Assert (Expected = Actual,
"Expected " & '"' & Expected & '"' & ", " &
"Got " & '"' & Actual & '"');
end;
end Test_Put;
function Read_File (File_Name : String; File_Size : Natural)
return String is
subtype File_String is String (1 .. File_Size);
package File_String_IO is new Ada.Direct_IO (File_String);
File : File_String_IO.File_Type;
Contents : File_String;
begin
File_String_IO.Open (File, File_String_IO.In_File, File_Name);
File_String_IO.Read (File, Contents);
File_String_IO.Close (File);
return Contents;
end Read_File;
Unfortunately, the result is:
FAIL Test Vectors.Put
Expected "Something.", Got "Something.
"
It seems that Ada automagically adds a newline to the end of the file. I realize that I could add a (CR)LF to my expected string like this:
Expected : constant String := "Something.";
& Ada.Characters.Latin_1.CR
& Ada.Characters.Latin_1.LF;
but a) It does not feel right to alter my expected string and b) This will run on a Windows machine, but on Unix/Linux/Mac I would have to drop the "CR". In other words, the success of my test run is platform dependent while my code is not, which is bad.
So my question is: how can I write to the file without appending a newline? Other suggestions on how to test for output are highly welcome as well.
I have seen this related question but couldn't deduce any useful information from it apart that I might try the Append_File
instead of the Out_File
mode, which did not resolve my issue.
Sorry for my previous answer, I missed that the file you were reading was one you created earlier in the program.
In Ada.Text_IO
, the RM (A.10(7-8)) says "the end of a file is marked by the combination of a line terminator immediately followed by a page terminator and then a file terminator", and "The actual nature of terminators is not defined by the language and hence depends on the implementation" ... "they are not necessarily implemented as characters or as sequences of characters". So when you create say_something_test.txt
, it will always end with a "line terminator" although that doesn't necessarily mean it will end with an LF. That's implementation-dependent. The only thing you're guaranteed is that if you use Ada.Text_IO
to create a file, it will work correctly if you read it back in with Ada.Text_IO
. But if you want this level of control of the actual bytes written to the file, then Ada.Text_IO
would not really be suitable; you'd be better off using Ada.Stream_IO
.
Whether an CR and/or LF is written to the end of the file is implementation-dependent. It looks like GNAT does add LF (and maybe CR) to the end, and it doesn't provide a way (such as a Form
parameter) to turn this behavior off. At least I didn't see one in the manual.
If you're really determined to use Ada.Text_IO
to write say_something_test.txt
and Ada.Direct_IO
to read it back in, then you need to be aware that the file may or may not contain CR/LF, and the input routine should check for those characters and strip them off so that the string can be compared to the expected value.