-
Notifications
You must be signed in to change notification settings - Fork 103
/
priority.rb
192 lines (161 loc) · 4.39 KB
/
priority.rb
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
require "fileutils"
module Test
module Unit
module Priority
class << self
def included(base)
base.extend(ClassMethods)
base.class_eval do
setup :priority_setup, :before => :prepend
teardown :priority_teardown, :after => :append
end
end
@@enabled = false
def enabled?
@@enabled
end
def enable
require "fileutils"
require "tmpdir"
@@enabled = true
end
def disable
@@enabled = false
end
@@default = :normal
def default
@@default || :normal
end
def default=(default)
@@default = default
end
def available_values
Checker.available_priorities
end
end
class Checker
class << self
def have_priority?(name)
singleton_class = (class << self; self; end)
singleton_class.method_defined?(priority_check_method_name(name))
end
def need_to_run?(test)
priority = test[:priority] || Priority.default
if have_priority?(priority)
__send__(priority_check_method_name(priority), test)
else
true
end
end
def available_priorities
methods(false).collect do |name|
/\Arun_priority_(.+)\?\z/ =~ name.to_s
$1
end.compact
end
def run_priority_must?(test)
true
end
def run_priority_important?(test)
rand > 0.1
end
def run_priority_high?(test)
rand > 0.3
end
def run_priority_normal?(test)
rand > 0.5
end
def run_priority_low?(test)
rand > 0.75
end
def run_priority_never?(test)
false
end
private
def priority_check_method_name(priority_name)
"run_priority_#{priority_name}?"
end
end
attr_reader :test
def initialize(test)
@test = test
end
def setup
FileUtils.rm_f(passed_file)
end
def teardown
if @test.__send__(:passed?)
FileUtils.touch(passed_file)
else
FileUtils.rm_f(passed_file)
end
end
def need_to_run?
!previous_test_success? or self.class.need_to_run?(@test)
end
private
def previous_test_success?
File.exist?(passed_file)
end
def result_dir
components = [
".test-result",
escape_class_name(@test.class.name || "AnonymousTestCase"),
escaped_method_name,
]
parent_directories = [File.dirname($0), Dir.pwd]
if Process.respond_to?(:uid)
parent_directories << File.join(Dir.tmpdir, Process.uid.to_s)
end
parent_directories.each do |parent_directory|
dir = File.expand_path(File.join(parent_directory, *components))
begin
FileUtils.mkdir_p(dir)
return dir
rescue Errno::EACCES
end
end
raise Errno::EACCES, parent_directories.join(", ")
end
def passed_file
File.join(result_dir, "passed")
end
def escape_class_name(class_name)
class_name.gsub(/(?:[: \\\/])/, "_")
end
def escaped_method_name
@test.method_name.to_s.gsub(/(?:[: ]|[!?=]$)/) do |matched|
case matched
when ":"
"_colon_"
when " "
"_"
when "!"
".destructive"
when "?"
".predicate"
when "="
".equal"
end
end
end
end
module ClassMethods
def priority(name, *tests)
unless Checker.have_priority?(name)
raise ArgumentError, "unknown priority: #{name}"
end
attribute(:priority, name, {:keep => true}, *tests)
end
end
def priority_setup
return unless Priority.enabled?
Checker.new(self).setup
end
def priority_teardown
return unless Priority.enabled?
Checker.new(self).teardown
end
end
end
end