fixman 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/History.txt +6 -0
- data/Manifest.txt +23 -0
- data/README.md +176 -0
- data/Rakefile +19 -0
- data/bin/fixman +50 -0
- data/lib/fixman.rb +13 -0
- data/lib/fixman/command_line.rb +184 -0
- data/lib/fixman/configuration.rb +161 -0
- data/lib/fixman/controller.rb +121 -0
- data/lib/fixman/raw_task.rb +103 -0
- data/lib/fixman/repository.rb +99 -0
- data/lib/fixman/task.rb +19 -0
- data/lib/fixman/task_parse_error.rb +12 -0
- data/lib/fixman/tester.rb +69 -0
- data/lib/fixman/utilities.rb +8 -0
- data/test/test_command_line.rb +250 -0
- data/test/test_configuration.rb +58 -0
- data/test/test_controller.rb +16 -0
- data/test/test_fixman.rb +7 -0
- data/test/test_raw_task.rb +97 -0
- data/test/test_repository.rb +21 -0
- data/test/test_task.rb +28 -0
- data/test/test_tester.rb +89 -0
- metadata +163 -0
data/lib/fixman/task.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fixman
|
2
|
+
class Task
|
3
|
+
attr_reader :name, :condition
|
4
|
+
|
5
|
+
def initialize(name, condition, command, cleanup)
|
6
|
+
@name = name
|
7
|
+
@condition = condition
|
8
|
+
@command = command
|
9
|
+
@cleanup = cleanup
|
10
|
+
end
|
11
|
+
|
12
|
+
def run target
|
13
|
+
success = @command.call(target)
|
14
|
+
@cleanup.call(target)
|
15
|
+
|
16
|
+
success
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Fixman
|
5
|
+
class Tester
|
6
|
+
TERMINAL_WIDTH = 80
|
7
|
+
|
8
|
+
def initialize(configuration)
|
9
|
+
@conf = configuration
|
10
|
+
@target_cache = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def test
|
14
|
+
@conf.raw_tasks.each do |raw_task|
|
15
|
+
raw_task.refine.each do |task|
|
16
|
+
puts(test_task task)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def test_task task
|
24
|
+
puts "Collecting targets for #{task.name}..."
|
25
|
+
targets = collect task.condition
|
26
|
+
failures = []
|
27
|
+
puts "Running the #{task.name} on targets..."
|
28
|
+
targets.each do |target|
|
29
|
+
failures << target unless task.run target
|
30
|
+
end
|
31
|
+
report task.name, targets, failures
|
32
|
+
end
|
33
|
+
|
34
|
+
def collect(condition)
|
35
|
+
if @target_cache[condition]
|
36
|
+
@target_cache[condition]
|
37
|
+
else
|
38
|
+
targets = []
|
39
|
+
places_to_search = [@conf.fixtures_base]
|
40
|
+
places_to_search.each do |place|
|
41
|
+
# exclude symbolic links to avoid cycles
|
42
|
+
place.each_child do |child|
|
43
|
+
next if child.symlink?
|
44
|
+
targets << child if condition.call(child)
|
45
|
+
places_to_search << child if child.directory?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@target_cache[condition] = targets
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def report(name, targets, failures)
|
53
|
+
n_of_targets = targets.size
|
54
|
+
n_of_successes = n_of_targets - failures.size
|
55
|
+
|
56
|
+
sio = StringIO.new
|
57
|
+
sio.puts "#{name} (#{n_of_successes}/#{n_of_targets})"
|
58
|
+
sio.puts '-' * TERMINAL_WIDTH
|
59
|
+
if n_of_successes == n_of_targets
|
60
|
+
sio.puts 'All targets ran as expected.'
|
61
|
+
else
|
62
|
+
sio.puts "Failing targets:"
|
63
|
+
sio.puts failures.sort
|
64
|
+
end
|
65
|
+
sio.puts
|
66
|
+
sio.string
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'fixman'
|
2
|
+
require 'minitest'
|
3
|
+
|
4
|
+
class TestCommandLine < Minitest::Test
|
5
|
+
extend Fixman::CommandLine
|
6
|
+
|
7
|
+
@@desired_input_index = 0
|
8
|
+
|
9
|
+
def test_parse_normal_options
|
10
|
+
options = TestCommandLine.parse_options! ['-c', 'my_conf.yaml']
|
11
|
+
assert_equal Pathname.new('my_conf.yaml'), options[:conf_path]
|
12
|
+
|
13
|
+
options = TestCommandLine.parse_options! []
|
14
|
+
assert_equal Pathname.new(Fixman::Configuration::DEFAULT_CONF_FILE),
|
15
|
+
options[:conf_path]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_parse_option_leaves_positional
|
19
|
+
args = %w(hey -c mey yey -c key)
|
20
|
+
TestCommandLine.parse_options! args
|
21
|
+
assert_equal %w(hey yey), args
|
22
|
+
|
23
|
+
args = %w(hey)
|
24
|
+
TestCommandLine.parse_options! args
|
25
|
+
assert_equal %w(hey), args
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_parse_normal_potisional
|
29
|
+
args = %w(add)
|
30
|
+
command, other_args = TestCommandLine.parse_positional_arguments!(args)
|
31
|
+
assert_equal [], args
|
32
|
+
assert_equal :add, command
|
33
|
+
assert_equal({}, other_args)
|
34
|
+
|
35
|
+
args = %w(update user/name)
|
36
|
+
command, other_args = TestCommandLine.parse_positional_arguments!(args)
|
37
|
+
assert_equal [], args
|
38
|
+
assert_equal :update, command
|
39
|
+
assert_equal({canonical_name: 'user/name', sha: nil}, other_args)
|
40
|
+
|
41
|
+
args = %w(uPdaTe uSEr/name someSHA)
|
42
|
+
command, other_args = TestCommandLine.parse_positional_arguments!(args)
|
43
|
+
assert_equal [], args
|
44
|
+
assert_equal :update, command
|
45
|
+
assert_equal({canonical_name: 'uSEr/name', sha: 'someSHA'}, other_args)
|
46
|
+
|
47
|
+
args = %w(fetch groupA groupB groupC)
|
48
|
+
command, other_args = TestCommandLine.parse_positional_arguments!(args)
|
49
|
+
assert_equal [], args
|
50
|
+
assert_equal :fetch, command
|
51
|
+
assert_equal({groups: [:groupa, :groupb, :groupc]}, other_args)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_start_session_optional
|
55
|
+
input = {}
|
56
|
+
template = { symbol: :test, prompt: 'Test prompt', label: '', type: :optional }
|
57
|
+
change_get_input "test value" do
|
58
|
+
assert_output(template[:prompt]) do
|
59
|
+
TestCommandLine.send(:start_session, input, template)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
expected_input = { test: 'test value' }
|
63
|
+
assert_equal(expected_input, input)
|
64
|
+
|
65
|
+
template = { symbol: :test2, prompt: 'Another prompt', label: ''}
|
66
|
+
change_get_input "test value2" do
|
67
|
+
assert_output(template[:prompt]) do
|
68
|
+
TestCommandLine.send(:start_session, input, template)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
expected_input[:test2] = 'test value2'
|
72
|
+
assert_equal(expected_input, input)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_start_session_mandatory
|
76
|
+
input = {}
|
77
|
+
template = {
|
78
|
+
symbol: :test,
|
79
|
+
prompt: 'Test prompt',
|
80
|
+
label: '',
|
81
|
+
type: :mandatory
|
82
|
+
}
|
83
|
+
change_get_input "TEST value" do
|
84
|
+
assert_output(template[:prompt]) do
|
85
|
+
TestCommandLine.send(:start_session, input, template)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
expected_input = { test: 'TEST value' }
|
89
|
+
assert_equal(expected_input, input)
|
90
|
+
|
91
|
+
input = {}
|
92
|
+
change_get_input [' ', '', 'TEST value'] do
|
93
|
+
assert_output(template[:prompt] * 3) do
|
94
|
+
TestCommandLine.send(:start_session, input, template)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
expected_input = { test: 'TEST value' }
|
98
|
+
assert_equal(expected_input, input)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_start_session_single_choice
|
102
|
+
input = {}
|
103
|
+
template = {
|
104
|
+
symbol: :test,
|
105
|
+
prompt: 'Test prompt',
|
106
|
+
label: '',
|
107
|
+
type: :single_choice,
|
108
|
+
choices: %w(1 2 3 4)
|
109
|
+
}
|
110
|
+
change_get_input "2" do
|
111
|
+
assert_output(%r|1/2/3|) do
|
112
|
+
TestCommandLine.send(:start_session, input, template)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
expected_input = { test: '2' }
|
116
|
+
assert_equal(expected_input, input)
|
117
|
+
|
118
|
+
input = {}
|
119
|
+
change_get_input [' ', '5', '3'] do
|
120
|
+
assert_output(%r|1/2/3/4.*1/2/3/4|m) do
|
121
|
+
TestCommandLine.send(:start_session, input, template)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
expected_input = { test: '3' }
|
125
|
+
assert_equal(expected_input, input)
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_start_session_multiple_choice
|
129
|
+
input = {}
|
130
|
+
template = {
|
131
|
+
symbol: :test,
|
132
|
+
prompt: 'Test prompt',
|
133
|
+
label: '',
|
134
|
+
type: :multiple_choice,
|
135
|
+
choices: %w(RUby pytHOn elixir)
|
136
|
+
}
|
137
|
+
change_get_input "pytHOn" do
|
138
|
+
assert_output(%r|RUby/pytHOn/elixir|) do
|
139
|
+
TestCommandLine.send(:start_session, input, template)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
expected_input = { test: ['pytHOn'] }
|
143
|
+
assert_equal(expected_input, input)
|
144
|
+
|
145
|
+
input = {}
|
146
|
+
change_get_input [' ', '5,RUby', 'elixir,pytHOn'] do
|
147
|
+
assert_output(%r|RUby.*RUby|m) do
|
148
|
+
TestCommandLine.send(:start_session, input, template)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
expected_input = { test: ['elixir', 'pytHOn'] }
|
152
|
+
assert_equal(expected_input, input)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_get_params
|
156
|
+
extra_templates = [
|
157
|
+
{
|
158
|
+
symbol: :notes,
|
159
|
+
prompt: 'Notes',
|
160
|
+
label: 'Notes',
|
161
|
+
type: :optional
|
162
|
+
},
|
163
|
+
{
|
164
|
+
symbol: :licence,
|
165
|
+
prompt: 'Licence',
|
166
|
+
label: 'Licence',
|
167
|
+
type: :single_choice,
|
168
|
+
choices: ['MIT', 'Apache']
|
169
|
+
}
|
170
|
+
]
|
171
|
+
|
172
|
+
inputs = [
|
173
|
+
'https://github.com/madgen/fixman',
|
174
|
+
'a , b, c',
|
175
|
+
'It is good to take notes',
|
176
|
+
'apache'
|
177
|
+
]
|
178
|
+
params = []
|
179
|
+
expected_sha = 'fake SHA'
|
180
|
+
assert_output(/URL.*Notes.*Licence.*Apache/m) do
|
181
|
+
params =
|
182
|
+
change_get_input inputs do
|
183
|
+
Fixman::Repository.stub(:retrieve_head_sha, expected_sha) do
|
184
|
+
TestCommandLine.get_params extra_templates, %w(d a e b c)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
assert_equal 'fixman', params[:name]
|
190
|
+
assert_equal 'madgen', params[:owner]
|
191
|
+
assert_equal inputs[0], params[:url]
|
192
|
+
assert_equal %w(a b c), params[:groups]
|
193
|
+
assert_equal inputs[2], params[:notes]
|
194
|
+
assert_equal 'Apache', params[:licence]
|
195
|
+
assert_equal expected_sha, params[:sha]
|
196
|
+
|
197
|
+
inputs = [
|
198
|
+
'https://bithub.com/madgen/fixman',
|
199
|
+
'fixman',
|
200
|
+
'madgen',
|
201
|
+
'a',
|
202
|
+
'It is good to take notes',
|
203
|
+
'mit'
|
204
|
+
]
|
205
|
+
assert_output(/URL.*Notes.*Licence.*Apache/m) do
|
206
|
+
params =
|
207
|
+
change_get_input inputs do
|
208
|
+
Fixman::Repository.stub(:retrieve_head_sha, expected_sha) do
|
209
|
+
TestCommandLine.get_params extra_templates, %w(d a e b c)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
assert_equal inputs[0], params[:url]
|
215
|
+
assert_equal inputs[1], params[:name]
|
216
|
+
assert_equal inputs[2], params[:owner]
|
217
|
+
assert_equal ['a'], params[:groups]
|
218
|
+
assert_equal inputs[4], params[:notes]
|
219
|
+
assert_equal 'MIT', params[:licence]
|
220
|
+
assert_equal expected_sha, params[:sha]
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def change_get_input(desired_input)
|
226
|
+
TestCommandLine.instance_eval { undef :get_input }
|
227
|
+
TestCommandLine.define_singleton_method :get_input do
|
228
|
+
result =
|
229
|
+
if desired_input.is_a? String
|
230
|
+
desired_input
|
231
|
+
elsif desired_input.is_a? Array
|
232
|
+
desired_input[@@desired_input_index]
|
233
|
+
end
|
234
|
+
@@desired_input_index += 1
|
235
|
+
result
|
236
|
+
end
|
237
|
+
|
238
|
+
result = yield
|
239
|
+
|
240
|
+
TestCommandLine.instance_eval do
|
241
|
+
undef :get_input
|
242
|
+
@@desired_input_index = 0
|
243
|
+
end
|
244
|
+
TestCommandLine.define_singleton_method :get_input do
|
245
|
+
gets.chomp
|
246
|
+
end
|
247
|
+
|
248
|
+
result
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fixman'
|
2
|
+
require 'minitest'
|
3
|
+
require 'classy_hash'
|
4
|
+
|
5
|
+
class TestConfiguration < Minitest::Test
|
6
|
+
def test_validate_minimal_conf
|
7
|
+
conf_params = {
|
8
|
+
fixtures_base: 'hello',
|
9
|
+
tasks: [
|
10
|
+
{
|
11
|
+
name: 'test_task',
|
12
|
+
command: {
|
13
|
+
action: 'wc',
|
14
|
+
}
|
15
|
+
}
|
16
|
+
],
|
17
|
+
}
|
18
|
+
|
19
|
+
assert_nil CH.validate(conf_params, Fixman::Configuration::CONF_SCHEMA)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_condition_schema_validation
|
23
|
+
schema = { condition: Fixman::Configuration::CONDITION_OR_CLEANUP_SCHEMA }
|
24
|
+
|
25
|
+
valid = {
|
26
|
+
condition: {
|
27
|
+
type: :ruby,
|
28
|
+
action: 'proc {}'
|
29
|
+
}
|
30
|
+
}
|
31
|
+
cond = valid[:condition]
|
32
|
+
assert_nil(CH.validate valid, schema)
|
33
|
+
|
34
|
+
cond[:type] = :shell
|
35
|
+
cond[:action] = 'wc'
|
36
|
+
assert_nil(CH.validate valid, schema)
|
37
|
+
|
38
|
+
cond.delete :type
|
39
|
+
assert_raises(RuntimeError) { CH.validate valid, schema }
|
40
|
+
|
41
|
+
cond[:type] = :something_else
|
42
|
+
assert_raises(RuntimeError) { CH.validate valid, schema }
|
43
|
+
|
44
|
+
cond[:type] = :ruby
|
45
|
+
cond[:action] = 'not a proc'
|
46
|
+
assert_raises(RuntimeError) { CH.validate valid, schema }
|
47
|
+
|
48
|
+
cond[:type] = :ruby
|
49
|
+
cond[:action] = 'proc {}'
|
50
|
+
cond[:exit_status] = 300
|
51
|
+
assert_nil CH.validate valid, schema
|
52
|
+
|
53
|
+
cond[:type] = :shell
|
54
|
+
cond[:action] = 'wc'
|
55
|
+
cond[:exit_status] = 300
|
56
|
+
assert_raises(RuntimeError) { CH.validate valid, schema }
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'fixman'
|
2
|
+
require 'minitest'
|
3
|
+
require 'minitest/mock'
|
4
|
+
|
5
|
+
class TestController < Minitest::Test
|
6
|
+
|
7
|
+
def test_write_ledger
|
8
|
+
original_ledger = ""
|
9
|
+
repos = Minitest::Mock.new.expect(:map, ['abc','def'])
|
10
|
+
Tempfile.open 'location' do |t|
|
11
|
+
Fixman::Controller.send :write_ledger, repos, original_ledger, t.path
|
12
|
+
t.rewind
|
13
|
+
assert_equal "---\n- abc\n- def\n", t.read
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|