Skip to content

Commit 1c7d5fc

Browse files
committed
SC06-071 Add a valgrind mode to the testsuite
Add a mode to run the testsuite under valgrind. To do this, the command line to run the language server must be modifiable: no longer read it from the .json files, but read it from the environment directly.
1 parent f327ad8 commit 1c7d5fc

File tree

4 files changed

+70
-19
lines changed

4 files changed

+70
-19
lines changed

source/tester/tester-tests.adb

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ with Ada.Command_Line;
1919
with Ada.Directories;
2020
with Ada.Text_IO;
2121
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
22-
with GNAT.OS_Lib;
22+
with GNAT.OS_Lib; use GNAT.OS_Lib;
23+
24+
with GNATCOLL.Utils; use GNATCOLL.Utils;
2325

2426
with Spawn.Processes.Monitor_Loop;
2527

@@ -31,8 +33,7 @@ package body Tester.Tests is
3133
type Command_Kind is (Start, Stop, Send, Comment);
3234

3335
procedure Do_Start
34-
(Self : in out Test'Class;
35-
Command : GNATCOLL.JSON.JSON_Value);
36+
(Self : in out Test'Class);
3637

3738
procedure Do_Stop
3839
(Self : in out Test'Class;
@@ -42,15 +43,20 @@ package body Tester.Tests is
4243
(Self : in out Test'Class;
4344
Command : GNATCOLL.JSON.JSON_Value);
4445

45-
Is_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\';
46+
function Wait_Factor return Integer;
47+
-- Return the factor to multiply the delays with - useful for valgrind
48+
-- runs. This is an integer read from the environment variable
49+
-- $ALS_WAIT_FACTOR if it is defined.
50+
51+
Is_Windows : constant Boolean := Directory_Separator = '\';
4652

4753
--------------
4854
-- Do_Abort --
4955
--------------
5056

5157
procedure Do_Abort (Self : Test) is
5258
begin
53-
GNAT.OS_Lib.OS_Exit (1);
59+
OS_Exit (1);
5460
end Do_Abort;
5561

5662
-------------
@@ -98,7 +104,7 @@ package body Tester.Tests is
98104
exit when GNATCOLL.JSON.Length (Self.Waits) = 0;
99105

100106
Total_Milliseconds_Waited := Total_Milliseconds_Waited + Timeout;
101-
if Total_Milliseconds_Waited > Max_Wait then
107+
if Total_Milliseconds_Waited > Max_Wait * Wait_Factor then
102108
declare
103109
Text : Spawn.String_Vectors.UTF_8_String_Vector;
104110
begin
@@ -126,8 +132,7 @@ package body Tester.Tests is
126132
--------------
127133

128134
procedure Do_Start
129-
(Self : in out Test'Class;
130-
Command : GNATCOLL.JSON.JSON_Value)
135+
(Self : in out Test'Class)
131136
is
132137
function Program_Name (Path : String) return String;
133138
-- Return full path to an exacutable designated by Path
@@ -138,21 +143,34 @@ package body Tester.Tests is
138143

139144
function Program_Name (Path : String) return String is
140145
begin
141-
if Is_Windows then
146+
if Is_Windows
147+
and then not Ends_With (Path, ".exe")
148+
then
142149
return Ada.Directories.Full_Name (Path & ".exe");
143150
else
144151
return Ada.Directories.Full_Name (Path);
145152
end if;
146153
end Program_Name;
147154

148-
Cmd : constant GNATCOLL.JSON.JSON_Array := Command.Get ("cmd");
155+
Command_Line : constant GNAT.OS_Lib.String_Access := Getenv ("ALS");
156+
149157
Args : Spawn.String_Vectors.UTF_8_String_Vector;
150158
begin
151-
for J in 2 .. GNATCOLL.JSON.Length (Cmd) loop
152-
Args.Append (GNATCOLL.JSON.Get (Cmd, J).Get);
153-
end loop;
159+
if Command_Line = null or else Command_Line.all = "" then
160+
raise Program_Error with "You must specify the command line in $ALS";
161+
end if;
162+
163+
declare
164+
Splits : constant Unbounded_String_Array :=
165+
Split (Command_Line.all, ' ');
166+
begin
167+
Self.Set_Program (Program_Name (To_String (Splits (Splits'First))));
168+
169+
for J in Splits'First + 1 .. Splits'Last loop
170+
Args.Append (To_String (Splits (J)));
171+
end loop;
172+
end;
154173

155-
Self.Set_Program (Program_Name (GNATCOLL.JSON.Get (Cmd, 1).Get));
156174
Self.Set_Arguments (Args);
157175
Self.Start;
158176

@@ -442,7 +460,7 @@ package body Tester.Tests is
442460

443461
case Kind is
444462
when Start =>
445-
Self.Do_Start (Value);
463+
Self.Do_Start;
446464
when Stop =>
447465
Self.Do_Stop (Value);
448466
when Send =>
@@ -461,11 +479,11 @@ package body Tester.Tests is
461479
select
462480
accept Cancel;
463481
or
464-
delay 2.0;
482+
delay 20.0 * Wait_Factor;
465483

466484
Ada.Text_IO.Put_Line ("Timeout on command:");
467485
Ada.Text_IO.Put_Line (Command.Write);
468-
GNAT.OS_Lib.OS_Exit (1);
486+
OS_Exit (1);
469487
end select;
470488
end Watch_Dog;
471489

@@ -494,4 +512,19 @@ package body Tester.Tests is
494512
end loop;
495513
end Run;
496514

515+
-----------------
516+
-- Wait_Factor --
517+
-----------------
518+
519+
function Wait_Factor return Integer is
520+
Factor : constant GNAT.OS_Lib.String_Access
521+
:= Getenv ("ALS_WAIT_FACTOR");
522+
begin
523+
if Factor = null or else Factor.all = "" then
524+
return 1;
525+
else
526+
return Integer'Value (Factor.all);
527+
end if;
528+
end Wait_Factor;
529+
497530
end Tester.Tests;

testsuite/drivers/basic.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def run(self, previous_values):
3131
[self.env.tester_run, json],
3232
cwd=wd,
3333
timeout=120,
34-
env={'ALS': self.env.als},
34+
env={'ALS': self.env.als,
35+
'ALS_WAIT_FACTOR': str(self.env.wait_factor)},
3536
ignore_environ=False)
3637
output += process.out
3738

testsuite/run_valgrind.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env sh
2+
3+
# This is a convenience command-line driver made for development mode
4+
# in valgrind memory check mode
5+
./run-tests --valgrind_memcheck --loglevel INFO --show-error-output $@

testsuite/testsuite.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ def add_options(self):
3333
help="Compute the source code coverage of testcases on ALS. This"
3434
" requires GNATcoverage working with instrumentation and will"
3535
" run a build of ALS before running tests.")
36+
self.main.argument_parser.add_argument(
37+
"--valgrind_memcheck", action="store_true",
38+
help="Runs the Ada Language Server under valgrind, in memory"
39+
" check mode. This requires valgrind on the PATH.")
3640

3741
def lookup_program(self, *args):
3842
"""
@@ -62,8 +66,16 @@ def tear_up(self):
6266
self.env.repo_base = os.path.abspath(os.path.join(
6367
os.path.dirname(__file__), '..'))
6468

69+
self.env.wait_factor = 1
70+
6571
# Absolute paths to programs that test drivers can use
66-
self.env.als = self.lookup_program('server', 'ada_language_server')
72+
if self.env.options.valgrind_memcheck:
73+
self.env.als = "{} --tool=memcheck --quiet {}".format(
74+
self.lookup_program("valgrind"),
75+
self.lookup_program('server', 'ada_language_server'))
76+
self.env.wait_factor = 20 # valgrind is slow
77+
else:
78+
self.env.als = self.lookup_program('server', 'ada_language_server')
6779
self.env.tester_run = self.lookup_program('tester', 'tester-run')
6880
self.env.codec_test = self.lookup_program('codec_test', 'codec_test')
6981

0 commit comments

Comments
 (0)