File: spec_helper.cr

package info (click to toggle)
crystal 1.14.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 24,384 kB
  • sloc: javascript: 6,400; sh: 695; makefile: 269; ansic: 121; python: 105; cpp: 77; xml: 32
file content (138 lines) | stat: -rw-r--r-- 3,644 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
require "spec"
require "../support/tempfile"
require "../support/fibers"
require "../support/win32"
require "../support/wasm32"
require "../support/interpreted"

def datapath(*components)
  File.join("spec", "std", "data", *components)
end

private class Witness
  @checked = false

  def check
    @checked = true
  end

  def checked?
    @checked
  end
end

def spawn_and_wait(before : Proc(_), file = __FILE__, line = __LINE__, &block)
  spawn_and_check(before, file, line) do |w|
    block.call
    w.check
  end
end

def spawn_and_check(before : Proc(_), file = __FILE__, line = __LINE__, &block : Witness -> _)
  done = Channel(Exception?).new
  w = Witness.new

  # State of the "before" filter:
  # 0 - not started
  # 1 - started
  # 2 - completed
  x = Atomic(Int32).new(0)

  before_fiber = spawn do
    x.set(1)

    # This is a workaround to ensure the "before" fiber
    # is unscheduled. Otherwise it might stay alive running the event loop
    spawn(same_thread: true) do
      while x.get != 2
        Fiber.yield
      end
    end

    before.call
    x.set(2)
  end

  spawn do
    begin
      # Wait until the "before" fiber starts
      while x.get == 0
        Fiber.yield
      end

      # Now wait until the "before" fiber is blocked
      wait_until_blocked before_fiber
      block.call w

      done.send nil
    rescue e
      done.send e
    end
  end

  ex = done.receive
  raise ex if ex
  unless w.checked?
    fail "Failed to stress expected path", file, line
  end
end

def compile_file(source_file, *, bin_name = "executable_file", flags = %w(), file = __FILE__, &)
  # can't use backtick in interpreted code (#12241)
  pending_interpreted! "Unable to compile Crystal code in interpreted code"

  with_temp_executable(bin_name, file: file) do |executable_file|
    compiler = ENV["CRYSTAL_SPEC_COMPILER_BIN"]? || "bin/crystal"
    args = ["build"] + flags + ["-o", executable_file, source_file]
    output = IO::Memory.new
    status = Process.run(compiler, args, env: {
      "CRYSTAL_PATH"         => Crystal::PATH,
      "CRYSTAL_LIBRARY_PATH" => Crystal::LIBRARY_PATH,
      "CRYSTAL_CACHE_DIR"    => Crystal::CACHE_DIR,
    }, output: output, error: output)

    unless status.success?
      fail "Compiler command `#{compiler} #{args.join(" ")}` failed with status #{status}.#{"\n" if output}#{output}"
    end

    File.exists?(executable_file).should be_true

    yield executable_file
  end
end

def compile_source(source, flags = %w(), file = __FILE__, &)
  with_tempfile("source_file", file: file) do |source_file|
    File.write(source_file, source)
    compile_file(source_file, flags: flags, file: file) do |executable_file|
      yield executable_file
    end
  end
end

def compile_and_run_file(source_file, flags = %w(), runtime_args = %w(), file = __FILE__)
  compile_file(source_file, flags: flags, file: file) do |executable_file|
    output, error = IO::Memory.new, IO::Memory.new
    status = Process.run executable_file, args: runtime_args, output: output, error: error

    {status, output.to_s, error.to_s}
  end
end

def compile_and_run_source(source, flags = %w(), runtime_args = %w(), file = __FILE__)
  with_tempfile("source_file", file: file) do |source_file|
    File.write(source_file, source)
    compile_and_run_file(source_file, flags, runtime_args, file: file)
  end
end

def compile_and_run_source_with_c(c_code, crystal_code, flags = %w(--debug), file = __FILE__, &)
  with_temp_c_object_file(c_code, file: file) do |o_filename|
    yield compile_and_run_source(%(
    require "prelude"

    @[Link(ldflags: #{o_filename.inspect})]
    #{crystal_code}
    ))
  end
end