mirror of
https://github.com/inspec/inspec
synced 2024-11-23 13:13:22 +00:00
rabbitmq parser: tree transformation to ruby objects
This commit is contained in:
parent
ea1137b0ee
commit
860750d967
1 changed files with 95 additions and 21 deletions
116
parslet.rb
116
parslet.rb
|
@ -5,21 +5,21 @@ class ErlAx < Parslet::Parser
|
|||
# only designed for rabbitmq config files for now:
|
||||
rule(:outermost) { filler? >> array.maybe >> dot.maybe }
|
||||
|
||||
rule(:expression) {
|
||||
rule(:exp) {
|
||||
(tuple | array | binary | string | bool | identifier | float | integer) >> filler?
|
||||
}
|
||||
|
||||
rule(:array) {
|
||||
str('[') >> filler? >> (
|
||||
expression >>
|
||||
(comma >> expression).repeat
|
||||
exp.repeat(1) >>
|
||||
(comma >> exp).repeat
|
||||
).maybe.as(:array) >> str(']') >> filler?
|
||||
}
|
||||
|
||||
rule(:tuple) {
|
||||
str('{') >> filler? >> (
|
||||
expression >> filler? >>
|
||||
(comma >> expression).repeat
|
||||
exp.repeat(1) >> filler? >>
|
||||
(comma >> exp).repeat
|
||||
).maybe.as(:tuple) >> str('}') >> filler?
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ end
|
|||
|
||||
|
||||
|
||||
|
||||
require 'minitest/autorun'
|
||||
require 'minitest/spec'
|
||||
describe ErlAx do
|
||||
|
@ -96,35 +97,35 @@ describe ErlAx do
|
|||
end
|
||||
|
||||
it 'parse simple root array' do
|
||||
_(parsestr("[].\n")).must_equal "{:array=>nil}"
|
||||
_(parsestr("[].\n")).must_equal '{:array=>nil}'
|
||||
end
|
||||
|
||||
it 'parses a root array with an int' do
|
||||
_(parsestr('[1].')).must_equal '{:array=>{:integer=>"1"@1}}'
|
||||
_(parsestr('[1].')).must_equal '{:array=>[{:integer=>"1"@1}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a float' do
|
||||
_(parsestr('[1.1].')).must_equal '{:array=>{:float=>{:integer=>"1"@1, :e=>".1"@2}}}'
|
||||
_(parsestr('[1.1].')).must_equal '{:array=>[{:float=>{:integer=>"1"@1, :e=>".1"@2}}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a double quoted string' do
|
||||
_(parsestr('["st\"r"].')).must_equal '{:array=>{:string=>"st\\\\\\"r"@2}}'
|
||||
_(parsestr('["st\"r"].')).must_equal '{:array=>[{:string=>"st\\\\\\"r"@2}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a single quoted string' do
|
||||
_(parsestr('[\'st\\\'r\'].')).must_equal '{:array=>{:string=>"st\\\\\'r"@2}}'
|
||||
_(parsestr('[\'st\\\'r\'].')).must_equal '{:array=>[{:string=>"st\\\\\'r"@2}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a binary' do
|
||||
_(parsestr('[<<0, G, B>>].')).must_equal '{:array=>{:binary=>"0, G, B"@3}}'
|
||||
_(parsestr('[<<0, G, B>>].')).must_equal '{:array=>[{:binary=>"0, G, B"@3}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a boolean' do
|
||||
_(parsestr('[true].')).must_equal '{:array=>{:bool=>"true"@1}}'
|
||||
_(parsestr('[true].')).must_equal '{:array=>[{:bool=>"true"@1}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with an identifier' do
|
||||
_(parsestr('[hello_world123].')).must_equal '{:array=>{:identifier=>"hello_world123"@1}}'
|
||||
_(parsestr('[hello_world123].')).must_equal '{:array=>[{:identifier=>"hello_world123"@1}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with multiple elements' do
|
||||
|
@ -132,23 +133,23 @@ describe ErlAx do
|
|||
end
|
||||
|
||||
it 'parses a root array with an tuple' do
|
||||
_(parsestr('[{}].')).must_equal '{:array=>{:tuple=>nil}}'
|
||||
_(parsestr('[{}].')).must_equal '{:array=>[{:tuple=>nil}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with an tuple' do
|
||||
_(parsestr('[{handshake_timeout, 100}].')).must_equal '{:array=>{:tuple=>[{:identifier=>"handshake_timeout"@2}, {:integer=>"100"@21}]}}'
|
||||
_(parsestr('[{handshake_timeout, 100}].')).must_equal '{:array=>[{:tuple=>[{:identifier=>"handshake_timeout"@2}, {:integer=>"100"@21}]}]}'
|
||||
end
|
||||
|
||||
it 'parses a root array with a stringy tuple' do
|
||||
_(parsestr('[{ab, [{"c", 1},{"d",2}]}].')).must_equal '{:array=>{:tuple=>[{:identifier=>"ab"@2}, {:array=>[{:tuple=>[{:string=>"c"@9}, {:integer=>"1"@13}]}, {:tuple=>[{:string=>"d"@18}, {:integer=>"2"@21}]}]}]}}'
|
||||
_(parsestr('[{ab, [{"c", 1},{"d",2}]}].')).must_equal '{:array=>[{:tuple=>[{:identifier=>"ab"@2}, {:array=>[{:tuple=>[{:string=>"c"@9}, {:integer=>"1"@13}]}, {:tuple=>[{:string=>"d"@18}, {:integer=>"2"@21}]}]}]}]}'
|
||||
end
|
||||
|
||||
it 'parses a complex deep array-tuple mix' do
|
||||
_(parsestr('[{rabbit,[{two,[]}]}].')).must_equal '{:array=>{:tuple=>[{:identifier=>"rabbit"@2}, {:array=>{:tuple=>[{:identifier=>"two"@11}, {:array=>nil}]}}]}}'
|
||||
_(parsestr('[{rabbit,[{two,[]}]}].')).must_equal '{:array=>[{:tuple=>[{:identifier=>"rabbit"@2}, {:array=>[{:tuple=>[{:identifier=>"two"@11}, {:array=>nil}]}]}]}]}'
|
||||
end
|
||||
|
||||
it 'parses a complex multi array tuple mix' do
|
||||
_(parsestr('[{rabbit,[{two,[]}]}, 3, false].')).must_equal '{:array=>[{:tuple=>[{:identifier=>"rabbit"@2}, {:array=>{:tuple=>[{:identifier=>"two"@11}, {:array=>nil}]}}]}, {:integer=>"3"@22}, {:bool=>"false"@25}]}'
|
||||
_(parsestr('[{rabbit,[{two,[]}]}, 3, false].')).must_equal '{:array=>[{:tuple=>[{:identifier=>"rabbit"@2}, {:array=>[{:tuple=>[{:identifier=>"two"@11}, {:array=>nil}]}]}]}, {:integer=>"3"@22}, {:bool=>"false"@25}]}'
|
||||
end
|
||||
|
||||
it 'parses a complex array-tuple mix with comments' do
|
||||
|
@ -161,10 +162,81 @@ describe ErlAx do
|
|||
{tcp_listeners, [5672]}
|
||||
]}].
|
||||
'
|
||||
_(parsestr(s)).must_equal '{:array=>{:tuple=>[{:identifier=>"rabbit"@29}, {:array=>{:tuple=>[{:identifier=>"tcp_listeners"@75}, {:array=>{:integer=>"5672"@91}}]}}]}}'
|
||||
_(parsestr(s)).must_equal '{:array=>[{:tuple=>[{:identifier=>"rabbit"@29}, {:array=>[{:tuple=>[{:identifier=>"tcp_listeners"@75}, {:array=>[{:integer=>"5672"@91}]}]}]}]}]}'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class ErlEr < Parslet::Transform
|
||||
class Tuple < Array; end
|
||||
class Identifier < String; end
|
||||
rule(string: simple(:x)) { x.to_s }
|
||||
rule(string: []) { '' }
|
||||
rule(integer: simple(:x)) { x.to_i }
|
||||
rule(float: { integer: simple(:a), e: simple(:b) }) { (a+b).to_f }
|
||||
rule(bool: 'true') { true }
|
||||
rule(bool: 'false') { false }
|
||||
rule(identifier: simple(:x)) { Identifier.new(x.to_s) }
|
||||
# TODO: binary!
|
||||
rule(array: subtree(:x)) { Array(x) }
|
||||
rule(tuple: subtree(:x)) {
|
||||
x.nil? ? Tuple.new : Tuple.new(x)
|
||||
}
|
||||
end
|
||||
|
||||
describe ErlEr do
|
||||
def parse(c)
|
||||
ErlEr.new.apply(ErlAx.new.parse(c))
|
||||
end
|
||||
|
||||
it 'parses a real rabbitmq config file' do
|
||||
it 'transforms and empty file' do
|
||||
_(parse('')).must_equal ''
|
||||
end
|
||||
|
||||
it 'transforms an empty array' do
|
||||
_(parse('[].')).must_equal []
|
||||
end
|
||||
|
||||
it 'transforms a simple array with one string' do
|
||||
_(parse('["one"].')).must_equal ['one']
|
||||
end
|
||||
|
||||
it 'transforms a simple array with an empty string' do
|
||||
_(parse('[\'\'].')).must_equal ['']
|
||||
end
|
||||
|
||||
it 'transforms a simple array with multiple values' do
|
||||
_(parse('[1, 1.1, true, false, "ok"].')).must_equal [1, 1.1, true, false, 'ok']
|
||||
end
|
||||
|
||||
it 'transforms a deep array' do
|
||||
_(parse('[[[[1]]]].')).must_equal [[[[1]]]]
|
||||
end
|
||||
|
||||
it 'transforms an empty tuple' do
|
||||
_(parse('[{}].')).must_equal [ErlEr::Tuple.new]
|
||||
end
|
||||
|
||||
it 'transforms a tuple with one element' do
|
||||
_(parse('[{1}].')).must_equal [ErlEr::Tuple.new([1])]
|
||||
end
|
||||
|
||||
it 'transforms a tuple with multiple elements' do
|
||||
_(parse('[{id123, 1, 1.1}].')).must_equal [ErlEr::Tuple.new([ErlEr::Identifier.new('id123'), 1, 1.1])]
|
||||
end
|
||||
|
||||
it 'transforms a deep tuple' do
|
||||
_(parse('[{{{1}}}].')).must_equal [ErlEr::Tuple.new([ErlEr::Tuple.new([ErlEr::Tuple.new([1])])])]
|
||||
end
|
||||
|
||||
it 'transforms a deep mix of tuple and array' do
|
||||
_(parse('[{[{1}]}].')).must_equal [ErlEr::Tuple.new([[ErlEr::Tuple.new([1])]])]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'complex use-case' do
|
||||
it 'parses a tricky rabbitmq config file' do
|
||||
f = 'rabbitmq.config'
|
||||
unless File.file?(f)
|
||||
puts "NO #{f}, skipping this check!"
|
||||
|
@ -172,6 +244,8 @@ describe ErlAx do
|
|||
end
|
||||
puts 'Wheeee, testing a real rabbitmq nasty config file'
|
||||
c = File.read(f)
|
||||
parsestr(c)
|
||||
_(ErlAx.new.parse(c).to_s).must_be_instance_of String
|
||||
res = ErlEr.new.apply(ErlAx.new.parse(c))
|
||||
# require "pry"; binding.pry
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue