class Regextest

This routine defines Regextest class

Copyright © 2016 Mikio Ikoma

Constants

VERSION

Attributes

reason[R]

@!attribute [r] reason

Reason if failed to generate
@return [hash] return reasons if failed to generate
@return [nil] return nil unless error
seed[R]

@!attribute [r] seed

Seed for randomization
@return [Fixnum] return seed for randomization
@return [nil] return nil if no seed provided

Public Class Methods

new(regex, options = {}) click to toggle source

Constructor of Regextest class @param [String|Regexp] regex regular expression object (or string) @param [Hash] options parameters for generating @option options [Regextest::RegexOption] :reg_options Regex option parameter @option options [Fixnum] :seed seed for randomization @option options [TrueClass] :verification specify true (or not speficy) to verify generated string using ruby Regexp. @option options [FalseClass] :verification specify false if skip to verify generated string. @return [Regextest] constructed object

# File lib/regextest.rb, line 33
def initialize(regex, options = {})
  @@parse_options = options
  @@parse_options[:reg_options] ||= Regextest::RegexOption.new
  @verification = (options && options[:verification] == false)?false:true
  @reg_string = nil
  @reg_exp = nil
  
  # Set seed for randomizing
  @seed = set_seed_for_randomizing(@@parse_options[:seed])

  # Covert to source string if necessary
  set_regex(regex)

  # Parse string
  @front_end = Regextest::Front.new(@reg_string, @@parse_options)
  
  # Prepare back-end process. (use generate method for generating string)
  @back_end = Regextest::Back.new(@front_end)
  
  @result = nil
  @reason = nil
end

Public Instance Methods

generate() click to toggle source

Genetate string matched with specified regular expression @return [MatchData] if matched and verified. @return [String] if matched without verification (i.e. return unverified matched string). @return [nil] nil if failed to generate @raise [RuntimeError] if something wrong… @raise [Regextest::RegextestTimeout] if detected timeout while verification. Option ‘verification: false’ may be workaround.

# File lib/regextest.rb, line 74
def generate
  start_time = Time.now
  0.step(TstFixnumMax) do | retry_count |
    duration = Time.now - start_time
    break if retry_count >= TstConstRetryMax && duration >= TstConstRetryMaxSecond
    
    # generate string
    reset_random_called
    @result = @back_end.generate(retry_count)
    if !@result
      TstLog "NG: Failed to generate"
      @reason = :failed_to_generate
      if !is_random?
        raise(RegextestError, "It is impossible to generate sample string of #{@reg_string}.")
      end
      next
    end

    result_string = @result.pre_match + @result.match + @result.post_match
    
    # verify generated string
    if @verification
      @result = verify(result_string)    # returns a match-object
      if !@result
        TstLog "NG: Failed to verify"
        @reason = :failed_to_verify
        next
      end
      # break if @result is verified
    else
      @result = result_string            # returns a string
    end
    break
  end
  
  if !@result
    raise(RegextestFailedToGenerate, "Regextest failed to generate sample string of #{@reg_string}.")
  end
  @result
end
to_json() click to toggle source

Get parsed result as JSON string @return [String] parsed result as JSON string

# File lib/regextest.rb, line 117
def to_json
  @front_end.get_json_string
end

Private Instance Methods

check_builtin(param) click to toggle source

add built-in functions if any

# File lib/regextest.rb, line 158
def check_builtin(param)
  builtin_functions = {}
  param.scan(/\\g[\<\'](_\w+_)[\>\']/) do | func_name |
    builtin_functions[func_name[0]] = true
  end
  if builtin_functions.keys.size > 0
    require 'regextest/front/builtin-functions'
    functions = Regextest::Front::BuiltinFunctions.new
    builtin_functions.keys.each do | func_name |
      if func_string = functions.find_func(func_name)
        param = param + func_string
      else
        raise "invalid built-in function name (#{func_name})"
      end
    end
  end
  param
end
set_regex(param) click to toggle source

Covert to source string if necessary

# File lib/regextest.rb, line 136
def set_regex(param)
  case param
  when String
    if md = param.match(/^\/(.*)\/([imx]*)$/)
      @reg_exp = eval(param)
      @reg_string = @reg_exp.source
    else
      new_param = check_builtin(param)
      @reg_string = new_param
      @reg_exp = /#{@reg_string}/
    end
  when Regexp
    @reg_exp = param
    @@parse_options[:reg_options].set(@reg_exp.options)   # inner regex options have priorty
    @reg_string = @@parse_options[:reg_options].prefix_reg + @reg_exp.source
  else
    raise "Error: string or regular expression required"
  end
  @@parse_options[:reg_source] = @reg_string
end
set_seed_for_randomizing(seed) click to toggle source

Set seed for randomizing

# File lib/regextest.rb, line 125
def set_seed_for_randomizing(seed)
  if seed
    raise "Invalid seed (#{seed}: #{seed.class}) specified" if !(Integer === seed)
    srand seed
    seed
  else
    srand   # return preset seed
  end
end
verify(result_string) click to toggle source

Verifies the result

# File lib/regextest.rb, line 178
def verify(result_string)
  md = nil
  begin
    Timeout.timeout(TstConstTimeout){
      md = @reg_exp.match(result_string)
    }
  rescue Timeout::Error => ex
    raise(RegextestTimeout,
          "Timeout(#{TstConstTimeout} sec) detected while verifying string(#{result_string}) matched with regex(#{@reg_exp}).")
  end
  
  if(md)
    # matched string sometime differs from expected one...
    if(md.pre_match  != @result.pre_match || 
       md.to_a[0]    != @result.match ||
       md.post_match != @result.post_match)
      @reason = :invalid_match_string
      TstLog "WARN: Invalid matched string, expected <--> actual"
      TstLog "  proc: #{md.pre_match.inspect}  <-->  #{@result.pre_match.inspect}"
      TstLog "  body: #{md.to_a[0].inspect}  <-->  #{@result.match.inspect}"
      TstLog "  succ: #{md.post_match.inspect}  <-->  #{@result.post_match.inspect}"
    end
  else
    @reason = { rc: :not_matched, string: result_string}
    raise("failed to generate. Not matched regex(#{@reg_string}) string(#{result_string.inspect})")
  end
  md
end