classTryouts# = Drill# # This class represents a drill. A drill is single test. #classDrillrequire'tryouts/drill/context'require'tryouts/drill/response'require'tryouts/drill/sergeant/cli'require'tryouts/drill/sergeant/api'require'tryouts/drill/sergeant/benchmark'require'tryouts/drill/sergeant/rbenchmark'classNoSergeant<Tryouts::Exception;endclassUnknownFormat<Tryouts::Exception;end# A symbol specifying the drill type. One of: :cli, :apiattr_reader:dtype# The name of the drill. This should match the name used in the dreams file. attr_reader:name# A Proc object which contains the drill logic. attr_reader:drill# A Sergeant object which executes the drillattr_reader:sergeant# An Array of Dream objects (the expected output of the test)attr_reader:dreams# A Reality object (the actual output of the test)attr_reader:reality@@valid_dtypes=[:api,:benchmark]# * +name+ The display name of this drill# * +dtype+ A Symbol representing the drill type. One of: :api, :benchmark# * +args+ These are dependent on the drill type. See the Sergeant classes# * +&drill+ The body of the drill. The return value of this block # is compared to the exepected output of the dreams. ## The DSL syntax:# * dream OUTPUT# * dream FORMAT, OUTPUT# * dream FORMAT, OUTPUT, REPS (benchmark only)#definitialize(name,dtype,*args,&drill)@name,@dtype,@drill,@skip=name,dtype,drill,false@dreams=[]case@dtypewhen:cli@sergeant=Tryouts::Drill::Sergeant::CLI.new*argswhen:apidefault_output=drill.nil??args.shift:nildream_output,format=*(args.size==1?args.first:args.reverse)@sergeant=Tryouts::Drill::Sergeant::API.newdefault_outputunlessargs.empty?@dreams<<Tryouts::Drill::Dream.new(dream_output,format)endwhen:benchmarkifargs.size==1reps=args.firstelsedream_output,format,reps=args[1],args[0],args[2]end@sergeant=Tryouts::Drill::Sergeant::Benchmark.newreps@dreams<<Tryouts::Drill::Dream.new(Tryouts::Stats,:class)unlessdream_output.nil?@dreams<<Tryouts::Drill::Dream.new(dream_output,format)endwhen:skip@skip=trueelseraiseNoSergeant,"Weird drill sergeant: #{@dtype}"end@clr=:red# For CLI drills, a block takes precedence over inline args. # A block will contain multiple shell commands (see Rye::Box#batch)drill_args=[]ifdtype==:cli&&drill.is_a?(Proc)@reality=Tryouts::Drill::Reality.newenddefself.valid_dtypes;@@valid_dtypes;enddefself.valid_dtype?(t);@@valid_dtypes.member?(t);enddefskip?;@skip;enddefrun(context=nil)begin@reality=@sergeant.run@drill,context# Store the stash from the drill block@reality.stash=context.stashifcontext.respond_to?:stash# If the drill block returned true we assume success if there's no dreamif@dreams.empty?&&@reality.output==true@dreams<<Tryouts::Drill::Dream.new@dreams.first.output=trueendrescue=>ex@reality.ecode,@reality.etype=-2,ex.class@reality.error,@reality.trace=ex.message,ex.backtraceendself.success?enddefflagifskip?"SKIP"elsifsuccess?"PASS".color(@clr).brightelsenote=@dreams.empty??'[nodream]':''"FAIL #{note}".color(@clr).brightendenddefinfoout=StringIO.newifTryouts.verbose>0if@dtype==:benchmarkunless@reality.output.nil?mean,sdev,sum=@reality.output.mean,@reality.output.sdev,@reality.output.sumout.puts'%6s%.4f (sdev:%.4f sum:%.4f)'.color(@clr)%['',mean,sdev,sum]endelseout.puts'%6s%s'.color(@clr)%['',@reality.output.inspect]endunless@reality.stash.empty?@reality.stash.each_pairdo|n,v|out.puts'%18s: %s'.color(@clr)%[n,v.inspect]endendendifTryouts.verbose>1@dreams.eachdo|dream|ifdream!=@realityout.puts'%6s%s'.color(:red)%['',dream.test_to_string(@reality)]elseout.puts'%6s%s'.color(:green)%["",dream.test_to_string(@reality)]endendout.putsendout.rewindout.readenddefreportreturnifskip?out=StringIO.new@dreams.eachdo|dream|nextifdream==reality#? :normal : :red out.puts'%12s: %s'.color(@clr)%["failed",dream.test_to_string(@reality)]out.puts'%12s: %s'%["drill",@reality.comparison_value(dream).inspect]out.puts'%12s: %s'%["dream",dream.comparison_value.inspect]out.putsendunless@reality.error.nil?out.puts'%14s: %s'%[@reality.etype,@reality.error.to_s.split($/).join($/+' '*16)]endunless@reality.trace.nil?trace=Tryouts.verbose>1?@reality.trace:[@reality.trace.first]out.puts'%14s %s'%['',trace.join($/+' '*16)]out.putsendout.rewindout.readenddefhas_error?!@reality.error.nil?enddefsuccess?returnfalseif@dreams.empty?&&@reality.output!=truebegin@dreams.each{|d|returnfalseunlessd==@reality}rescue=>exputsex.message,ex.backtraceifTryouts.debug?returnfalseend@clr=:greentrueenddefadd_dream(d);@dreams<<d;enddefadd_dreams(*d);@dreams+=d;endprivateend;end