Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 152 lines (130 sloc) 3.309 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
require "bundler/setup"
require "simplecov"
SimpleCov.start

$LOAD_PATH << File.expand_path("../lib", __FILE__)
require "twostroke"
require "paint"

trap("INT") { puts caller; exit! }

class TestCase
  T = Twostroke::Runtime::Types
  
  attr_reader :name, :status, :message
  
  def initialize(name, function, scope)
    @name = name
    @function = function
    @scope = scope
    @assertions = 0
  end
  
  def run
    set_test_helpers
    catch :test_failure do
      ex = catch :exception do
        @function.call @scope, nil, []
        
        if @assertions.zero?
          @status = :error
          @message = "No assertions"
          return false
        end
        @status = :pass
        return true
      end
      
      @status = :error
      if trace = ex.get("stack") and trace.is_a?(T::String)
        @message = trace.string
      else
        @message = T.to_string(ex).string
      end
    end
    false
  rescue => e
    @status = :error
    @message = ["#{e.class}: #{e.to_s}", *e.backtrace].join "\n"
    false
  end
  
  def fail(message)
    @status = :fail
    @message = message
    throw :test_failure
  end
  
private
  def set_test_helpers
    %w(assert assert_equal).each do |m|
      @scope.set_var m, T::Function.new(->(outer, this, args) {
        send m, *args
        nil
      }, nil, nil, [])
    end
  end

  def assert(condition, message = nil)
    @assertions += 1
    unless T.is_truthy condition
      fail message && T.to_string(message).string
    end
  end
  
  def assert_equal(a, b, message = nil)
    @assertions += 1
    unless T.seq a, b
      msg = "<#{T.to_string(a).string}> !== <#{T.to_string(b).string}>"
      msg << ": #{T.to_string(message).string}" if message
      fail msg
    end
  end
end

class TestFile
  attr_reader :file, :tests
  
  def initialize(file, ctx)
    @file = file
    @ctx = ctx
    @tests = []
    @scope = @ctx.vm.global_scope.close
    setup
  end
  
  def setup
    set_test_helpers
    if ex = catch(:exception) { @ctx.raw_exec File.read(@file), @scope; nil }
      STDERR.puts "could not load test file #{file}"
    end
  end
  
  def run
    tests.each do |test|
      if test.run
        print "."
      elsif test.status == :error
        print "E"
      else
        print "F"
      end
      STDOUT.flush
    end
  end
  
private
  def set_test_helpers
    @scope.set_var "test", Twostroke::Runtime::Types::Function.new(->(outer, this, args) {
      test *args
      nil
    }, nil, nil, [])
  end
  
  def test(name, function)
    name = Twostroke::Runtime::Types.to_string(name).string
    tests << TestCase.new(name, function, @scope)
  end
end

ctx = Twostroke::Context.new

files = Dir[File.expand_path("../test/*.js", __FILE__)]
          .sort
          .map { |file| TestFile.new file, ctx }
          .each &:run

results = files.map(&:tests).flatten.map(&:status)
puts "\n\nTests finished - #{results.count :fail} failures and #{results.count :error} errors from #{results.count} test cases\n\n"

files.each do |f|
  f.tests.each do |t|
    next if t.status == :pass
    if t.status == :fail
      print Paint[" FAIL ", :red]
    else
      print Paint[" ERROR ", :yellow]
    end
    puts "#{f.file} - #{t.name}"
    puts t.message.lines.map { |l| " #{l}" } if t.message
    puts
  end
end
Something went wrong with that request. Please try again.