diff --git a/spec/compiler/codegen/private_spec.cr b/spec/compiler/codegen/private_spec.cr index 613d0b0bd162..c2d2452952c7 100644 --- a/spec/compiler/codegen/private_spec.cr +++ b/spec/compiler/codegen/private_spec.cr @@ -14,11 +14,9 @@ describe "Codegen: private" do ] compiler.prelude = "empty" - output_filename = File.tempname("crystal-spec-output") - - compiler.compile sources, output_filename - ensure - File.delete(output_filename) if output_filename + with_temp_executable "crystal-spec-output" do |output_filename| + compiler.compile sources, output_filename + end end it "codegens overloaded private def in same file" do @@ -39,11 +37,9 @@ describe "Codegen: private" do ] compiler.prelude = "empty" - output_filename = File.tempname("crystal-spec-output") - - compiler.compile sources, output_filename - ensure - File.delete(output_filename) if output_filename + with_temp_executable "crystal-spec-output" do |output_filename| + compiler.compile sources, output_filename + end end it "doesn't include filename for private types" do diff --git a/spec/compiler/compiler_spec.cr b/spec/compiler/compiler_spec.cr index 6854302095fc..a0e24c795727 100644 --- a/spec/compiler/compiler_spec.cr +++ b/spec/compiler/compiler_spec.cr @@ -7,7 +7,7 @@ describe "Compiler" do end it "compiles a file" do - with_tempfile "compiler_spec_output" do |path| + with_temp_executable "compiler_spec_output" do |path| Crystal::Command.run ["build"].concat(program_flags_options).concat([compiler_datapath("compiler_sample"), "-o", path]) File.exists?(path).should be_true @@ -18,7 +18,7 @@ describe "Compiler" do it "runs subcommand in preference to a filename " do Dir.cd compiler_datapath do - with_tempfile "compiler_spec_output" do |path| + with_temp_executable "compiler_spec_output" do |path| Crystal::Command.run ["build"].concat(program_flags_options).concat(["compiler_sample", "-o", path]) File.exists?(path).should be_true diff --git a/spec/compiler/util_spec.cr b/spec/compiler/util_spec.cr new file mode 100644 index 000000000000..9a4815a9e588 --- /dev/null +++ b/spec/compiler/util_spec.cr @@ -0,0 +1,20 @@ +require "spec" +require "compiler/crystal/util" + +describe Crystal do + describe "normalize_path" do + sep = {{ flag?(:win32) ? "\\" : "/" }} + + it { Crystal.normalize_path("a").should eq ".#{sep}a" } + it { Crystal.normalize_path("./a/b").should eq ".#{sep}a#{sep}b" } + it { Crystal.normalize_path("../a/b").should eq ".#{sep}..#{sep}a#{sep}b" } + it { Crystal.normalize_path("/foo/bar").should eq "#{sep}foo#{sep}bar" } + + {% if flag?(:win32) %} + it { Crystal.normalize_path("C:\\foo\\bar").should eq "C:\\foo\\bar" } + it { Crystal.normalize_path("C:foo\\bar").should eq "C:foo\\bar" } + it { Crystal.normalize_path("\\foo\\bar").should eq "\\foo\\bar" } + it { Crystal.normalize_path("foo\\bar").should eq ".\\foo\\bar" } + {% end %} + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 0d17a2118e94..0a67b2f9f802 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -4,10 +4,10 @@ ENV["CRYSTAL_PATH"] = "#{__DIR__}/../src" require "spec" -{% skip_file if flag?(:win32) %} - require "../src/compiler/crystal/**" require "./support/syntax" +require "./support/tempfile" +require "./support/win32" class Crystal::Program def union_of(type1, type2, type3) @@ -114,22 +114,23 @@ def assert_no_errors(*args) semantic(*args) end -def warnings_result(code) - output_filename = Crystal.temp_executable("crystal-spec-output") - +def warnings_result(code, *, file = __FILE__) compiler = create_spec_compiler compiler.warnings = Warnings::All compiler.error_on_warnings = false compiler.prelude = "empty" # avoid issues in the current std lib compiler.color = false apply_program_flags(compiler.flags) - result = compiler.compile Compiler::Source.new("code.cr", code), output_filename - result.program.warning_failures + with_temp_executable("crystal-spec-output", file: file) do |output_filename| + result = compiler.compile Compiler::Source.new("code.cr", code), output_filename + + return result.program.warning_failures + end end def assert_warning(code, message, *, file = __FILE__, line = __LINE__) - warning_failures = warnings_result(code) + warning_failures = warnings_result(code, file: file) warning_failures.size.should eq(1), file, line warning_failures[0].should start_with(message), file, line end @@ -220,7 +221,7 @@ def create_spec_compiler compiler end -def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None, flags = nil) +def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug::None, flags = nil, *, file = __FILE__) if inject_primitives code = %(require "primitives"\n#{code}) end @@ -239,53 +240,24 @@ def run(code, filename = nil, inject_primitives = true, debug = Crystal::Debug:: ast.expressions[-1] = exps code = ast.to_s - output_filename = Crystal.temp_executable("crystal-spec-output") - compiler = create_spec_compiler compiler.debug = debug compiler.flags.concat flags if flags apply_program_flags(compiler.flags) - compiler.compile Compiler::Source.new("spec", code), output_filename - output = `#{Process.quote(output_filename)}` - File.delete(output_filename) + with_temp_executable("crystal-spec-output", file: file) do |output_filename| + compiler.compile Compiler::Source.new("spec", code), output_filename - SpecRunOutput.new(output) + output = `#{Process.quote(output_filename)}` + return SpecRunOutput.new(output) + end else new_program.run(code, filename: filename, debug: debug) end end -def build(code) - code_file = File.tempname("build_and_run_code") - - # write code to the temp file - File.write(code_file, code) - - binary_file = File.tempname("build_and_run_bin") - - `bin/crystal build #{encode_program_flags} #{Process.quote(code_file.path.to_s)} -o #{Process.quote(binary_file.path.to_s)}` - File.exists?(binary_file).should be_true - - yield binary_file -ensure - File.delete(code_file) if code_file - File.delete(binary_file) if binary_file -end - -def build_and_run(code) - build(code) do |binary_file| - out_io, err_io = IO::Memory.new, IO::Memory.new - status = Process.run(binary_file, output: out_io, error: err_io) - - {status, out_io.to_s, err_io.to_s} - end -end - -def test_c(c_code, crystal_code) - c_filename = "#{__DIR__}/temp_abi.c" - o_filename = "#{__DIR__}/temp_abi.o" - begin +def test_c(c_code, crystal_code, *, file = __FILE__) + with_tempfile("temp_abi.c", "temp_abi.o", file: file) do |c_filename, o_filename| File.write(c_filename, c_code) `#{Crystal::Compiler::CC} #{Process.quote(c_filename)} -c -o #{Process.quote(o_filename)}`.should be_truthy @@ -293,11 +265,8 @@ def test_c(c_code, crystal_code) yield run(%( require "prelude" - @[Link(ldflags: "#{o_filename}")] + @[Link(ldflags: #{o_filename.inspect})] #{crystal_code} )) - ensure - File.delete(c_filename) - File.delete(o_filename) end end diff --git a/spec/std/spec_helper.cr b/spec/std/spec_helper.cr index faee17463a46..b87590327247 100644 --- a/spec/std/spec_helper.cr +++ b/spec/std/spec_helper.cr @@ -1,29 +1,12 @@ require "spec" require "../support/tempfile" require "../support/fibers" +require "../support/win32" def datapath(*components) File.join("spec", "std", "data", *components) end -{% if flag?(:win32) %} - def pending_win32(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) - pending("#{description} [win32]", file, line, end_line) - end - - def pending_win32(*, describe, file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) - pending_win32(describe, file, line, end_line) { } - end -{% else %} - def pending_win32(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) - it(description, file, line, end_line, &block) - end - - def pending_win32(*, describe, file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) - describe(describe, file, line, end_line, &block) - end -{% end %} - private class Witness @checked = false @@ -92,8 +75,8 @@ def spawn_and_check(before : Proc(_), file = __FILE__, line = __LINE__, &block : end end -def compile_file(source_file, flags = %w(--debug)) - with_tempfile("executable_file") do |executable_file| +def compile_file(source_file, flags = %w(--debug), file = __FILE__) + with_temp_executable("executable_file", file: file) do |executable_file| Process.run("bin/crystal", ["build"] + flags + ["-o", executable_file, source_file]) File.exists?(executable_file).should be_true @@ -101,17 +84,17 @@ def compile_file(source_file, flags = %w(--debug)) end end -def compile_source(source, flags = %w(--debug)) - with_tempfile("source_file") do |source_file| +def compile_source(source, flags = %w(--debug), file = __FILE__) + with_tempfile("source_file", file: file) do |source_file| File.write(source_file, source) - compile_file(source_file, flags) do |executable_file| + compile_file(source_file, flags, file: file) do |executable_file| yield executable_file end end end -def compile_and_run_file(source_file, flags = %w(--debug)) - compile_file(source_file) do |executable_file| +def compile_and_run_file(source_file, flags = %w(--debug), file = __FILE__) + compile_file(source_file, file: file) do |executable_file| output, error = IO::Memory.new, IO::Memory.new status = Process.run executable_file, output: output, error: error @@ -119,9 +102,9 @@ def compile_and_run_file(source_file, flags = %w(--debug)) end end -def compile_and_run_source(source, flags = %w(--debug)) - with_tempfile("source_file") do |source_file| +def compile_and_run_source(source, flags = %w(--debug), file = __FILE__) + with_tempfile("source_file", file: file) do |source_file| File.write(source_file, source) - compile_and_run_file(source_file, flags) + compile_and_run_file(source_file, flags, file: file) end end diff --git a/spec/support/tempfile.cr b/spec/support/tempfile.cr index 4f527e35329c..0c47ee765e90 100644 --- a/spec/support/tempfile.cr +++ b/spec/support/tempfile.cr @@ -34,6 +34,15 @@ def with_tempfile(*paths, file = __FILE__) end end +def with_temp_executable(name, file = __FILE__) + {% if flag?(:win32) %} + name += ".exe" + {% end %} + with_tempfile(name, file: file) do |tempname| + yield tempname + end +end + if SPEC_TEMPFILE_CLEANUP at_exit do FileUtils.rm_r(SPEC_TEMPFILE_PATH) if Dir.exists?(SPEC_TEMPFILE_PATH) diff --git a/spec/support/win32.cr b/spec/support/win32.cr new file mode 100644 index 000000000000..da82d1ca24c3 --- /dev/null +++ b/spec/support/win32.cr @@ -0,0 +1,19 @@ +require "spec" + +{% if flag?(:win32) %} + def pending_win32(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) + pending("#{description} [win32]", file, line, end_line) + end + + def pending_win32(*, describe, file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) + pending_win32(describe, file, line, end_line) { } + end +{% else %} + def pending_win32(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) + it(description, file, line, end_line, &block) + end + + def pending_win32(*, describe, file = __FILE__, line = __LINE__, end_line = __END_LINE__, &block) + describe(describe, file, line, end_line, &block) + end +{% end %} diff --git a/src/compiler/crystal/util.cr b/src/compiler/crystal/util.cr index fe1ef625cb9c..578396c0c888 100644 --- a/src/compiler/crystal/util.cr +++ b/src/compiler/crystal/util.cr @@ -62,10 +62,8 @@ module Crystal end def self.normalize_path(path) - path_start = ".#{File::SEPARATOR}" - unless path.starts_with?(path_start) || path.starts_with?(File::SEPARATOR) - path = path_start + path - end - path.rstrip(File::SEPARATOR) + path = ::Path[path].normalize + path = ::Path["."] / path unless path.anchor + path.to_s end end diff --git a/src/prelude.cr b/src/prelude.cr index 810e27b395fc..5ccd0f959358 100644 --- a/src/prelude.cr +++ b/src/prelude.cr @@ -7,12 +7,6 @@ # to also add them to `docs_main.cr` if their content needs to # appear in the API docs. -private macro no_win(stmt) - {% unless flag?(:win32) %} - {{stmt}} - {% end %} -end - # This list requires ordered statements require "crystal/once" require "lib_c" @@ -57,7 +51,9 @@ require "intrinsics" require "io" require "kernel" require "math/math" -no_win require "mutex" +{% unless flag?(:win32) %} + require "mutex" +{% end %} require "named_tuple" require "nil" require "humanize" @@ -73,7 +69,9 @@ require "range" require "reference" require "regex" require "set" -no_win require "signal" +{% unless flag?(:win32) %} + require "signal" +{% end %} require "slice" require "static_array" require "struct"