gherkin 1.0.30-universal-dotnet

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.
Files changed (104) hide show
  1. data/.gitattributes +2 -0
  2. data/.gitignore +9 -0
  3. data/.mailmap +2 -0
  4. data/History.txt +187 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +59 -0
  7. data/Rakefile +58 -0
  8. data/VERSION.yml +5 -0
  9. data/bin/gherkin +5 -0
  10. data/cucumber.yml +3 -0
  11. data/features/escaped_pipes.feature +8 -0
  12. data/features/feature_parser.feature +226 -0
  13. data/features/native_lexer.feature +19 -0
  14. data/features/parser_with_native_lexer.feature +205 -0
  15. data/features/pretty_printer.feature +14 -0
  16. data/features/step_definitions/eyeball_steps.rb +3 -0
  17. data/features/step_definitions/gherkin_steps.rb +30 -0
  18. data/features/step_definitions/pretty_formatter_steps.rb +55 -0
  19. data/features/steps_parser.feature +46 -0
  20. data/features/support/env.rb +33 -0
  21. data/ikvm/.gitignore +3 -0
  22. data/java/.gitignore +2 -0
  23. data/java/src/main/java/gherkin/lexer/.gitignore +1 -0
  24. data/java/src/main/resources/gherkin/.gitignore +1 -0
  25. data/lib/.gitignore +4 -0
  26. data/lib/gherkin.rb +2 -0
  27. data/lib/gherkin/c_lexer.rb +17 -0
  28. data/lib/gherkin/cli/main.rb +33 -0
  29. data/lib/gherkin/formatter/argument.rb +27 -0
  30. data/lib/gherkin/formatter/colors.rb +119 -0
  31. data/lib/gherkin/formatter/escaping.rb +15 -0
  32. data/lib/gherkin/formatter/monochrome_format.rb +9 -0
  33. data/lib/gherkin/formatter/pretty_formatter.rb +168 -0
  34. data/lib/gherkin/i18n.rb +176 -0
  35. data/lib/gherkin/i18n.yml +588 -0
  36. data/lib/gherkin/i18n_lexer.rb +38 -0
  37. data/lib/gherkin/native.rb +7 -0
  38. data/lib/gherkin/native/ikvm.rb +55 -0
  39. data/lib/gherkin/native/java.rb +47 -0
  40. data/lib/gherkin/native/null.rb +9 -0
  41. data/lib/gherkin/parser/event.rb +45 -0
  42. data/lib/gherkin/parser/filter_listener.rb +199 -0
  43. data/lib/gherkin/parser/meta.txt +5 -0
  44. data/lib/gherkin/parser/parser.rb +142 -0
  45. data/lib/gherkin/parser/root.txt +11 -0
  46. data/lib/gherkin/parser/steps.txt +4 -0
  47. data/lib/gherkin/parser/tag_expression.rb +50 -0
  48. data/lib/gherkin/rb_lexer.rb +8 -0
  49. data/lib/gherkin/rb_lexer/.gitignore +1 -0
  50. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  51. data/lib/gherkin/rubify.rb +18 -0
  52. data/lib/gherkin/tools.rb +8 -0
  53. data/lib/gherkin/tools/files.rb +35 -0
  54. data/lib/gherkin/tools/reformat.rb +19 -0
  55. data/lib/gherkin/tools/stats.rb +21 -0
  56. data/lib/gherkin/tools/stats_listener.rb +57 -0
  57. data/ragel/i18n/.gitignore +1 -0
  58. data/ragel/lexer.c.rl.erb +425 -0
  59. data/ragel/lexer.java.rl.erb +216 -0
  60. data/ragel/lexer.rb.rl.erb +173 -0
  61. data/ragel/lexer_common.rl.erb +50 -0
  62. data/spec/gherkin/c_lexer_spec.rb +21 -0
  63. data/spec/gherkin/csharp_lexer_spec.rb +20 -0
  64. data/spec/gherkin/fixtures/1.feature +8 -0
  65. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  66. data/spec/gherkin/fixtures/complex.feature +45 -0
  67. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  68. data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
  69. data/spec/gherkin/fixtures/i18n_no.feature +7 -0
  70. data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
  71. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  72. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  73. data/spec/gherkin/fixtures/with_bom.feature +3 -0
  74. data/spec/gherkin/formatter/argument_spec.rb +28 -0
  75. data/spec/gherkin/formatter/colors_spec.rb +19 -0
  76. data/spec/gherkin/formatter/pretty_formatter_spec.rb +162 -0
  77. data/spec/gherkin/formatter/spaces.feature +9 -0
  78. data/spec/gherkin/formatter/tabs.feature +9 -0
  79. data/spec/gherkin/i18n_lexer_spec.rb +26 -0
  80. data/spec/gherkin/i18n_spec.rb +144 -0
  81. data/spec/gherkin/java_lexer_spec.rb +21 -0
  82. data/spec/gherkin/parser/filter_listener_spec.rb +390 -0
  83. data/spec/gherkin/parser/parser_spec.rb +50 -0
  84. data/spec/gherkin/parser/tag_expression_spec.rb +116 -0
  85. data/spec/gherkin/rb_lexer_spec.rb +19 -0
  86. data/spec/gherkin/sexp_recorder.rb +32 -0
  87. data/spec/gherkin/shared/lexer_spec.rb +550 -0
  88. data/spec/gherkin/shared/py_string_spec.rb +150 -0
  89. data/spec/gherkin/shared/row_spec.rb +104 -0
  90. data/spec/gherkin/shared/tags_spec.rb +50 -0
  91. data/spec/spec_helper.rb +87 -0
  92. data/tasks/bench.rake +188 -0
  93. data/tasks/bench/feature_builder.rb +49 -0
  94. data/tasks/bench/generated/.gitignore +1 -0
  95. data/tasks/bench/null_listener.rb +4 -0
  96. data/tasks/compile.rake +89 -0
  97. data/tasks/cucumber.rake +26 -0
  98. data/tasks/gems.rake +45 -0
  99. data/tasks/ikvm.rake +47 -0
  100. data/tasks/ragel_task.rb +70 -0
  101. data/tasks/rdoc.rake +12 -0
  102. data/tasks/release.rake +26 -0
  103. data/tasks/rspec.rake +15 -0
  104. metadata +257 -0
