mirror of
https://github.com/boostorg/build.git
synced 2026-02-17 01:32:12 +00:00
Updated Boost Jam to execute commands directly on Windows when that is requested by setting the JAMSHELL variable to '%', the same as for Unix OSs, and not change the user's request under covers to running the command via the default shell if it is 8191 characters long or shorter. Renamed the related Boost Build core_nt_line_length.py test to core_nt_cmd_line.py and updated it with more detailed test cases.
[SVN r79097]
This commit is contained in:
@@ -233,13 +233,9 @@ int exec_check
|
||||
if ( is_raw_command_request( *pShell ) )
|
||||
{
|
||||
int const raw_cmd_length = raw_command_length( command->value );
|
||||
if ( !raw_cmd_length )
|
||||
if ( raw_cmd_length < 0 )
|
||||
{
|
||||
return EXEC_CHECK_SKIP;
|
||||
}
|
||||
else if ( raw_cmd_length < maxline() )
|
||||
{
|
||||
/* Fallback to default shell. */
|
||||
/* Invalid characters detected - fallback to default shell. */
|
||||
list_free( *pShell );
|
||||
*pShell = L0;
|
||||
}
|
||||
@@ -250,7 +246,7 @@ int exec_check
|
||||
return EXEC_CHECK_TOO_LONG;
|
||||
}
|
||||
else
|
||||
return EXEC_CHECK_OK;
|
||||
return raw_cmd_length ? EXEC_CHECK_OK : EXEC_CHECK_SKIP;
|
||||
}
|
||||
|
||||
/* Now we know we are using an external shell. Note that there is no need to
|
||||
|
||||
243
v2/test/core_nt_cmd_line.py
Executable file
243
v2/test/core_nt_cmd_line.py
Executable file
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2001 Dave Abrahams
|
||||
# Copyright 2011 Steven Watanabe
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Tests Windows command line construction.
|
||||
#
|
||||
# Note that the regular 'echo' is an internal shell command on Windows and
|
||||
# therefore can not be called directly as a standalone Windows process.
|
||||
|
||||
import BoostBuild
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
executable = sys.executable.replace("\\", "/")
|
||||
if " " in executable:
|
||||
executable = '"%s"' % executable
|
||||
|
||||
|
||||
def string_of_length(n):
|
||||
if n <= 0:
|
||||
return ""
|
||||
n -= 1
|
||||
y = ['', '$(1x10-1)', '$(10x10-1)', '$(100x10-1)', '$(1000x10-1)']
|
||||
result = []
|
||||
for i in reversed(xrange(5)):
|
||||
x, n = divmod(n, 10 ** i)
|
||||
result += [y[i]] * x
|
||||
result.append('x')
|
||||
return " ".join(result)
|
||||
|
||||
|
||||
# Boost Jam currently does not allow preparing actions with completly empty
|
||||
# content as it always requires at least a single whitespace after the opening
|
||||
# brace in order to satisfy.
|
||||
def test_raw_empty():
|
||||
t = BoostBuild.Tester("-d2 -d+4", pass_d0=False, pass_toolset=0,
|
||||
use_test_config=False)
|
||||
t.write("file.jam", """\
|
||||
actions do_empty { %s}
|
||||
JAMSHELL = %% ;
|
||||
do_empty all ;
|
||||
""" % (" \n\n\r\r\v\v\t\t \t \r\r \n\n"))
|
||||
t.run_build_system("-ffile.jam")
|
||||
t.expect_output_line("do_empty*", False)
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_raw_nt(n=None, error=False):
|
||||
t = BoostBuild.Tester("-d1 -d+4", pass_d0=False, pass_toolset=0,
|
||||
use_test_config=False)
|
||||
|
||||
cmd_prefix = "%s -c \"print('XXX: " % executable
|
||||
cmd_suffix = "')\""
|
||||
cmd_extra_length = len(cmd_prefix) + len(cmd_suffix)
|
||||
|
||||
if n == None:
|
||||
n = cmd_extra_length
|
||||
|
||||
data_length = n - cmd_extra_length
|
||||
if data_length < 0:
|
||||
BoostBuild.annotation("failure", """\
|
||||
Can not construct Windows command of desired length. Requested command length
|
||||
too short for the current test configuration.
|
||||
Requested command length: %d
|
||||
Minimal supported command length: %d
|
||||
""" % (n, cmd_extra_length))
|
||||
t.fail_test(1, dump_difference=False)
|
||||
|
||||
# Each $(Xx10-1) variable contains X words of 9 characters each, which,
|
||||
# including spaces between words, brings the total number of characters in
|
||||
# its string representation to X * 10 - 1 (X * 9 characters + (X - 1)
|
||||
# spaces).
|
||||
t.write("file.jam", """\
|
||||
ten = 0 1 2 3 4 5 6 7 8 9 ;
|
||||
|
||||
1x10-1 = 123456789 ;
|
||||
10x10-1 = $(ten)12345678 ;
|
||||
100x10-1 = $(ten)$(ten)1234567 ;
|
||||
1000x10-1 = $(ten)$(ten)$(ten)123456 ;
|
||||
|
||||
actions do_echo
|
||||
{
|
||||
%s%s%s
|
||||
}
|
||||
JAMSHELL = %% ;
|
||||
do_echo all ;
|
||||
""" % (cmd_prefix, string_of_length(data_length), cmd_suffix))
|
||||
t.run_build_system("-ffile.jam", status=1 if error else 0)
|
||||
if error:
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.expect_output_line("do_echo action is too long (%d, max 32766):" % n)
|
||||
t.expect_output_line("XXX: *", False)
|
||||
else:
|
||||
t.expect_output_line("Executing raw command directly")
|
||||
t.expect_output_line("do_echo action is too long*", False)
|
||||
|
||||
m = re.search("^XXX: (.*)$", t.stdout(), re.MULTILINE)
|
||||
if not m:
|
||||
BoostBuild.annotation("failure", "Expected output line starting "
|
||||
"with 'XXX: ' not found.")
|
||||
t.fail_test(1, dump_difference=False)
|
||||
if len(m.group(1)) != data_length:
|
||||
BoostBuild.annotation("failure", """Unexpected output data length.
|
||||
Expected: %d
|
||||
Received: %d""" % (n, len(m.group(1))))
|
||||
t.fail_test(1, dump_difference=False)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_raw_to_shell_fallback_nt():
|
||||
t = BoostBuild.Tester("-d1 -d+4", pass_d0=False, pass_toolset=0,
|
||||
use_test_config=False)
|
||||
|
||||
cmd_prefix = '%s -c print(' % executable
|
||||
cmd_suffix = ')'
|
||||
|
||||
t.write("file_multiline.jam", """\
|
||||
actions do_multiline
|
||||
{
|
||||
echo one
|
||||
|
||||
|
||||
echo two
|
||||
}
|
||||
JAMSHELL = % ;
|
||||
do_multiline all ;
|
||||
""")
|
||||
t.run_build_system("-ffile_multiline.jam")
|
||||
t.expect_output_line("do_multiline all")
|
||||
t.expect_output_line("one")
|
||||
t.expect_output_line("two")
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
|
||||
t.write("file_redirect.jam", """\
|
||||
actions do_redirect { echo one > two.txt }
|
||||
JAMSHELL = % ;
|
||||
do_redirect all ;
|
||||
""")
|
||||
t.run_build_system("-ffile_redirect.jam")
|
||||
t.expect_output_line("do_redirect all")
|
||||
t.expect_output_line("one", False)
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
t.expect_addition("two.txt")
|
||||
|
||||
t.write("file_pipe.jam", """\
|
||||
actions do_pipe { echo one | echo two }
|
||||
JAMSHELL = % ;
|
||||
do_pipe all ;
|
||||
""")
|
||||
t.run_build_system("-ffile_pipe.jam")
|
||||
t.expect_output_line("do_pipe all")
|
||||
t.expect_output_line("one", False)
|
||||
t.expect_output_line("two")
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
|
||||
t.write("file_single_quoted.jam", """\
|
||||
actions do_single_quoted { %s'5>10'%s }
|
||||
JAMSHELL = %% ;
|
||||
do_single_quoted all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system("-ffile_single_quoted.jam")
|
||||
t.expect_output_line("do_single_quoted all")
|
||||
t.expect_output_line("5>10")
|
||||
t.expect_output_line("Executing raw command directly")
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.write("file_double_quoted.jam", """\
|
||||
actions do_double_quoted { %s"5>10"%s }
|
||||
JAMSHELL = %% ;
|
||||
do_double_quoted all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system("-ffile_double_quoted.jam")
|
||||
t.expect_output_line("do_double_quoted all")
|
||||
# The difference between this example and the similar previous one using
|
||||
# single instead of double quotes stems from how the used Python executable
|
||||
# parses the command-line string received from Windows.
|
||||
t.expect_output_line("False")
|
||||
t.expect_output_line("Executing raw command directly")
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C", False)
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.write("file_escaped_quote.jam", """\
|
||||
actions do_escaped_quote { %s\\"5>10\\"%s }
|
||||
JAMSHELL = %% ;
|
||||
do_escaped_quote all ;
|
||||
""" % (cmd_prefix, cmd_suffix))
|
||||
t.run_build_system("-ffile_escaped_quote.jam")
|
||||
t.expect_output_line("do_escaped_quote all")
|
||||
t.expect_output_line("5>10")
|
||||
t.expect_output_line("Executing raw command directly", False)
|
||||
t.expect_output_line("Executing using a command file and the shell: "
|
||||
"cmd.exe /Q/C")
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# main()
|
||||
# ------
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
if os.name == 'nt':
|
||||
test_raw_empty()
|
||||
|
||||
# Can not test much shorter lengths as the shortest possible command line
|
||||
# line length constructed in this depends on the runtime environment, e.g.
|
||||
# path to the Panther executable running this test.
|
||||
test_raw_nt()
|
||||
test_raw_nt(255)
|
||||
test_raw_nt(1000)
|
||||
test_raw_nt(8000)
|
||||
test_raw_nt(8191)
|
||||
test_raw_nt(8192)
|
||||
test_raw_nt(10000)
|
||||
test_raw_nt(30000)
|
||||
test_raw_nt(32766)
|
||||
# CreateProcessA() Windows API places a limit of 32768 on the allowed
|
||||
# command-line length, including a trailing Unicode (2-byte) nul-terminator
|
||||
# character.
|
||||
test_raw_nt(32767, error=True)
|
||||
test_raw_nt(40000, error=True)
|
||||
test_raw_nt(100001, error=True)
|
||||
|
||||
test_raw_to_shell_fallback_nt()
|
||||
@@ -1,52 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2001 Dave Abrahams
|
||||
# Copyright 2011 Steven Watanabe
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import BoostBuild
|
||||
import os
|
||||
|
||||
t = BoostBuild.Tester(pass_toolset=0, pass_d0=False)
|
||||
|
||||
t.write("file.jam", """
|
||||
if $(NT)
|
||||
{
|
||||
#
|
||||
# Build a really long commandline. (> 10K characters).
|
||||
#
|
||||
ten = 0 1 2 3 4 5 6 7 8 9 ;
|
||||
1x7chars = 0_____ ;
|
||||
# add a digit and multiply by 10
|
||||
10x8chars = $(ten)$(1x7chars) ;
|
||||
# add a digit to each of 10 strings and multiply by 10
|
||||
100x9chars = $(ten)$(10x8chars) ;
|
||||
# add a digit to each of 100 strings and multiply by 10
|
||||
1000x10chars = $(ten)$(100x9chars) ;
|
||||
|
||||
#
|
||||
# Cause line_length_test to be built
|
||||
#
|
||||
actions do_echo
|
||||
{
|
||||
echo $(text)
|
||||
}
|
||||
|
||||
400x10chars = $(ten[1-4])$(100x9chars) ;
|
||||
|
||||
text on line_length_test = $(400x10chars) 40$(10x8chars[1-9]) 01234 ;
|
||||
text on line_length_test = $(1000x10chars) $(1000x10chars) ;
|
||||
JAMSHELL on line_length_test = % ;
|
||||
DEPENDS all : line_length_test ;
|
||||
|
||||
do_echo line_length_test ;
|
||||
}
|
||||
else
|
||||
{
|
||||
NOCARE all ;
|
||||
}
|
||||
""")
|
||||
t.run_build_system("-ffile.jam")
|
||||
|
||||
t.cleanup()
|
||||
@@ -175,7 +175,7 @@ tests = ["absolute_sources",
|
||||
"core_actions_quietly",
|
||||
"core_at_file",
|
||||
"core_bindrule",
|
||||
"core_nt_line_length",
|
||||
"core_nt_cmd_line",
|
||||
"core_option_d2",
|
||||
"core_option_l",
|
||||
"core_option_n",
|
||||
|
||||
Reference in New Issue
Block a user