metric_fu 4.8.0 → 4.9.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 +8 -8
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.metrics +1 -66
- data/.travis.yml +1 -0
- data/CONTRIBUTORS +13 -11
- data/DEV.md +21 -18
- data/Gemfile +1 -2
- data/Gemfile.devtools +0 -1
- data/HISTORY.md +7 -1
- data/README.md +79 -19
- data/Rakefile +0 -1
- data/checksum/metric_fu-4.8.0.gem.sha512 +1 -0
- data/gem_tasks/usage_test.rake +30 -0
- data/lib/metric_fu/configuration.rb +6 -1
- data/lib/metric_fu/data_structures/line_numbers.rb +1 -1
- data/lib/metric_fu/environment.rb +2 -7
- data/lib/metric_fu/logging/mf_debugger.rb +4 -4
- data/lib/metric_fu/metric.rb +2 -2
- data/lib/metric_fu/metrics/cane/template_awesome/cane.html.erb +74 -85
- data/lib/metric_fu/metrics/churn/churn.rb +1 -2
- data/lib/metric_fu/metrics/flay/template_awesome/flay.html.erb +2 -1
- data/lib/metric_fu/metrics/flog/template_awesome/flog.html.erb +2 -1
- data/lib/metric_fu/metrics/rails_best_practices/template_awesome/rails_best_practices.html.erb +2 -1
- data/lib/metric_fu/metrics/rcov/external_client.rb +24 -0
- data/lib/metric_fu/metrics/rcov/rcov.rb +9 -100
- data/lib/metric_fu/metrics/rcov/rcov_format_coverage.rb +140 -0
- data/lib/metric_fu/metrics/rcov/simplecov_formatter.rb +64 -0
- data/lib/metric_fu/metrics/rcov/template_awesome/rcov.html.erb +5 -1
- data/lib/metric_fu/metrics/reek/reek_grapher.rb +7 -1
- data/lib/metric_fu/metrics/reek/template_awesome/reek.html.erb +2 -1
- data/lib/metric_fu/metrics/roodi/template_awesome/roodi.html.erb +2 -1
- data/lib/metric_fu/metrics/stats/template_awesome/stats.html.erb +2 -2
- data/lib/metric_fu/reporting/graphs/grapher.rb +5 -20
- data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +1 -1
- data/lib/metric_fu/reporting/templates/awesome/layout.html.erb +8 -3
- data/lib/metric_fu/reporting/templates/javascripts/bluff_graph.js +15 -0
- data/lib/metric_fu/reporting/templates/javascripts/excanvas.js +1 -1
- data/lib/metric_fu/reporting/templates/javascripts/highcharts.js +294 -0
- data/lib/metric_fu/reporting/templates/javascripts/highcharts_graph.js +38 -0
- data/lib/metric_fu/reporting/templates/javascripts/standalone-framework.js +17 -0
- data/lib/metric_fu/reporting/templates/javascripts/utils.js +9 -0
- data/lib/metric_fu/templates/css/bluff.css +10 -10
- data/lib/metric_fu/templates/css/integrity.css +3 -0
- data/lib/metric_fu/templates/report.html.erb +3 -4
- data/lib/metric_fu/version.rb +1 -1
- data/metric_fu.gemspec +1 -0
- data/spec/fixtures/coverage.rb +13 -0
- data/spec/fixtures/exit0.sh +3 -0
- data/spec/fixtures/exit1.sh +3 -0
- data/spec/metric_fu/formatter/html_spec.rb +2 -2
- data/spec/metric_fu/metrics/rcov/simplecov_formatter_spec.rb +41 -0
- data/spec/spec_helper.rb +7 -8
- data/spec/support/usage_test.rb +134 -0
- data/spec/usage_test_spec.rb +69 -0
- metadata +39 -3
- metadata.gz.sig +0 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
createGraphElement("div");
|
2
|
+
|
3
|
+
if(document.getElementById('graph')) {
|
4
|
+
var chart = new Highcharts.Chart({
|
5
|
+
chart: {
|
6
|
+
animation: false,
|
7
|
+
renderTo: 'graph'
|
8
|
+
},
|
9
|
+
legend: {
|
10
|
+
align: 'center',
|
11
|
+
verticalAlign: 'top',
|
12
|
+
y: 25
|
13
|
+
},
|
14
|
+
plotOptions: {
|
15
|
+
line: {
|
16
|
+
animation: false,
|
17
|
+
lineWidth: 3,
|
18
|
+
marker: {
|
19
|
+
radius: 6
|
20
|
+
},
|
21
|
+
pointPlacement: 'on'
|
22
|
+
}
|
23
|
+
},
|
24
|
+
title: {
|
25
|
+
text: graph_title
|
26
|
+
},
|
27
|
+
xAxis: {
|
28
|
+
categories: graph_labels,
|
29
|
+
tickmarkPlacement: 'on'
|
30
|
+
},
|
31
|
+
yAxis: {
|
32
|
+
maxPadding: 0,
|
33
|
+
min: 0,
|
34
|
+
minPadding: 0
|
35
|
+
},
|
36
|
+
series: graph_series
|
37
|
+
});
|
38
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/*
|
2
|
+
Highcharts JS v3.0.9 (2014-01-15)
|
3
|
+
|
4
|
+
Standalone Highcharts Framework
|
5
|
+
|
6
|
+
License: MIT License
|
7
|
+
*/
|
8
|
+
var HighchartsAdapter=function(){function o(c){function b(b,a,d){b.removeEventListener(a,d,!1)}function d(b,a,d){d=b.HCProxiedMethods[d.toString()];b.detachEvent("on"+a,d)}function a(a,c){var f=a.HCEvents,i,g,k,j;if(a.removeEventListener)i=b;else if(a.attachEvent)i=d;else return;c?(g={},g[c]=!0):g=f;for(j in g)if(f[j])for(k=f[j].length;k--;)i(a,j,f[j][k])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(a,b){var d=this,c=this.HCEvents,g;if(d.addEventListener)d.addEventListener(a,
|
9
|
+
b,!1);else if(d.attachEvent){g=function(a){b.call(d,a)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[b.toString()]=g;d.attachEvent("on"+a,g)}c[a]===r&&(c[a]=[]);c[a].push(b)},unbind:function(c,h){var f,i;c?(f=this.HCEvents[c]||[],h?(i=HighchartsAdapter.inArray(h,f),i>-1&&(f.splice(i,1),this.HCEvents[c]=f),this.removeEventListener?b(this,c,h):this.attachEvent&&d(this,c,h)):(a(this,c),this.HCEvents[c]=[])):(a(this),this.HCEvents={})},trigger:function(a,b){var d=this.HCEvents[a]||
|
10
|
+
[],c=d.length,g,k,j;k=function(){b.defaultPrevented=!0};for(g=0;g<c;g++){j=d[g];if(b.stopped)break;b.preventDefault=k;b.target=this;if(!b.type)b.type=a;j.call(this,b)===!1&&b.preventDefault()}}});return c}var r,l=document,p=[],m=[],q,n;Math.easeInOutSine=function(c,b,d,a){return-d/2*(Math.cos(Math.PI*c/a)-1)+b};return{init:function(c){if(!l.defaultView)this._getStyle=function(b,d){var a;return b.style[d]?b.style[d]:(d==="opacity"&&(d="filter"),a=b.currentStyle[d.replace(/\-(\w)/g,function(b,a){return a.toUpperCase()})],
|
11
|
+
d==="filter"&&(a=a.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),a===""?1:a)},this.adapterRun=function(b,d){var a={width:"clientWidth",height:"clientHeight"}[d];if(a)return b.style.zoom=1,b[a]-2*parseInt(HighchartsAdapter._getStyle(b,"padding"),10)};if(!Array.prototype.forEach)this.each=function(b,d){for(var a=0,c=b.length;a<c;a++)if(d.call(b[a],b[a],a,b)===!1)return a};if(!Array.prototype.indexOf)this.inArray=function(b,d){var a,c=0;if(d)for(a=d.length;c<a;c++)if(d[c]===b)return c;
|
12
|
+
return-1};if(!Array.prototype.filter)this.grep=function(b,d){for(var a=[],c=0,h=b.length;c<h;c++)d(b[c],c)&&a.push(b[c]);return a};n=function(b,c,a){this.options=c;this.elem=b;this.prop=a};n.prototype={update:function(){var b;b=this.paths;var d=this.elem,a=d.element;b&&a?d.attr("d",c.step(b[0],b[1],this.now,this.toD)):d.attr?a&&d.attr(this.prop,this.now):(b={},b[d]=this.now+this.unit,Highcharts.css(d,b));this.options.step&&this.options.step.call(this.elem,this.now,this)},custom:function(b,c,a){var e=
|
13
|
+
this,h=function(a){return e.step(a)},f;this.startTime=+new Date;this.start=b;this.end=c;this.unit=a;this.now=this.start;this.pos=this.state=0;h.elem=this.elem;h()&&m.push(h)===1&&(q=setInterval(function(){for(f=0;f<m.length;f++)m[f]()||m.splice(f--,1);m.length||clearInterval(q)},13))},step:function(b){var c=+new Date,a;a=this.options;var e;if(this.elem.stopAnimation)a=!1;else if(b||c>=a.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();b=this.options.curAnim[this.prop]=
|
14
|
+
!0;for(e in a.curAnim)a.curAnim[e]!==!0&&(b=!1);b&&a.complete&&a.complete.call(this.elem);a=!1}else e=c-this.startTime,this.state=e/a.duration,this.pos=a.easing(e,0,1,a.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),a=!0;return a}};this.animate=function(b,d,a){var e,h="",f,i,g;b.stopAnimation=!1;if(typeof a!=="object"||a===null)e=arguments,a={duration:e[2],easing:e[3],complete:e[4]};if(typeof a.duration!=="number")a.duration=400;a.easing=Math[a.easing]||Math.easeInOutSine;
|
15
|
+
a.curAnim=Highcharts.extend({},d);for(g in d)i=new n(b,a,g),f=null,g==="d"?(i.paths=c.init(b,b.d,d.d),i.toD=d.d,e=0,f=1):b.attr?e=b.attr(g):(e=parseFloat(HighchartsAdapter._getStyle(b,g))||0,g!=="opacity"&&(h="px")),f||(f=parseFloat(d[g])),i.custom(e,f,h)}},_getStyle:function(c,b){return window.getComputedStyle(c).getPropertyValue(b)},getScript:function(c,b){var d=l.getElementsByTagName("head")[0],a=l.createElement("script");a.type="text/javascript";a.src=c;a.onload=b;d.appendChild(a)},inArray:function(c,
|
16
|
+
b){return b.indexOf?b.indexOf(c):p.indexOf.call(b,c)},adapterRun:function(c,b){return parseInt(HighchartsAdapter._getStyle(c,b),10)},grep:function(c,b){return p.filter.call(c,b)},map:function(c,b){for(var d=[],a=0,e=c.length;a<e;a++)d[a]=b.call(c[a],c[a],a,c);return d},offset:function(c){for(var b=0,d=0;c;)b+=c.offsetLeft,d+=c.offsetTop,c=c.offsetParent;return{left:b,top:d}},addEvent:function(c,b,d){o(c).bind(b,d)},removeEvent:function(c,b,d){o(c).unbind(b,d)},fireEvent:function(c,b,d,a){var e;l.createEvent&&
|
17
|
+
(c.dispatchEvent||c.fireEvent)?(e=l.createEvent("Events"),e.initEvent(b,!0,!0),e.target=c,Highcharts.extend(e,d),c.dispatchEvent?c.dispatchEvent(e):c.fireEvent(b,e)):c.HCExtended===!0&&(d=d||{},c.trigger(b,d));d&&d.defaultPrevented&&(a=null);a&&a(d)},washMouseEvent:function(c){return c},stop:function(c){c.stopAnimation=!0},each:function(c,b){return Array.prototype.forEach.call(c,b)}}}();
|
@@ -0,0 +1,9 @@
|
|
1
|
+
function createGraphElement(elementType) {
|
2
|
+
var graphContainer = document.getElementById("graph_container");
|
3
|
+
|
4
|
+
if(graphContainer) {
|
5
|
+
var graphElement = document.createElement(elementType);
|
6
|
+
graphElement.setAttribute("id", "graph");
|
7
|
+
graphContainer.appendChild(graphElement);
|
8
|
+
}
|
9
|
+
}
|
@@ -1,15 +1,15 @@
|
|
1
1
|
.bluff-tooltip {
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
background: #fff;
|
3
|
+
border: 1px solid #d1edf5;
|
4
|
+
padding: 8px 8px 6px;
|
5
5
|
}
|
6
6
|
.bluff-tooltip .color {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
display: block;
|
8
|
+
height: 4px;
|
9
|
+
width: 30px;
|
10
|
+
margin: 0 0 4px;
|
11
|
+
overflow: hidden;
|
12
12
|
}
|
13
13
|
.bluff-tooltip .data {
|
14
|
-
|
15
|
-
}
|
14
|
+
font-weight: bold;
|
15
|
+
}
|
@@ -1,10 +1,9 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
3
|
<style>
|
4
|
-
|
5
|
-
<%= inline_css('css/bluff.css') if MetricFu.configuration.graph_engine == :bluff %>
|
6
|
-
<%= inline_css('css/rcov.css') if @metrics.has_key?(:rcov) %>
|
4
|
+
<%= inline_css('css/syntax.css') %>
|
7
5
|
</style>
|
6
|
+
<title>Analyzed File Report</title>
|
8
7
|
</head>
|
9
8
|
<body>
|
10
9
|
<table cellpadding='0' cellspacing='0' class='ruby'>
|
@@ -27,6 +26,6 @@
|
|
27
26
|
</td>
|
28
27
|
</tr>
|
29
28
|
<% end %>
|
30
|
-
|
29
|
+
</table>
|
31
30
|
</body>
|
32
31
|
</html>
|
data/lib/metric_fu/version.rb
CHANGED
data/metric_fu.gemspec
CHANGED
@@ -67,7 +67,7 @@ describe MetricFu::Formatter::HTML do
|
|
67
67
|
it "copies common javascripts to the output directory" do
|
68
68
|
expect {
|
69
69
|
MetricFu::Formatter::HTML.new.finish
|
70
|
-
}.to create_file("#{directory('output_directory')}/
|
70
|
+
}.to create_file("#{directory('output_directory')}/highcharts*.js")
|
71
71
|
end
|
72
72
|
|
73
73
|
it "creates graphs for appropriate metrics" do
|
@@ -118,7 +118,7 @@ describe MetricFu::Formatter::HTML do
|
|
118
118
|
it "copies common javascripts to the custom output directory" do
|
119
119
|
expect {
|
120
120
|
MetricFu::Formatter::HTML.new(output: @output).finish
|
121
|
-
}.to create_file("#{directory('base_directory')}/#{@output}/
|
121
|
+
}.to create_file("#{directory('base_directory')}/#{@output}/highcharts*.js")
|
122
122
|
end
|
123
123
|
|
124
124
|
it "creates graphs for appropriate metrics in the custom output directory " do
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'simplecov'
|
3
|
+
require 'metric_fu/metrics/rcov/simplecov_formatter'
|
4
|
+
|
5
|
+
describe SimpleCov::Formatter::MetricFu do
|
6
|
+
before do
|
7
|
+
@rcov_file = subject.coverage_file_path
|
8
|
+
File.delete( @rcov_file ) if File.exists?( @rcov_file )
|
9
|
+
|
10
|
+
@result = SimpleCov::Result.new(
|
11
|
+
{
|
12
|
+
FIXTURE.fixtures_path.join('coverage.rb').expand_path.to_s =>
|
13
|
+
[1,1,1,1,nil,1,0,1,1,nil,0,1,1]
|
14
|
+
}
|
15
|
+
)
|
16
|
+
|
17
|
+
# Set to default encoding
|
18
|
+
Encoding.default_internal = nil if defined?(Encoding)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "test_format" do
|
22
|
+
SimpleCov::Formatter::MetricFu.new.format( @result )
|
23
|
+
|
24
|
+
expect(File.exists?( @rcov_file )).to be_truthy
|
25
|
+
end
|
26
|
+
|
27
|
+
it "test_encoding" do
|
28
|
+
# This is done in many rails environments
|
29
|
+
Encoding.default_internal = 'UTF-8' if defined?(Encoding)
|
30
|
+
|
31
|
+
SimpleCov::Formatter::MetricFu.new.format( @result )
|
32
|
+
end
|
33
|
+
|
34
|
+
it "test_create_content" do
|
35
|
+
content = SimpleCov::Formatter::MetricFu::FormatLikeRCov.new(@result).format
|
36
|
+
test = "\="*80
|
37
|
+
|
38
|
+
expect(content).to match(/#{test}/)
|
39
|
+
expect(content).to match(/!! value \* value/)
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,27 +1,26 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# add lib to the load path just like rubygems does
|
2
|
+
$:.unshift File.expand_path("../../lib", __FILE__)
|
3
3
|
if ENV['COVERAGE']
|
4
4
|
require 'simplecov'
|
5
5
|
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
6
6
|
begin
|
7
7
|
puts '[COVERAGE] Running with SimpleCov HTML Formatter'
|
8
|
-
require '
|
9
|
-
formatters << SimpleCov::Formatter::
|
10
|
-
puts '[COVERAGE] Running with SimpleCov
|
8
|
+
require 'metric_fu/metrics/rcov/simplecov_formatter'
|
9
|
+
formatters << SimpleCov::Formatter::MetricFu
|
10
|
+
puts '[COVERAGE] Running with SimpleCov MetricFu Formatter'
|
11
11
|
rescue LoadError
|
12
|
-
puts '[COVERAGE] SimpleCov
|
12
|
+
puts '[COVERAGE] SimpleCov MetricFu formatter could not be loaded'
|
13
13
|
end
|
14
14
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ *formatters ]
|
15
15
|
SimpleCov.start
|
16
16
|
end
|
17
17
|
|
18
|
+
require 'rspec/autorun'
|
18
19
|
require 'date'
|
19
20
|
require 'test_construct'
|
20
21
|
require 'json'
|
21
22
|
require 'pry-nav'
|
22
23
|
|
23
|
-
# add lib to the load path just like rubygems does
|
24
|
-
$:.unshift File.expand_path("../../lib", __FILE__)
|
25
24
|
require 'metric_fu'
|
26
25
|
include MetricFu
|
27
26
|
def mf_log(msg); mf_debug(msg); end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# usage_test = UsageTest.new
|
2
|
+
# usage_test.test_files(EXAMPLE_FILES)
|
3
|
+
|
4
|
+
# puts "SUCCESS!"
|
5
|
+
# Process.exit! 0
|
6
|
+
require 'metric_fu/logging/mf_debugger'
|
7
|
+
require 'open3'
|
8
|
+
class UsageTest
|
9
|
+
def initialize
|
10
|
+
@markdown = Redcarpet::Markdown.new(HTMLRenderAndVerifyCodeBlocks, :fenced_code_blocks => true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_files(paths)
|
14
|
+
in_test_directory do
|
15
|
+
Array(paths).each do |path|
|
16
|
+
puts "Testing #{path}"
|
17
|
+
@markdown.render(File.read(path))
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
end
|
21
|
+
puts "SUCCESS!"
|
22
|
+
Process.exit! 0
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def in_test_directory
|
28
|
+
Dir.mktmpdir do |dir|
|
29
|
+
Dir.chdir(dir) {
|
30
|
+
`git init; touch README; git add README; git commit -m 'first'`
|
31
|
+
yield
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
SnippetRunner = Struct.new(:code, :language) do
|
37
|
+
include MfDebugger
|
38
|
+
SystemCommandError = Class.new(StandardError)
|
39
|
+
TestResult = Struct.new(:success, :captured_output)
|
40
|
+
|
41
|
+
def test!
|
42
|
+
time = Time.now
|
43
|
+
test_result = run_code
|
44
|
+
mf_debug "#{Time.now - time} seconds"
|
45
|
+
if test_result.success
|
46
|
+
print '.'
|
47
|
+
else
|
48
|
+
puts 'x'
|
49
|
+
puts "Red :( language: #{language}, code #{code}, #{test_result.captured_output}"
|
50
|
+
Process.exit! 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def run_code(test_result = TestResult.new(:no_result,''))
|
55
|
+
test_result.captured_output = case language
|
56
|
+
when 'ruby' then eval_ruby
|
57
|
+
when 'sh' then run_system_command
|
58
|
+
else mf_debug "Cannot test language: #{language.inspect}"
|
59
|
+
end
|
60
|
+
test_result.success = true
|
61
|
+
test_result
|
62
|
+
rescue StandardError => run_error
|
63
|
+
test_result.captured_output = exception_message(run_error)
|
64
|
+
test_result.success = false
|
65
|
+
test_result
|
66
|
+
rescue SystemExit => system_exit
|
67
|
+
puts "I am a system exit"
|
68
|
+
test_result.captured_output = exception_message(system_exit)
|
69
|
+
test_result.success = system_exit.success?
|
70
|
+
test_result
|
71
|
+
end
|
72
|
+
|
73
|
+
def eval_ruby(fail_on_empty=false)
|
74
|
+
capture_output(fail_on_empty) do
|
75
|
+
instance_eval(code)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def run_system_command(fail_on_empty=true)
|
80
|
+
out = ''
|
81
|
+
err = ''
|
82
|
+
pid = :not_set
|
83
|
+
exit_status = :not_set
|
84
|
+
Open3.popen3(code) do |stdin, stdout, stderr, wait_thr|
|
85
|
+
out << stdout.read.chomp
|
86
|
+
err << stderr.read.chomp
|
87
|
+
pid = wait_thr.pid
|
88
|
+
exit_status = wait_thr.value
|
89
|
+
end
|
90
|
+
exit_code = exit_status.exitstatus
|
91
|
+
case exit_code
|
92
|
+
when 0 then "Ran with exit status #{exit_code}"
|
93
|
+
when (1..Float::INFINITY) then fail SystemCommandError.new("Failed with exit status #{exit_code}. #{err}----#{out}")
|
94
|
+
else fail SystemCommandError.new("Execution failed with exit status #{exit_code}. #{err}----#{out}")
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
def exception_message(e)
|
100
|
+
"#{e.class}\t#{e.message}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def capture_output(fail_on_empty)
|
104
|
+
exception = nil
|
105
|
+
stderr = :not_set
|
106
|
+
stdout = :not_set
|
107
|
+
MfDebugger::Logger.capture_output(STDOUT) do
|
108
|
+
stdout =
|
109
|
+
MfDebugger::Logger.capture_output(STDERR) do
|
110
|
+
begin
|
111
|
+
stderr = yield
|
112
|
+
rescue Exception => e
|
113
|
+
exception = e
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
if [nil, '', :not_set].none? {|c| c == stderr }
|
118
|
+
mf_debug "Captured STDERR"
|
119
|
+
stderr
|
120
|
+
elsif [nil, '', :not_set].none? {|c| c == stdout }
|
121
|
+
mf_debug "Captured STDOUT"
|
122
|
+
stdout
|
123
|
+
elsif exception
|
124
|
+
mf_debug "Captured Exception"
|
125
|
+
raise exception
|
126
|
+
else
|
127
|
+
mf_debug "Captured Nothing"
|
128
|
+
if fail_on_empty
|
129
|
+
fail SystemCommandError.new 'No output generated or exception caught'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
describe 'usage test' do
|
2
|
+
ROOT_PATH = File.expand_path("..", File.dirname(__FILE__))
|
3
|
+
require File.join(ROOT_PATH, 'spec/support/usage_test')
|
4
|
+
|
5
|
+
context 'evaluating ruby code' do
|
6
|
+
specify 'succeeds when the code runs without errors' do
|
7
|
+
code = "1 + 1"
|
8
|
+
test_result = SnippetRunner.new(code, 'ruby').run_code
|
9
|
+
expect(test_result.captured_output).to eq(2)
|
10
|
+
expect(test_result.success).to eq(true)
|
11
|
+
end
|
12
|
+
specify 'fails when the code raises a standard error' do
|
13
|
+
code = "fail NameError.new('no name')"
|
14
|
+
test_result = SnippetRunner.new(code, 'ruby').run_code
|
15
|
+
expect(test_result.captured_output).to match('NameError')
|
16
|
+
expect(test_result.captured_output).to match('no name')
|
17
|
+
expect(test_result.success).to eq(false)
|
18
|
+
end
|
19
|
+
specify 'succeeds when the code exits with a zero exit status' do
|
20
|
+
code = "puts 1 + 1; exit 0"
|
21
|
+
test_result = SnippetRunner.new(code, 'ruby').run_code
|
22
|
+
expect(test_result.captured_output).to match('SystemExit')
|
23
|
+
expect(test_result.success).to eq(true)
|
24
|
+
end
|
25
|
+
specify 'fails when the code exits with a non-zero exit status' do
|
26
|
+
code = "puts 1 + 1; exit 1"
|
27
|
+
test_result = SnippetRunner.new(code, 'ruby').run_code
|
28
|
+
expect(test_result.captured_output).to match('SystemExit')
|
29
|
+
expect(test_result.success).to eq(false)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
context 'evaluating shell commands' do
|
34
|
+
specify 'succeeds when the command runs without errors' do
|
35
|
+
code = "which ruby"
|
36
|
+
test_result = SnippetRunner.new(code, 'sh').run_code
|
37
|
+
expect(test_result.captured_output).to match("exit status 0")
|
38
|
+
expect(test_result.success).to eq(true)
|
39
|
+
end
|
40
|
+
specify 'fails when the command runs with an error' do
|
41
|
+
code = "sandwhich_fu ruby"
|
42
|
+
test_result = SnippetRunner.new(code, 'sh').run_code
|
43
|
+
expect(test_result.captured_output).to match(failed_command_error)
|
44
|
+
expect(test_result.success).to eq(false)
|
45
|
+
end
|
46
|
+
specify 'succeeds when the code exits with a zero exit status' do
|
47
|
+
code = "sh #{fixtures_path.join('exit0.sh').to_path}"
|
48
|
+
test_result = SnippetRunner.new(code, 'sh').run_code
|
49
|
+
expect(test_result.captured_output).to match("exit status 0")
|
50
|
+
expect(test_result.success).to eq(true)
|
51
|
+
end
|
52
|
+
specify 'fails when the code exits with a non-zero exit status' do
|
53
|
+
code = "sh #{fixtures_path.join('exit1.sh').to_path}"
|
54
|
+
test_result = SnippetRunner.new(code, 'sh').run_code
|
55
|
+
expect(test_result.captured_output).to match("exit status 1")
|
56
|
+
expect(test_result.success).to eq(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def failed_command_error
|
62
|
+
defined?(JRUBY_VERSION) ? 'IOError' : 'Errno::ENOENT'
|
63
|
+
end
|
64
|
+
|
65
|
+
def fixtures_path
|
66
|
+
fixtures_dir = File.join(File.expand_path('..', File.dirname(__FILE__)), 'spec', 'fixtures')
|
67
|
+
Pathname(fixtures_dir)
|
68
|
+
end
|
69
|
+
end
|