module CucumberCsteps

Constants

TYPE_MAP
VERSION

Public Class Methods

define_steps(filename, library_name, library_file) click to toggle source
# File lib/cucumber_csteps/define_steps.rb, line 22
def self.define_steps(filename, library_name, library_file)
  module_name = library_name.camelize
  module_code = %Q{
    module #{module_name}
      extend FFI::Library
      ffi_lib ['#{library_name}', '#{library_file}']

      begin
        attach_function('before_scenario', [], :void)
        before_hook = proc { #{module_name}.before_scenario() }
        Cucumber::RbSupport::RbDsl.register_rb_hook('before', [], before_hook)
      rescue FFI::NotFoundError
      end

      begin
        attach_function('after_scenario', [], :void)
        after_hook = proc { #{module_name}.after_scenario() }
        Cucumber::RbSupport::RbDsl.register_rb_hook('after', [], proc { after_hook() })
      rescue FFI::NotFoundError
      end
    end
  }

  eval(module_code)

  step_prefix = find_step_prefix(filename)
  step_definitions = find_step_definitions(filename)
  step_definitions.map do |step_definition, line_number|
    step = parse_cstep(step_definition)
    fun_name = "#{step_prefix}#{line_number}".to_sym
    args = step.c_args.map { |arg| TYPE_MAP[arg.type][:ffi_type] }.join(",")

    attach_code = %Q{
      module #{module_name}
        #{fun_name} = attach_function('#{fun_name}', [#{args}], :void)
      end
    }

    eval(attach_code)

    lambda_args = step.c_args.map do |arg|
      arg.identifier
    end.join(",")

    fun_args = step.c_args.map do |arg|
      cast_op = TYPE_MAP[arg.type][:cast_op]
      "#{arg.identifier}.#{cast_op}"
    end.join(",")

    code_block = %Q{lambda { |#{lambda_args}| 
      CucumberCsteps.try_and_catch_abort do
        #{module_name}.#{fun_name}(#{fun_args})
      end
     }}

    [step.regex, eval(code_block) ]
  end
end
load_steps(lib_name, lib_file, glob_patterns) click to toggle source
# File lib/cucumber_csteps/define_steps.rb, line 14
def self.load_steps(lib_name, lib_file, glob_patterns)
  Dir.glob(glob_patterns).each do |file|
    CucumberCsteps.define_steps(file, lib_name, lib_file).each do |regex, block|
      Cucumber::RbSupport::RbDsl.register_rb_step_definition(regex, block)
    end
  end
end
parse_cstep(s) click to toggle source
# File lib/cucumber_csteps/parser.rb, line 6
def self.parse_cstep(s)
  tree = CStepParser.new.parse(s)
  CStepTransform.new.apply(tree)
end
try_and_catch_abort() { || ... } click to toggle source
# File lib/cucumber_csteps/step_wrapper.rb, line 13
def self.try_and_catch_abort(&block)
  step_failed = false
  
  on_sigabrt = Proc.new do |signum|
    step_failed = true
    throw :error
  end

  StdLib.signal(6, on_sigabrt)
  catch(:error) do
    yield
  end

  if step_failed
    fail()
  end
   
end

Private Class Methods

find_step_definitions(filename) click to toggle source
# File lib/cucumber_csteps/define_steps.rb, line 93
def self.find_step_definitions(filename)
  step_regex = /^\s*(GIVEN|WHEN|THEN)\s*(.*)/
  code = File.read(filename)

  matching_lines = []
  code.lines.each_with_index do |line, line_number|
    if line.match(step_regex)
      matching_lines << [line, line_number + 1]
    end
  end

  matching_lines
end
find_step_prefix(filename) click to toggle source
# File lib/cucumber_csteps/define_steps.rb, line 83
def self.find_step_prefix(filename)
  step_prefix_regex = /#define\s+STEP_PREFIX\s+(\w+)/
  code = File.read(filename)

  prefixes = code.lines.select { |l| l =~ step_prefix_regex }
  raise "Step file '#{filename}' contains #{prefixes.size} STEP_PREFIX definitions." if prefixes.size != 1

  prefixes.first.match(step_prefix_regex)[1]
end