@@ -0,0 +1,150 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ shared_examples_for "a Gherkin lexer lexing py_strings" do
7
+
8
+ def ps(content)
9
+ '"""%s"""' % ("\n" + content + "\n")
10
+ end
11
+
12
+ it "should provide the amount of indentation of the triple quotes to the listener" do
13
+ str = <<EOS
14
+ Feature: some feature
15
+ Scenario: some scenario
16
+ Given foo
17
+ """
18
+ Hello
19
+ Goodbye
20
+ """
21
+ Then bar
22
+ EOS
23
+ @listener.should_receive(:py_string).with(" Hello\nGoodbye", 4)
24
+ @lexer.scan(str)
25
+ end
26
+
27
+ it "should parse a simple py_string" do
28
+ @listener.should_receive(:py_string).with("I am a py_string", 1)
29
+ @lexer.scan ps("I am a py_string")
30
+ end
31
+
32
+ it "should parse an empty py_string" do
33
+ @listener.should_receive(:py_string).with("", 4)
34
+ @lexer.scan("Feature: Hi\nScenario: Hi\nGiven a step\n\"\"\"\n\"\"\"")
35
+ end
36
+
37
+ it "should treat a string containing only newlines as only newlines" do
38
+ py_string = <<EOS
39
+ """
40
+
41
+
42
+
43
+ """
44
+ EOS
45
+ @listener.should_receive(:py_string).with("\n\n", 1)
46
+ @lexer.scan(py_string)
47
+ end
48
+
49
+ it "should parse content separated by two newlines" do
50
+ @lexer.scan ps("A\n\nB")
51
+ @listener.to_sexp.should == [
52
+ [:py_string, "A\n\nB", 1],
53
+ [:eof]
54
+ ]
55
+ end
56
+
57
+ it "should parse a multiline string" do
58
+ @listener.should_receive(:py_string).with("A\nB\nC\nD", 1)
59
+ @lexer.scan ps("A\nB\nC\nD")
60
+ end
61
+
62
+ it "should ignore unescaped quotes inside the string delimeters" do
63
+ @listener.should_receive(:py_string).with("What does \"this\" mean?", 1)
64
+ @lexer.scan ps('What does "this" mean?')
65
+ end
66
+
67
+ it "should preserve whitespace within the triple quotes" do
68
+ str = <<EOS
69
+ """
70
+ Line one
71
+ Line two
72
+ """
73
+ EOS
74
+ @listener.should_receive(:py_string).with(" Line one\nLine two", 1)
75
+ @lexer.scan(str)
76
+ end
77
+
78
+ it "should preserve tabs within the content" do
79
+ @listener.should_receive(:py_string).with("I have\tsome tabs\nInside\t\tthe content", 1)
80
+ @lexer.scan ps("I have\tsome tabs\nInside\t\tthe content")
81
+ end
82
+
83
+ it "should handle complex py_strings" do
84
+ py_string = <<EOS
85
+ # Feature comment
86
+ @one
87
+ Feature: Sample
88
+
89
+ @two @three
90
+ Scenario: Missing
91
+ Given missing
92
+
93
+ 1 scenario (1 passed)
94
+ 1 step (1 passed)
95
+
96
+ EOS
97
+
98
+ @listener.should_receive(:py_string).with(py_string, 1)
99
+ @lexer.scan ps(py_string)
100
+ end
101
+
102
+ it "should allow whitespace after the closing py_string delimiter" do
103
+ str = <<EOS
104
+ """
105
+ Line one
106
+ """
107
+ EOS
108
+ @listener.should_receive(:py_string).with(" Line one", 1)
109
+ @lexer.scan(str)
110
+ end
111
+
112
+ it "should preserve the last newline(s) at the end of a py_string" do
113
+ str = <<EOS
114
+ """
115
+ PyString text
116
+
117
+
118
+ """
119
+ EOS
120
+ @listener.should_receive(:py_string).with("PyString text\n\n",1)
121
+ @lexer.scan(str)
122
+ end
123
+
124
+ it "should preserve CRLFs within py_strings" do
125
+ @listener.should_receive(:py_string).with("Line one\r\nLine two\r\n", 1)
126
+ @lexer.scan("\"\"\"\r\nLine one\r\nLine two\r\n\r\n\"\"\"")
127
+ end
128
+
129
+ it "should unescape escaped triple quotes" do
130
+ str = <<EOS
131
+ """
132
+ \\"\\"\\"
133
+ """
134
+ EOS
135
+ @listener.should_receive(:py_string).with('"""', 1)
136
+ @lexer.scan(str)
137
+ end
138
+
139
+ it "should not unescape escaped single quotes" do
140
+ str = <<EOS
141
+ """
142
+ \\" \\"\\"
143
+ """
144
+ EOS
145
+ @listener.should_receive(:py_string).with('\" \"\"', 1)
146
+ @lexer.scan(str)
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ shared_examples_for "a Gherkin lexer lexing rows" do
7
+ rows = {
8
+ "|a|b|\n" => %w{a b},
9
+ "|a|b|c|\n" => %w{a b c},
10
+ }
11
+
12
+ rows.each do |text, expected|
13
+ it "should parse #{text}" do
14
+ @listener.should_receive(:row).with(r(expected), 1)
15
+ @lexer.scan(text.dup)
16
+ end
17
+ end
18
+
19
+ it "should parse a row with many cells" do
20
+ @listener.should_receive(:row).with(r(%w{a b c d e f g h i j k l m n o p}), 1)
21
+ @lexer.scan("|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|\n")
22
+ end
23
+
24
+ it "should parse multicharacter cell content" do
25
+ @listener.should_receive(:row).with(r(%w{foo bar}), 1)
26
+ @lexer.scan("| foo | bar |\n")
27
+ end
28
+
29
+ it "should escape backslashed pipes" do
30
+ @listener.should_receive(:row).with(r(['|', 'the', '\a', '\\', '|\\|']), 1)
31
+ @lexer.scan('| \| | the | \a | \\ | \|\\\| |' + "\n")
32
+ end
33
+
34
+ it "should parse cells with spaces within the content" do
35
+ @listener.should_receive(:row).with(r(["Dill pickle", "Valencia orange"]), 1)
36
+ @lexer.scan("| Dill pickle | Valencia orange |\n")
37
+ end
38
+
39
+ it "should allow utf-8" do
40
+ @lexer.scan(" | ůﻚ | 2 | \n")
41
+ @listener.to_sexp.should == [
42
+ [:row, ["ůﻚ", "2"], 1],
43
+ [:eof]
44
+ ]
45
+ end
46
+
47
+ it "should allow utf-8 using should_receive" do
48
+ @listener.should_receive(:row).with(r(['繁體中文 而且','並且','繁體中文 而且','並且']), 1)
49
+ @lexer.scan("| 繁體中文 而且|並且| 繁體中文 而且|並且|\n")
50
+ end
51
+
52
+ it "should parse a 2x2 table" do
53
+ @listener.should_receive(:row).with(r(%w{1 2}), 1)
54
+ @listener.should_receive(:row).with(r(%w{3 4}), 2)
55
+ @lexer.scan("| 1 | 2 |\n| 3 | 4 |\n")
56
+ end
57
+
58
+ it "should parse a 2x2 table with empty cells" do
59
+ @listener.should_receive(:row).with(r(['1', '']), 1)
60
+ @listener.should_receive(:row).with(r(['', '4']), 2)
61
+ @lexer.scan("| 1 | |\n|| 4 |\n")
62
+ end
63
+
64
+ it "should parse a row with empty cells" do
65
+ @listener.should_receive(:row).with(r(['1', '']), 1).twice
66
+ @lexer.scan("| 1 | |\n")
67
+ @lexer.scan("|1||\n")
68
+ end
69
+
70
+ it "should parse a 1x2 table that does not end in a newline" do
71
+ @listener.should_receive(:row).with(r(%w{1 2}), 1)
72
+ @lexer.scan("| 1 | 2 |")
73
+ end
74
+
75
+ it "should parse a row without spaces and with a newline" do
76
+ @listener.should_receive(:row).with(r(%w{1 2}), 1)
77
+ @lexer.scan("|1|2|\n")
78
+ end
79
+
80
+ it "should parse a row with whitespace after the rows" do
81
+ @listener.should_receive(:row).with(r(%w{1 2}), 1)
82
+ @lexer.scan("| 1 | 2 | \n ")
83
+ end
84
+
85
+ it "should parse a row with lots of whitespace" do
86
+ @listener.should_receive(:row).with(r(["abc", "123"]), 1)
87
+ @lexer.scan(" \t| \t abc\t| \t123\t \t\t| \t\t \t \t\n ")
88
+ end
89
+
90
+ it "should parse a table with a commented-out row" do
91
+ @listener.should_receive(:row).with(r(["abc"]), 1)
92
+ @listener.should_receive(:comment).with("#|123|", 2)
93
+ @listener.should_receive(:row).with(r(["def"]), 3)
94
+ @lexer.scan("|abc|\n#|123|\n|def|\n")
95
+ end
96
+
97
+ it "should raise LexingError for rows that aren't closed" do
98
+ lambda {
99
+ @lexer.scan("|| oh hello \n")
100
+ }.should raise_error(/Parsing error on line 1: '|| oh hello/)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ shared_examples_for "a Gherkin lexer lexing tags" do
7
+ it "should lex a single tag" do
8
+ @listener.should_receive(:tag).with("@dog", 1)
9
+ @lexer.scan("@dog\n")
10
+ end
11
+
12
+ it "should lex multiple tags" do
13
+ @listener.should_receive(:tag).twice
14
+ @lexer.scan("@dog @cat\n")
15
+ end
16
+
17
+ it "should lex UTF-8 tags" do
18
+ @listener.should_receive(:tag).with("@シナリオテンプレート", 1)
19
+ @lexer.scan("@シナリオテンプレート\n")
20
+ end
21
+
22
+ it "should lex mixed tags" do
23
+ @listener.should_receive(:tag).with("@wip", 1).ordered
24
+ @listener.should_receive(:tag).with("@Значения", 1).ordered
25
+ @lexer.scan("@wip @Значения\n")
26
+ end
27
+
28
+ it "should lex wacky identifiers" do
29
+ @listener.should_receive(:tag).exactly(4).times
30
+ @lexer.scan("@BJ-x98.77 @BJ-z12.33 @O_o" "@#not_a_comment\n")
31
+ end
32
+
33
+ # TODO: Ask on ML for opinions about this one
34
+ it "should lex tags without spaces between them?" do
35
+ @listener.should_receive(:tag).twice
36
+ @lexer.scan("@one@two\n")
37
+ end
38
+
39
+ it "should not lex tags beginning with two @@ signs" do
40
+ @listener.should_not_receive(:tag)
41
+ lambda { @lexer.scan("@@test\n") }.should raise_error(/Lexing error on line 1/)
42
+ end
43
+
44
+ it "should not lex a lone @ sign" do
45
+ @listener.should_not_receive(:tag)
46
+ lambda { @lexer.scan("@\n") }.should raise_error(/Lexing error on line 1/)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,87 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'spec/gherkin'))
4
+ require 'gherkin'
5
+ require 'stringio'
6
+ require 'gherkin/sexp_recorder'
7
+ require 'rubygems'
8
+ require 'spec'
9
+ require 'spec/autorun'
10
+ require 'shared/lexer_spec'
11
+ require 'shared/tags_spec'
12
+ require 'shared/py_string_spec'
13
+ require 'shared/row_spec'
14
+
15
+ if defined?(JRUBY_VERSION)
16
+ class OutputStreamStringIO < Java.java.io.ByteArrayOutputStream
17
+ def rewind
18
+ end
19
+
20
+ def read
21
+ toString("UTF-8")
22
+ end
23
+ end
24
+ end
25
+
26
+ class StringIO
27
+ class << self
28
+ def new
29
+ if defined?(JRUBY_VERSION)
30
+ OutputStreamStringIO.new
31
+ else
32
+ super
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ module GherkinSpecHelper
39
+ def scan_file(file)
40
+ @lexer.scan(File.new(File.dirname(__FILE__) + "/gherkin/fixtures/" + file).read)
41
+ end
42
+
43
+ def rubify_hash(hash)
44
+ if defined?(JRUBY_VERSION)
45
+ h = {}
46
+ hash.keySet.each{|key| h[key] = hash[key]}
47
+ h
48
+ else
49
+ hash
50
+ end
51
+ end
52
+ end
53
+
54
+ Spec::Runner.configure do |c|
55
+ c.include(GherkinSpecHelper)
56
+ end
57
+
58
+ # Allows comparison of Java List with Ruby Array (rows)
59
+ Spec::Matchers.define :r do |expected|
60
+ match do |row|
61
+ def row.inspect
62
+ "r " + self.map{|cell| cell}.inspect
63
+ end
64
+ row.map{|cell| cell}.should == expected
65
+ end
66
+ end
67
+
68
+ Spec::Matchers.define :a do |expected|
69
+ match do |array|
70
+ def array.inspect
71
+ "a " + self.map{|e| e.to_sym}.inspect
72
+ end
73
+ array.map{|e| e.to_sym}.should == expected
74
+ end
75
+ end
76
+
77
+ Spec::Matchers.define :sym do |expected|
78
+ match do |actual|
79
+ expected.to_s == actual.to_s
80
+ end
81
+ end
82
+
83
+ Spec::Matchers.define :allow do |event|
84
+ match do |parser|
85
+ parser.expected.index(event)
86
+ end
87
+ end
@@ -0,0 +1,188 @@
1
+ %w{/../lib /bench}.each do |l|
2
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + l)
3
+ end
4
+
5
+ require 'benchmark'
6
+
7
+ GENERATED_FEATURES = File.expand_path(File.dirname(__FILE__) + "/bench/generated")
8
+
9
+ class RandomFeatureGenerator
10
+ def initialize(number)
11
+ require 'faker'
12
+ require 'feature_builder'
13
+
14
+ @number = number
15
+ end
16
+
17
+ def generate
18
+ @number.times do
19
+ name = catch_phrase
20
+ feature = FeatureBuilder.new(name) do |f|
21
+ num_scenarios = rand_in(1..10)
22
+ num_scenarios.times do
23
+ f.scenario(bs) do |steps|
24
+ num_steps = rand_in(3..10)
25
+ num_steps.times do
26
+ steps.step(sentence, self)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ write feature.to_s, name
32
+ end
33
+ end
34
+
35
+ def write(content, name)
36
+ File.open(GENERATED_FEATURES + "/#{name.downcase.gsub(/[\s\-\/]/, '_')}.feature", "w+") do |file|
37
+ file << content
38
+ end
39
+ end
40
+
41
+ def rand_in(range)
42
+ ary = range.to_a
43
+ ary[rand(ary.length - 1)]
44
+ end
45
+
46
+ def catch_phrase
47
+ Faker::Company.catch_phrase
48
+ end
49
+
50
+ def bs
51
+ Faker::Company.bs.capitalize
52
+ end
53
+
54
+ def sentence
55
+ Faker::Lorem.sentence
56
+ end
57
+
58
+ def table_cell
59
+ Faker::Lorem.words(rand(2)+1).join(" ")
60
+ end
61
+ end
62
+
63
+ class Benchmarker
64
+ def initialize
65
+ @features = Dir[GENERATED_FEATURES + "/**/*feature"]
66
+ end
67
+
68
+ def report(lexer)
69
+ Benchmark.bm do |x|
70
+ x.report("#{lexer}:") { send :"run_#{lexer}" }
71
+ end
72
+ end
73
+
74
+ def report_all
75
+ Benchmark.bmbm do |x|
76
+ x.report("native_gherkin:") { run_native_gherkin }
77
+ x.report("native_gherkin_no_parser:") { run_native_gherkin_no_parser }
78
+ x.report("rb_gherkin:") { run_rb_gherkin }
79
+ x.report("cucumber:") { run_cucumber }
80
+ x.report("tt:") { run_tt }
81
+ end
82
+ end
83
+
84
+ def run_cucumber
85
+ require 'cucumber'
86
+ require 'logger'
87
+ step_mother = Cucumber::StepMother.new
88
+ logger = Logger.new(STDOUT)
89
+ logger.level = Logger::INFO
90
+ step_mother.log = logger
91
+ step_mother.load_plain_text_features(@features)
92
+ end
93
+
94
+ def run_tt
95
+ require 'cucumber'
96
+ # Using Cucumber's Treetop lexer, but never calling #build to build the AST
97
+ lexer = Cucumber::Parser::NaturalLanguage.new(nil, 'en').parser
98
+ @features.each do |file|
99
+ source = IO.read(file)
100
+ parse_tree = lexer.parse(source)
101
+ if parse_tree.nil?
102
+ raise Cucumber::Parser::SyntaxError.new(lexer, file, 0)
103
+ end
104
+ end
105
+ end
106
+
107
+ def run_rb_gherkin
108
+ require 'gherkin'
109
+ require 'gherkin/i18n_lexer'
110
+ require 'null_listener'
111
+ parser = Gherkin::Parser::Parser.new(NullListener.new, true, "root")
112
+ lexer = Gherkin::I18nLexer.new(parser, true)
113
+ @features.each do |feature|
114
+ lexer.scan(File.read(feature))
115
+ end
116
+ end
117
+
118
+ def run_native_gherkin
119
+ require 'gherkin'
120
+ require 'gherkin/i18n_lexer'
121
+ require 'null_listener'
122
+ parser = Gherkin::Parser::Parser.new(NullListener.new, true, "root")
123
+ lexer = Gherkin::I18nLexer.new(parser, false)
124
+ @features.each do |feature|
125
+ lexer.scan(File.read(feature))
126
+ end
127
+ end
128
+
129
+ def run_native_gherkin_no_parser
130
+ require 'gherkin'
131
+ require 'gherkin/i18n_lexer'
132
+ require 'null_listener'
133
+ lexer = Gherkin::I18nLexer.new(NullListener.new, false)
134
+ @features.each do |feature|
135
+ lexer.scan(File.read(feature))
136
+ end
137
+ end
138
+ end
139
+
140
+ desc "Generate 500 random features and benchmark Cucumber, Treetop and Gherkin with them"
141
+ task :bench => ["bench:clean", "bench:gen"] do
142
+ benchmarker = Benchmarker.new
143
+ benchmarker.report_all
144
+ end
145
+
146
+ namespace :bench do
147
+ desc "Generate [number] features with random content, or 500 features if number is not provided"
148
+ task :gen, :number do |t, args|
149
+ args.with_defaults(:number => 500)
150
+ generator = RandomFeatureGenerator.new(args.number.to_i)
151
+ generator.generate
152
+ end
153
+
154
+ desc "Benchmark Cucumber AST building from the features in tasks/bench/generated"
155
+ task :cucumber do
156
+ benchmarker = Benchmarker.new
157
+ benchmarker.report("cucumber")
158
+ end
159
+
160
+ desc "Benchmark the Treetop parser with the features in tasks/bench/generated"
161
+ task :tt do
162
+ benchmarker = Benchmarker.new
163
+ benchmarker.report("tt")
164
+ end
165
+
166
+ desc "Benchmark the Ruby Gherkin lexer+parser with the features in tasks/bench/generated"
167
+ task :rb_gherkin do
168
+ benchmarker = Benchmarker.new
169
+ benchmarker.report("rb_gherkin")
170
+ end
171
+
172
+ desc "Benchmark the ntive Gherkin lexer+parser with the features in tasks/bench/generated"
173
+ task :native_gherkin do
174
+ benchmarker = Benchmarker.new
175
+ benchmarker.report("native_gherkin")
176
+ end
177
+
178
+ desc "Benchmark the native Gherkin lexer (no parser) with the features in tasks/bench/generated"
179
+ task :native_gherkin_no_parser do
180
+ benchmarker = Benchmarker.new
181
+ benchmarker.report("native_gherkin_no_parser")
182
+ end
183
+
184
+ desc "Remove all generated features in tasks/bench/generated"
185
+ task :clean do
186
+ rm_f FileList[GENERATED_FEATURES + "/**/*feature"]
187
+ end
188
+ end