Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions spec/compiler/codegen/private_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions spec/compiler/compiler_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
20 changes: 20 additions & 0 deletions spec/compiler/util_spec.cr
Original file line number Diff line number Diff line change
@@ -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
67 changes: 18 additions & 49 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -239,65 +240,33 @@ 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

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
39 changes: 11 additions & 28 deletions spec/std/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -92,36 +75,36 @@ 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

yield executable_file
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

{status, output.to_s, error.to_s}
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
9 changes: 9 additions & 0 deletions spec/support/tempfile.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions spec/support/win32.cr
Original file line number Diff line number Diff line change
@@ -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 %}
8 changes: 3 additions & 5 deletions src/compiler/crystal/util.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
14 changes: 6 additions & 8 deletions src/prelude.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand Down