sus 0.17.2 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/bin/sus-host +104 -0
 - data/bin/sus-tree +12 -0
 - data/lib/sus/assertions.rb +79 -7
 - data/lib/sus/base.rb +3 -2
 - data/lib/sus/clock.rb +8 -0
 - data/lib/sus/config.rb +20 -21
 - data/lib/sus/expect.rb +11 -6
 - data/lib/sus/file.rb +20 -5
 - data/lib/sus/identity.rb +36 -0
 - data/lib/sus/output/buffered.rb +1 -3
 - data/lib/sus/registry.rb +9 -4
 - data/lib/sus/tree.rb +27 -0
 - data/lib/sus/version.rb +1 -1
 - data/lib/sus.rb +1 -0
 - data.tar.gz.sig +2 -4
 - metadata +7 -2
 - metadata.gz.sig +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: e39bdf28a3135bf28cf66714d3ac2998c1c863e979c172573a3e5e509de2246e
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 88273ca646abe719cb562693f233d6210d8e505456ae8dd663d74971086d33b7
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: eca3ca7daddbc30591698658f6d87cc11a56c9dee2456b1060339fe1442aa5d8479a11ccdf7d9f4e7d617478ff033b0c24482db8d8145b7046e69a106a75409c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2df536e6206a37f475bde130d8a6f8f4f8c8eab49a3ea2f7d29f48b4a64b53d6145cc77c27f2105043385756cc8d44d34983334a6de633c5c8d78275777b1ee7
         
     | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
    
        data/bin/sus-host
    ADDED
    
    | 
         @@ -0,0 +1,104 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative '../lib/sus/config'
         
     | 
| 
      
 6 
     | 
    
         
            +
            config = Sus::Config.load
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require_relative '../lib/sus'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            verbose = false
         
     | 
| 
      
 11 
     | 
    
         
            +
            guard = Thread::Mutex.new
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require 'etc'
         
     | 
| 
      
 14 
     | 
    
         
            +
            count = Etc.nprocessors
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            $stdout.sync = true
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            input = $stdin.dup
         
     | 
| 
      
 19 
     | 
    
         
            +
            $stdin.reopen(File::NULL)
         
     | 
| 
      
 20 
     | 
    
         
            +
            output = $stdout.dup
         
     | 
| 
      
 21 
     | 
    
         
            +
            $stdout.reopen($stderr)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            def failure_messages_for(assertions)
         
     | 
| 
      
 24 
     | 
    
         
            +
            	messages = []
         
     | 
| 
      
 25 
     | 
    
         
            +
            	
         
     | 
| 
      
 26 
     | 
    
         
            +
            	assertions.each_failure do |failure|
         
     | 
| 
      
 27 
     | 
    
         
            +
            		messages << failure.message
         
     | 
| 
      
 28 
     | 
    
         
            +
            	end
         
     | 
| 
      
 29 
     | 
    
         
            +
            	
         
     | 
| 
      
 30 
     | 
    
         
            +
            	return messages
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            while line = input.gets
         
     | 
| 
      
 34 
     | 
    
         
            +
            	message = JSON.parse(line)
         
     | 
| 
      
 35 
     | 
    
         
            +
            	
         
     | 
| 
      
 36 
     | 
    
         
            +
            	if tests = message['run']
         
     | 
| 
      
 37 
     | 
    
         
            +
            		jobs = Thread::Queue.new
         
     | 
| 
      
 38 
     | 
    
         
            +
            		results = Thread::Queue.new
         
     | 
| 
      
 39 
     | 
    
         
            +
            		
         
     | 
| 
      
 40 
     | 
    
         
            +
            		top = Sus::Assertions.new(measure: true)
         
     | 
| 
      
 41 
     | 
    
         
            +
            		config.before_tests(top)
         
     | 
| 
      
 42 
     | 
    
         
            +
            		
         
     | 
| 
      
 43 
     | 
    
         
            +
            		aggregate = Thread.new do
         
     | 
| 
      
 44 
     | 
    
         
            +
            			while result = results.pop
         
     | 
| 
      
 45 
     | 
    
         
            +
            				top.add(result)
         
     | 
| 
      
 46 
     | 
    
         
            +
            			end
         
     | 
| 
      
 47 
     | 
    
         
            +
            		end
         
     | 
| 
      
 48 
     | 
    
         
            +
            		
         
     | 
| 
      
 49 
     | 
    
         
            +
            		loader = Thread.new do
         
     | 
| 
      
 50 
     | 
    
         
            +
            			registry = config.load_registry(tests)
         
     | 
| 
      
 51 
     | 
    
         
            +
            			
         
     | 
| 
      
 52 
     | 
    
         
            +
            			registry.each do |child|
         
     | 
| 
      
 53 
     | 
    
         
            +
            				jobs << child
         
     | 
| 
      
 54 
     | 
    
         
            +
            			end
         
     | 
| 
      
 55 
     | 
    
         
            +
            			
         
     | 
| 
      
 56 
     | 
    
         
            +
            			jobs.close
         
     | 
| 
      
 57 
     | 
    
         
            +
            		end
         
     | 
| 
      
 58 
     | 
    
         
            +
            		
         
     | 
| 
      
 59 
     | 
    
         
            +
            		workers = count.times.map do |index|
         
     | 
| 
      
 60 
     | 
    
         
            +
            			Thread.new do
         
     | 
| 
      
 61 
     | 
    
         
            +
            				while job = jobs.pop
         
     | 
| 
      
 62 
     | 
    
         
            +
            					guard.synchronize do
         
     | 
| 
      
 63 
     | 
    
         
            +
            						output.puts JSON.generate({started: job.identity})
         
     | 
| 
      
 64 
     | 
    
         
            +
            					end
         
     | 
| 
      
 65 
     | 
    
         
            +
            					
         
     | 
| 
      
 66 
     | 
    
         
            +
            					assertions = Sus::Assertions.new(measure: true)
         
     | 
| 
      
 67 
     | 
    
         
            +
            					job.call(assertions)
         
     | 
| 
      
 68 
     | 
    
         
            +
            					results.push(assertions)
         
     | 
| 
      
 69 
     | 
    
         
            +
            					
         
     | 
| 
      
 70 
     | 
    
         
            +
            					guard.synchronize do
         
     | 
| 
      
 71 
     | 
    
         
            +
            						if assertions.passed?
         
     | 
| 
      
 72 
     | 
    
         
            +
            							output.puts JSON.generate({passed: job.identity, duration: assertions.clock.ms})
         
     | 
| 
      
 73 
     | 
    
         
            +
            						elsif assertions.errored?
         
     | 
| 
      
 74 
     | 
    
         
            +
            							output.puts JSON.generate({errored: job.identity, messages: failure_messages_for(assertions), duration: assertions.clock.ms})
         
     | 
| 
      
 75 
     | 
    
         
            +
            						else
         
     | 
