lib/uttk/strategies/Strategy.rb in uttk-0.3.6.1 vs lib/uttk/strategies/Strategy.rb in uttk-0.4.5.0
- old
+ new
@@ -1,9 +1,9 @@
# Author:: The Uttk Team.
# Copyright:: Copyright (c) 2004, 2005 Uttk team. All rights reserved.
# License:: LGPL
-# $Id: /w/fey/uttk/trunk/lib/uttk/strategies/Strategy.rb 22184 2006-02-23T16:12:25.225774Z pouillar $
+# $Id: /w/fey/uttk/trunk/lib/uttk/strategies/Strategy.rb 24392 2006-07-10T07:36:43.181560Z ertai $
require 'set'
require 'timeout'
@@ -461,10 +461,156 @@
check_assertion('post-assertions', @post_assertion)
end
protected :check_post_assertion
+ # FIXME move them to separate files
+ def mk_system_runner env={}
+ hooker = StrategyHooker.new @symtbl, @log, env
+ OCmd::Runners::System.new.hooker_subscribe hooker
+ end
+
+ class StrategyHooker
+ include Hooker
+
+ attr_reader :env, :symtbl, :log
+
+ def initialize symtbl, log, env={}
+ @env, @symtbl, @log = env, symtbl, log
+ end
+
+ def display_command cmd
+ cmd.do_symtbl_gsub! @symtbl
+ @log[:running] = cmd.to_sh
+ end
+
+ def before_exec cmd, data
+ env_sub = proc do |k,v|
+ ENV[k.to_s] = v.do_symtbl_gsub(@symtbl).gsub(/\$(\w+)/) { ENV[$1] }
+ end
+ @env.each(&env_sub)
+ @symtbl[:env].each(&env_sub) if @symtbl[:env]
+ end
+
+ def exception_raised_during_exec
+ @data.status = 127
+ fail 'exception raised during exec'
+ end
+
+ def already_killed data
+ @log.already_killed = data.pid
+ end
+
+ end # class StrategyHooker
+
+
+ class CommandMatcher < UM::UnifiedMatcher
+ make Concrete
+ cattr_accessor :stream_matcher
+
+ rule :to_ocmd
+
+ final(Hash, OCmd::Datas::Data) do |ref, my|
+ raise ArgumentError, 'ref is empty' if ref.empty?
+ result = UM::MatcherResults.new
+ for k,v in ref do
+ result << stream_matcher[v, my.send(k), k]
+ end
+ result
+ end
+
+ final(OCmd::Datas::Data, OCmd::Datas::Data) do |ref, my|
+ result = UM::MatcherResults.new
+ result << stream_matcher[ref.status, my.status, 'status']
+ result << stream_matcher[ref.output, my.output, 'output']
+ result << stream_matcher[ref.error, my.error, 'error']
+ result
+ end
+
+ def [] matcher, ref, my, name=nil
+ matcher = matcher.new if matcher.is_a? Class
+ self.stream_matcher = matcher
+ super(ref, my, name)
+ end
+
+ end
+
+ ::UM::StreamMatcher.class_eval do
+ final(NilClass, Object, :message => '') { |ref, my| [ true, nil ] }
+ end
+
+ ::UM::GnuDiffMatcher.runner = OCmd::Runners::System.new
+
+ ::UM::MatcherResults.class_eval do
+ def to_uttk_log log
+ each do |r|
+ log << r
+ end
+ end
+ end
+
+ ::UM::MatcherResult.class_eval do
+ if true
+ def to_uttk_log log
+ raise ArgumentError, "no name for this matcher result" if @name.nil?
+ log.new_node @name do
+ log.reason = message unless message.empty?
+ if data.nil? or data.is_a? MatchData
+ log.my = my.to_s_for_uttk_log unless my.nil?
+ log.ref = ref.to_s_for_uttk_log unless ref.nil?
+ else
+ log.diff = data.output.read
+ end
+ end
+ end
+ else
+ def to_uttk_log log
+ raise ArgumentError, "no name for this matcher result" if @name.nil?
+ log["#{@name}_reason"] = message unless message.empty?
+ if data.nil? or data.is_a? MatchData
+ log["my_#@name"] = my.to_s_for_uttk_log unless my.nil?
+ log["ref_#@name"] = ref.to_s_for_uttk_log unless ref.nil?
+ else
+ log["#{@name}_diff"] = data.output.read
+ end
+ end
+ end
+ end
+
+ ::OCmd::Commands::Command.class_eval do
+ def symtbl_gsub! symtbl
+ res = @command.symtbl_gsub!(symtbl)
+ res = @args.symtbl_gsub!(symtbl) || res
+ res = @dir.symtbl_gsub!(symtbl) || res
+ (res)? self : nil
+ end
+ def symtbl_gsub symtbl
+ command = @command.symtbl_gsub symtbl
+ args = @args.symtbl_gsub symtbl
+ dir = @dir.symtbl_gsub symtbl
+ if command || args || dir
+ self.class.new(command || @command, args || @args, dir || @dir)
+ else
+ nil
+ end
+ end
+ end
+
+ cattr_accessor :command_matcher
+ self.command_matcher ||= CommandMatcher.new
+
+ # Examples:
+ # assert_cmd @matcher, @data, :output => /foo*/, :error => '', :exit => 0
+ # assert_cmd UM::StreamMatcher, @data, :output => 'foo.txt'.to_path
+ # The given matcher is used to match command data contents.
+ def assert_cmd matcher, my, ref
+ matcher_result = command_matcher[matcher, ref, my]
+ @log << matcher_result
+ fail if matcher_result.failure?
+ return matcher_result
+ end
+
# Display conclusions.
# Here you can finish some tasks even when the test fails.
# Exceptions are absolutly forbidden in this method.
def epilogue
unless @save.nil?
@@ -498,11 +644,10 @@
def pass_hook
end
protected :pass_hook
-
#
# Assertions
#
def raise_status ( status )
@@ -522,12 +667,17 @@
# Force the test to pass
def pass
raise_status PassStatus.new
end
- # Skip the test
+ # Skip the test (by default the weight is 0%)
def skip ( *args )
raise_status_custom SkipStatus, *args
+ end
+
+ # Skip the test: the weight is 100%.
+ def skip_pass ( message=nil )
+ raise_status SkipStatus.new(PassStatus.new.weight, message)
end
# Force an Error status
def raise_error ( message=nil )
@symtbl[:flow] << :error