summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorara.t.howard <ara.t.howard@gmail.com>2012-03-05 08:00:01 -0700
committerara.t.howard <ara.t.howard@gmail.com>2012-03-05 08:00:01 -0700
commitbe7849ec387b1cb4bcf4181afc4dc6128f53b727 (patch)
tree78e96ad98c56083bf8cb27e784e1b2ce46dfb072
parenta648bf424c50cb4a74c81b19a782337b814bb7d3 (diff)
downloadsystemu-be7849ec387b1cb4bcf4181afc4dc6128f53b727.tar.gz
first commit of platform independent test suite
-rw-r--r--test/systemu_test.rb64
-rw-r--r--test/testing.rb195
2 files changed, 259 insertions, 0 deletions
diff --git a/test/systemu_test.rb b/test/systemu_test.rb
new file mode 100644
index 0000000..19fac1d
--- /dev/null
+++ b/test/systemu_test.rb
@@ -0,0 +1,64 @@
+
+Testing SystemU do
+
+##
+#
+ testing 'that simple usage works' do
+ status, stdout, stderr = assert{ systemu :bin/:ls }
+ assert{ status == 0 }
+ assert{ stdout['lib'] }
+ assert{ stderr.strip.empty? }
+ end
+
+ testing 'program with stdin' do
+ stdin = '42'
+ status, stdout, stderr = assert{ systemu :bin/:cat, :stdin => stdin }
+ assert{ status == 0 }
+ assert{ stdout == stdin }
+ end
+
+end
+
+
+
+
+
+BEGIN {
+
+# silly hax to build commands we can shell out to on any platform. since
+# tests might run on windoze we assume only that 'ruby' is available and build
+# other command-line programs from it.
+#
+ module Kernel
+ private
+ def bin(which, options = {}, &block)
+ case which.to_s
+ when 'ls'
+ %| ruby -e'puts Dir.glob("*").sort' |
+
+ when 'cat'
+ %| ruby -e'STDOUT.write(ARGF.read)' |
+
+ when 'find'
+ %| ruby -e'puts Dir.glob("**/**").sort' |
+ end
+ end
+ end
+
+# just let's us write: :bin/:ls
+#
+ class Symbol
+ def / other, options = {}, &block
+ eval "#{ self }(:#{ other }, options, &block)"
+ end
+ end
+
+ testdir = File.dirname(File.expand_path(__FILE__))
+ rootdir = File.dirname(testdir)
+ libdir = File.join(rootdir, 'lib')
+ require File.join(libdir, 'systemu')
+ require File.join(testdir, 'testing')
+
+
+ Dir.chdir(rootdir)
+}
diff --git a/test/testing.rb b/test/testing.rb
new file mode 100644
index 0000000..d7870fc
--- /dev/null
+++ b/test/testing.rb
@@ -0,0 +1,195 @@
+require 'test/unit'
+
+testdir = File.expand_path(File.dirname(__FILE__))
+rootdir = File.dirname(testdir)
+libdir = File.join(rootdir, 'lib')
+
+STDOUT.sync = true
+
+$:.unshift(testdir) unless $:.include?(testdir)
+$:.unshift(libdir) unless $:.include?(libdir)
+$:.unshift(rootdir) unless $:.include?(rootdir)
+
+class Testing
+ class Slug < ::String
+ def Slug.for(*args)
+ string = args.flatten.compact.join('-')
+ words = string.to_s.scan(%r/\w+/)
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
+ words.delete_if{|word| word.nil? or word.strip.empty?}
+ new(words.join('-').downcase)
+ end
+ end
+
+ class Context
+ attr_accessor :name
+
+ def initialize(name, *args)
+ @name = name
+ end
+
+ def to_s
+ Slug.for(name)
+ end
+ end
+end
+
+def Testing(*args, &block)
+ Class.new(::Test::Unit::TestCase) do
+
+ ## class methods
+ #
+ class << self
+ def contexts
+ @contexts ||= []
+ end
+
+ def context(*args, &block)
+ return contexts.last if(args.empty? and block.nil?)
+
+ context = Testing::Context.new(*args)
+ contexts.push(context)
+
+ begin
+ block.call(context)
+ ensure
+ contexts.pop
+ end
+ end
+
+ def slug_for(*args)
+ string = [context, args].flatten.compact.join('-')
+ words = string.to_s.scan(%r/\w+/)
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
+ words.delete_if{|word| word.nil? or word.strip.empty?}
+ words.join('-').downcase.sub(/_$/, '')
+ end
+
+ def name() const_get(:Name) end
+
+ def testno()
+ '%05d' % (@testno ||= 0)
+ ensure
+ @testno += 1
+ end
+
+ def testing(*args, &block)
+ method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_')
+ define_method(method, &block)
+ end
+
+ def test(*args, &block)
+ testing(*args, &block)
+ end
+
+ def setup(&block)
+ define_method(:setup, &block) if block
+ end
+
+ def teardown(&block)
+ define_method(:teardown, &block) if block
+ end
+
+ def prepare(&block)
+ @prepare ||= []
+ @prepare.push(block) if block
+ @prepare
+ end
+
+ def cleanup(&block)
+ @cleanup ||= []
+ @cleanup.push(block) if block
+ @cleanup
+ end
+ end
+
+ ## configure the subclass!
+ #
+ const_set(:Testno, '0')
+ slug = slug_for(*args).gsub(%r/-/,'_')
+ name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_')
+ name = name.upcase!
+ const_set(:Name, name)
+ const_set(:Missing, Object.new.freeze)
+
+ ## instance methods
+ #
+ alias_method('__assert__', 'assert')
+
+ def assert(*args, &block)
+ if args.size == 1 and args.first.is_a?(Hash)
+ options = args.first
+ expected = getopt(:expected, options){ missing }
+ actual = getopt(:actual, options){ missing }
+ if expected == missing and actual == missing
+ actual, expected, *ignored = options.to_a.flatten
+ end
+ expected = expected.call() if expected.respond_to?(:call)
+ actual = actual.call() if actual.respond_to?(:call)
+ assert_equal(expected, actual)
+ end
+
+ if block
+ label = "assert(#{ args.join(' ') })"
+ result = nil
+ assert_nothing_raised{ result = block.call }
+ __assert__(result, label)
+ result
+ else
+ result = args.shift
+ label = "assert(#{ args.join(' ') })"
+ __assert__(result, label)
+ result
+ end
+ end
+
+ def missing
+ self.class.const_get(:Missing)
+ end
+
+ def getopt(opt, hash, options = nil, &block)
+ [opt.to_s, opt.to_s.to_sym].each do |key|
+ return hash[key] if hash.has_key?(key)
+ end
+ default =
+ if block
+ block.call
+ else
+ options.is_a?(Hash) ? options[:default] : nil
+ end
+ return default
+ end
+
+ def subclass_of exception
+ class << exception
+ def ==(other) super or self > other end
+ end
+ exception
+ end
+
+ ##
+ #
+ module_eval(&block)
+
+ self.setup()
+ self.prepare.each{|b| b.call()}
+
+ at_exit{
+ self.teardown()
+ self.cleanup.each{|b| b.call()}
+ }
+
+ self
+ end
+end
+
+
+if $0 == __FILE__
+
+ Testing 'Testing' do
+ testing('foo'){ assert true }
+ test{ assert true }
+ p instance_methods.grep(/test/)
+ end
+
+end