fiveruns_tuneup_core 0.5.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.
data/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ lib/fiveruns/tuneup/bar.rb
2
+ lib/fiveruns/tuneup/helpers.rb
3
+ lib/fiveruns/tuneup/panel.rb
4
+ lib/fiveruns/tuneup/run.rb
5
+ lib/fiveruns/tuneup/step.rb
6
+ lib/fiveruns/tuneup/templating.rb
7
+ lib/fiveruns_tuneup_core.rb
8
+ Manifest
9
+ Rakefile
10
+ test/fixtures/a.json
11
+ test/run_test.rb
12
+ test/step_test.rb
13
+ test/test_helper.rb
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ Echoe.new 'fiveruns_tuneup_core' do |p|
5
+ p.version = '0.5.0'
6
+ p.author = "FiveRuns Development Team"
7
+ p.email = 'dev@fiveruns.com'
8
+ p.project = 'fiveruns'
9
+ p.summary = "Core utilities for FiveRuns TuneUp panels"
10
+ p.url = "http://tuneup.fiveruns.com"
11
+ p.include_rakefile = true
12
+ p.runtime_dependencies = %w(json)
13
+ p.development_dependencies = %w(echoe FakeWeb Shoulda)
14
+ p.rcov_options = '--exclude gems --exclude version.rb --sort coverage --text-summary --html -o coverage'
15
+ end
16
+
17
+ task :coverage do
18
+ system "open coverage/index.html" if PLATFORM['darwin']
19
+ end
@@ -0,0 +1,120 @@
1
+
2
+ # Gem::Specification for Fiveruns_tuneup_core-0.5.0
3
+ # Originally generated by Echoe
4
+
5
+ --- !ruby/object:Gem::Specification
6
+ name: fiveruns_tuneup_core
7
+ version: !ruby/object:Gem::Version
8
+ version: 0.5.0
9
+ platform: ruby
10
+ authors:
11
+ - FiveRuns Development Team
12
+ autorequire:
13
+ bindir: bin
14
+
15
+ date: 2008-10-11 00:00:00 -07:00
16
+ default_executable:
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
19
+ name: json
20
+ type: :runtime
21
+ version_requirement:
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: "0"
27
+ version:
28
+ - !ruby/object:Gem::Dependency
29
+ name: echoe
30
+ type: :development
31
+ version_requirement:
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: "0"
37
+ version:
38
+ - !ruby/object:Gem::Dependency
39
+ name: FakeWeb
40
+ type: :development
41
+ version_requirement:
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ - !ruby/object:Gem::Dependency
49
+ name: Shoulda
50
+ type: :development
51
+ version_requirement:
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ description: Core utilities for FiveRuns TuneUp panels
59
+ email: dev@fiveruns.com
60
+ executables: []
61
+
62
+ extensions: []
63
+
64
+ extra_rdoc_files:
65
+ - lib/fiveruns/tuneup/bar.rb
66
+ - lib/fiveruns/tuneup/helpers.rb
67
+ - lib/fiveruns/tuneup/panel.rb
68
+ - lib/fiveruns/tuneup/run.rb
69
+ - lib/fiveruns/tuneup/step.rb
70
+ - lib/fiveruns/tuneup/templating.rb
71
+ - lib/fiveruns_tuneup_core.rb
72
+ files:
73
+ - lib/fiveruns/tuneup/bar.rb
74
+ - lib/fiveruns/tuneup/helpers.rb
75
+ - lib/fiveruns/tuneup/panel.rb
76
+ - lib/fiveruns/tuneup/run.rb
77
+ - lib/fiveruns/tuneup/step.rb
78
+ - lib/fiveruns/tuneup/templating.rb
79
+ - lib/fiveruns_tuneup_core.rb
80
+ - Manifest
81
+ - Rakefile
82
+ - test/fixtures/a.json
83
+ - test/run_test.rb
84
+ - test/step_test.rb
85
+ - test/test_helper.rb
86
+ - fiveruns_tuneup_core.gemspec
87
+ has_rdoc: true
88
+ homepage: http://tuneup.fiveruns.com
89
+ post_install_message:
90
+ rdoc_options:
91
+ - --line-numbers
92
+ - --inline-source
93
+ - --title
94
+ - Fiveruns_tuneup_core
95
+ - --main
96
+ - README.rdoc
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: "0"
104
+ version:
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: "1.2"
110
+ version:
111
+ requirements: []
112
+
113
+ rubyforge_project: fiveruns
114
+ rubygems_version: 1.3.0
115
+ specification_version: 2
116
+ summary: Core utilities for FiveRuns TuneUp panels
117
+ test_files:
118
+ - test/run_test.rb
119
+ - test/step_test.rb
120
+ - test/test_helper.rb
@@ -0,0 +1,41 @@
1
+ module Fiveruns
2
+ module Tuneup
3
+
4
+ class Bar
5
+ include Templating
6
+
7
+ attr_reader :step
8
+ def initialize(step)
9
+ @step = step
10
+ end
11
+
12
+ private
13
+
14
+ def template
15
+ %(
16
+ <ul id="<%= 'tuneup-root-bar' if step.is_a?(RootStep) %>" class="tuneup-bar">
17
+ <% %w(model view controller).each do |layer| %>
18
+ <%= component layer %>
19
+ <% end %>
20
+ </ul>
21
+ )
22
+ end
23
+
24
+ def component(layer)
25
+ width = width_of(layer)
26
+ return '' unless width > 0
27
+ %(
28
+ <li title="#{layer.to_s.capitalize}" style="width: #{width}px;" class="tuneup-layer-#{layer}">#{layer.to_s[0,1].capitalize if width >= 12}</li>
29
+ )
30
+ end
31
+
32
+ def width_of(layer)
33
+ portion = step.layer_portions[layer.to_sym]
34
+ result = portion * 200 * step.proportion
35
+ result < 1 && portion != 0 ? 1 : result
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ module Fiveruns
2
+ module Tuneup
3
+
4
+ def self.format_caller(trace)
5
+ valid_lines = trace.reject { |line| line =~ /fiveruns_tuneup/ }[0,5]
6
+ linked_lines = valid_lines.map { |line| editor_link_line(line) }
7
+ '<pre>%s</pre>' % linked_lines.join("\n")
8
+ end
9
+
10
+ def self.strip_root(text)
11
+ if defined?(::Fiveruns::Tuneup::STRIP_ROOT)
12
+ pattern = /^#{Regexp.quote ::Fiveruns::Tuneup::STRIP_ROOT}\/?/o
13
+ if text =~ pattern
14
+ result = text.sub(pattern, '')
15
+ in_app = result !~ /^gems\//
16
+ return [in_app, result]
17
+ end
18
+ end
19
+ [false, text]
20
+ end
21
+
22
+ # TODO: Refactor
23
+ def self.editor_link_line(line)
24
+ filename, number, extra = line.match(/^(.+?):(\d+)(?::in\b(.*?))?/)[1, 2]
25
+ in_app, line = strip_root(line)
26
+ name = if line.size > 87
27
+ "&hellip;#{CGI.escapeHTML line.sub(/^.*?(.{84})$/, '\1')}"
28
+ else
29
+ line
30
+ end
31
+ name = if in_app
32
+ if name =~ /`/
33
+ name.sub(/^(.*?)\s+`(.*?)'$/, %q(<span class='tuneup-app-line'>\1</span> `<b class='tuneup-app-line'>\2</b>'))
34
+ else
35
+ %(<span class='tuneup-app-line'>#{name}</span>)
36
+ end
37
+ else
38
+ name.sub(/([^\/\\]+\.\S+:\d+:in)\s+`(.*?)'$/, %q(\1 `<b>\2</b>'))
39
+ end
40
+ %(<a title='%s' href='txmt://open/?url=file://%s&line=%d'>%s</a>%s) % [CGI.escapeHTML(line), filename, number, name, extra]
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ module Fiveruns
2
+ module Tuneup
3
+
4
+ class << self
5
+ attr_accessor :javascripts_path
6
+ attr_accessor :stylesheets_path
7
+ end
8
+
9
+ def self.insert_panel(body, run, allow_share = false)
10
+ return body unless run
11
+ tag = body[/(<body[^>]*>)/i, 1]
12
+ return body unless tag
13
+ panel = Panel.new(run, allow_share)
14
+ body.sub(/<\/head>/i, head << '</head>').sub(tag, tag + panel.to_html)
15
+ end
16
+
17
+ def self.head
18
+ %(
19
+ <script src='#{javascripts_path}/init.js' type='text/javascript'></script>
20
+ <link rel='stylesheet' type='text/css' href='#{stylesheets_path}/tuneup.css'/>
21
+ )
22
+ end
23
+
24
+ class Panel
25
+ include Templating
26
+
27
+ attr_reader :run, :root
28
+ def initialize(run, allow_share = false)
29
+ @run = run
30
+ @root = run.data
31
+ @allow_share = allow_share
32
+ end
33
+
34
+ def allow_share?
35
+ @allow_share
36
+ end
37
+
38
+ private
39
+
40
+ def template
41
+ %(
42
+ <div id="tuneup"><h1>FiveRuns TuneUp</h1><div style="display: block;" id="tuneup-content"><div id="tuneup-panel">
43
+ <div id="tuneup-data">
44
+ <div id="tuneup-top">
45
+ <%= root.to_html %>
46
+ <% if allow_share? %>
47
+ <a href="/fiveruns_tuneup_merb/share/<%= run.slug %>" id="tuneup-save-link">Share this Run</a>
48
+ <% end %>
49
+ </div>
50
+ <ul id="tuneup-details">
51
+ <% root.children.each do |child| %>
52
+ <%= child.to_html %>
53
+ <% end %>
54
+ <li style="clear: both;"/>
55
+ </ul>
56
+ </div>
57
+ </div></div></div>
58
+ )
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,139 @@
1
+ module Fiveruns
2
+ module Tuneup
3
+
4
+ class Run
5
+
6
+ class << self
7
+ attr_accessor :directory
8
+ attr_accessor :api_key
9
+ end
10
+
11
+ def self.environment
12
+ @environment ||= {
13
+ # :framework needs to be set, as well as <framework>_version
14
+ :framework => nil,
15
+ :ruby_version => RUBY_VERSION,
16
+ :ruby_platform => RUBY_PLATFORM
17
+ }
18
+ end
19
+
20
+ def self.slug_of(filename)
21
+ url_directory, file = filename.split(File::SEPARATOR)[-2, 2]
22
+ File.join(url_directory, File.basename(file, '.json.gz'))
23
+ end
24
+
25
+ def self.all(format = :slug)
26
+ files = Dir[File.join(directory, '*', '*.json.gz')]
27
+ format == :slug ? files.map { |file| slug_of(file) } : files
28
+ end
29
+
30
+ def self.all_for(url, format = :slug)
31
+ run_directory = Digest::SHA1.hexdigest(url.to_s)
32
+ files = Dir[File.join(directory, run_directory, '*.json.gz')]
33
+ format == :slug ? files.map { |file| slug_of(file) } : files
34
+ end
35
+
36
+ def self.last(format = :slug)
37
+ all(format).sort_by { |f| File.basename(f) }.last
38
+ end
39
+
40
+ def self.service_uri
41
+ @service_uri = URI.parse(ENV['TUNEUP_COLLECTOR'] || 'https://tuneup-collector.fiveruns.com')
42
+ end
43
+
44
+ def self.share(slug)
45
+ if api_key?
46
+ file = Dir[File.join(directory, "%s.json.gz" % slug)].first
47
+ if file
48
+ run = load(File.open(file, 'rb') { |f| f.read })
49
+ http = Net::HTTP.new(service_uri.host, service_uri.port)
50
+ http.use_ssl = true if service_uri.scheme == 'https'
51
+ body = "api_key=#{api_key}&run=#{CGI.escape(run.to_json)}"
52
+ begin
53
+ resp = http.post('/runs.json', body, "Content-Type" => 'application/x-www-form-urlencoded')
54
+ case resp.code.to_i
55
+ when 201
56
+ return JSON.load(resp.body)['run_id']
57
+ else
58
+ # TODO: return error info
59
+ return false
60
+ end
61
+ rescue Exception => e
62
+ # TODO: return error info
63
+ return false
64
+ end
65
+ else
66
+ raise ArgumentError, "Invalid run: #{slug}"
67
+ end
68
+ else
69
+ raise ArgumentError, "No API Key set"
70
+ end
71
+ end
72
+
73
+ def self.api_key?
74
+ @api_key
75
+ end
76
+
77
+ def self.load(compressed)
78
+ file = JSON.load(Zlib::Inflate.inflate(compressed))
79
+ step = Fiveruns::Tuneup::Step.load(file['data'])
80
+ new(file['url'], step, file['environment'], Time.at(file['collected_at']))
81
+ end
82
+
83
+ attr_reader :url, :data, :environment, :collected_at
84
+ def initialize(url, data, environment = self.class.environment, collected_at = Time.now)
85
+ @url = url
86
+ @data = data
87
+ @environment = environment
88
+ @collected_at = collected_at
89
+ validate!
90
+ end
91
+
92
+ def validate!
93
+ unless environment.is_a?(Hash)
94
+ raise ArgumentError, "Invalid environment information (must be a Hash): #{environment.inspect}"
95
+ end
96
+ end
97
+
98
+ def save
99
+ compressed = Zlib::Deflate.deflate(to_json)
100
+ create_directory
101
+ File.open(full_path, 'wb') { |f| f.write compressed }
102
+ end
103
+
104
+ def full_path
105
+ File.join(self.class.directory, path)
106
+ end
107
+
108
+ def slug
109
+ @slug ||= "%s/%d-%d" % [
110
+ Digest::SHA1.hexdigest(url),
111
+ (collected_at.to_f * 1000),
112
+ (data.time * 1000)
113
+ ]
114
+ end
115
+
116
+ def path
117
+ "%s.json.gz" % slug
118
+ end
119
+
120
+ def to_json
121
+ {
122
+ :id => slug,
123
+ :url => url,
124
+ :environment => environment,
125
+ :collected_at => collected_at.to_f,
126
+ :data => data
127
+ }.to_json
128
+ end
129
+
130
+ private
131
+
132
+ def create_directory
133
+ FileUtils.mkdir_p File.dirname(full_path)
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+ end
@@ -0,0 +1,303 @@
1
+ require 'json'
2
+
3
+ module Fiveruns
4
+ module Tuneup
5
+
6
+ class CalculationError < ::RuntimeError; end
7
+
8
+ def self.record(&block)
9
+ Step.reset!
10
+ root = RootStep.new
11
+ root.record(&block)
12
+ root
13
+ end
14
+
15
+ def self.step(name, layer, extras = {}, &block)
16
+ trace = format_caller(caller)
17
+ Step.new(name, layer, extras.merge('Caller' => trace), nil).record(&block)
18
+ end
19
+
20
+ class RootStep
21
+
22
+ include Templating
23
+ attr_reader :children, :bar
24
+ attr_accessor :time, :parent
25
+ def initialize(time = nil)
26
+ @time = time
27
+ @children = []
28
+ @bar = Bar.new(self)
29
+ end
30
+
31
+ def root
32
+ parent ? parent.root : self
33
+ end
34
+
35
+ def record
36
+ start = Time.now
37
+ result = Step.inside(self) { yield }
38
+ @time = Time.now - start
39
+ result
40
+ end
41
+ def disparity
42
+ result = time - children.inject(0) { |sum, child| sum + child.time }
43
+ if result < 0
44
+ #TODO resolve instances where sum of child times exceed parent time
45
+ #raise CalculationError, "Child steps exceed parent step size"
46
+ result = 0
47
+ end
48
+ result
49
+ end
50
+ def add_child(child)
51
+ child.parent = self
52
+ children << child
53
+ end
54
+ def format_time(time)
55
+ '%.2fms' % (time * 1000)
56
+ end
57
+ def layer_portions
58
+ children.first.layer_portions
59
+ end
60
+ def to_json
61
+ {:children => children, :time => time}.to_json
62
+ end
63
+
64
+ def proportion
65
+ time / root.time
66
+ end
67
+
68
+ def to_html_with_children
69
+ to_html << children.map { |c| c.to_html }.join
70
+ end
71
+
72
+ def template
73
+ %(
74
+ <div id="tuneup-summary">
75
+ <%= bar.to_html %>
76
+ <%= (time * 1000).to_i %> ms
77
+ </div>
78
+ )
79
+ end
80
+
81
+ end
82
+
83
+ class Step < RootStep
84
+
85
+ def self.load(source, depth = 0)
86
+ hash = source.is_a?(Hash) ? source : JSON.load(source)
87
+ step = if hash['layer']
88
+ Step.new(hash['name'], hash['layer'], hash['extras'], hash['time'])
89
+ elsif depth == 0
90
+ RootStep.new(hash['time'])
91
+ else
92
+ raise ArgumentError, "Could not find data for step in #{hash.inspect}"
93
+ end
94
+ hash['children'].each do |child_hash|
95
+ child = load(child_hash)
96
+ step.add_child(child)
97
+ end
98
+ step
99
+ end
100
+
101
+ def self.stack
102
+ @stack ||= []
103
+ end
104
+
105
+ def self.reset!
106
+ stack.clear
107
+ end
108
+
109
+ def self.inside(step)
110
+ unless stack.empty?
111
+ stack.last.add_child(step)
112
+ end
113
+ stack << step
114
+ result = yield
115
+ stack.pop
116
+ result
117
+ end
118
+
119
+ attr_reader :name, :layer, :extras
120
+ def initialize(name, layer, raw_extras = {}, time = nil)
121
+ super(time)
122
+ @name = name
123
+ @layer = layer.to_sym
124
+ @extras = build_extras(raw_extras)
125
+ end
126
+
127
+ def children_with_disparity
128
+ return children if children.empty?
129
+ layer_name = layer if respond_to?(:layer)
130
+ extra_step = DisparityStep.new(layer_name, disparity)
131
+ extra_step.parent = parent
132
+ children + [extra_step]
133
+ end
134
+
135
+ def layer_portions
136
+ @layer_portions ||= begin
137
+ result = {:model => 0, :view => 0, :controller => 0}
138
+ if children.empty?
139
+ result[layer] = 1
140
+ else
141
+ times = layer_times
142
+
143
+ times[layer] ||= 0
144
+ times.inject(result) do |all, (l, t)|
145
+ result[l] = t / time
146
+ result
147
+ end
148
+ end
149
+ result
150
+ end
151
+ end
152
+
153
+ def layer_times
154
+ if children.empty?
155
+ return {layer => time}
156
+ end
157
+
158
+ totals = {:model => 0, :view => 0, :controller => 0}
159
+ children_with_disparity.inject(totals) do |all, child|
160
+ breakdown = child.layer_times
161
+ breakdown.each { |l,t| all[l] += t }
162
+ all
163
+ end
164
+ totals
165
+ end
166
+
167
+ def to_json
168
+ extras_hash = extras.inject({}) { |all, extra| all[extra.name] = extra; all }
169
+ {:name => name, :children => children, :time => time, :extras => extras_hash, :layer => layer}.to_json
170
+ end
171
+
172
+ private
173
+
174
+ def build_extras(raw_extras)
175
+ raw_extras.sort_by { |k, v| k.to_s }.map do |name, data|
176
+ data = case data
177
+ when Array
178
+ data
179
+ when Hash
180
+ [data['content'], data['extended']]
181
+ else
182
+ [data]
183
+ end
184
+ Extra.new(name, *data )
185
+ end
186
+ end
187
+
188
+ def template
189
+ %(
190
+ <li class="<%= html_class %>">
191
+ <ul class="tuneup-step-info">
192
+ <li class="tuneup-title">
193
+ <span class="time"><%= '%.2f' % (time * 1000) %> ms</span>
194
+ <a class='tuneup-step-name' title="<%=h name.to_s %>"><%=h name.to_s %></a>
195
+ <% if !extras.empty? %>
196
+ <a class='tuneup-step-extras-link'>(?)</a>
197
+ <% end %>
198
+ </li>
199
+ <li class="tuneup-detail-bar"><%= bar.to_html %></li>
200
+ <li style="clear: both;"/>
201
+ </ul>
202
+ <% if !extras.empty? %>
203
+ <div class='tuneup-step-extras'>
204
+ <div>
205
+ <dl>
206
+ <% extras.each do |extra| %>
207
+ <%= extra.to_html %>
208
+ <% end %>
209
+ </dl>
210
+ </div>
211
+ </div>
212
+ <% end %>
213
+ <%= html_children %>
214
+ </li>
215
+ )
216
+ end
217
+
218
+ private
219
+
220
+ def html_class
221
+ %W(fiveruns_tuneup_step #{'with_children' if children.any?} #{'tuneup-opened' if root.children.first.object_id == self.object_id}).compact.join(' ')
222
+ end
223
+
224
+ def html_children
225
+ return unless children.any?
226
+ %(<ul class='fiveruns_tuneup_children'>%s</ul>) % children_with_disparity.map { |child| child.to_html }.join
227
+ end
228
+
229
+ class Extra
230
+ include Templating
231
+
232
+ attr_reader :name, :content, :extended
233
+ def initialize(name, content, extended = {})
234
+ @name = name
235
+ @content = content
236
+ @extended = extended
237
+ end
238
+
239
+ def to_json
240
+ {:content => content, :extended => extended}.to_json
241
+ end
242
+
243
+ private
244
+
245
+ def template
246
+ %(
247
+ <dt><%= h name.to_s %></dt>
248
+ <dd>
249
+ <%= content %>
250
+ <% if extended.any? %>
251
+ <% extended.each do |name, value| %>
252
+ <div class='tuneup-step-extra-extended' title='<%= h name.to_s %>'><%= value %></div>
253
+ <% end %>
254
+ <% end %>
255
+ </dd>
256
+ )
257
+ end
258
+
259
+ end
260
+
261
+ end
262
+
263
+ class DisparityStep < Step
264
+
265
+ def initialize(layer_name, disparity)
266
+ super '(Other)', layer_name, {}, disparity
267
+ @extras = build_extras description
268
+ end
269
+
270
+ private
271
+
272
+ def description
273
+ {
274
+ 'What is this?' => %(
275
+ <p>
276
+ <b>Other</b> is the amount of time spent executing
277
+ code that TuneUp doesn't wrap to extract more information.
278
+ To reduce overhead and make the listing more
279
+ manageable, we don't generate steps for every operation.
280
+ </p>
281
+ <p>#{layer_description}</p>
282
+ )
283
+ }
284
+ end
285
+
286
+ def layer_description
287
+ case layer
288
+ when :model
289
+ "In the <i>model</i> layer, this is probably ORM overhead (out of your control)."
290
+ when :view
291
+ "In the <i>view</i> layer, this is probably framework overhead during render (out of your control)."
292
+ when :controller
293
+ %(
294
+ In the <i>controller</i> layer, this is probably framework overhead during action execution (out of your control),
295
+ or time spent executing your code in the action (calls to private methods, libraries, etc).
296
+ )
297
+ end
298
+ end
299
+
300
+ end
301
+
302
+ end
303
+ end
@@ -0,0 +1,19 @@
1
+ require 'erb'
2
+
3
+ module Fiveruns
4
+ module Tuneup
5
+
6
+ module Templating
7
+
8
+ def h(text)
9
+ CGI.escapeHTML(text)
10
+ end
11
+
12
+ def to_html
13
+ ERB.new(template).result(binding)
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require 'zlib'
2
+ require 'digest/sha1'
3
+ require 'fileutils'
4
+ require 'net/https'
5
+
6
+ $:.unshift(File.dirname(__FILE__))
7
+
8
+ require 'fiveruns/tuneup/templating'
9
+ require 'fiveruns/tuneup/step'
10
+ require 'fiveruns/tuneup/helpers'
11
+ require 'fiveruns/tuneup/bar'
12
+ require 'fiveruns/tuneup/panel'
13
+ require 'fiveruns/tuneup/run'
@@ -0,0 +1 @@
1
+ {"name":"Perform Index action in UsersController","time":90.2631282806396,"children":[{"name":"Before filter verify_authenticity_token","caller":[],"time":0.0331401824951172,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter get_settings","caller":[],"time":6.44207000732422,"extras":{},"children":[{"name":"Find Setting","caller":[],"time":2.26306915283203,"extras":{},"children":[{"name":"Find Setting by SQL","caller":[],"time":1.82700157165527,"extras":{"Database Query":{"content":"SELECT * FROM \"settings\" LIMIT 1","extended":{}}},"children":[],"layer":"model"}],"layer":"model"}],"layer":"controller"},{"name":"Before filter auth_token_login","caller":[],"time":0.0472068786621094,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter check_bans","caller":[],"time":0.00810623168945312,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter check_privacy","caller":[],"time":3.39198112487793,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter check_admin_only_create","caller":[],"time":0.281095504760742,"extras":{},"children":[{"name":"Invoke current_controller action","caller":[],"time":0.0150203704833984,"extras":{},"children":[],"layer":"controller"}],"layer":"controller"},{"name":"Before filter set_timezone","caller":[],"time":0.0388622283935547,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter update_online_at","caller":[],"time":0.00810623168945312,"extras":{},"children":[],"layer":"controller"},{"name":"Before filter get_layout_vars","caller":[],"time":23.6580371856689,"extras":{},"children":[{"name":"Find User","caller":[],"time":0.960111618041992,"extras":{},"children":[{"name":"Find User by SQL","caller":[],"time":0.478029251098633,"extras":{"Database Query":{"content":"SELECT * FROM \"users\" ORDER BY users.id DESC LIMIT 1","extended":{}}},"children":[],"layer":"model"}],"layer":"model"}],"layer":"controller"},{"name":"Invoke index action","caller":[],"time":7.27701187133789,"extras":{},"children":[{"name":"Find User","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/vendor\/plugins\/will_paginate\/lib\/will_paginate\/finder.rb",82]],"time":1.47318840026855,"extras":{},"children":[{"name":"Find User by SQL","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/vendor\/plugins\/will_paginate\/lib\/will_paginate\/finder.rb",82]],"time":1.12009048461914,"extras":{"Database Query":{"content":"SELECT * FROM \"users\" ORDER BY profile_updated_at desc LIMIT 30 OFFSET 0","extended":{}}},"children":[],"layer":"model"}],"layer":"model"}],"layer":"controller"},{"name":"Render file users\/index","caller":[],"time":4.08506393432617,"extras":{},"children":[{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/users\/index.html.erb",1]],"time":0.0150203704833984,"extras":{},"children":[],"layer":"controller"}],"layer":"view"},{"name":"Render file layouts\/application","caller":[],"time":31.7168235778809,"extras":{},"children":[{"name":"Invoke current_action action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",30]],"time":0.00786781311035156,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",32]],"time":0.00596046447753906,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_action action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",30]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",32]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",12]],"time":0.00596046447753906,"extras":{},"children":[],"layer":"controller"},{"name":"Render shared\/reminders","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",16]],"time":2.88176536560059,"extras":{},"children":[{"name":"Render file shared\/reminders","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",16]],"time":2.61068344116211,"extras":{},"children":[{"name":"Find Event","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/reminders.html.erb",1]],"time":1.8608570098877,"extras":{},"children":[{"name":"Find Event by SQL","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/reminders.html.erb",1]],"time":0.553131103515625,"extras":{"Database Query":{"content":"SELECT * FROM \"events\" WHERE (\"events\".\"reminder\" = 't' AND \"events\".\"date\" BETWEEN '2008-10-05 21:30:02' AND '2008-10-06 05:30:02') ORDER BY date asc","extended":{}}},"children":[],"layer":"model"}],"layer":"model"}],"layer":"view"}],"layer":"view"},{"name":"Render shared\/tabs","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",20]],"time":2.75588035583496,"extras":{},"children":[{"name":"Render file shared\/tabs","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",20]],"time":2.49886512756348,"extras":{},"children":[{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.0119209289550781,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",59]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/helpers\/application_helper.rb",57]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"}],"layer":"view"}],"layer":"view"},{"name":"Render shared\/nav","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",23]],"time":0.870943069458008,"extras":{},"children":[{"name":"Render file shared\/nav","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",23]],"time":0.646829605102539,"extras":{},"children":[{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav.html.erb",38]],"time":0.00596046447753906,"extras":{},"children":[],"layer":"controller"}],"layer":"view"}],"layer":"view"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",24]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",25]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Render shared\/flash","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",26]],"time":0.363826751708984,"extras":{},"children":[{"name":"Render file shared\/flash","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",26]],"time":0.14495849609375,"extras":{},"children":[],"layer":"view"}],"layer":"view"},{"name":"Render shared\/nav2","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",28]],"time":8.07309150695801,"extras":{},"children":[{"name":"Render file shared\/nav2","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",28]],"time":7.85112380981445,"extras":{},"children":[{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",1]],"time":0.00596046447753906,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",14]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",24]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",32]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",46]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",52]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",60]],"time":0.003814697265625,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",68]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",75]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",87]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",98]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",112]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",118]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",125]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",133]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",145]],"time":0.00810623168945312,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",155]],"time":0.00476837158203125,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",165]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",177]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",185]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",191]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",201]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",208]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",215]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",229]],"time":0.00405311584472656,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",235]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",242]],"time":0.00476837158203125,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_action action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",242]],"time":0.00596046447753906,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",248]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_action action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",248]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_controller action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",256]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"},{"name":"Invoke current_action action","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/nav2.html.erb",256]],"time":0.00500679016113281,"extras":{},"children":[],"layer":"controller"}],"layer":"view"}],"layer":"view"},{"name":"Render shared\/stats","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",29]],"time":2.74991989135742,"extras":{},"children":[{"name":"Render file shared\/stats","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/layouts\/application.html.erb",29]],"time":2.48098373413086,"extras":{},"children":[{"name":"Find User","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/stats.html.erb",3]],"time":1.84106826782227,"extras":{},"children":[{"name":"Find User by SQL","caller":[["\/Users\/bruce\/git\/fiveruns\/el-dorado\/app\/views\/shared\/stats.html.erb",3]],"time":1.22594833374023,"extras":{"Database Query":{"content":"SELECT * FROM \"users\" WHERE (logged_out = 'f' and (online_at > '2008-10-05 23:25:02' or chatting_at > '2008-10-05 23:29:32')) ORDER BY login asc","extended":{}}},"children":[],"layer":"model"}],"layer":"model"}],"layer":"view"}],"layer":"view"}],"layer":"view"}]}
data/test/run_test.rb ADDED
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class RunTest < Test::Unit::TestCase
4
+
5
+ context "Persistence" do
6
+
7
+ setup do
8
+ @directory = File.expand_path(File.dirname(__FILE__) << "/tmp")
9
+ FileUtils.rm_rf @directory rescue nil
10
+ FileUtils.mkdir_p @directory
11
+ Fiveruns::Tuneup::Run.directory = @directory
12
+ @json = read_json :a
13
+ @root = Fiveruns::Tuneup::Step.load(@json)
14
+ end
15
+
16
+ def teardown
17
+ FileUtils.rm_rf @directory rescue nil
18
+ end
19
+
20
+ context "using Run#save" do
21
+ setup do
22
+ setup_run
23
+ end
24
+ should "write to filesystem" do
25
+ assert_nothing_raised do
26
+ @run.save
27
+ end
28
+ assert_equal 1, Dir[File.join(@directory, '*')].size
29
+ end
30
+ end
31
+
32
+ context "loading" do
33
+ setup do
34
+ setup_run.save
35
+ end
36
+ should "create Run instances" do
37
+ assert_equal 1, Fiveruns::Tuneup::Run.all_for(@run.url).size
38
+ Fiveruns::Tuneup::Run.all_for(@run.url, :filename).each do |file|
39
+ data = File.open(file, 'rb') { |f| f.read }
40
+ assert_kind_of Fiveruns::Tuneup::Run, Fiveruns::Tuneup::Run.load(data)
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ private
48
+
49
+ def setup_run
50
+ @timestamp = 1223597107.58871
51
+ @run = Fiveruns::Tuneup::Run.new(
52
+ 'http://localhost:3000',
53
+ @root,
54
+ Fiveruns::Tuneup::Run.environment,
55
+ Time.at(@timestamp)
56
+ )
57
+ end
58
+
59
+ end
data/test/step_test.rb ADDED
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class StepTest < Test::Unit::TestCase
4
+
5
+ context "loading from JSON" do
6
+ setup do
7
+ @json = read_json(:a)
8
+ @root = Fiveruns::Tuneup::Step.load(@json)
9
+ end
10
+ should "create a RootStep" do
11
+ assert_kind_of Fiveruns::Tuneup::RootStep, @root
12
+ assert_equal JSON.load(@json)['children'].size, @root.children.size
13
+ end
14
+ should "have normal children" do
15
+ @root.children.each do |child|
16
+ assert_normal_node(child)
17
+ assert_valid_extras(child)
18
+ end
19
+ end
20
+ end
21
+
22
+ def assert_normal_node(node)
23
+ assert node.is_a?(Fiveruns::Tuneup::Step)
24
+ node.children.each do |child|
25
+ assert_normal_node(child)
26
+ end
27
+ end
28
+
29
+ def assert_valid_extras(node)
30
+ node.extras.each do |key, extra|
31
+ assert_kind_of String, key
32
+ assert_kind_of Fiveruns::Tuneup::Step::Extra, extra
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'shoulda'
5
+
6
+ require File.dirname(__FILE__) << "/../lib/fiveruns_tuneup_core"
7
+
8
+ class Test::Unit::TestCase
9
+
10
+ private
11
+
12
+ def read_json(name)
13
+ File.read(File.dirname(__FILE__) << "/fixtures/#{name}.json")
14
+ end
15
+
16
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fiveruns_tuneup_core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - FiveRuns Development Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-11 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: echoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: FakeWeb
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: Shoulda
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description: Core utilities for FiveRuns TuneUp panels
56
+ email: dev@fiveruns.com
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files:
62
+ - lib/fiveruns/tuneup/bar.rb
63
+ - lib/fiveruns/tuneup/helpers.rb
64
+ - lib/fiveruns/tuneup/panel.rb
65
+ - lib/fiveruns/tuneup/run.rb
66
+ - lib/fiveruns/tuneup/step.rb
67
+ - lib/fiveruns/tuneup/templating.rb
68
+ - lib/fiveruns_tuneup_core.rb
69
+ files:
70
+ - lib/fiveruns/tuneup/bar.rb
71
+ - lib/fiveruns/tuneup/helpers.rb
72
+ - lib/fiveruns/tuneup/panel.rb
73
+ - lib/fiveruns/tuneup/run.rb
74
+ - lib/fiveruns/tuneup/step.rb
75
+ - lib/fiveruns/tuneup/templating.rb
76
+ - lib/fiveruns_tuneup_core.rb
77
+ - Manifest
78
+ - Rakefile
79
+ - test/fixtures/a.json
80
+ - test/run_test.rb
81
+ - test/step_test.rb
82
+ - test/test_helper.rb
83
+ - fiveruns_tuneup_core.gemspec
84
+ has_rdoc: true
85
+ homepage: http://tuneup.fiveruns.com
86
+ post_install_message:
87
+ rdoc_options:
88
+ - --line-numbers
89
+ - --inline-source
90
+ - --title
91
+ - Fiveruns_tuneup_core
92
+ - --main
93
+ - README.rdoc
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: "1.2"
107
+ version:
108
+ requirements: []
109
+
110
+ rubyforge_project: fiveruns
111
+ rubygems_version: 1.3.0
112
+ signing_key:
113
+ specification_version: 2
114
+ summary: Core utilities for FiveRuns TuneUp panels
115
+ test_files:
116
+ - test/run_test.rb
117
+ - test/step_test.rb
118
+ - test/test_helper.rb