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