Skip to content

Commit 06ea7a2

Browse files
committed
Gracefully error out upon PATH lookup failure
We perform a PATH lookup of gnatcov to determine the installation prefix of gnatcov, and in select situations this can fail. This used to raise an exception during elaboration, it is now changed to emit a better error message.
1 parent 6535240 commit 06ea7a2

File tree

4 files changed

+104
-4
lines changed

4 files changed

+104
-4
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!windows-host DEAD Test requires conditions only available on Windows, see #393
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Check that gnatcov does not crash during elaboration when it fails to find
3+
itself in PATH.
4+
5+
This requires a fairly specific setup for both path lookup to work in the
6+
terminal, but not from gnatcov. So far we have managed to do it by
7+
- Being on a Windows system
8+
- Having the gnatcov executable being in a case-sensitive directory
9+
- Modifying the gnatcov.exe filename to change the case of the executable
10+
suffix
11+
- Invoking gnatcov without the executable suffix.
12+
13+
This test aims to re-create these conditions, and thus removes some stuff from
14+
the environment to make sure we have a the right conditions.
15+
"""
16+
17+
import os
18+
19+
from e3.os.fs import which
20+
from e3.fs import mkdir, cp
21+
22+
from SUITE.context import thistest
23+
from SUITE.cutils import Wdir, contents_of
24+
from SUITE.tutils import run_and_log
25+
26+
27+
tmp = Wdir("tmp_")
28+
29+
# Create an empty directory in which we'll change the case sensitivity and
30+
# butcher the gnatcov exec.
31+
gnatcov_install = os.path.abspath("fake_gnatcov_bin")
32+
mkdir(gnatcov_install)
33+
34+
# Enable file sensitivity for the install dir. This needs to be done while the
35+
# directory is empty.
36+
run_and_log(
37+
["fsutil.exe", "file", "setCaseSensitiveInfo", gnatcov_install, "enable"]
38+
)
39+
40+
# Copy the gnatcov.exe program and change its executable suffix casing
41+
cp(which("gnatcov.exe"), os.path.join(gnatcov_install, "gnatcov.EXE"))
42+
43+
# Run gnatcov without anything on the environment to make sure we don't pick up
44+
# the correctly installed gnatcov, not the GNATCOV_PREFIX env var which would
45+
# bypass the path lookup check. We also go through a cmd indirection to avoid
46+
# the path lookup that takes place in e3.os.process.Run.
47+
#
48+
# We also need gnatcov to be invoked without the exe prefix here as the os
49+
# search should work, but the command name for gnatcov will still not have
50+
# the exe suffix.
51+
crash_log = "xcov.log"
52+
p = run_and_log(
53+
["cmd", "/c", "gnatcov"],
54+
env={"PATH": gnatcov_install},
55+
output=crash_log,
56+
ignore_environ=True,
57+
)
58+
59+
thistest.fail_if(
60+
p.status == 0,
61+
comment="gnatcov did not exit with a failure status",
62+
)
63+
64+
thistest.fail_if_not_equal(
65+
what="Unexpected error message from gnatcov",
66+
expected="Could not locate the invoked gnatcov command: <empty string>."
67+
" If gnatcov is installed on a case sensitive filesystem or directory,"
68+
" ensure the casing as the executable filename is used when invoking the"
69+
" program.",
70+
actual=contents_of(crash_log).strip(),
71+
)
72+
73+
thistest.result()

tools/gnatcov/gnatcov.adb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ with Switches; use Switches;
3131
procedure GNATcov is
3232
Use_Gnatcov64 : Boolean := False;
3333
begin
34+
-- Check that gnatcov detected its own installation directory correctly
35+
36+
if Support_Files.Gnatcov_Prefix = Support_Files.Not_Found then
37+
Warning_Or_Error
38+
("Could not locate the invoked gnatcov command: "
39+
& (if Command_Name /= "" then Command_Name else "<empty string>")
40+
& ". If gnatcov is installed on a case sensitive filesystem or"
41+
& " directory, ensure the casing as the executable filename is"
42+
& " used when invoking the program.");
43+
Set_Exit_Status (Failure);
44+
raise Xcov_Exit_Exc;
45+
end if;
46+
3447
-- Parse arguments just enough to determine the target, then run the
3548
-- corresponding bits-specific main (see gnatcov_arch_specific.adb),
3649
-- forwarding all arguments as-is.

tools/gnatcov/support_files.ads

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ with Ada.Environment_Variables; use Ada.Environment_Variables;
2323
with GNAT.OS_Lib;
2424

2525
package Support_Files is
26+
use type GNAT.OS_Lib.String_Access;
2627

2728
-- This package offers various helpers to locate support files in gnatcov's
2829
-- installation prefix.
@@ -35,18 +36,30 @@ package Support_Files is
3536
-- Name of the environment variable which, when defined, provides the name
3637
-- of the "gnatcov" command that the user ran.
3738

39+
Not_Found : constant String := "GNATCOV_NOT_FOUND";
40+
-- Magic value propagated throughout the elaboration if we can't lookup
41+
-- gnatcov on PATH. An error will be reported after elaboration completes.
42+
3843
Gnatcov_Command_Name : String :=
3944
(if Value (Command_Name_Envvar, "") = ""
4045
then Command_Name
4146
else Value (Command_Name_Envvar));
4247

43-
Gnatcov_Dir : constant String := Containing_Directory
44-
(GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all);
45-
-- Directory that contains the current program
48+
Gnatcov_Exec : constant GNAT.OS_Lib.String_Access :=
49+
GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name);
50+
51+
Gnatcov_Dir : constant String :=
52+
(if Gnatcov_Exec /= null
53+
then Containing_Directory (Gnatcov_Exec.all)
54+
else Not_Found);
55+
-- Use a magic value when we can't locate gnatcov on path
4656

4757
Gnatcov_Prefix : constant String :=
4858
(if Value (Prefix_Envvar, "") = ""
49-
then Containing_Directory (Gnatcov_Dir)
59+
then
60+
(if Gnatcov_Dir /= Not_Found
61+
then Containing_Directory (Gnatcov_Dir)
62+
else Not_Found)
5063
else Value (Prefix_Envvar));
5164
-- Installation prefix for gnatcov
5265

0 commit comments

Comments
 (0)