-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.rb
executable file
·191 lines (164 loc) · 4.38 KB
/
server.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
#!/usr/bin/env ruby
require 'bundler/setup'
require 'sinatra'
require 'sinatra/config_file'
require 'haml'
require 'auger'
require 'json'
configure do
set :auger_cfg, 'cfg' #default values
config_file 'config.yml' #overwrite from config file if it exists
set :path, settings.auger_cfg.split(File::PATH_SEPARATOR)
end
def list_files
settings.path.map do |dir|
Dir["#{dir}/*.rb"]
end.flatten
end
def load_projects
list_files.inject({}) do |hash, file|
project = Auger::Config.load(file).projects.first
id = File.basename(file).sub(/\.\w+$/, "")
hash[id] = project
hash
end
end
def find_file(name)
settings.path.map do |dir|
File.join(dir, "#{name}.rb")
end.find do |file|
File.exists?(file)
end
end
def load_project(name)
Auger::Config.load(find_file(name)).projects.first
end
class Auger::Project
def to_hash
{
:name => @name,
:servers => self.servers.map(&:name),
## FIXME
# :roles => self.roles.map do |name, servers|
# { :name => name, :servers => servers.map(&:name) }
# end,
:roles => [ "foo", "bar" ],
:tests => self.tests.map(&:name),
}
end
end
def format_outcome(outcome)
case outcome
when TrueClass then
"\u2713"
when MatchData then # boolean if no captures, otherwise list captures
outcome.captures.empty? ? "\u2713" : outcome.captures.join(' ')
when FalseClass then
"\u2717"
when NilClass then
"nil"
when Exception then
"#{outcome.class}: #{outcome.to_s}"
else
outcome
end
end
module Auger
class Result
def format
id = self.test.id
outcome =
case self.outcome
when TrueClass then "\u2713"
when MatchData then @outcome.captures.empty? ? "\u2713" : @outcome.captures.join(' ')
when FalseClass then "\u2717"
when NilClass then "nil"
when Exception then "#{@outcome.class}: #{@outcome.to_s}"
else @outcome.to_s
end
status =
case self.status
when FalseClass, NilClass then :error
when Exception then :exception
when Status then self.status.value
else :ok
end
[id, outcome, status]
end
end
end
def run_tests(project)
tests = project.tests # list of all tests for project
tests.each_with_index { |test, i| test.id = i } # give tests unique ids
threads = {}
project.servers.each do |server|
threads[server.name] = []
project.connections(*server.roles).each do |connection|
threads[server.name] << Thread.new do
conn = connection.try_open(server)
connection.requests.map do |request|
response, time = request.try_run(conn)
request.tests.map do |test|
test.run(response).format << time # return 4-element array
end
end.flatten(1)
#connection.try_close(conn) ## FIXME
end
end
end
results = Hash.new { |hash, key| hash[key] = [] } #test results keyed by servername
## get test results indexed server and test id
threads.map do |server, server_threads|
server_threads.map do |thread|
thread.value.each do |id, *result| # value waits on thread
results[server][id] = result
end
end
end
success = results.values.all? {|server| server.all? {|test_result| test_result[1] == :ok }}
headers['X-Test-Result'] = (success ? '0' : '1')
return {
:project => project.name,
:tests => tests.map(&:name),
:servers => project.servers.map do |server|
r = results[server.name]
{
:name => server.name,
:results => tests.map { |test| r.fetch(test.id, nil) }
}
end,
:success => success
}
end
get '/projects/:id/tests' do
content_type :json
JSON(projects[params[:id]].tests.map { |test| test.name })
end
get '/projects/:id' do
content_type :json
JSON(load_project(params[:id]).to_hash)
end
get '/projects' do
projects = load_projects.sort_by do |k,v|
v.name
end.map do |id, project|
{ :id => id, :name => project.name }
end
content_type :json
JSON(projects)
end
get '/run/:id' do
project = load_project(params[:id])
content_type :json
JSON(run_tests(project))
end
get '/:id' do
@project = params[:id]
haml :project
end
get '/' do
@projects = load_projects.sort_by do |id, project|
project.name
end
haml :index
end