File: example.rb

package info (click to toggle)
ruby-parslet 2.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,260 kB
  • sloc: ruby: 6,157; sh: 8; javascript: 3; makefile: 3
file content (121 lines) | stat: -rw-r--r-- 2,493 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
require 'tempfile'
require 'cod'

require 'site'
require 'fail_site'

class Example
  def initialize(title, file, line)
    @title = title
    @file, @line = file, line
    
    @lines = []
    
    @sites = {}
    @site_by_line = {}
  end
  
  def to_s
    "'#@title'"
  end
  
  def <<(line)
    @lines << line
  end
  
  attr_reader :output
  
  def skip?
    !@lines.grep(/# =>/)
  end
  
  def run
    # Create a tempfile per output
    tempfiles = [:err, :out].inject({}) { |h, name| 
      h[name] = Tempfile.new(name.to_s); h }
    
    # Where code results are communicated.  
    $instrumentation = Cod.pipe
    
    code = produce_example_code
    pid = fork do
      redirect_streams(tempfiles)
      # puts example_code
      eval(code, nil, @file, @line-2) 
    end
    Process.wait(pid)

    # Read these tempfiles.
    @output = tempfiles.inject({}) { |h, (name, io)| 
      io.rewind
      h[name] = io.read; 
      io.close 
      h }
            
    loop do
      begin
        site_id, probe_value = $instrumentation.get
      rescue Exception => ex
        break if ex.message.match(/All pipe ends/)
      end
      fail "No such site #{site_id}." unless @sites.has_key?(site_id)

      @sites[site_id].store probe_value
    end
    
    $instrumentation.close; $instrumentation = nil

    return $?.success?
  end
  
  def redirect_streams(io_hash)
    {
      out: $stdout, 
      err: $stderr
    }.each do |name, io|
      io.reopen(io_hash[name])
    end
  end
  
  def produce_example_code
    root = File.expand_path(File.dirname(__FILE__))

    '' <<
      "$:.unshift #{root.inspect}\n" <<
      "load 'prelude.rb'\n" <<
      instrument(@lines).join("\n") <<
      "\nload 'postscriptum.rb'\n"
  end
  def instrument(code)
    code.map { |line| 
      md = line.match(/(?<pre>.*)# (?<type>=>|raises) (?<expectation>.*)/) 
      next line unless md
      
      if md[:type] == 'raises'
        site = FailSite.new(line, md[:pre], md[:expectation].strip)
      else
        site = Site.new(line, md[:pre], md[:expectation].strip) 
      end

      add_site site
      site.to_instrumented_line }
  end
  def add_site(site)
    @sites[site.id] = site
    @site_by_line[site.original_line] = site
  end
  
  def produce_modified_code
    @lines.map { |line| 
      site = @site_by_line[line]
      next line unless site 
      
      site.format_documentation_line }
  end
  
  def check_expectations
    @sites.each do |_, site|
      site.check
    end
  end
end