ci-syntax-tool 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/LICENSE +27 -0
- data/README.md +109 -0
- data/Rakefile +43 -0
- data/bin/ci-syntax-tool +12 -0
- data/ci-syntax-tool.gemspec +27 -0
- data/lib/ci-syntax-tool.rb +6 -0
- data/lib/ci-syntax-tool/checker.rb +63 -0
- data/lib/ci-syntax-tool/command_line.rb +229 -0
- data/lib/ci-syntax-tool/format/base.rb +50 -0
- data/lib/ci-syntax-tool/format/junit.rb +54 -0
- data/lib/ci-syntax-tool/format/progress.rb +60 -0
- data/lib/ci-syntax-tool/format_factory.rb +55 -0
- data/lib/ci-syntax-tool/language/base.rb +56 -0
- data/lib/ci-syntax-tool/language/yaml.rb +41 -0
- data/lib/ci-syntax-tool/language_factory.rb +41 -0
- data/lib/ci-syntax-tool/result.rb +134 -0
- data/lib/ci-syntax-tool/version.rb +10 -0
- data/rubocop.yml +11 -0
- data/test/features/.keep +0 -0
- data/test/features/command-line-help.feature +15 -0
- data/test/features/format-junit.feature +29 -0
- data/test/features/language-yaml.feature +34 -0
- data/test/features/pluggable-formatters.feature +42 -0
- data/test/features/pluggable-languages.feature +15 -0
- data/test/features/require-ruby.feature +38 -0
- data/test/features/step_definitions/cli_steps.rb +46 -0
- data/test/features/step_definitions/format_steps.rb +63 -0
- data/test/features/step_definitions/junit_steps.rb +57 -0
- data/test/features/step_definitions/language_steps.rb +39 -0
- data/test/features/step_definitions/require_steps.rb +38 -0
- data/test/features/support/feature_helper.rb +142 -0
- data/test/fixtures/.keep +0 -0
- data/test/fixtures/files/clean/README.md +6 -0
- data/test/fixtures/files/clean/ansiblish.yaml +12 -0
- data/test/fixtures/files/clean/kitchenish.yml +17 -0
- data/test/fixtures/files/clean/rubocopish.yaml +11 -0
- data/test/fixtures/files/error/bad-indentation.yaml +5 -0
- data/test/fixtures/files/error/missing-array-element.yaml +5 -0
- data/test/fixtures/files/error/unquoted-jinja-template.yaml +3 -0
- data/test/fixtures/files/error/very-high-yaml-version.yaml +3 -0
- data/test/fixtures/require/invalid.rb +6 -0
- data/test/fixtures/require/mock_format.rb +10 -0
- data/test/fixtures/require/second.rb +10 -0
- data/test/fixtures/require/valid.rb +10 -0
- data/test/unit/.keep +0 -0
- data/test/unit/format_factory_spec.rb +46 -0
- data/test/unit/language_factory_spec.rb +46 -0
- data/test/unit/result_spec.rb +18 -0
- data/test/unit/spec_helper.rb +31 -0
- metadata +201 -0
data/rubocop.yml
ADDED
data/test/features/.keep
ADDED
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: Command line help
|
2
|
+
|
3
|
+
In order to be able to learn about the options available for syntax checking
|
4
|
+
As a developer
|
5
|
+
I want to be able to interactively get help on the options from the command line
|
6
|
+
|
7
|
+
Scenario: Command help
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line with the help option
|
10
|
+
Then the simple usage text should be displayed along with a zero exit code
|
11
|
+
|
12
|
+
Scenario: Display version
|
13
|
+
Given I have installed the tool
|
14
|
+
When I run it on the command line with the version option
|
15
|
+
Then the current version should be displayed
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: jUnit / SureFire format
|
2
|
+
|
3
|
+
In order to be able to use the tool with many popular CI tools
|
4
|
+
As a developer
|
5
|
+
I want to be able to have output formatted as jUnit-style XML reports
|
6
|
+
|
7
|
+
Scenario: List available core formats
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line with the list-formats option
|
10
|
+
Then JUnit should be included in the listed formats
|
11
|
+
|
12
|
+
Scenario: Use JUnit format on clean files
|
13
|
+
Given I have installed the tool
|
14
|
+
When I run it on the command line with the JUnit format on clean files
|
15
|
+
Then I should get a 0 exit code
|
16
|
+
And the generated files should be valid XML
|
17
|
+
And the JUnit files should have the correct structure
|
18
|
+
And the JUnit files should have 0 errors
|
19
|
+
And the JUnit files should have 0 warnings
|
20
|
+
|
21
|
+
Scenario: Use JUnit format on error files
|
22
|
+
Given I have installed the tool
|
23
|
+
When I run it on the command line with the JUnit format on error files
|
24
|
+
Then I should get a 1 exit code
|
25
|
+
And the generated files should be valid XML
|
26
|
+
And the JUnit files should have the correct structure
|
27
|
+
And the JUnit files should have 3 errors
|
28
|
+
And the JUnit files should have 0 warnings
|
29
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Feature: Pluggable formatters
|
2
|
+
|
3
|
+
In order to be able to check YAML files for errors
|
4
|
+
As a developer
|
5
|
+
I want to be able to run the tool on yaml files
|
6
|
+
|
7
|
+
Scenario: Use YAML explicitly on clean files
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line specifying the YAML language and clean files
|
10
|
+
Then I should get a 0 exit code
|
11
|
+
And the output should show only files for YAML
|
12
|
+
And the output should have 0 warnings
|
13
|
+
And the output should have 0 errors
|
14
|
+
|
15
|
+
|
16
|
+
Scenario: Run all lamnguages on clean files
|
17
|
+
Given I have installed the tool
|
18
|
+
When I run it on the command line specifying all languages and clean files
|
19
|
+
Then I should get a 0 exit code
|
20
|
+
And the output should include files for YAML
|
21
|
+
And the output should have 0 warnings
|
22
|
+
And the output should have 0 errors
|
23
|
+
|
24
|
+
|
25
|
+
Scenario: Use YAML explicitly on error files
|
26
|
+
Given I have installed the tool
|
27
|
+
When I run it on the command line specifying the YAML language and error files
|
28
|
+
Then I should get a 1 exit code
|
29
|
+
And the output should show only files for YAML
|
30
|
+
And the output should have 0 warnings
|
31
|
+
And the output should have 3 errors
|
32
|
+
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Feature: Pluggable formatters
|
2
|
+
|
3
|
+
In order to be able to use the tool with whatever CI engine I need
|
4
|
+
As a developer
|
5
|
+
I want to be able to output the results of language checks in various formats
|
6
|
+
|
7
|
+
Scenario: List available core formats
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line with the list-formats option
|
10
|
+
Then I should get a list of the core formats along with a zero exit code
|
11
|
+
|
12
|
+
Scenario: Reject an invalid format
|
13
|
+
Given I have installed the tool
|
14
|
+
When I run it on the command line with the format option and the argument foo
|
15
|
+
Then I should get an error message and the exit code 4
|
16
|
+
|
17
|
+
Scenario: Reject multiple formats without destination
|
18
|
+
Given I have installed the tool
|
19
|
+
When I run it on the command line with two format options and 0 destinations
|
20
|
+
Then I should get an error message and the exit code 4
|
21
|
+
|
22
|
+
Scenario: Reject multiple formats with ambiguous destination count
|
23
|
+
Given I have installed the tool
|
24
|
+
When I run it on the command line with two format options and 1 destinations
|
25
|
+
Then I should get an error message and the exit code 4
|
26
|
+
|
27
|
+
Scenario: Use multiple formatters with correct number of destinations
|
28
|
+
Given I have installed the tool
|
29
|
+
When I run it on the command line with two format options and 2 destinations
|
30
|
+
Then I should get a 0 exit code
|
31
|
+
|
32
|
+
Scenario: Create destination files automatically
|
33
|
+
Given I have installed the tool
|
34
|
+
When I run it on the command line with a destination in the current directory
|
35
|
+
Then the file should be created
|
36
|
+
|
37
|
+
Scenario: Create destination directories automatically
|
38
|
+
Given I have installed the tool
|
39
|
+
When I run it on the command line with a destination in a directory that does not exist
|
40
|
+
Then the file should be created
|
41
|
+
|
42
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: Pluggable languages
|
2
|
+
|
3
|
+
In order to be able to use the tool on whatever language I need
|
4
|
+
As a developer
|
5
|
+
I want to be able to extend the tool by adding support for new languages
|
6
|
+
|
7
|
+
Scenario: List available core languages
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line with the list-languages option
|
10
|
+
Then I should get a list of the core languages along with a zero exit code
|
11
|
+
|
12
|
+
Scenario: Reject an invalid language
|
13
|
+
Given I have installed the tool
|
14
|
+
When I run it on the command line with the lang option and the argument foo
|
15
|
+
Then I should get an error message and the exit code 3
|
@@ -0,0 +1,38 @@
|
|
1
|
+
Feature: Load extra Ruby files
|
2
|
+
|
3
|
+
In order to be able to use the tool with custom plugins
|
4
|
+
As a developer
|
5
|
+
I want to be able to load additional ruby files
|
6
|
+
|
7
|
+
Scenario: Load a valid ruby file
|
8
|
+
Given I have installed the tool
|
9
|
+
When I run it on the command line with the require option and a valid ruby file
|
10
|
+
Then the valid ruby file should have been loaded
|
11
|
+
And I should get a 0 exit code
|
12
|
+
|
13
|
+
Scenario: Reject a missing file with a nice message
|
14
|
+
Given I have installed the tool
|
15
|
+
When I run it on the command line with the require option and a missing ruby file
|
16
|
+
Then I should get an error message about the missing require file
|
17
|
+
And I should get a 5 exit code
|
18
|
+
|
19
|
+
Scenario: Reject an invalid file with a nice message
|
20
|
+
Given I have installed the tool
|
21
|
+
When I run it on the command line with the require option and a invalid ruby file
|
22
|
+
Then I should get an error message about the invalid require file
|
23
|
+
And I should get a 5 exit code
|
24
|
+
|
25
|
+
Scenario: Reject an invalid file with a stacktrace when debug flag is present
|
26
|
+
Given I have installed the tool
|
27
|
+
When I run it on the command line with the require option and the debug option and a invalid ruby file
|
28
|
+
Then I should get a stack trace about the invalid require file
|
29
|
+
And I should get a 5 exit code
|
30
|
+
|
31
|
+
Scenario: Accept multiple requires
|
32
|
+
Given I have installed the tool
|
33
|
+
When I run it on the command line with two requires
|
34
|
+
Then the first ruby file should have been loaded
|
35
|
+
And the second ruby file should have been loaded
|
36
|
+
And I should get a 0 exit code
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Given(/^I have installed the tool$/) do
|
2
|
+
end
|
3
|
+
|
4
|
+
# TODO: Add code to target fixture directory by default
|
5
|
+
When(/^I run it on the command line with the ([^ ]+) option(?: and the argument )?([^ ]+)?$/) do |option, arg|
|
6
|
+
options = []
|
7
|
+
if option.match(/\-\w$/)
|
8
|
+
options << option
|
9
|
+
else
|
10
|
+
options << "--#{option}"
|
11
|
+
end
|
12
|
+
if arg
|
13
|
+
options << arg
|
14
|
+
end
|
15
|
+
@run_result = run_check(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^the simple usage text should be displayed along with a non\-zero exit code$/) do
|
19
|
+
refute_empty(@run_result[:stderr], 'Expected to see an error message on STDERR')
|
20
|
+
refute_equal(@run_result[:exit_status], 0)
|
21
|
+
assert_usage_message
|
22
|
+
end
|
23
|
+
|
24
|
+
Then(/^the simple usage text should be displayed along with a zero exit code$/) do
|
25
|
+
assert_empty(@run_result[:stderr])
|
26
|
+
assert_equal(@run_result[:exit_status], 0)
|
27
|
+
assert_usage_message
|
28
|
+
end
|
29
|
+
|
30
|
+
Then(/^the current version should be displayed$/) do
|
31
|
+
assert_match(/^ci-syntax-tool/, @run_result[:stdout], 'Version string should include tool name')
|
32
|
+
assert_match(Regexp.new(Regexp.escape(CI::Syntax::Tool::VERSION)), @run_result[:stdout], 'Version string should include the version')
|
33
|
+
assert_equal(@run_result[:stdout].split("\n").length, 1, 'Version output should be exactly one line long')
|
34
|
+
assert_empty(@run_result[:stderr])
|
35
|
+
assert_equal(@run_result[:exit_status], 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
Then(/^I should get an error message and the exit code (\d+)$/) do |expected_exit_status|
|
39
|
+
refute_empty(@run_result[:stderr], 'Expected to see an error message on STDERR')
|
40
|
+
assert_equal(expected_exit_status.to_i, @run_result[:exit_status])
|
41
|
+
end
|
42
|
+
|
43
|
+
Then(/^I should get a (\d+) exit code$/) do |expected_exit_status|
|
44
|
+
assert_equal(expected_exit_status.to_i, @run_result[:exit_status].to_i)
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
When(/^I run it on the command line with two format options and (\d) destination(?:s)$/) do |dest_count|
|
4
|
+
options = [
|
5
|
+
'--require', Dir.pwd + '/' + 'test/fixtures/require/mock_format.rb',
|
6
|
+
'--format', 'MockFormat',
|
7
|
+
'--format', 'MockFormat',
|
8
|
+
]
|
9
|
+
(0..(dest_count.to_i-1)).to_a.each do |i|
|
10
|
+
options << '--output'
|
11
|
+
options << 'test/tmp/dest-' + i.to_s
|
12
|
+
end
|
13
|
+
options << 'test/fixtures/files/clean'
|
14
|
+
@run_result = run_check(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
When(/^I run it on the command line with a destination in (the current directory|a directory that does not exist)$/) do |mode|
|
18
|
+
path = 'output-create-test-1'
|
19
|
+
options = [
|
20
|
+
'--output'
|
21
|
+
]
|
22
|
+
if mode == 'the current directory'
|
23
|
+
FileUtils.rm_f path
|
24
|
+
options << path
|
25
|
+
else
|
26
|
+
dir = 'test/tmp/output-create-dir'
|
27
|
+
FileUtils.rm_f dir
|
28
|
+
options << dir + '/' + path
|
29
|
+
end
|
30
|
+
options << 'test/fixtures/files/clean'
|
31
|
+
@expected_output_paths = [ path ]
|
32
|
+
@run_result = run_check(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
When(/^I run it on the command line with the ([^ ]+) format on ([^ ]+) files$/) do |fmt_name, fixture|
|
36
|
+
path = "test/tmp/#{fmt_name}.out"
|
37
|
+
FileUtils.rm_f path
|
38
|
+
options = [
|
39
|
+
'--format', fmt_name,
|
40
|
+
'--output', path,
|
41
|
+
'--lang', 'YAML',
|
42
|
+
"test/fixtures/files/#{fixture}",
|
43
|
+
]
|
44
|
+
@expected_output_paths = [ path ]
|
45
|
+
@run_result = run_check(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
Then(/^I should get a list of the core formats along with a zero exit code$/) do
|
49
|
+
assert_equal(0, @run_result[:exit_status])
|
50
|
+
assert_format_list
|
51
|
+
end
|
52
|
+
|
53
|
+
Then(/^([^ ]+) should be included in the listed formats$/) do |fmt_name|
|
54
|
+
actual = @run_result[:stdout].split("\n")
|
55
|
+
assert_includes(actual, fmt_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
Then(/^the file(?:s)? should be created$/) do
|
59
|
+
@expected_output_paths.each do |path|
|
60
|
+
assert(File.exist?(path), "#{path} should exist")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
Then(/^the generated files should be valid XML$/) do
|
4
|
+
@expected_output_paths.each do |path|
|
5
|
+
begin
|
6
|
+
doc = File.open(path) { |f| Nokogiri::XML(f) }
|
7
|
+
pass
|
8
|
+
rescue
|
9
|
+
flunk
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Then(/^the JUnit files should have the correct structure$/) do
|
15
|
+
@expected_output_paths.each do |path|
|
16
|
+
|
17
|
+
# puts "POINT A:" + path
|
18
|
+
|
19
|
+
doc = File.open(path) { |f| Nokogiri::XML(f) }
|
20
|
+
|
21
|
+
# puts "POINT B:" + doc.to_s
|
22
|
+
assert_equal(1, doc.xpath('/testsuites').length, "It should have one root testsuites element")
|
23
|
+
|
24
|
+
# It should have nonzero testsuite elements with a name attribute reflecting the language
|
25
|
+
match = doc.xpath('/testsuites/testsuite')
|
26
|
+
assert(match.length > 0, "It should have nonzero testsuite elements")
|
27
|
+
langs = CI::Syntax::Tool::LanguageFactory.all_language_names
|
28
|
+
match.each do |node|
|
29
|
+
assert_includes(langs, node.at_xpath('@name').to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
# It should have nonzero testcase elements, one per file, with name = sanitized filename
|
33
|
+
match = doc.xpath('/testsuites/testsuite/testcase')
|
34
|
+
assert(match.length > 0, "It should have nonzero testcase elements")
|
35
|
+
match.each do |node|
|
36
|
+
file = node.at_xpath('@name').to_s
|
37
|
+
refute_empty(file, "testcase should have a name attribute")
|
38
|
+
end
|
39
|
+
|
40
|
+
# It may have failure elements which must have a type=warning or error
|
41
|
+
match = doc.xpath('/testsuites/testsuite/testcase/failure')
|
42
|
+
match.each do |node|
|
43
|
+
type = node.at_xpath('@type').to_s
|
44
|
+
assert_includes(['warning', 'error'], type, "Each failure type should be either a warning or an error")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
Then(/^the JUnit files should have (\d+) (error|warning)s$/) do |count, level|
|
51
|
+
actual_count = 0
|
52
|
+
@expected_output_paths.each do |path|
|
53
|
+
doc = File.open(path) { |f| Nokogiri::XML(f) }
|
54
|
+
actual_count += doc.xpath("//failure[@type=\"#{level}\"]").length
|
55
|
+
end
|
56
|
+
assert_equal(count.to_i, actual_count)
|
57
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
When(/^I run it on the command line specifying(?: the)? ([^ ]+) language(?:s)? and ([^ ]+) files$/) do |lang_name, fixture_group|
|
2
|
+
options = [
|
3
|
+
'--require', Dir.pwd + '/' + 'test/fixtures/require/mock_format.rb',
|
4
|
+
'--format', 'MockFormat',
|
5
|
+
]
|
6
|
+
unless lang_name == 'all'
|
7
|
+
options << '--lang'
|
8
|
+
options << lang_name
|
9
|
+
end
|
10
|
+
options << 'test/fixtures/files/' + fixture_group
|
11
|
+
|
12
|
+
@run_result = run_check(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
Then(/^I should get a list of the core languages along with a zero exit code$/) do
|
16
|
+
assert_equal(0, @run_result[:exit_status].to_i)
|
17
|
+
assert_language_list
|
18
|
+
end
|
19
|
+
|
20
|
+
Then(/^the output should have (\d+) (error|warning)s$/) do |count, level|
|
21
|
+
actual = @run_result[:overall_result].send((level +'_count').to_sym)
|
22
|
+
assert_equal(count.to_i, actual)
|
23
|
+
end
|
24
|
+
|
25
|
+
Then(/^the output should show only files for ([^ ]+)$/) do |lang_name|
|
26
|
+
touched = @run_result[:overall_result].file_paths
|
27
|
+
matched = files_matching_language(touched, lang_name)
|
28
|
+
extra = touched - matched
|
29
|
+
assert_empty(extra, "The touched files should ONLY include files for #{lang_name}")
|
30
|
+
refute_empty(matched, "The touched files should include files for #{lang_name}")
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
Then(/^the output should include files for ([^ ]+)$/) do | lang_name|
|
35
|
+
touched = @run_result[:overall_result].file_paths
|
36
|
+
matched = files_matching_language(touched, lang_name)
|
37
|
+
refute_empty(matched, "The touched files should include files for #{lang_name}")
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
When(/^I run it on the command line with the require option (and the debug option )?and a (valid|invalid|missing) ruby file$/) do |need_debug, require_file|
|
2
|
+
options = [
|
3
|
+
'--require', Dir.pwd + '/' + 'test/fixtures/require/' + require_file + '.rb',
|
4
|
+
]
|
5
|
+
if need_debug then
|
6
|
+
options << '--debug'
|
7
|
+
end
|
8
|
+
options << 'test/fixtures/files/clean'
|
9
|
+
@run_result = run_check(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
When(/^I run it on the command line with two requires$/) do
|
13
|
+
options = [
|
14
|
+
'--require', Dir.pwd + '/' + 'test/fixtures/require/valid.rb',
|
15
|
+
'--require', Dir.pwd + '/' + 'test/fixtures/require/second.rb',
|
16
|
+
]
|
17
|
+
options << 'test/fixtures/files/clean'
|
18
|
+
@run_result = run_check(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
Then(/^I should get an error message about the (missing|invalid) require file$/) do |which_require|
|
22
|
+
assert_match(Regexp.new("Could not load .+ because it appears to be #{which_require}."), @run_result[:stderr])
|
23
|
+
assert_equal(1, @run_result[:stderr].split("\n").length, 'Stderr should be a single line, not a nasty stacktrace')
|
24
|
+
assert_empty(@run_result[:stdout], 'Stdout should be silent')
|
25
|
+
end
|
26
|
+
|
27
|
+
Then(/^I should get a stack trace about the invalid require file$/) do
|
28
|
+
assert_match(Regexp.new("Could not load .+ because it appears to be invalid."), @run_result[:stderr])
|
29
|
+
assert_match(Regexp.new('(Error|Exception)'),@run_result[:stderr], 'Stderr should include a stack trace')
|
30
|
+
assert_empty(@run_result[:stdout], 'Stdout should be silent')
|
31
|
+
end
|
32
|
+
|
33
|
+
Then(/^the (valid|first|second) ruby file should have been loaded$/) do |which_require|
|
34
|
+
klass_name = which_require == 'first' ? 'valid' : which_require
|
35
|
+
klass_name.capitalize!
|
36
|
+
klass_name = 'CI::Syntax::Tool::Test::' + klass_name + 'Require'
|
37
|
+
assert_class_loaded(klass_name)
|
38
|
+
end
|