| 
      
 76 
     | 
    
         
            +
            							output.puts JSON.generate({failed: job.identity, messages: failure_messages_for(assertions), duration: assertions.clock.ms})
         
     | 
| 
      
 77 
     | 
    
         
            +
            						end
         
     | 
| 
      
 78 
     | 
    
         
            +
            					end
         
     | 
| 
      
 79 
     | 
    
         
            +
            				end
         
     | 
| 
      
 80 
     | 
    
         
            +
            			end
         
     | 
| 
      
 81 
     | 
    
         
            +
            		end
         
     | 
| 
      
 82 
     | 
    
         
            +
            		
         
     | 
| 
      
 83 
     | 
    
         
            +
            		loader.join
         
     | 
| 
      
 84 
     | 
    
         
            +
            		workers.each(&:join)
         
     | 
| 
      
 85 
     | 
    
         
            +
            		results.close
         
     | 
| 
      
 86 
     | 
    
         
            +
            		
         
     | 
| 
      
 87 
     | 
    
         
            +
            		aggregate.join
         
     | 
| 
      
 88 
     | 
    
         
            +
            		config.after_tests(top)
         
     | 
| 
      
 89 
     | 
    
         
            +
            		
         
     | 
| 
      
 90 
     | 
    
         
            +
            		workers.each(&:join)
         
     | 
| 
      
 91 
     | 
    
         
            +
            		
         
     | 
| 
      
 92 
     | 
    
         
            +
            		if config.respond_to?(:covered)
         
     | 
| 
      
 93 
     | 
    
         
            +
            			if covered = config.covered and covered.record?
         
     | 
| 
      
 94 
     | 
    
         
            +
            				covered.policy.each do |coverage|
         
     | 
| 
      
 95 
     | 
    
         
            +
            					output.puts JSON.generate({coverage: coverage.path, counts: coverage.counts})
         
     | 
| 
      
 96 
     | 
    
         
            +
            				end
         
     | 
| 
      
 97 
     | 
    
         
            +
            			end
         
     | 
| 
      
 98 
     | 
    
         
            +
            		end
         
     | 
| 
      
 99 
     | 
    
         
            +
            		
         
     | 
| 
      
 100 
     | 
    
         
            +
            		output.puts JSON.generate({finished: true, message: top.output.string, duration: top.clock.ms})
         
     | 
| 
      
 101 
     | 
    
         
            +
            	else
         
     | 
| 
      
 102 
     | 
    
         
            +
            		$stderr.puts "Unknown message: #{message}"
         
     | 
| 
      
 103 
     | 
    
         
            +
            	end
         
     | 
| 
      
 104 
     | 
    
         
            +
            end
         
     | 
    
        data/bin/sus-tree
    ADDED
    
    
    
        data/lib/sus/assertions.rb
    CHANGED
    
    | 
         @@ -41,6 +41,7 @@ module Sus 
     | 
|
| 
       41 
41 
     | 
    
         
             
            			@count = 0
         
     | 
| 
       42 
42 
     | 
    
         
             
            		end
         
     | 
| 
       43 
43 
     | 
    
         | 
| 
      
 44 
     | 
    
         
            +
            		attr :identity
         
     | 
| 
       44 
45 
     | 
    
         
             
            		attr :target
         
     | 
| 
       45 
46 
     | 
    
         
             
            		attr :output
         
     | 
| 
       46 
47 
     | 
    
         
             
            		attr :level
         
     | 
| 
         @@ -75,6 +76,13 @@ module Sus 
     | 
|
| 
       75 
76 
     | 
    
         
             
            			"\#<#{self.class} #{@passed.size} passed #{@failed.size} failed #{@deferred.size} deferred #{@skipped.size} skipped #{@errored.size} errored>"
         
     | 
| 
       76 
77 
     | 
    
         
             
            		end
         
     | 
| 
       77 
78 
     | 
    
         | 
| 
      
 79 
     | 
    
         
            +
            		def message
         
     | 
| 
      
 80 
     | 
    
         
            +
            			{
         
     | 
| 
      
 81 
     | 
    
         
            +
            				text: @output.string,
         
     | 
| 
      
 82 
     | 
    
         
            +
            				location: @identity&.to_location
         
     | 
| 
      
 83 
     | 
    
         
            +
            			}
         
     | 
| 
      
 84 
     | 
    
         
            +
            		end
         
     | 
| 
      
 85 
     | 
    
         
            +
            		
         
     | 
| 
       78 
86 
     | 
    
         
             
            		def total
         
     | 
| 
       79 
87 
     | 
    
         
             
            			@passed.size + @failed.size + @deferred.size + @skipped.size + @errored.size
         
     | 
| 
       80 
88 
     | 
    
         
             
            		end
         
     | 
| 
         @@ -138,24 +146,65 @@ module Sus 
     | 
|
| 
       138 
146 
     | 
    
         
             
            			@errored.any?
         
     | 
| 
       139 
147 
     | 
    
         
             
            		end
         
     | 
| 
       140 
148 
     | 
    
         | 
| 
      
 149 
     | 
    
         
            +
            		class Assert
         
     | 
| 
      
 150 
     | 
    
         
            +
            			def initialize(identity, message)
         
     | 
| 
      
 151 
     | 
    
         
            +
            				@identity = identity
         
     | 
| 
      
 152 
     | 
    
         
            +
            				@message = message
         
     | 
| 
      
 153 
     | 
    
         
            +
            			end
         
     | 
| 
      
 154 
     | 
    
         
            +
            			
         
     | 
| 
      
 155 
     | 
    
         
            +
            			attr :identity
         
     | 
| 
      
 156 
     | 
    
         
            +
            			attr :message
         
     | 
| 
      
 157 
     | 
    
         
            +
            			
         
     | 
| 
      
 158 
     | 
    
         
            +
            			def each_failure(&block)
         
     | 
| 
      
 159 
     | 
    
         
            +
            				yield self
         
     | 
| 
      
 160 
     | 
    
         
            +
            			end
         
     | 
| 
      
 161 
     | 
    
         
            +
            			
         
     | 
| 
      
 162 
     | 
    
         
            +
            			def message
         
     | 
| 
      
 163 
     | 
    
         
            +
            				{
         
     | 
| 
      
 164 
     | 
    
         
            +
            					text: @message,
         
     | 
| 
      
 165 
     | 
    
         
            +
            					location: @identity&.to_location
         
     | 
| 
      
 166 
     | 
    
         
            +
            				}
         
     | 
| 
      
 167 
     | 
    
         
            +
            			end
         
     | 
| 
      
 168 
     | 
    
         
            +
            		end
         
     | 
| 
      
 169 
     | 
    
         
            +
            		
         
     | 
| 
       141 
170 
     | 
    
         
             
            		def assert(condition, message = nil)
         
     | 
| 
       142 
171 
     | 
    
         
             
            			@count += 1
         
     | 
| 
       143 
172 
     | 
    
         | 
| 
      
 173 
     | 
    
         
            +
            			message ||= self.output.string
         
     | 
