require 'ibm_db2'
require 'stringio'
require 'test/unit'

unless ENV['DB2INSTANCE']
  puts 'Database environment is not set up'
  puts 'Run ". /home/db2inst1/sqllib/db2profile" and retry'
  exit -1
end

Dir['tests/prepare*.rb'].each { |file| require file }
Dir['tests/test_*.rb'].each { |file| require file }

module Config
  require 'yaml'
  configdata = open('config.yml') {|f| YAML::load f}
  configdata['connection'].each {|name,value| define_method(name) {value}}

  alias db database
  alias username user
end

class TestIbmDb2 < Test::Unit::TestCase
  include Config

  ####################################################################
  #                         test support                             #
  ####################################################################

  def setup
    prepconn = DB2::connect database, user, password
    prepare prepconn
    DB2::close prepconn
  end

  def teardown
    GC::start
  end

  def capture 
    stdout = $stdout
    buffer = $stdout = StringIO.new
    yield
    $stdout = stdout
    buffer.rewind
    buffer.read.strip
  end

  def expected
    open(caller[1].split(':')[0]) {|f| f.read}.split("\n__END__\n",2)[-1].strip
  end

  def assert_expect &block
    assert_equal expected, capture(&block)
  end

  def assert_expectf &block
    pattern = expected
    '\.[]*?+|(){}^$/'.each_byte { |c| pattern.gsub! c.chr, "\\#{c.chr}" }
    pattern.gsub! '%s', '.*?'
    pattern.gsub! '%d', '\d+'
    pattern.gsub! "\n", '\n'

    assert_match Regexp.new('^' + pattern + '$'), capture(&block)
  end

  ####################################################################
  #                        PHP to Ruby mappings                      #
  ####################################################################

  def _GET
    {}
  end

  def isset var
    (var != nil)
  end

  def header data
  end

  def ini_set name, value
  end

  NULL = nil

  def var_dump var, indent=''
    case var
    when String:
      puts "#{indent}string(#{var.length}) #{var.inspect}"
    when Fixnum:
      puts "#{indent}int(#{var})"
    when Array:
      puts "#{indent}array(#{var.length}) {"
      var.each_with_index { |child,i|
        puts "#{indent}  [#{i}]=>"
        var_dump child, "#{indent}  "
      }
      puts "#{indent}}"
    when DB2::Connection:
      puts "#{indent}resource(1) of type (conn struct)"
    when DB2::RowObject:
      keys = var.keys.sort
      keys.unshift("ID") if keys.delete("ID")
      puts "#{indent}object(stdClass)#1 (#{keys.length}) {"
      keys.each {|key|
        puts "#{indent}  [\"#{key}\"]=>"
        var_dump var.send(key), "#{indent}  "
      }
      puts "}"
    when TrueClass:
      puts "#{indent}bool(true)"
    when FalseClass:
      puts "#{indent}bool(false)"
    when NilClass:
      puts "#{indent}NULL"
    else
      puts "#{indent}#{var.class} #{var.inspect}"
    end
  end

  def print_r var
    case var
    when Array:
      puts "Array"
      puts "("
      var.each_with_index { |child,i|
        puts "    [#{i}] => #{child}"
      }
      puts ")"
    when DB2::Statement:
      puts "Resource id #1"
    else
      puts "#{var.class} #{var.inspect}"
    end
  end

end
