#!/usr/bin/env ruby

# :nodoc:

require 'test/unit'
require '../lib/xmlconfigfile'

class TC_ReadAccess < Test::Unit::TestCase # :nodoc:
  def setup
    ENV['PARAM_1'] = 'param1'
    ENV['PARAM2']  = '4711'
    @config = XmlConfigFile.new('original_files/config.xml')
  end

  def test_get_existing_string_parameter
    assert_equal('shop', @config.get_string('/config/db/name'))
    assert_equal('shop', @config['/config/db/name'])
    assert_equal('shop', @config.get_string('*/db/name'))
    assert_equal('shop', @config['*/db/name'])
    assert_equal('shop', @config.get_string('/config/db/name'))

    @config.path_prefix = '/config/db/'
    assert_equal('shop', @config.get_string('name'))
    assert_equal('maik', @config.get_string('user'))

    @config.path_prefix = "/config/arr3/db[@env='test']/"
    assert_equal('addresses', @config.get_string('name'))
    assert_equal('scott', @config.get_string('user'))
  end

  def test_get_unknown_string_parameter
    assert_equal(nil, @config.get_string('/config/xyz'))
    assert_equal(nil, @config['/config/xyz'])
  end

  def test_get_unknown_string_parameter_with_default
    assert_equal('guest', @config.get_string('/config/db/pwd', 'guest'))
    assert_equal('guest', @config['/config/db/pwd', 'guest'])
  end

  def test_get_object
  
  	assert_equal('/foo/moo/doo', @config.get_object('/config/moo/any_convert/syntax'))
  	assert_equal(42, @config.get_object('/config/int-amount'))
    assert_equal(12345678901234567890, @config.get_object('/config/bigint-amount'))
    assert_equal(-42, @config.get_object('/config/negative-int-amount'))
    assert_equal(100, @config.get_object('/config/timer/@value'))
    assert_equal(255, @config.get_object('/config/hex-int-amount'))
    assert_equal(254, @config.get_object('/config/octal-int-amount'))
    assert_equal(3.14, @config.get_object('/config/float-amount'))
    assert_equal(-3.14, @config.get_object('/config/negative-float-amount'))
    
    @config.auto_convert_boolean = false
    assert_equal(true, @config.get_object('/config/bools/no-1'))
    assert_equal(false, @config.get_object('/config/bools/no-2'))
    assert_equal(1, @config.get_object('/config/bools/no-3'))
    assert_equal(0, @config.get_object('/config/bools/no-4'))
    assert_equal("yes", @config.get_object('/config/bools/no-5'))
    assert_equal("no", @config.get_object('/config/bools/no-6'))
    assert_equal("on", @config.get_object('/config/bools/no-7'))
    assert_equal("off", @config.get_object('/config/bools/no-8'))
    assert_equal(true, @config.get_object('/config/bools/no-9'))
    assert_equal(false, @config.get_object('/config/bools/no-10'))
    assert_equal("yEs", @config.get_object('/config/bools/no-11'))
    assert_equal("nO", @config.get_object('/config/bools/no-12'))
    assert_equal("oN", @config.get_object('/config/bools/no-13'))
    assert_equal("oFf", @config.get_object('/config/bools/no-14'))
    
    @config.auto_convert_boolean = true
    assert_equal(true, @config.get_object('/config/bools/no-1'))
    assert_equal(false, @config.get_object('/config/bools/no-2'))
    assert_equal(true, @config.get_object('/config/bools/no-3'))
    assert_equal(false, @config.get_object('/config/bools/no-4'))
    assert_equal(true, @config.get_object('/config/bools/no-5'))
    assert_equal(false, @config.get_object('/config/bools/no-6'))
    assert_equal(true, @config.get_object('/config/bools/no-7'))
    assert_equal(false, @config.get_object('/config/bools/no-8'))
    assert_equal(true, @config.get_object('/config/bools/no-9'))
    assert_equal(false, @config.get_object('/config/bools/no-10'))
    assert_equal(true, @config.get_object('/config/bools/no-11'))
    assert_equal(false, @config.get_object('/config/bools/no-12'))
    assert_equal(true, @config.get_object('/config/bools/no-13'))
    assert_equal(false, @config.get_object('/config/bools/no-14'))
  end

  def test_get_strange_parameter_name
    assert_equal(nil, @config.get_string('?'))
    assert_equal(nil, @config['?'])
  end

  def test_get_existing_int_parameter
    assert_equal(42, @config.get_int('/config/int-amount'))
    assert_equal(12345678901234567890, @config.get_int('/config/bigint-amount'))
    assert_equal(-42, @config.get_int('/config/negative-int-amount'))
    assert_equal(100, @config.get_int('/config/timer/@value'))
    assert_equal(255, @config.get_int('/config/hex-int-amount'))
    assert_equal(254, @config.get_int('/config/octal-int-amount'))
  end

  def test_get_unknown_int_parameter
    assert_equal(nil, @config.get_int('/config/xyz'))
  end

  def test_get_unknown_int_parameter_with_default
    assert_equal(4711, @config.get_int('/config/unknown-amount', 4711))
  end
  
  def test_get_invalid_int_parameter
    assert_raises(ArgumentError) { @config.get_int('/config/db/name') }
  end

  def test_get_existing_float_parameter
    assert_equal(3.14, @config.get_float('/config/float-amount'))
    assert_equal(-3.14, @config.get_float('/config/negative-float-amount'))
  end

  def test_get_unknown_float_parameter
    assert_equal(nil, @config.get_float('/config/xyz'))
  end

  def test_get_invalid_float_parameter
    assert_raises(ArgumentError) { @config.get_float('/config/db/name') }
  end

  def test_get_unknown_float_parameter_with_default
    assert_equal(2.71, @config.get_float('/config/e', 2.71))
  end

  def test_get_existing_boolean_parameter
    assert_equal(true, @config.get_boolean('/config/bools/no-1'))
    assert_equal(false, @config.get_boolean('/config/bools/no-2'))
    assert_equal(true, @config.get_boolean('/config/bools/no-3'))
    assert_equal(false, @config.get_boolean('/config/bools/no-4'))
    assert_equal(true, @config.get_boolean('/config/bools/no-5'))
    assert_equal(false, @config.get_boolean('/config/bools/no-6'))
    assert_equal(true, @config.get_boolean('/config/bools/no-7'))
    assert_equal(false, @config.get_boolean('/config/bools/no-8'))
    assert_equal(true, @config.get_boolean('/config/bools/no-9'))
    assert_equal(false, @config.get_boolean('/config/bools/no-10'))
    assert_equal(true, @config.get_boolean('/config/bools/no-11'))
    assert_equal(false, @config.get_boolean('/config/bools/no-12'))
    assert_equal(true, @config.get_boolean('/config/bools/no-13'))
    assert_equal(false, @config.get_boolean('/config/bools/no-14'))
  end

  def test_get_unknown_boolean_parameter
    assert_equal(true, @config.get_boolean('/config/bools/not-exist', true))
    assert_equal(nil, @config.get_boolean('/config/bools/not-exist'))
  end

  def test_get_invalid_boolean_parameter
    assert_raises(ArgumentError) { @config.get_boolean('/config/db/name') }
  end

  def test_get_unknown_boolean_parameter_with_default
    assert_equal(true, @config.get_boolean('/config/xyz', true))
  end

  def test_user_defined_boolean_values
    # Try the german variant.
    @config.true_values  = ['wahr']
    @config.false_values = ['falsch']
    assert_raises(ArgumentError) { @config.get_boolean('/config/bools/no-1') }
    assert_equal(true, @config.get_boolean('/config/german-true'))
    assert_equal(false, @config.get_boolean('/config/german-false'))
    assert_equal(true, @config.get_boolean('/config/german-true/@case'))
    assert_equal(false, @config.get_boolean('/config/german-false/@case'))

    # Try the klingon variant.
    @config.true_values  = ["HIja'", "  HISlaH  "]
    @config.false_values = ["ghobe'"]
    assert_equal(true, @config.get_boolean('/config/klingon-true/@alternative'))
    assert_equal(true, @config.get_boolean('/config/klingon-true'))
    assert_equal(false, @config.get_boolean('/config/klingon-false'))
  end

  def test_get_parameters_auto_convert_any
    expectedResult = {
      'moo.any_convert.avalible' => true,
      'moo.any_convert.not_avalible' => false,
      'moo.any_convert.five' => 5,
      'moo.any_convert.fivetimesten' => 5*10,
      'moo.any_convert.float' => 3.14,
      "moo.any_convert.syntax"=> "/foo/moo/doo"
    }
    # Ensure Off
    @config.auto_convert_boolean = false
    @config.auto_convert_any = true
    assert_equal(expectedResult, @config.get_parameters('/config/moo/any_convert[@id=3]/*'))

    expectedResult = {
      'moo.any_convert.avalible' => 'true',
      'moo.any_convert.not_avalible' => 'false',
      'moo.any_convert.five' => '5',
      'moo.any_convert.fivetimesten' => '5*10',
      'moo.any_convert.float' => '3.14',
      "moo.any_convert.syntax"=>"/foo/moo/doo"
    }
    # Ensure both off
    @config.auto_convert_any = false
    @config.auto_convert_boolean = false
    assert_equal(expectedResult, @config.get_parameters('/config/moo/any_convert[@id=3]/*'))
  end

  def test_get_parameters_auto_convert_boolean
    expectedResult = {
      'moo.boolean_convert.avalible' => true,
      'moo.boolean_convert.not_avalible' => false
    }

    @config.auto_convert_boolean = true
    assert_equal(expectedResult, @config.get_parameters('/config/moo/boolean_convert[@id=2]/*'))

    expectedResult = {
      'moo.boolean_convert.avalible' => 'true',
      'moo.boolean_convert.not_avalible' => 'false'
    }
    @config.auto_convert_boolean = false	
    assert_equal(expectedResult, @config.get_parameters('/config/moo/boolean_convert[@id=2]/*'))
  end

  def test_get_parameters_no_hash_key_element_path
    expectedResult = {
      'name' => 'delivery',
      'user' => 'curtis'
    }
    @config.no_hash_key_element_path = true;

    assert_equal(expectedResult, @config.get_parameters('/config/moo/db[@id=1]/*'))

    expectedResult = {
      'moo.db.name' => 'delivery',
      'moo.db.user' => 'curtis'
    }
    @config.no_hash_key_element_path = nil;

    assert_equal(expectedResult, @config.get_parameters('/config/moo/db[@id=1]/*'))

    expectedResult = {
      'moo.db.name' => 'delivery',
      'moo.db.user' => 'curtis'
    }
    @config.no_hash_key_element_path = false;

    assert_equal(expectedResult, @config.get_parameters('/config/moo/db[@id=1]/*')) 
  end

  def test_get_parameters_no_hash_key_element_path_with_attributes
    @config.expand_attributes = true
    expectedResult = {
      'name' => 'delivery',
      'user' => 'curtis',
      'name.role' => 'pizza'
    }
    @config.no_hash_key_element_path = true;

    assert_equal(expectedResult, @config.get_parameters('/config/moo/db[@id=1]/*'))

    expectedResult = {
      'moo.db.name' => 'delivery',
      'moo.db.user' => 'curtis',
      'moo.db.name.role' => 'pizza'
    }
    @config.no_hash_key_element_path = false;

    assert_equal(expectedResult, @config.get_parameters('/config/moo/db[@id=1]/*'))
  end

  def test_get_parameters_without_attributes
    expectedResult = {
      'db.name' => 'shop',
      'db.user' => 'maik'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*'))
    
    expectedResult = {
      'db-name' => 'shop', 
      'db-user' => 'maik'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*', '-'))
    
    expectedResult = {
      'db-silly-name' => 'shop',
      'db-silly-user' => 'maik'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*', '-silly-'))
  end

  def test_get_parameters_with_attributes
    @config.expand_attributes = true
    expectedResult = {
      'db.name' => 'shop',
      'db.user' => 'maik',
      'db.name.role' => 'admin'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*'))
    
    expectedResult = {
      'db-name' => 'shop', 
      'db-user' => 'maik',
      'db-name-role' => 'admin'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*', '-'))
    
    expectedResult = {
      'db-silly-name' => 'shop',
      'db-silly-user' => 'maik',
      'db-silly-name-silly-role' => 'admin'
    }
    assert_equal(expectedResult, @config.get_parameters('/config/db/*', '-silly-'))
  end

  def test_get_parameters_with_empty_elements
    all = @config.get_parameters('//*')
    assert(all.has_key?('splash-screen'), "'splash-screen' element not found.")
    assert_equal(nil, all['splash-screen'])
    assert(all.has_key?('empty-element'), "'empty-element' element not found.")
    assert_equal(nil, all['empty-element'])
  end

  def test_get_string_array
    expectedResult = [
      { 
        'arr.db.name' => 'shop',
        'arr.db.user' => 'maik'
      },
      {
        'arr.db.name' => 'factory',
        'arr.db.user' => 'anna'
      },
      {
        'arr.db.name' => 'integ',
        'arr.db.user' => 'developer'
      }
    ]
    assert_equal(expectedResult, @config.get_string_array('/config/arr/db'))
    assert_equal(expectedResult, @config.get_string_array('//arr/db'))

    expectedResult = [
      { 
        'arr3.db.name' => 'addresses',
        'arr3.db.user' => 'scott',
        'arr3.db.pwd'  => 'tiger',
        'arr3.db.host' => 'example.com',
        'arr3.db.driver.vendor'  => 'MySql',
        'arr3.db.driver.version' => '3.23'
      },
      {
        'arr3.db.name' => 'addresses',
        'arr3.db.user' => 'production',
        'arr3.db.pwd'  => 'secret',
        'arr3.db.host' => 'example.com',
        'arr3.db.driver.vendor'  => 'Oracle',
        'arr3.db.driver.version' => '8.1'
      }
    ]
    assert_equal(expectedResult, @config.get_string_array('//arr3/db'))
  end

end