| 
      
 174 
     | 
    
         
            +
            			backtrace = Output::Backtrace.first(@identity)
         
     | 
| 
      
 175 
     | 
    
         
            +
            			identity = @identity&.scoped
         
     | 
| 
      
 176 
     | 
    
         
            +
            			
         
     | 
| 
       144 
177 
     | 
    
         
             
            			if condition
         
     | 
| 
       145 
     | 
    
         
            -
            				@passed <<  
     | 
| 
      
 178 
     | 
    
         
            +
            				@passed << Assert.new(identity, message)
         
     | 
| 
       146 
179 
     | 
    
         | 
| 
       147 
180 
     | 
    
         
             
            				if !@orientation || @verbose
         
     | 
| 
       148 
     | 
    
         
            -
            					@output.puts(:indent, *pass_prefix, message 
     | 
| 
      
 181 
     | 
    
         
            +
            					@output.puts(:indent, *pass_prefix, message, backtrace)
         
     | 
| 
       149 
182 
     | 
    
         
             
            				end
         
     | 
| 
       150 
183 
     | 
    
         
             
            			else
         
     | 
| 
       151 
     | 
    
         
            -
            				@failed <<  
     | 
| 
      
 184 
     | 
    
         
            +
            				@failed << Assert.new(identity, message)
         
     | 
| 
       152 
185 
     | 
    
         | 
| 
       153 
186 
     | 
    
         
             
            				if @orientation || @verbose
         
     | 
| 
       154 
     | 
    
         
            -
            					@output.puts(:indent, *fail_prefix, message 
     | 
| 
      
 187 
     | 
    
         
            +
            					@output.puts(:indent, *fail_prefix, message, backtrace)
         
     | 
| 
       155 
188 
     | 
    
         
             
            				end
         
     | 
| 
       156 
189 
     | 
    
         
             
            			end
         
     | 
| 
       157 
190 
     | 
    
         
             
            		end
         
     | 
| 
       158 
191 
     | 
    
         | 
| 
      
 192 
     | 
    
         
            +
            		def each_failure(&block)
         
     | 
| 
      
 193 
     | 
    
         
            +
            			return to_enum(__method__) unless block_given?
         
     | 
| 
      
 194 
     | 
    
         
            +
            			
         
     | 
| 
      
 195 
     | 
    
         
            +
            			# if self.failed? and @identity
         
     | 
| 
      
 196 
     | 
    
         
            +
            			# 	yield self
         
     | 
| 
      
 197 
     | 
    
         
            +
            			# end
         
     | 
| 
      
 198 
     | 
    
         
            +
            			
         
     | 
| 
      
 199 
     | 
    
         
            +
            			@failed.each do |assertions|
         
     | 
| 
      
 200 
     | 
    
         
            +
            				assertions.each_failure(&block)
         
     | 
| 
      
 201 
     | 
    
         
            +
            			end
         
     | 
| 
      
 202 
     | 
    
         
            +
            			
         
     | 
| 
      
 203 
     | 
    
         
            +
            			@errored.each do |assertions|
         
     | 
| 
      
 204 
     | 
    
         
            +
            				assertions.each_failure(&block)
         
     | 
| 
      
 205 
     | 
    
         
            +
            			end
         
     | 
| 
      
 206 
     | 
    
         
            +
            		end
         
     | 
| 
      
 207 
     | 
    
         
            +
            		
         
     | 
| 
       159 
208 
     | 
    
         
             
            		def skip(reason)
         
     | 
| 
       160 
209 
     | 
    
         
             
            			@output.puts(:indent, :skipped, skip_prefix, reason)
         
     | 
| 
       161 
210 
     | 
    
         
             
            			@skipped << self
         
     | 
| 
         @@ -184,8 +233,31 @@ module Sus 
     | 
|
| 
       184 
233 
     | 
    
         
             
            			end
         
     | 
| 
       185 
234 
     | 
    
         
             
            		end
         
     | 
| 
       186 
235 
     | 
    
         | 
| 
      
 236 
     | 
    
         
            +
            		class Error
         
     | 
| 
      
 237 
     | 
    
         
            +
            			def initialize(identity, error)
         
     | 
| 
      
 238 
     | 
    
         
            +
            				@identity = identity
         
     | 
| 
      
 239 
     | 
    
         
            +
            				@error = error
         
     | 
| 
      
 240 
     | 
    
         
            +
            			end
         
     | 
| 
      
 241 
     | 
    
         
            +
            			
         
     | 
| 
      
 242 
     | 
    
         
            +
            			attr :identity
         
     | 
| 
      
 243 
     | 
    
         
            +
            			attr :error
         
     | 
| 
      
 244 
     | 
    
         
            +
            			
         
     | 
| 
      
 245 
     | 
    
         
            +
            			def each_failure(&block)
         
     | 
| 
      
 246 
     | 
    
         
            +
            				yield self
         
     | 
| 
      
 247 
     | 
    
         
            +
            			end
         
     | 
| 
      
 248 
     | 
    
         
            +
            			
         
     | 
| 
      
 249 
     | 
    
         
            +
            			def message
         
     | 
| 
      
 250 
     | 
    
         
            +
            				{
         
     | 
| 
      
 251 
     | 
    
         
            +
            					text: @error.message,
         
     | 
| 
      
 252 
     | 
    
         
            +
            					location: @identity&.to_location
         
     | 
| 
      
 253 
     | 
    
         
            +
            				}
         
     | 
| 
      
 254 
     | 
    
         
            +
            			end
         
     | 
| 
      
 255 
     | 
    
         
            +
            		end
         
     | 
| 
      
 256 
     | 
    
         
            +
            		
         
     | 
| 
       187 
257 
     | 
    
         
             
            		def error!(error)
         
     | 
| 
       188 
     | 
    
         
            -
            			 
     | 
| 
      
 258 
     | 
    
         
            +
            			identity = @identity.scoped(error.backtrace_locations)
         
     | 
| 
      
 259 
     | 
    
         
            +
            			
         
     | 
| 
      
 260 
     | 
    
         
            +
            			@errored << Error.new(identity, error)
         
     | 
| 
       189 
261 
     | 
    
         | 
| 
       190 
262 
     | 
    
         
             
            			lines = error.message.split(/\r?\n/)
         
     | 
| 
       191 
263 
     | 
    
         | 
| 
         @@ -198,11 +270,11 @@ module Sus 
     | 
|
| 
       198 
270 
     | 
    
         
             
            			@output.write(Output::Backtrace.for(error, @identity))
         
     | 
| 
       199 
271 
     | 
    
         
             
            		end
         
     | 
| 
       200 
272 
     | 
    
         | 
| 
       201 
     | 
    
         
            -
            		def nested(target, identity: @identity, isolated: false, inverted: false, **options)
         
     | 
| 
      
 273 
     | 
    
         
            +
            		def nested(target, identity: @identity, isolated: false, buffered: false, inverted: false, **options)
         
     | 
| 
       202 
274 
     | 
    
         
             
            			result = nil
         
     | 
| 
       203 
275 
     | 
    
         | 
| 
       204 
276 
     | 
    
         
             
            			# Isolated assertions need to have buffered output so they can be replayed if they fail:
         
     | 
| 
       205 
     | 
    
         
            -
            			if isolated
         
     | 
| 
      
 277 
     | 
    
         
            +
            			if isolated or buffered
         
     | 
| 
       206 
278 
     | 
    
         
             
            				output = @output.buffered
         
     | 
| 
       207 
279 
     | 
    
         
             
            			else
         
     | 
| 
       208 
280 
     | 
    
         
             
            				output = @output
         
     | 
    
        data/lib/sus/base.rb
    CHANGED
    
    | 
         @@ -39,12 +39,13 @@ module Sus 
     | 
|
| 
       39 
39 
     | 
    
         
             
            		end
         
     | 
| 
       40 
40 
     | 
    
         
             
            	end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
            	def self.base(description = nil)
         
     | 
| 
      
 42 
     | 
    
         
            +
            	def self.base(description = nil, root: nil)
         
     | 
| 
       43 
43 
     | 
    
         
             
            		base = Class.new(Base)
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
            		base.extend(Context)
         
     | 
| 
      
 46 
     | 
    
         
            +
            		base.identity = Identity.new(root) if root
         
     | 
| 
       46 
47 
     | 
    
         
             
            		base.description = description
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
            		
         
     | 
| 
       48 
49 
     | 
    
         
             
            		return base
         
     | 
| 
       49 
50 
     | 
    
         
             
            	end
         
     | 
| 
       50 
51 
     | 
    
         
             
            end
         
     | 
    
        data/lib/sus/clock.rb
    CHANGED
    
    | 
         @@ -33,6 +33,10 @@ module Sus 
     | 
|
| 
       33 
33 
     | 
    
         
             
            			duration
         
     | 
| 
       34 
34 
     | 
    
         
             
            		end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
            		def ms
         
     | 
| 
      
 37 
     | 
    
         
            +
            			duration * 1000.0
         
     | 
| 
      
 38 
     | 
    
         
            +
            		end
         
     | 
| 
      
 39 
     | 
    
         
            +
            		
         
     | 
| 
       36 
40 
     | 
    
         
             
            		def to_s
         
     | 
| 
       37 
41 
     | 
    
         
             
            			duration = self.duration
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
         @@ -45,6 +49,10 @@ module Sus 
     | 
|
| 
       45 
49 
     | 
    
         
             
            			end
         
     | 
| 
       46 
50 
     | 
    
         
             
            		end
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
      
 52 
     | 
    
         
            +
            		def reset!(duration = 0.0)
         
     | 
| 
      
 53 
     | 
    
         
            +
            			@duration = duration
         
     | 
| 
      
 54 
     | 
    
         
            +
            		end
         
     | 
| 
      
 55 
     | 
    
         
            +
            		
         
     | 
| 
       48 
56 
     | 
    
         
             
            		def start!
         
     | 
| 
       49 
57 
     | 
    
         
             
            			@start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         
     | 
| 
       50 
58 
     | 
    
         
             
            		end
         
     | 
    
        data/lib/sus/config.rb
    CHANGED
    
    | 
         @@ -82,12 +82,12 @@ module Sus 
     | 
|
| 
       82 
82 
     | 
    
         
             
            			@registry ||= self.load_registry
         
     | 
| 
       83 
83 
     | 
    
         
             
            		end
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
            		def load_registry
         
     | 
| 
       86 
     | 
    
         
            -
            			registry = Sus::Registry.new
         
     | 
| 
      
 85 
     | 
    
         
            +
            		def load_registry(paths = @paths)
         
     | 
| 
      
 86 
     | 
    
         
            +
            			registry = Sus::Registry.new(root: @root)
         
     | 
| 
       87 
87 
     | 
    
         | 
| 
       88 
     | 
    
         
            -
            			if  
     | 
| 
      
 88 
     | 
    
         
            +
            			if paths&.any?
         
     | 
| 
       89 
89 
     | 
    
         
             
            				registry = Sus::Filter.new(registry)
         
     | 
| 
       90 
     | 
    
         
            -
            				 
     | 
| 
      
 90 
     | 
    
         
            +
            				paths.each do |path|
         
     | 
| 
       91 
91 
     | 
    
         
             
            					registry.load(path)
         
     | 
| 
       92 
92 
     | 
    
         
             
            				end
         
     | 
| 
       93 
93 
     | 
    
         
             
            			else
         
     | 
| 
         @@ -99,42 +99,41 @@ module Sus 
     | 
|
| 
       99 
99 
     | 
    
         
             
            			return registry
         
     | 
| 
       100 
100 
     | 
    
         
             
            		end
         
     | 
| 
       101 
101 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
            		def before_tests(assertions)
         
     | 
| 
      
 102 
     | 
    
         
            +
            		def before_tests(assertions, output: self.output)
         
     | 
| 
      
 103 
     | 
    
         
            +
            			@clock.reset!
         
     | 
| 
       103 
104 
     | 
    
         
             
            			@clock.start!
         
     | 
| 
       104 
105 
     | 
    
         
             
            		end
         
     | 
| 
       105 
106 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
            		def after_tests(assertions)
         
     | 
| 
      
 107 
     | 
    
         
            +
            		def after_tests(assertions, output: self.output)
         
     | 
| 
       107 
108 
     | 
    
         
             
            			@clock.stop!
         
     | 
| 
       108 
109 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
            			self.print_summary(assertions)
         
     | 
| 
      
 110 
     | 
    
         
            +
            			self.print_summary(output, assertions)
         
     | 
| 
       110 
111 
     | 
    
         
             
            		end
         
     | 
| 
       111 
112 
     | 
    
         | 
| 
       112 
113 
     | 
    
         
             
            		protected
         
     | 
| 
       113 
114 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
            		def print_summary(assertions)
         
     | 
| 
       115 
     | 
    
         
            -
            			output = self.output
         
     | 
| 
       116 
     | 
    
         
            -
            			
         
     | 
| 
      
 115 
     | 
    
         
            +
            		def print_summary(output, assertions)
         
     | 
| 
       117 
116 
     | 
    
         
             
            			assertions.print(output)
         
     | 
| 
       118 
117 
     | 
    
         
             
            			output.puts
         
     | 
| 
       119 
118 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
            			print_finished_statistics(assertions)
         
     | 
| 
      
 119 
     | 
    
         
            +
            			print_finished_statistics(output, assertions)
         
     | 
| 
       121 
120 
     | 
    
         | 
| 
       122 
121 
     | 
    
         
             
            			if !partial? and assertions.passed?
         
     | 
| 
       123 
     | 
    
         
            -
            				print_test_feedback(assertions)
         
     | 
| 
      
 122 
     | 
    
         
            +
            				print_test_feedback(output, assertions)
         
     | 
| 
       124 
123 
     | 
    
         
             
            			end
         
     | 
| 
       125 
124 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
            			print_slow_tests(assertions)
         
     | 
| 
       127 
     | 
    
         
            -
            			print_failed_assertions(assertions)
         
     | 
| 
      
 125 
     | 
    
         
            +
            			print_slow_tests(output, assertions)
         
     | 
| 
      
 126 
     | 
    
         
            +
            			print_failed_assertions(output, assertions)
         
     | 
| 
       128 
127 
     | 
    
         
             
            		end
         
     | 
| 
       129 
128 
     | 
    
         | 
| 
       130 
     | 
    
         
            -
            		def print_finished_statistics(assertions)
         
     | 
| 
      
 129 
     | 
    
         
            +
            		def print_finished_statistics(output, assertions)
         
     | 
| 
       131 
130 
     | 
    
         
             
            			duration = @clock.duration
         
     | 
| 
       132 
131 
     | 
    
         
             
            			rate = assertions.count / duration
         
     | 
| 
       133 
132 
     | 
    
         | 
| 
       134 
133 
     | 
    
         
             
            			output.puts "🏁 Finished in ", @clock, "; #{rate.round(3)} assertions per second."
         
     | 
| 
       135 
134 
     | 
    
         
             
            		end
         
     | 
| 
       136 
135 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
            		def print_test_feedback(assertions)
         
     | 
| 
      
 136 
     | 
    
         
            +
            		def print_test_feedback(output, assertions)
         
     | 
| 
       138 
137 
     | 
    
         
             
            			duration = @clock.duration
         
     | 
| 
       139 
138 
     | 
    
         
             
            			rate = assertions.count / duration
         
     | 
| 
       140 
139 
     | 
    
         | 
| 
         @@ -179,7 +178,7 @@ module Sus 
     | 
|
| 
       179 
178 
     | 
    
         
             
            			end
         
     | 
| 
       180 
179 
     | 
    
         
             
            		end
         
     | 
| 
       181 
180 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
            		def print_slow_tests(assertions, threshold = 0.1)
         
     | 
| 
      
 181 
     | 
    
         
            +
            		def print_slow_tests(output, assertions, threshold = 0.1)
         
     | 
| 
       183 
182 
     | 
    
         
             
            			slowest_tests = assertions.passed.select{|test| test.clock > threshold}.sort_by(&:clock).reverse!
         
     | 
| 
       184 
183 
     | 
    
         | 
| 
       185 
184 
     | 
    
         
             
            			if slowest_tests.empty?
         
     | 
| 
         @@ -193,7 +192,7 @@ module Sus 
     | 
|
| 
       193 
192 
     | 
    
         
             
            			end
         
     | 
| 
       194 
193 
     | 
    
         
             
            		end
         
     | 
| 
       195 
194 
     | 
    
         | 
| 
       196 
     | 
    
         
            -
            		def print_assertions(title, assertions)
         
     | 
| 
      
 195 
     | 
    
         
            +
            		def print_assertions(output, title, assertions)
         
     | 
| 
       197 
196 
     | 
    
         
             
            			if assertions.any?
         
     | 
| 
       198 
197 
     | 
    
         
             
            				output.puts
         
     | 
| 
       199 
198 
     | 
    
         
             
            				output.puts title
         
     | 
| 
         @@ -206,9 +205,9 @@ module Sus 
     | 
|
| 
       206 
205 
     | 
    
         
             
            			end
         
     | 
| 
       207 
206 
     | 
    
         
             
            		end
         
     | 
| 
       208 
207 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
            		def print_failed_assertions(assertions)
         
     | 
| 
       210 
     | 
    
         
            -
            			print_assertions("🤔 Failed assertions:", assertions.failed)
         
     | 
| 
       211 
     | 
    
         
            -
            			print_assertions("🔥 Errored assertions:", assertions.errored)
         
     | 
| 
      
 208 
     | 
    
         
            +
            		def print_failed_assertions(output, assertions)
         
     | 
| 
      
 209 
     | 
    
         
            +
            			print_assertions(output, "🤔 Failed assertions:", assertions.failed)
         
     | 
| 
      
 210 
     | 
    
         
            +
            			print_assertions(output, "🔥 Errored assertions:", assertions.errored)
         
     | 
| 
       212 
211 
     | 
    
         
             
            		end
         
     | 
| 
       213 
212 
     | 
    
         
             
            	end
         
     | 
| 
       214 
213 
     | 
    
         
             
            end
         
     | 
    
        data/lib/sus/expect.rb
    CHANGED
    
    | 
         @@ -5,14 +5,16 @@ 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module Sus
         
     | 
| 
       7 
7 
     | 
    
         
             
            	class Expect
         
     | 
| 
       8 
     | 
    
         
            -
            		def initialize(assertions, subject, inverted: false)
         
     | 
| 
      
 8 
     | 
    
         
            +
            		def initialize(assertions, subject, inverted: false, buffered: false)
         
     | 
| 
       9 
9 
     | 
    
         
             
            			@assertions = assertions
         
     | 
| 
       10 
10 
     | 
    
         
             
            			@subject = subject
         
     | 
| 
       11 
11 
     | 
    
         
             
            			@inverted = inverted
         
     | 
| 
      
 12 
     | 
    
         
            +
            			@buffered = buffered
         
     | 
| 
       12 
13 
     | 
    
         
             
            		end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
            		
         
     | 
| 
       14 
15 
     | 
    
         
             
            		attr :subject
         
     | 
| 
       15 
16 
     | 
    
         
             
            		attr :inverted
         
     | 
| 
      
 17 
     | 
    
         
            +
            		attr :assertions
         
     | 
| 
       16 
18 
     | 
    
         | 
| 
       17 
19 
     | 
    
         
             
            		def not
         
     | 
| 
       18 
20 
     | 
    
         
             
            			self.dup.tap do |expect|
         
     | 
| 
         @@ -31,13 +33,16 @@ module Sus 
     | 
|
| 
       31 
33 
     | 
    
         
             
            		end
         
     | 
| 
       32 
34 
     | 
    
         | 
| 
       33 
35 
     | 
    
         
             
            		def to(predicate)
         
     | 
| 
       34 
     | 
    
         
            -
            			 
     | 
| 
      
 36 
     | 
    
         
            +
            			# This gets the identity scoped to the current call stack, which ensures that any failures are logged at this point in the code.
         
     | 
| 
      
 37 
     | 
    
         
            +
            			identity = @assertions.identity&.scoped
         
     | 
| 
      
 38 
     | 
    
         
            +
            			
         
     | 
| 
      
 39 
     | 
    
         
            +
            			@assertions.nested(self, inverted: @inverted, buffered: @buffered, identity: identity) do |assertions|
         
     | 
| 
       35 
40 
     | 
    
         
             
            				predicate.call(assertions, @subject)
         
     | 
| 
       36 
41 
     | 
    
         
             
            			end
         
     | 
| 
       37 
42 
     | 
    
         | 
| 
       38 
43 
     | 
    
         
             
            			return self
         
     | 
| 
       39 
44 
     | 
    
         
             
            		end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 45 
     | 
    
         
            +
            		
         
     | 
| 
       41 
46 
     | 
    
         
             
            		def and(predicate)
         
     | 
| 
       42 
47 
     | 
    
         
             
            			return to(predicate)
         
     | 
| 
       43 
48 
     | 
    
         
             
            		end
         
     | 
| 
         @@ -46,9 +51,9 @@ module Sus 
     | 
|
| 
       46 
51 
     | 
    
         
             
            	class Base
         
     | 
| 
       47 
52 
     | 
    
         
             
            		def expect(subject = nil, &block)
         
     | 
| 
       48 
53 
     | 
    
         
             
            			if block_given?
         
     | 
| 
       49 
     | 
    
         
            -
            				Expect.new(@__assertions__, block)
         
     | 
| 
      
 54 
     | 
    
         
            +
            				Expect.new(@__assertions__, block, buffered: true)
         
     | 
| 
       50 
55 
     | 
    
         
             
            			else
         
     | 
| 
       51 
     | 
    
         
            -
            				Expect.new(@__assertions__, subject)
         
     | 
| 
      
 56 
     | 
    
         
            +
            				Expect.new(@__assertions__, subject, buffered: true)
         
     | 
| 
       52 
57 
     | 
    
         
             
            			end
         
     | 
| 
       53 
58 
     | 
    
         
             
            		end
         
     | 
| 
       54 
59 
     | 
    
         
             
            	end
         
     | 
    
        data/lib/sus/file.rb
    CHANGED
    
    | 
         @@ -19,11 +19,17 @@ module Sus 
     | 
|
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
            		def self.build(parent, path)
         
     | 
| 
       21 
21 
     | 
    
         
             
            			base = Class.new(parent)
         
     | 
| 
      
 22 
     | 
    
         
            +
            			
         
     | 
| 
       22 
23 
     | 
    
         
             
            			base.extend(File)
         
     | 
| 
       23 
24 
     | 
    
         
             
            			base.description = path
         
     | 
| 
       24 
     | 
    
         
            -
            			base.identity = Identity. 
     | 
| 
      
 25 
     | 
    
         
            +
            			base.identity = Identity.file(parent.identity, path)
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
            			 
     | 
| 
      
 27 
     | 
    
         
            +
            			begin
         
     | 
| 
      
 28 
     | 
    
         
            +
            				TOPLEVEL_CLASS_EVAL.call(base, path)
         
     | 
| 
      
 29 
     | 
    
         
            +
            			rescue StandardError, LoadError, SyntaxError => error
         
     | 
| 
      
 30 
     | 
    
         
            +
            				# We add this as a child of the base class so that it is included in the tree under the file rather than completely replacing it, which can be confusing:
         
     | 
| 
      
 31 
     | 
    
         
            +
            				base.add FileLoadError.build(self, path, error)
         
     | 
| 
      
 32 
     | 
    
         
            +
            			end
         
     | 
| 
       27 
33 
     | 
    
         | 
| 
       28 
34 
     | 
    
         
             
            			return base
         
     | 
| 
       29 
35 
     | 
    
         
             
            		end
         
     | 
| 
         @@ -35,7 +41,8 @@ module Sus 
     | 
|
| 
       35 
41 
     | 
    
         | 
| 
       36 
42 
     | 
    
         
             
            	class FileLoadError
         
     | 
| 
       37 
43 
     | 
    
         
             
            		def self.build(parent, path, error)
         
     | 
| 
       38 
     | 
    
         
            -
            			 
     | 
| 
      
 44 
     | 
    
         
            +
            			identity = Identity.file(parent.identity, path).scoped(error.backtrace_locations)
         
     | 
| 
      
 45 
     | 
    
         
            +
            			self.new(identity, path, error)
         
     | 
| 
       39 
46 
     | 
    
         
             
            		end
         
     | 
| 
       40 
47 
     | 
    
         | 
| 
       41 
48 
     | 
    
         
             
            		def initialize(identity, path, error)
         
     | 
| 
         @@ -50,6 +57,16 @@ module Sus 
     | 
|
| 
       50 
57 
     | 
    
         
             
            			true
         
     | 
| 
       51 
58 
     | 
    
         
             
            		end
         
     | 
| 
       52 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
            		EMPTY = Hash.new.freeze
         
     | 
| 
      
 61 
     | 
    
         
            +
            		
         
     | 
| 
      
 62 
     | 
    
         
            +
            		def children
         
     | 
| 
      
 63 
     | 
    
         
            +
            			EMPTY
         
     | 
| 
      
 64 
     | 
    
         
            +
            		end
         
     | 
| 
      
 65 
     | 
    
         
            +
            		
         
     | 
| 
      
 66 
     | 
    
         
            +
            		def description
         
     | 
| 
      
 67 
     | 
    
         
            +
            			@path
         
     | 
| 
      
 68 
     | 
    
         
            +
            		end
         
     | 
| 
      
 69 
     | 
    
         
            +
            		
         
     | 
| 
       53 
70 
     | 
    
         
             
            		def print(output)
         
     | 
| 
       54 
71 
     | 
    
         
             
            			output.write("file ", :path, @identity)
         
     | 
| 
       55 
72 
     | 
    
         
             
            		end
         
     | 
| 
         @@ -66,8 +83,6 @@ module Sus 
     | 
|
| 
       66 
83 
     | 
    
         
             
            	module Context
         
     | 
| 
       67 
84 
     | 
    
         
             
            		def file(path)
         
     | 
| 
       68 
85 
     | 
    
         
             
            			add File.build(self, path)
         
     | 
| 
       69 
     | 
    
         
            -
            		rescue StandardError, LoadError, SyntaxError => error
         
     | 
| 
       70 
     | 
    
         
            -
            			add FileLoadError.build(self, path, error)
         
     | 
| 
       71 
86 
     | 
    
         
             
            		end
         
     | 
| 
       72 
87 
     | 
    
         
             
            	end
         
     | 
| 
       73 
88 
     | 
    
         
             
            end
         
     | 
    
        data/lib/sus/identity.rb
    CHANGED
    
    | 
         @@ -5,6 +5,10 @@ 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module Sus
         
     | 
| 
       7 
7 
     | 
    
         
             
            	class Identity
         
     | 
| 
      
 8 
     | 
    
         
            +
            		def self.file(parent, path, name = path, **options)
         
     | 
| 
      
 9 
     | 
    
         
            +
            			self.new(path, name, nil, nil, **options)
         
     | 
| 
      
 10 
     | 
    
         
            +
            		end
         
     | 
| 
      
 11 
     | 
    
         
            +
            		
         
     | 
| 
       8 
12 
     | 
    
         
             
            		def self.nested(parent, name, location = nil, **options)
         
     | 
| 
       9 
13 
     | 
    
         
             
            			location ||= caller_locations(3...4).first
         
     | 
| 
       10 
14 
     | 
    
         | 
| 
         @@ -32,6 +36,13 @@ module Sus 
     | 
|
| 
       32 
36 
     | 
    
         
             
            			self.key
         
     | 
| 
       33 
37 
     | 
    
         
             
            		end
         
     | 
| 
       34 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
            		def to_location
         
     | 
| 
      
 40 
     | 
    
         
            +
            			{
         
     | 
| 
      
 41 
     | 
    
         
            +
            				path: ::File.expand_path(@path),
         
     | 
| 
      
 42 
     | 
    
         
            +
            				line: @line,
         
     | 
| 
      
 43 
     | 
    
         
            +
            			}
         
     | 
| 
      
 44 
     | 
    
         
            +
            		end
         
     | 
| 
      
 45 
     | 
    
         
            +
            		
         
     | 
| 
       35 
46 
     | 
    
         
             
            		def inspect
         
     | 
| 
       36 
47 
     | 
    
         
             
            			"\#<#{self.class} #{self.to_s}>"
         
     | 
| 
       37 
48 
     | 
    
         
             
            		end
         
     | 
| 
         @@ -69,8 +80,33 @@ module Sus 
     | 
|
| 
       69 
80 
     | 
    
         
             
            			return @key
         
     | 
| 
       70 
81 
     | 
    
         
             
            		end
         
     | 
| 
       71 
82 
     | 
    
         | 
| 
      
 83 
     | 
    
         
            +
            		# Given a set of locations, find the first one which matches this identity and return a new identity with the updated line number. This can be used to extract a location from a backtrace.
         
     | 
| 
      
 84 
     | 
    
         
            +
            		def scoped(locations = nil)
         
     | 
| 
      
 85 
     | 
    
         
            +
            			if locations
         
     | 
| 
      
 86 
     | 
    
         
            +
            				# This code path is normally taken if we've got an exception with a backtrace:
         
     | 
| 
      
 87 
     | 
    
         
            +
            				locations.each do |location|
         
     | 
| 
      
 88 
     | 
    
         
            +
            					if location.path == @path
         
     | 
| 
      
 89 
     | 
    
         
            +
            						return self.with_line(location.lineno)
         
     | 
| 
      
 90 
     | 
    
         
            +
            					end
         
     | 
| 
      
 91 
     | 
    
         
            +
            				end
         
     | 
| 
      
 92 
     | 
    
         
            +
            			else
         
     | 
| 
      
 93 
     | 
    
         
            +
            				# In theory this should be a bit faster:
         
     | 
| 
      
 94 
     | 
    
         
            +
            				Thread.each_caller_location do |location|
         
     | 
| 
      
 95 
     | 
    
         
            +
            					if location.path == @path
         
     | 
| 
      
 96 
     | 
    
         
            +
            						return self.with_line(location.lineno)
         
     | 
| 
      
 97 
     | 
    
         
            +
            					end
         
     | 
| 
      
 98 
     | 
    
         
            +
            				end
         
     | 
| 
      
 99 
     | 
    
         
            +
            			end
         
     | 
| 
      
 100 
     | 
    
         
            +
            			
         
     | 
| 
      
 101 
     | 
    
         
            +
            			return self
         
     | 
| 
      
 102 
     | 
    
         
            +
            		end
         
     | 
| 
      
 103 
     | 
    
         
            +
            		
         
     | 
| 
       72 
104 
     | 
    
         
             
            		protected
         
     | 
| 
       73 
105 
     | 
    
         | 
| 
      
 106 
     | 
    
         
            +
            		def with_line(line)
         
     | 
| 
      
 107 
     | 
    
         
            +
            			Identity.new(@path, @name, line, @parent, unique: @unique)
         
     | 
| 
      
 108 
     | 
    
         
            +
            		end
         
     | 
| 
      
 109 
     | 
    
         
            +
            		
         
     | 
| 
       74 
110 
     | 
    
         
             
            		def append_unique_key(key, unique = @unique)
         
     | 
| 
       75 
111 
     | 
    
         
             
            			if @parent
         
     | 
| 
       76 
112 
     | 
    
         
             
            				@parent.append_unique_key(key)
         
     | 
    
        data/lib/sus/output/buffered.rb
    CHANGED
    
    | 
         @@ -30,14 +30,12 @@ module Sus 
     | 
|
| 
       30 
30 
     | 
    
         
             
            				self.class.new(self)
         
     | 
| 
       31 
31 
     | 
    
         
             
            			end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
            			attr :output
         
     | 
| 
       34 
     | 
    
         
            -
            			
         
     | 
| 
       35 
33 
     | 
    
         
             
            			def each(&block)
         
     | 
| 
       36 
34 
     | 
    
         
             
            				@chunks.each(&block)
         
     | 
| 
       37 
35 
     | 
    
         
             
            			end
         
     | 
| 
       38 
36 
     | 
    
         | 
| 
       39 
37 
     | 
    
         
             
            			def append(buffer)
         
     | 
| 
       40 
     | 
    
         
            -
            				@chunks.concat(buffer. 
     | 
| 
      
 38 
     | 
    
         
            +
            				@chunks.concat(buffer.chunks)
         
     | 
| 
       41 
39 
     | 
    
         
             
            				@tee&.append(buffer)
         
     | 
| 
       42 
40 
     | 
    
         
             
            			end
         
     | 
| 
       43 
41 
     | 
    
         | 
    
        data/lib/sus/registry.rb
    CHANGED
    
    | 
         @@ -23,16 +23,21 @@ module Sus 
     | 
|
| 
       23 
23 
     | 
    
         
             
            		DIRECTORY_GLOB = "**/*.rb"
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
            		# Create a top level scope with self as the instance:
         
     | 
| 
       26 
     | 
    
         
            -
            		def initialize( 
     | 
| 
       27 
     | 
    
         
            -
            			@base = base
         
     | 
| 
      
 26 
     | 
    
         
            +
            		def initialize(**options)
         
     | 
| 
      
 27 
     | 
    
         
            +
            			@base = Sus.base(self, **options)
         
     | 
| 
      
 28 
     | 
    
         
            +
            			@loaded = {}
         
     | 
| 
       28 
29 
     | 
    
         
             
            		end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       30 
31 
     | 
    
         
             
            		attr :base
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
       32 
33 
     | 
    
         
             
            		def print(output)
         
     | 
| 
       33 
34 
     | 
    
         
             
            			output.write("Test Registry")
         
     | 
| 
       34 
35 
     | 
    
         
             
            		end
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
      
 37 
     | 
    
         
            +
            		def to_s
         
     | 
| 
      
 38 
     | 
    
         
            +
            			@base.identity.to_s
         
     | 
| 
      
 39 
     | 
    
         
            +
            		end
         
     | 
| 
      
 40 
     | 
    
         
            +
            		
         
     | 
| 
       36 
41 
     | 
    
         
             
            		def load(path)
         
     | 
| 
       37 
42 
     | 
    
         
             
            			if ::File.directory?(path)
         
     | 
| 
       38 
43 
     | 
    
         
             
            				load_directory(path)
         
     | 
| 
         @@ -42,7 +47,7 @@ module Sus 
     | 
|
| 
       42 
47 
     | 
    
         
             
            		end
         
     | 
| 
       43 
48 
     | 
    
         | 
| 
       44 
49 
     | 
    
         
             
            		private def load_file(path)
         
     | 
| 
       45 
     | 
    
         
            -
            			@base.file(path)
         
     | 
| 
      
 50 
     | 
    
         
            +
            			@loaded[path] ||= @base.file(path)
         
     | 
| 
       46 
51 
     | 
    
         
             
            		end
         
     | 
| 
       47 
52 
     | 
    
         | 
| 
       48 
53 
     | 
    
         
             
            		private def load_directory(path)
         
     | 
    
        data/lib/sus/tree.rb
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Sus
         
     | 
| 
      
 2 
     | 
    
         
            +
            	class Tree
         
     | 
| 
      
 3 
     | 
    
         
            +
            		def initialize(context)
         
     | 
| 
      
 4 
     | 
    
         
            +
            			@context = context
         
     | 
| 
      
 5 
     | 
    
         
            +
            		end
         
     | 
| 
      
 6 
     | 
    
         
            +
            		
         
     | 
| 
      
 7 
     | 
    
         
            +
            		def traverse(current = @context, &block)
         
     | 
| 
      
 8 
     | 
    
         
            +
            			node = {}
         
     | 
| 
      
 9 
     | 
    
         
            +
            			
         
     | 
| 
      
 10 
     | 
    
         
            +
            			node[:self] = yield(current)
         
     | 
| 
      
 11 
     | 
    
         
            +
            			
         
     | 
| 
      
 12 
     | 
    
         
            +
            			if children = current.children # and children.any?
         
     | 
| 
      
 13 
     | 
    
         
            +
            				node[:children] = children.values.map do |context|
         
     | 
| 
      
 14 
     | 
    
         
            +
            					self.traverse(context, &block)
         
     | 
| 
      
 15 
     | 
    
         
            +
            				end
         
     | 
| 
      
 16 
     | 
    
         
            +
            			end
         
     | 
| 
      
 17 
     | 
    
         
            +
            			
         
     | 
| 
      
 18 
     | 
    
         
            +
            			return node
         
     | 
| 
      
 19 
     | 
    
         
            +
            		end
         
     | 
| 
      
 20 
     | 
    
         
            +
            		
         
     | 
| 
      
 21 
     | 
    
         
            +
            		def to_json(options = nil)
         
     | 
| 
      
 22 
     | 
    
         
            +
            			traverse do |context|
         
     | 
| 
      
 23 
     | 
    
         
            +
            				[context.identity, context.description, context.leaf?]
         
     | 
| 
      
 24 
     | 
    
         
            +
            			end.to_json(options)
         
     | 
| 
      
 25 
     | 
    
         
            +
            		end
         
     | 
| 
      
 26 
     | 
    
         
            +
            	end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/sus/version.rb
    CHANGED
    
    
    
        data/lib/sus.rb
    CHANGED
    
    
    
        data.tar.gz.sig
    CHANGED
    
    | 
         @@ -1,4 +1,2 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            ǜ���Դ���2w�D1�}�yOy`��b��.yG��qJc����M
         
     | 
| 
       4 
     | 
    
         
            -
            X*�e�
         
     | 
| 
      
 1 
     | 
    
         
            +
            am�����tJ��)�p����Bn�ɠϝռ:����*����-TIV�3#AFH�pg�a�WY��*k5�:�4^�>z�I�=UD,ϑk*�8�t�۳nb"��k��~�k(x�&}���M-�c�H��̚���kΑ�
         
     | 
| 
      
 2 
     | 
    
         
            +
            ��P߾��D;q�����!��� �L7V�����d���^�@s��?kF� ��:-�a�3ag��=\{�<����#!ȔDI����p����kvM�$��K`�zP��jOם¡�)bѽ/��y�#���թ��
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: sus
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.18.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Samuel Williams
         
     | 
| 
         @@ -38,7 +38,7 @@ cert_chain: 
     | 
|
| 
       38 
38 
     | 
    
         
             
              Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
         
     | 
| 
       39 
39 
     | 
    
         
             
              voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
         
     | 
| 
       40 
40 
     | 
    
         
             
              -----END CERTIFICATE-----
         
     | 
| 
       41 
     | 
    
         
            -
            date: 2023-02- 
     | 
| 
      
 41 
     | 
    
         
            +
            date: 2023-02-20 00:00:00.000000000 Z
         
     | 
| 
       42 
42 
     | 
    
         
             
            dependencies:
         
     | 
| 
       43 
43 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       44 
44 
     | 
    
         
             
              name: bake-test
         
     | 
| 
         @@ -87,11 +87,15 @@ email: 
     | 
|
| 
       87 
87 
     | 
    
         
             
            executables:
         
     | 
| 
       88 
88 
     | 
    
         
             
            - sus
         
     | 
| 
       89 
89 
     | 
    
         
             
            - sus-parallel
         
     | 
| 
      
 90 
     | 
    
         
            +
            - sus-tree
         
     | 
| 
      
 91 
     | 
    
         
            +
            - sus-host
         
     | 
| 
       90 
92 
     | 
    
         
             
            extensions: []
         
     | 
| 
       91 
93 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       92 
94 
     | 
    
         
             
            files:
         
     | 
| 
       93 
95 
     | 
    
         
             
            - bin/sus
         
     | 
| 
      
 96 
     | 
    
         
            +
            - bin/sus-host
         
     | 
| 
       94 
97 
     | 
    
         
             
            - bin/sus-parallel
         
     | 
| 
      
 98 
     | 
    
         
            +
            - bin/sus-tree
         
     | 
| 
       95 
99 
     | 
    
         
             
            - lib/sus.rb
         
     | 
| 
       96 
100 
     | 
    
         
             
            - lib/sus/assertions.rb
         
     | 
| 
       97 
101 
     | 
    
         
             
            - lib/sus/base.rb
         
     | 
| 
         @@ -131,6 +135,7 @@ files: 
     | 
|
| 
       131 
135 
     | 
    
         
             
            - lib/sus/registry.rb
         
     | 
| 
       132 
136 
     | 
    
         
             
            - lib/sus/respond_to.rb
         
     | 
| 
       133 
137 
     | 
    
         
             
            - lib/sus/shared.rb
         
     | 
| 
      
 138 
     | 
    
         
            +
            - lib/sus/tree.rb
         
     | 
| 
       134 
139 
     | 
    
         
             
            - lib/sus/version.rb
         
     | 
| 
       135 
140 
     | 
    
         
             
            - lib/sus/with.rb
         
     | 
| 
       136 
141 
     | 
    
         
             
            - license.md
         
     | 
    
        metadata.gz.sig
    CHANGED
    
    | 
         Binary file 
     |