diff --git a/base/options.jl b/base/options.jl index 0706b1c07d72f..f7dec64f9b41d 100644 --- a/base/options.jl +++ b/base/options.jl @@ -39,6 +39,7 @@ struct JLOptions outputjitbc::Ptr{UInt8} outputo::Ptr{UInt8} outputji::Ptr{UInt8} + output_code_coverage::Ptr{UInt8} incremental::Int8 end diff --git a/base/util.jl b/base/util.jl index 479062c058161..b635f752d8abe 100644 --- a/base/util.jl +++ b/base/util.jl @@ -399,42 +399,79 @@ printstyled(io::IO, msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) with_output_color(print, color, io, msg...; bold=bold) printstyled(msg...; bold::Bool=false, color::Union{Int,Symbol}=:normal) = printstyled(stdout, msg...; bold=bold, color=color) + """ Base.julia_cmd(juliapath=joinpath(Sys.BINDIR::String, julia_exename())) Return a julia command similar to the one of the running process. -Propagates the `--cpu-target`, `--sysimage`, --compile `, `--depwarn` -and `--inline` command line arguments. +Propagates any of the `--cpu-target`, `--sysimage`, `--compile`, `--sysimage-native-code`, +`--compiled-modules`, `--inline`, `--check-bounds`, `--opt_level`, `-g`, +`--code-coverage`, and `--depwarn` +command line arguments that are not at their default values. + +Among others, `--math-mode`, `--warn-overwrite`, and `--trace_precompile` are notably not propagated currently. !!! compat "Julia 1.1" - The `--inline` flag is only propagated in Julia 1.1 and later. + Only the `--cpu-target`, `--sysimage`, `--depwarn`, `--compile` and `--check-bounds` flags were propagated before Julia 1.1. """ function julia_cmd(julia=joinpath(Sys.BINDIR::String, julia_exename())) opts = JLOptions() cpu_target = unsafe_string(opts.cpu_target) image_file = unsafe_string(opts.image_file) - compile = if opts.compile_enabled == 0 - "no" - elseif opts.compile_enabled == 2 - "all" - elseif opts.compile_enabled == 3 - "min" - else - "yes" - end - depwarn = if opts.depwarn == 0 - "no" - elseif opts.depwarn == 2 - "error" - else - "yes" - end - inline = if opts.can_inline == 0 - "no" - else - "yes" - end - `$julia -C$cpu_target -J$image_file --compile=$compile --depwarn=$depwarn --inline=$inline` + addflags = String[] + let compile = if opts.compile_enabled == 0 + "no" + elseif opts.compile_enabled == 2 + "all" + elseif opts.compile_enabled == 3 + "min" + else + "" # default = "yes" + end + isempty(compile) || push!(addflags, "--compile=$compile") + end + let depwarn = if opts.depwarn == 0 + "no" + elseif opts.depwarn == 2 + "error" + else + "" # default = "yes" + end + isempty(depwarn) || push!(addflags, "--depwarn=$depwarn") + end + let check_bounds = if opts.check_bounds == 1 + "yes" # on + elseif opts.check_bounds == 2 + "no" # off + else + "" # "default" + end + isempty(check_bounds) || push!(addflags, "--check-bounds=$check_bounds") + end + opts.can_inline == 0 && push!(addflags, "--inline=no") + opts.use_compiled_modules == 0 && push!(addflags, "--compiled-modules=no") + opts.opt_level == 2 || push!(addflags, "-O$(opts.opt_level)") + push!(addflags, "-g$(opts.debug_level)") + if opts.code_coverage != 0 + # Forward the code-coverage flag only if applicable (if the filename is pid-dependent) + coverage_file = (opts.output_code_coverage != C_NULL) ? unsafe_string(opts.output_code_coverage) : "" + if isempty(coverage_file) || occursin("%p", coverage_file) + if opts.code_coverage == 1 + push!(addflags, "--code-coverage=user") + elseif opts.code_coverage == 2 + push!(addflags, "--code-coverage=all") + end + isempty(coverage_file) || push!(addflags, "--code-coverage=$coverage_file") + end + end + if opts.malloc_log != 0 + if opts.malloc_log == 1 + push!(addflags, "--track-allocation=user") + elseif opts.malloc_log == 2 + push!(addflags, "--track-allocation=all") + end + end + return `$julia -C$cpu_target -J$image_file $addflags` end function julia_exename() diff --git a/src/codegen.cpp b/src/codegen.cpp index 9a8da73e388ac..9f14b3b7efda7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1732,20 +1732,68 @@ static void write_log_data(logdata_t &logData, const char *extension) } extern "C" int jl_getpid(); -extern "C" void jl_write_coverage_data(void) + +static void write_lcov_data(logdata_t &logData, const std::string &outfile) { - std::ostringstream stm; - stm << jl_getpid(); - std::string outf = "." + stm.str() + ".cov"; - write_log_data(coverageData, outf.c_str()); + std::ofstream outf(outfile.c_str(), std::ofstream::ate | std::ofstream::out); + //std::string base = std::string(jl_options.julia_bindir); + //base = base + "/../share/julia/base/"; + logdata_t::iterator it = logData.begin(); + for (; it != logData.end(); it++) { + const std::string &filename = it->first(); + const std::vector &values = it->second; + if (!values.empty()) { + //if (!isabspath(filename.c_str())) + // filename = base + filename; + outf << "SF:" << filename << std::endl; + size_t n_covered = 0; + size_t n_instrumented = 0; + size_t lno = 0; + for (auto &itv : values) { + if (itv) { + logdata_block &data = *itv; + for (int i = 0; i < logdata_blocksize; i++) { + auto cov = data[i]; + if (cov > 0) { + n_instrumented++; + if (cov > 1) + n_covered++; + outf << "DA:" << lno << ',' << (cov - 1) << std::endl; + } + lno++; + } + } + else { + lno += logdata_blocksize; + } + } + outf << "LH:" << n_covered << std::endl; + outf << "LF:" << n_instrumented << std::endl; + outf << "end_of_record" << std::endl; + } + } + outf.close(); +} + +extern "C" void jl_write_coverage_data(const char *output) +{ + if (output) { + StringRef output_pattern(output); + if (output_pattern.endswith(".info")) + write_lcov_data(coverageData, jl_format_filename(output_pattern)); + } + else { + std::ostringstream stm; + stm << "." << jl_getpid() << ".cov"; + write_log_data(coverageData, stm.str().c_str()); + } } extern "C" void jl_write_malloc_log(void) { std::ostringstream stm; - stm << jl_getpid(); - std::string outf = "." + stm.str() + ".mem"; - write_log_data(mallocData, outf.c_str()); + stm << "." << jl_getpid() << ".mem"; + write_log_data(mallocData, stm.str().c_str()); } // --- constant determination --- diff --git a/src/init.c b/src/init.c index c3e4ede715b56..59e04998a85b5 100644 --- a/src/init.c +++ b/src/init.c @@ -163,7 +163,7 @@ static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg) jl_uv_exitcleanup_add(handle, (struct uv_shutdown_queue*)arg); } -void jl_write_coverage_data(void); +void jl_write_coverage_data(const char*); void jl_write_malloc_log(void); void jl_write_compiler_output(void); @@ -222,7 +222,7 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) jl_write_compiler_output(); jl_print_gc_stats(JL_STDERR); if (jl_options.code_coverage) - jl_write_coverage_data(); + jl_write_coverage_data(jl_options.output_code_coverage); if (jl_options.malloc_log) jl_write_malloc_log(); if (jl_base_module) { @@ -462,7 +462,7 @@ int isabspath(const char *in) } static char *abspath(const char *in, int nprefix) -{ // compute an absolute path location, so that chdir doesn't change the file reference +{ // compute an absolute realpath location, so that chdir doesn't change the file reference // ignores (copies directly over) nprefix characters at the start of abspath #ifndef _OS_WINDOWS_ char *out = realpath(in + nprefix, NULL); @@ -495,6 +495,8 @@ static char *abspath(const char *in, int nprefix) jl_error("fatal error: unexpected error while retrieving current working directory"); } out = (char*)malloc(path_size + 1 + sz + nprefix); + if (!out) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); memcpy(out, in, nprefix); memcpy(out + nprefix, path, path_size); out[nprefix + path_size] = PATHSEPSTRING[0]; @@ -508,6 +510,8 @@ static char *abspath(const char *in, int nprefix) jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); } char *out = (char*)malloc(n + nprefix); + if (!out) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); DWORD m = GetFullPathName(in + nprefix, n, out + nprefix, NULL); if (n != m + 1) { jl_error("fatal error: jl_options.image_file path too long or GetFullPathName failed"); @@ -517,6 +521,38 @@ static char *abspath(const char *in, int nprefix) return out; } +// create an absolute-path copy of the input path format string +// formed as `joinpath(replace(pwd(), "%" => "%%"), in)` +// unless `in` starts with `%` +static const char *absformat(const char *in) +{ + if (in[0] == '%' || isabspath(in)) + return in; + // get an escaped copy of cwd + size_t path_size = PATH_MAX; + char path[PATH_MAX]; + if (uv_cwd(path, &path_size)) { + jl_error("fatal error: unexpected error while retrieving current working directory"); + } + size_t sz = strlen(in) + 1; + size_t i, fmt_size = 0; + for (i = 0; i < path_size; i++) + fmt_size += (path[i] == '%' ? 2 : 1); + char *out = (char*)malloc(fmt_size + 1 + sz); + if (!out) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); + fmt_size = 0; + for (i = 0; i < path_size; i++) { // copy-replace pwd portion + char c = path[i]; + out[fmt_size++] = c; + if (c == '%') + out[fmt_size++] = '%'; + } + out[fmt_size++] = PATHSEPSTRING[0]; // path sep + memcpy(out + fmt_size, in, sz); // copy over format, including nul + return out; +} + static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) { // this function resolves the paths in jl_options to absolute file locations as needed // and it replaces the pointers to `julia_bindir`, `julia_bin`, `image_file`, and output file paths @@ -527,6 +563,8 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) // calling `julia_init()` char *free_path = (char*)malloc(PATH_MAX); size_t path_size = PATH_MAX; + if (!free_path) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); if (uv_exepath(free_path, &path_size)) { jl_error("fatal error: unexpected error while retrieving exepath"); } @@ -534,6 +572,8 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_error("fatal error: jl_options.julia_bin path too long"); } jl_options.julia_bin = (char*)malloc(path_size+1); + if (!jl_options.julia_bin) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); memcpy((char*)jl_options.julia_bin, free_path, path_size); ((char*)jl_options.julia_bin)[path_size] = '\0'; if (!jl_options.julia_bindir) { @@ -550,6 +590,8 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) if (rel == JL_IMAGE_JULIA_HOME && !isabspath(jl_options.image_file)) { // build time path, relative to JULIA_BINDIR free_path = (char*)malloc(PATH_MAX); + if (!free_path) + jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno)); int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", jl_options.julia_bindir, jl_options.image_file); if (n >= PATH_MAX || n < 0) { @@ -572,8 +614,10 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_options.outputbc = abspath(jl_options.outputbc, 0); if (jl_options.machine_file) jl_options.machine_file = abspath(jl_options.machine_file, 0); - if (jl_options.project && strncmp(jl_options.project, "@.", strlen(jl_options.project)) != 0) + if (jl_options.project && (strcmp(jl_options.project, "@.") != 0 || strcmp(jl_options.project, "@") != 0)) jl_options.project = abspath(jl_options.project, 0); + if (jl_options.output_code_coverage) + jl_options.output_code_coverage = absformat(jl_options.output_code_coverage); const char **cmdp = jl_options.cmds; if (cmdp) { @@ -600,6 +644,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_get_ptls_states_getter(); #endif jl_ptls_t ptls = jl_get_ptls_states(); + (void)ptls; assert(ptls); // make sure early that we have initialized ptls jl_safepoint_init(); libsupport_init(); htable_new(&jl_current_modules, 0); diff --git a/src/jloptions.c b/src/jloptions.c index 42fdafb9d0dcd..3e5e2f20c096e 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -68,6 +68,7 @@ jl_options_t jl_options = { 0, // quiet NULL, // output-jit-bc NULL, // output-o NULL, // output-ji + NULL, // output-code_coverage 0, // incremental 0 // image_file_specified }; @@ -129,6 +130,9 @@ static const char opts[] = // instrumentation options " --code-coverage={none|user|all}, --code-coverage\n" " Count executions of source lines (omitting setting is equivalent to \"user\")\n" + " --code-coverage=tracefile.info\n" + " Append coverage information to the LCOV tracefile (filename supports format tokens).\n" +// TODO: These TOKENS are defined in `runtime_ccall.cpp`. A more verbose `--help` should include that list here. " --track-allocation={none|user|all}, --track-allocation\n" " Count bytes allocated by each source line\n\n" @@ -437,12 +441,18 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) break; case opt_code_coverage: if (optarg != NULL) { - if (!strcmp(optarg,"user")) + size_t endof = strlen(optarg); + if (!strcmp(optarg, "user")) codecov = JL_LOG_USER; - else if (!strcmp(optarg,"all")) + else if (!strcmp(optarg, "all")) codecov = JL_LOG_ALL; - else if (!strcmp(optarg,"none")) + else if (!strcmp(optarg, "none")) codecov = JL_LOG_NONE; + else if (endof > 5 && !strcmp(optarg + endof - 5, ".info")) { + if (codecov == JL_LOG_NONE) + codecov = JL_LOG_ALL; + jl_options.output_code_coverage = optarg; + } else jl_errorf("julia: invalid argument to --code-coverage (%s)", optarg); break; diff --git a/src/julia.h b/src/julia.h index fbc1eb2461b66..9624abba6acb2 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1810,6 +1810,7 @@ typedef struct { const char *outputjitbc; const char *outputo; const char *outputji; + const char *output_code_coverage; int8_t incremental; int8_t image_file_specified; } jl_options_t; @@ -1820,6 +1821,7 @@ JL_DLLEXPORT ssize_t jl_sizeof_jl_options(void); // Parse an argc/argv pair to extract general julia options, passing back out // any arguments that should be passed on to the script. JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp); +JL_DLLEXPORT char *jl_format_filename(const char *output_pattern); // Set julia-level ARGS array according to the arguments provided in // argc/argv diff --git a/src/processor.cpp b/src/processor.cpp index bcc524f07d7ac..539ff22e7e914 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -2,6 +2,10 @@ // Processor feature detection +#include "llvm-version.h" +#include +#include + #include "processor.h" #include "julia.h" @@ -10,10 +14,6 @@ #include #include -#include "llvm-version.h" -#include -#include - #include "julia_assert.h" // CPU target string is a list of strings separated by `;` each string starts with a CPU diff --git a/src/processor.h b/src/processor.h index 8fc004364c6a5..114e46912c2a9 100644 --- a/src/processor.h +++ b/src/processor.h @@ -208,4 +208,5 @@ struct jl_target_spec_t { std::vector jl_get_llvm_clone_targets(void); std::string jl_get_cpu_name_llvm(void); std::string jl_get_cpu_features_llvm(void); +std::string jl_format_filename(llvm::StringRef output_pattern); #endif diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 60b03adcaa87f..d66ba27914ec8 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -5,6 +5,8 @@ #include #include #include +#include + #include "julia.h" #include "julia_internal.h" #include "processor.h" @@ -107,6 +109,84 @@ jl_value_t *jl_get_JIT(void) return jl_pchar_to_string(HostJITName.data(), HostJITName.size()); } +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +extern "C" int jl_getpid(); + +// Form a file name from a pattern made by replacing tokens, +// similar to many of those provided by ssh_config TOKENS: +// +// %% A literal `%'. +// %p The process PID +// %d Local user's home directory. +// %i The local user ID. +// %L The local hostname. +// %l The local hostname, including the domain name. +// %u The local username. +std::string jl_format_filename(StringRef output_pattern) +{ + std::string buf; + llvm::raw_string_ostream outfile(buf); + bool special = false; + char hostname[MAXHOSTNAMELEN + 1]; + uv_passwd_t pwd; + bool got_pwd = false; + for (auto c : output_pattern) { + if (special) { + if (!got_pwd && (c == 'i' || c == 'd' || c == 'u')) { + uv_os_get_passwd(&pwd); + got_pwd = true; + } + switch (c) { + case 'p': + outfile << jl_getpid(); + break; + case 'd': + outfile << pwd.homedir; + break; + case 'i': + outfile << pwd.uid; + break; + case 'l': + if (getdomainname(hostname, sizeof(hostname)) == 0) { + hostname[sizeof(hostname) - 1] = '\0'; /* Null terminate, just to be safe. */ + outfile << hostname; + } + JL_FALLTHROUGH; + case 'L': + if (gethostname(hostname, sizeof(hostname)) == 0) { + hostname[sizeof(hostname) - 1] = '\0'; /* Null terminate, just to be safe. */ + outfile << hostname; + } + break; + case 'u': + outfile << pwd.username; + break; + default: + outfile << c; + break; + } + special = false; + } + else if (c == '%') { + special = true; + } + else { + outfile << c; + } + } + if (got_pwd) + uv_os_free_passwd(&pwd); + return outfile.str(); +} + +extern "C" JL_DLLEXPORT char *jl_format_filename(const char *output_pattern) +{ + return strdup(jl_format_filename(StringRef(output_pattern)).c_str()); +} + static void *trampoline_freelist; diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 473a0452adfeb..d5a756a98a1b5 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -24,8 +24,27 @@ function readchomperrors(exename::Cmd) return (success(p), fetch(o), fetch(e)) end +function format_filename(s) + p = ccall(:jl_format_filename, Cstring, (Cstring,), s) + r = unsafe_string(p) + ccall(:free, Cvoid, (Cstring,), p) + return r +end -let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` +let + fn = format_filename("a%d %p %i %L %l %u z") + hd = withenv("HOME" => nothing) do + homedir() + end + @test startswith(fn, "a$hd ") + @test endswith(fn, " z") + @test !occursin('%', fn) + @test occursin(" $(getpid()) ", fn) + @test occursin(" $(Libc.gethostname()) ", fn) + @test format_filename("%a%%b") == "a%b" +end + +let exename = `$(Base.julia_cmd()) --startup-file=no` # tests for handling of ENV errors let v = writereadpipeline("println(\"REPL: \", @which(less), @isdefined(InteractiveUtils))", setenv(`$exename -i -E 'empty!(LOAD_PATH); @isdefined InteractiveUtils'`, @@ -65,7 +84,7 @@ let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` end end -let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` +let exename = `$(Base.julia_cmd()) --startup-file=no` # --version let v = split(read(`$exename -v`, String), "julia version ")[end] @test Base.VERSION_STRING == chomp(v) @@ -186,14 +205,36 @@ let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` @test !success(`$exename --history-file=false`) # --code-coverage - @test readchomp(`$exename -E "Bool(Base.JLOptions().code_coverage)"`) == "false" - @test readchomp(`$exename -E "Bool(Base.JLOptions().code_coverage)" - --code-coverage=none`) == "false" - - @test readchomp(`$exename -E "Bool(Base.JLOptions().code_coverage)" - --code-coverage`) == "true" - @test readchomp(`$exename -E "Bool(Base.JLOptions().code_coverage)" - --code-coverage=user`) == "true" + mktempdir() do dir + helperdir = joinpath(@__DIR__, "testhelpers") + inputfile = joinpath(helperdir, "coverage_file.jl") + expected = read(joinpath(helperdir, "coverage_file.info"), String) + covfile = replace(joinpath(dir, "coverage.info"), "%" => "%%") + @test !isfile(covfile) + defaultcov = readchomp(`$exename -E "Bool(Base.JLOptions().code_coverage)" -L $inputfile`) + opts = Base.JLOptions() + coverage_file = (opts.output_code_coverage != C_NULL) ? unsafe_string(opts.output_code_coverage) : "" + @test !isfile(covfile) + @test defaultcov == string(opts.code_coverage != 0 && (isempty(coverage_file) || occursin("%p", coverage_file))) + @test readchomp(`$exename -E "Base.JLOptions().code_coverage" -L $inputfile + --code-coverage=$covfile --code-coverage=none`) == "0" + @test !isfile(covfile) + @test readchomp(`$exename -E "Base.JLOptions().code_coverage" -L $inputfile + --code-coverage=$covfile --code-coverage`) == "1" + @test isfile(covfile) + @test occursin(expected, read(covfile, String)) + rm(covfile) + @test readchomp(`$exename -E "Base.JLOptions().code_coverage" -L $inputfile + --code-coverage=$covfile --code-coverage=user`) == "1" + @test isfile(covfile) + @test occursin(expected, read(covfile, String)) + rm(covfile) + @test readchomp(`$exename -E "Base.JLOptions().code_coverage" -L $inputfile + --code-coverage=$covfile --code-coverage=all`) == "2" + @test isfile(covfile) + @test occursin(expected, read(covfile, String)) + rm(covfile) + end # --track-allocation @test readchomp(`$exename -E "Bool(Base.JLOptions().malloc_log)"`) == "false" @@ -242,11 +283,13 @@ let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes --startup-file=no` let JL_OPTIONS_CHECK_BOUNDS_DEFAULT = 0, JL_OPTIONS_CHECK_BOUNDS_ON = 1, JL_OPTIONS_CHECK_BOUNDS_OFF = 2 - @test parse(Int,readchomp(`$exename -E "Int(Base.JLOptions().check_bounds)"`)) == + exename_default_checkbounds = `$exename` + filter!(a -> !startswith(a, "--check-bounds="), exename_default_checkbounds.exec) + @test parse(Int, readchomp(`$exename_default_checkbounds -E "Int(Base.JLOptions().check_bounds)"`)) == JL_OPTIONS_CHECK_BOUNDS_DEFAULT - @test parse(Int,readchomp(`$exename -E "Int(Base.JLOptions().check_bounds)" + @test parse(Int, readchomp(`$exename -E "Int(Base.JLOptions().check_bounds)" --check-bounds=yes`)) == JL_OPTIONS_CHECK_BOUNDS_ON - @test parse(Int,readchomp(`$exename -E "Int(Base.JLOptions().check_bounds)" + @test parse(Int, readchomp(`$exename -E "Int(Base.JLOptions().check_bounds)" --check-bounds=no`)) == JL_OPTIONS_CHECK_BOUNDS_OFF end # check-bounds takes yes/no as argument @@ -436,7 +479,7 @@ end libjulia = abspath(Libdl.dlpath((ccall(:jl_is_debugbuild, Cint, ()) != 0) ? "libjulia-debug" : "libjulia")) # test error handling code paths of running --sysimage -let exename = joinpath(Sys.BINDIR, Base.julia_exename()), +let exename = Base.julia_cmd() sysname = unsafe_string(Base.JLOptions().image_file) for nonexist_image in ( joinpath(@__DIR__, "nonexistent"), @@ -467,7 +510,7 @@ let exename = joinpath(Sys.BINDIR, Base.julia_exename()), end end -let exename = `$(Base.julia_cmd()) --sysimage-native-code=yes` +let exename = Base.julia_cmd() # --startup-file let JL_OPTIONS_STARTUPFILE_ON = 1, JL_OPTIONS_STARTUPFILE_OFF = 2 @@ -563,6 +606,12 @@ end # Issue #29855 for yn in ("no", "yes") - exename = `$(Base.julia_cmd()) --startup-file=no --inline=$yn` - @test occursin("--inline=$yn", first(writereadpipeline("Base.julia_cmd()", exename))) + exename = `$(Base.julia_cmd()) --inline=no --startup-file=no --inline=$yn` + v = writereadpipeline("Base.julia_cmd()", exename) + if yn == "no" + @test occursin(r" --inline=no", v[1]) + else + @test !occursin(" --inline", v[1]) + end + @test v[2] end diff --git a/test/spawn.jl b/test/spawn.jl index 2840f5ecea030..3a165d6254a03 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -524,11 +524,7 @@ end # Sys.which() testing psep = if Sys.iswindows() ";" else ":" end withenv("PATH" => "$(Sys.BINDIR)$(psep)$(ENV["PATH"])") do - julia_exe = joinpath(Sys.BINDIR, "julia") - if Sys.iswindows() - julia_exe *= ".exe" - end - + julia_exe = joinpath(Sys.BINDIR, Base.julia_exename()) @test Sys.which("julia") == realpath(julia_exe) @test Sys.which(julia_exe) == realpath(julia_exe) end diff --git a/test/testenv.jl b/test/testenv.jl index fa37efbfc32f2..9094ab66f197e 100644 --- a/test/testenv.jl +++ b/test/testenv.jl @@ -10,20 +10,20 @@ if !@isdefined(testenv_defined) if haskey(ENV, "JULIA_TEST_EXEFLAGS") const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` else - inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` - cov_flag = `` - if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` - elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` + const test_exeflags = Base.julia_cmd() + filter!(test_exeflags.exec) do c + return !(startswith(c, "--depwarn") || startswith(c, "--check-bounds")) end - const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` + push!(test_exeflags.exec, "--check-bounds=yes") + push!(test_exeflags.exec, "--startup-file=no") + push!(test_exeflags.exec, "--depwarn=error") end if haskey(ENV, "JULIA_TEST_EXENAME") + popfirst!(test_exeflags.exec) const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` else - const test_exename = `$(joinpath(Sys.BINDIR, Base.julia_exename()))` + const test_exename = popfirst!(test_exeflags.exec) end addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) diff --git a/test/testhelpers/coverage_file.info b/test/testhelpers/coverage_file.info new file mode 100644 index 0000000000000..6d99187c9b097 --- /dev/null +++ b/test/testhelpers/coverage_file.info @@ -0,0 +1,10 @@ +SF:/data/vtjnash/julia/test/testhelpers/coverage_file.jl +DA:4,2 +DA:5,0 +DA:7,1 +DA:8,1 +DA:9,5 +DA:11,1 +LH:5 +LF:6 +end_of_record diff --git a/test/testhelpers/coverage_file.jl b/test/testhelpers/coverage_file.jl new file mode 100644 index 0000000000000..87ab5766f6046 --- /dev/null +++ b/test/testhelpers/coverage_file.jl @@ -0,0 +1,17 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +function code_coverage_test() + if rand(1:2) == 3 + return "hello" + else + r = Int[] + for i = 1:3 + push!(r, i) + end + return r + end +end + +exit(code_coverage_test() == [1, 2, 3] ? 0 : 1) + +# end of file