Module: Tap::Test::Utils

Defined in:
lib/tap/test/utils.rb

Defined Under Namespace

Classes: DereferenceError

Class Method Summary collapse

Class Method Details

.clear_dir(dir) ⇒ Object

Attempts to recursively remove the specified method directory and all files within it. Raises an error if the removal does not succeed.



182
183
184
185
# File 'lib/tap/test/utils.rb', line 182

def clear_dir(dir)
  # clear out the folder if it exists
  FileUtils.rm_r(dir) if File.exists?(dir)
end

.dereference(source_dirs, reference_dir, pattern = '**/*.ref', tempdir = Dir::tmpdir) ⇒ Object

Dereferences source files with reference files for the duration of the block. The mappings of source to reference files are determined using reference_map; dereferenced files are at the same location as the source files, but with the ‘.ref’ extname removed.

Notes:

  • The reference extname is implicitly specified in pattern; the final extname of the source file is removed during dereferencing regardless of what it is.



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
# File 'lib/tap/test/utils.rb', line 95

def dereference(source_dirs, reference_dir, pattern='**/*.ref', tempdir=Dir::tmpdir)
  mapped_paths = []
  begin
    [*source_dirs].each do |source_dir|
      reference_map(source_dir, reference_dir, pattern).each do |source, reference|
        
        # move the source file to a temporary location
        tempfile = Tempfile.new(File.basename(source), tempdir)
        tempfile.close
        FileUtils.mv(source, tempfile.path)
        
        # copy the reference to the target
        target = source.chomp(File.extname(source))
        FileUtils.cp_r(reference, target)
        
        mapped_paths << [target, source, tempfile]
      end
    end unless reference_dir == nil
    
    yield
    
  ensure
    mapped_paths.each do |target, source, tempfile|
      # remove the target and restore the original source file
      FileUtils.rm_r(target) if File.exists?(target)
      FileUtils.mv(tempfile.path, source)
    end
  end
end

.each_pair(a, b, &block) ⇒ Object

Yields to the input block for each pair of entries in the input arrays. An error is raised if the input arrays do not have equal numbers of entries.



160
161
162
163
164
# File 'lib/tap/test/utils.rb', line 160

def each_pair(a, b, &block) # :yields: entry_a, entry_b,
  each_pair_with_index(a,b) do |entry_a, entry_b, index|
    yield(entry_a, entry_b)
  end
end

.each_pair_with_index(a, b, error_msg = nil, &block) ⇒ Object

Same as each_pair but yields the index of the entries as well.



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tap/test/utils.rb', line 167

def each_pair_with_index(a, b, error_msg=nil, &block) # :yields: entry_a, entry_b, index
  a = [a] unless a.kind_of?(Array)
  b = [b] unless b.kind_of?(Array)
  
  unless a.length == b.length
    raise ArgumentError, (error_msg || "The input arrays must have an equal number of entries.")
  end
  
  0.upto(a.length-1) do |index|
    yield(a[index], b[index], index)
  end
end

.reference_map(source_dir, reference_dir, pattern = '**/*.ref') ⇒ Object

Generates an array of [source, reference] pairs mapping source files to reference files under the source and reference dirs, respectively. Only files under source dir matching the pattern will be mapped. Mappings are either (in this order):

  • the path under reference_dir contained in the source file

  • a direct translation of the source file from the source to the reference dir, minus the extname

Notes:

  • Source files may contain comments but should otherwise consist only of indentation (which is stripped) and the reference path.

  • If a mapped path cannot be found, dereference raises

    a DereferenceError.

example

root
|- input
|   |- dir.ref
|   |- ignored.txt
|   |- one.txt.ref
|   `- two.txt.ref
`- ref
    |- dir
    |- one.txt
    `- path
        `- to
            `- two.txt

The ‘two.txt.ref’ file contains a reference path:

File.read('/root/input/two.txt.ref')    # => 'path/to/two.txt'

Now:

reference_map('/root/input', '/root/ref')
# => [
# ['/root/input/dir.ref',     '/root/ref/dir'],
# ['/root/input/one.txt.ref', '/root/ref/one.txt'],
# ['/root/input/two.txt.ref', '/root/ref/path/to/two.txt']]

And since no path matches ‘ignored.txt’:

reference_map('/root/input', '/root/ref', '**/*.txt')     
# !> DereferenceError


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/tap/test/utils.rb', line 62

def reference_map(source_dir, reference_dir, pattern='**/*.ref')
  Dir.glob(File.join(source_dir, pattern)).sort.collect do |source|
    # use the path specified in the source file
    relative_path = File.read(source).gsub(/#.*$/, "").strip
    
    # use the relative filepath of the source file to the
    # source dir (minus the extname) if no path is specified
    if relative_path.empty?
      relative_path = Tap::Root.relative_filepath(source_dir, source).chomp(File.extname(source))
    end
    
    reference = File.join(reference_dir, relative_path)
    
    # raise an error if no reference file is found
    unless File.exists?(reference)
      raise DereferenceError, "no reference found for: #{source}"
    end

    [source, reference]
  end
end

.template(paths, attributes = {}, tempdir = Dir::tmpdir) ⇒ Object

Uses a Tap::Support::Templater to template and replace the contents of path, for the duration of the block. The attributes will be available in the template context.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/tap/test/utils.rb', line 128

def template(paths, attributes={}, tempdir=Dir::tmpdir)
  mapped_paths = []
  begin
    [*paths].each do |path|
      # move the source file to a temporary location
      tempfile = Tempfile.new(File.basename(path), tempdir)
      tempfile.close
      FileUtils.cp(path, tempfile.path)
        
      # template the source file
      content = File.read(path)
      File.open(path, "wb") do |file|
        file << Support::Templater.new(content, attributes).build
      end
      
      mapped_paths << [path, tempfile]
    end

    yield
    
  ensure
    mapped_paths.each do |path, tempfile|
      # restore the original source file
      FileUtils.rm(path) if File.exists?(path)
      FileUtils.mv(tempfile.path, path)
    end
  end
end

.try_remove_dir(dir) ⇒ Object

Attempts to remove the specified directory. The root will not be removed if the directory does not exist, or is not empty.



190
191
192
193
194
195
196
197
# File 'lib/tap/test/utils.rb', line 190

def try_remove_dir(dir)
  # Remove the directory if possible
  begin
    FileUtils.rmdir(dir) if File.exists?(dir) && Dir.glob(File.join(dir, "*")).empty?
  rescue
    # rescue cases where there is a hidden file, for example .svn
  end
end

.whitespace_escape(str) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
# File 'lib/tap/test/utils.rb', line 214

def whitespace_escape(str)
  str.to_s.gsub(/\s/) do |match|
    case match
    when "\n" then "\\n\n"
    when "\t" then "\\t"
    when "\r" then "\\r"
    when "\f" then "\\f"
    else match
    end
  end
end

.with_argv(argv = []) ⇒ Object

Sets ARGV to the input argv for the duration of the block.



200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/tap/test/utils.rb', line 200

def with_argv(argv=[])
  current_argv = ARGV.dup
  begin
    ARGV.clear
    ARGV.concat(argv)
    
    yield
    
  ensure
    ARGV.clear
    ARGV.concat(current_argv)
  end
end