#!/usr/bin/env ruby

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

class TC_ToHash < Test::Unit::TestCase # :nodoc:
  def test_original
    config = XmlConfigFile.new('original_files/original_pod.xml')
    expected = {
      'logdir'        => '/var/log/foo/',
      'debugfile'     => '/tmp/foo.debug',

      'server'        => {
        'sahara'        => {
          'osversion'     => '2.6',
          'osname'        => 'solaris',
          'address'       => [ '10.0.0.101', '10.0.1.101' ]
        },

        'gobi'          => {
          'osversion'     => '6.5',
          'osname'        => 'irix',
          'address'       => '10.0.0.102'
        },

        'kalahari'      => {
          'osversion'     => '2.0.34',
          'osname'        => 'linux',
          'address'       => [ '10.0.0.103', '10.0.1.103' ]
        }
      }
    }
    assert_equal(expected, config.to_hash)

    config.force_array = true
    expected = {
      'logdir'        => '/var/log/foo/',
      'debugfile'     => '/tmp/foo.debug',

      'server'        => {
        'sahara'        => {
          'osversion'     => '2.6',
          'osname'        => 'solaris',
          'address'       => [ '10.0.0.101', '10.0.1.101' ]
        },

        'gobi'          => {
          'osversion'     => '6.5',
          'osname'        => 'irix',
          'address'       => [ '10.0.0.102' ]
        },

        'kalahari'      => {
          'osversion'     => '2.0.34',
          'osname'        => 'linux',
          'address'       => [ '10.0.0.103', '10.0.1.103' ]
        }
      }
    }
    assert_equal(expected, config.to_hash)
  end

  def test_keep_root
    config = XmlConfigFile.new('original_files/to_hash.xml')
    expected = {
      'abc' => {
        'z' => ['ZZZ', {}, {}]
      },
      'b'   => [
        {
          'c' => ['Eins', 'Eins', 'Zwei']
        },
        {
          'c' => [
            'Drei',
            'Zwei',
            { 'd' => 'yo' }
          ]
        }
      ],
      'xyz'  => 'Hallo',
      'att'  => { 'test' => '42' },
      'att2' => { 'test' => '4711', 'content' => 'CONTENT' },
      'element' => [
        {
          'att'     => '1',
          'content' => 'one'
        },
        {
          'att'     => '2',
          'content' => 'two'
        },
        {
          'att'     => '3',
          'content' => 'three'
        },
      ],
    }
    assert_equal(expected, config.to_hash)
    config.keep_root = true
    assert_equal({ 'a' => expected }, config.to_hash)

    config.keep_root = false
    config.suppress_empty = true
    expected = {
      'abc' => {
        'z' => 'ZZZ'
      },
      'b'   => [
        {
          'c' => ['Eins', 'Eins', 'Zwei']
        },
        {
          'c' => [
            'Drei',
            'Zwei',
            { 'd' => 'yo' }
          ]
        }
      ],
      'xyz'  => 'Hallo',
      'att'  => { 'test' => '42' },
      'att2' => { 'test' => '4711', 'content' => 'CONTENT' },
      'element' => [
        {
          'att'     => '1',
          'content' => 'one'
        },
        {
          'att'     => '2',
          'content' => 'two'
        },
        {
          'att'     => '3',
          'content' => 'three'
        },
      ],
    }
    assert_equal(expected, config.to_hash)
  end

  def test_force_content
    config = XmlConfigFile.new('original_files/opt.xml')
    expected = {
      'x' => 'text1',
      'y' => { 'a' => '2', 'content' => 'text2' }
    }
    assert_equal(expected, config.to_hash)

    config.force_content = true
    expected = {
      'x' => {             'content' => 'text1' },
      'y' => { 'a' => '2', 'content' => 'text2' }
    }
    assert_equal(expected, config.to_hash)

    config.content_key = 'text'
    expected = {
      'x' => {             'text' => 'text1' },
      'y' => { 'a' => '2', 'text' => 'text2' }
    }
    assert_equal(expected, config.to_hash)

    # content_key is still 'text'.
    config.force_content = false
    expected = {
      'x' => 'text1',
      'y' => { 'a' => '2', 'text' => 'text2' }
    }
    assert_equal(expected, config.to_hash)
  end

  def test_force_array
    config = XmlConfigFile.new('original_files/opt.xml')
    config.force_array = true
    expected = {
      'x' => ['text1'],
      'y' => [{ 'a' => '2', 'content' => 'text2' }]
    }
    assert_equal(expected, config.to_hash)

    config.force_array = ['x']
    expected = {
      'x' => ['text1'],
      'y' => { 'a' => '2', 'content' => 'text2' }
    }
    assert_equal(expected, config.to_hash)

    config.force_array = ['y']
    expected = {
      'x' => 'text1',
      'y' => [{ 'a' => '2', 'content' => 'text2' }]
    }
    assert_equal(expected, config.to_hash)

    config.force_array = ['x', 'y']
    expected = {
      'x' => ['text1'],
      'y' => [{ 'a' => '2', 'content' => 'text2' }]
    }
    assert_equal(expected, config.to_hash)

    config.force_array = []
    expected = {
      'x' => 'text1',
      'y' => { 'a' => '2', 'content' => 'text2' }
    }
    assert_equal(expected, config.to_hash)

    config.force_array = false
    expected = {
      'x' => 'text1',
      'y' => { 'a' => '2', 'content' => 'text2' }
    }
    assert_equal(expected, config.to_hash)
  end

  def test_no_attr
    config = XmlConfigFile.new('original_files/att.xml')
    expected = {
      'x' => { 'a' => '1', 'b' => '2', 'content' => 'Hello' }, 
      'y' => { 'c' => '5',             'content' => 'World' },
      'z' => { 'inner' => 'Inner' },
    }
    assert_equal(expected, config.to_hash)

    config.no_attr = true
    expected = {
      'x' => 'Hello', 
      'y' => 'World',
      'z' => { 'inner' => 'Inner' },
    }
    assert_equal(expected, config.to_hash)

    config = XmlConfigFile.new('original_files/opt.xml')
    config.no_attr = true
    expected = {
      'x' => 'text1',
      'y' => 'text2'
    }
    assert_equal(expected, config.to_hash)

    config.force_content = true
    expected = {
      'x' => { 'content'=> 'text1'},
      'y' => { 'content'=> 'text2'}
    }
    assert_equal(expected, config.to_hash)

    config.keep_root = true
    expected = {
      'opt' => {
        'x' => { 'content'=> 'text1'},
        'y' => { 'content'=> 'text2'}
      }
    }
    assert_equal(expected, config.to_hash)
  end

  def test_minimum
    config = XmlConfigFile.new('original_files/empty.xml')
    assert_equal({}, config.to_hash)
    config.keep_root = true
    assert_equal({'config' => {}}, config.to_hash)

    config = XmlConfigFile.new('original_files/empty_and_text.xml')
    assert_equal('Hello', config.to_hash)
    config.keep_root = true
    assert_equal({'config' => 'Hello'}, config.to_hash)

    config = XmlConfigFile.new('original_files/empty_att.xml')
    assert_equal({ 'att' => 'Hello'}, config.to_hash)
    config.keep_root = true
    assert_equal({'config' => {'att' => 'Hello'}}, config.to_hash)

    config = XmlConfigFile.new('original_files/empty_att_text.xml')
    assert_equal({ 'att' => 'Hello', 'content' => 'Test'}, config.to_hash)
    config.keep_root = true
    assert_equal({
      'config' => {
        'att'     => 'Hello',
        'content' => 'Test'
      }
    }, config.to_hash)
  end

  def test_key_attr
    config = XmlConfigFile.new('original_files/keyattr.xml')
    config.key_attr = { 'user' => '+login' }
    expected = {
      'user' => {
        'stty' => {
          'fullname' => 'Simon T Tyson',
          'login'    => 'stty'
        },
        'grep' => {
          'fullname' => 'Gary R Epstein',
          'login'    => 'grep'
        }
      }
    }
    assert_equal(expected, config.to_hash)

    config.key_attr = { 'user' => '-login' }
    expected = {
      'user' => {
        'stty' => {
          'fullname' => 'Simon T Tyson',
          '-login'   => 'stty'
        },
        'grep' => {
          'fullname' => 'Gary R Epstein',
          '-login'   => 'grep'
        }
      }
    }
    assert_equal(expected, config.to_hash)
  end

  def test_response_types
    config = XmlConfigFile.new('original_files/response_checker.xml')
    expected = {
      'db' => {
        'pwd'  => {},
        'user' => {},
        'name' => 'DBI:Mysql:shop'
      },
      'response-types' => {
        'response-type' => {
          'QuotaExceeded' => {
            'code' => '3'
          },
          'UnknownDomain' => {
            'code' => '5'
          },
          'UnknownReason' => {
            'code' => '0'
          },
          'UnknownRecipient' => {
            'code' => '1'
          },
          'SyntaxError' => {
            'code' => '4'
          },
          'MailboxSuspended' => {
            'code' => '6'
          },
          'VirusAlert' => {
            'code' => '7'
          },
          'AutoResponse' => {
            'code' => '2'
          }
        }
      },
      'mailbox' => {
        'path' => 'd:/usr/maik/project/valentins/response_checker_1.0.0/test/data'
      },
      'log4r_config' => {
        'outputter' => {
          'logfile' => {
            'level' => 'DEBUG',
            'filename' => 'd:/usr/maik/project/valentins/response_checker_1.0.0/logs/response_checker.log',
            'formatter' => {
              'pattern' => '%d [%l] %m',
              'type' => 'PatternFormatter'
            },
            'type' => 'FileOutputter'
          },
          'console' => {
            'level' => 'DEBUG',
            'type' => 'StderrOutputter'
          }
        },
        'logger' => {
          'ResponseClassifier' => {
            'level' => 'DEBUG',
            'outputters' => 'logfile'
          },
          'ResponseChecker' => {
            'level' => 'DEBUG',
            'outputters' => 'logfile'
          }
        }
      },
      'response-patterns' => {
        'patterns' => [
          {
            'pattern' => [
              'Benutzerquote wurde überschritten',
              '(user is )?over quota',
              'Maildirectory voll',
              '(quota|mailbox has) exceeded',
              'allowed quota',
              'mailbox (full|voll|exceeds)',
              '(account|mailbox) is full'
            ],
            'type' => 'QuotaExceeded'
          },
          {
            'pattern' => [
              'Auto((-?reply)|-Submitted| Response|responder)',
              'Abwesenheitsnotiz',
              'automated respo',
              'automatische'
            ],
            'type' => 'AutoResponse'
          },
          {
            'pattern' => [
              'benutzer unbekannt',
              'no such mailbox',
              'unbekannte E-Mail-Adresse',
              'Unbekannter Empfänger',
              'User is (not known|unknown)',
              'No such user',
              'name is not recognized',
              'unknown user',
              'user unknown',
              'user_unknown',
              'invalid recipient',
              'no mailbox',
              'Recipient not allowed',
              'not allowed to receive mail'
            ],
            'type' => 'UnknownRecipient'
          },
          {
            'pattern' => 'malformed address',
            'type' => 'SyntaxError'
          },
          {
            'pattern' => [
              'host not found',
              'bad destination',
              'unknown subdomain'
            ],
            'type' => 'UnknownDomain'
          },
          {
            'pattern' => [
              'mailbox has been suspended',
              'mail-address is no longer valid'
            ],
            'type' => 'MailboxSuspended'
          },
          {
            'pattern' => 'Virus',
            'type' => 'VirusAlert'
          },
          {
            'pattern' => [
              'not listed in',
              'did not reach the following',
              'cannot be delivered',
              'Nachricht nicht empfangen|zugestellt',
              'konnte nicht ausgeliefert werden',
              'message? could not be delivered',
              'nger fehlgeschlagen',
              'cannot find the path specified',
              'Error During Delivery',
              'failure notice',
              'Undeliverable mail',
              'undeliverable',
              'Unzustellbar',
              'Mailzustellung fehlgeschlagen',
              'Undelivered Mail',
              'Delivery failure',
              'permanent fatal errors',
              'returning message to sender',
              'mailbox unavailable',
              'recipients failed',
              'does not exist',
              'Warning: message',
              '\\berror'
            ],
            'type' => 'UnknownReason'
          }
        ]
      }
    }
    assert_equal(expected, config.to_hash)

    config.force_array = true
    config.key_attr = []

    expected = {
      'db' => [
        {
          'pwd' => [
            {}
          ],
          'user' => [
              {}
            ],
          'name' => [
              'DBI:Mysql:shop'
            ]
        }
      ],
      'response-types' => [
        {
          'response-type' => [
            {
              'code' => '0',
              'name' => 'UnknownReason'
            },
            {
              'code' => '1',
              'name' => 'UnknownRecipient'
            },
            {
              'code' => '2',
              'name' => 'AutoResponse'
            },
            {
              'code' => '3',
              'name' => 'QuotaExceeded'
            },
            {
              'code' => '4',
              'name' => 'SyntaxError'
            },
            {
              'code' => '5',
              'name' => 'UnknownDomain'
            },
            {
              'code' => '6',
              'name' => 'MailboxSuspended'
            },
            {
              'code' => '7',
              'name' => 'VirusAlert'
            }
            ]
          }
        ],
        'mailbox' => [
          {
            'path' => 'd:/usr/maik/project/valentins/response_checker_1.0.0/test/data'
          }
        ],
        'log4r_config' => [
          {
            'outputter' => [
              {
                'level' => 'DEBUG',
                'type' => 'StderrOutputter',
                'name' => 'console'
              },
              {
                'level' => 'DEBUG',
                'filename' => [
                  'd:/usr/maik/project/valentins/response_checker_1.0.0/logs/response_checker.log'
                ],
                'formatter' => [
                  {
                    'pattern' => '%d [%l] %m',
                    'type' => 'PatternFormatter'
                  }
                ],
                'type' => 'FileOutputter',
                'name' => 'logfile'
              }
            ],
            'logger' => [
              {
                'level' => 'DEBUG',
                'outputters' => 'logfile',
                'name' => 'ResponseChecker'
              },
              {
                'level' => 'DEBUG',
                'outputters' => 'logfile',
                'name' => 'ResponseClassifier'
              }
            ]
          }
        ],
        'response-patterns' => [
          {
            'patterns' => [
              {
                'pattern' => [
                  'Benutzerquote wurde überschritten',
                  '(user is )?over quota',
                  'Maildirectory voll',
                  '(quota|mailbox has) exceeded',
                  'allowed quota',
                  'mailbox (full|voll|exceeds)',
                  '(account|mailbox) is full'
                ],
                'type' => 'QuotaExceeded'
              },
              {
                'pattern' => [
                  'Auto((-?reply)|-Submitted| Response|responder)',
                  'Abwesenheitsnotiz',
                  'automated respo',
                  'automatische'
                ],
                'type' => 'AutoResponse'
              },
              {
                'pattern' => [
                  'benutzer unbekannt',
                  'no such mailbox',
                  'unbekannte E-Mail-Adresse',
                  'Unbekannter Empfänger',
                  'User is (not known|unknown)',
                  'No such user',
                  'name is not recognized',
                  'unknown user',
                  'user unknown',
                  'user_unknown',
                  'invalid recipient',
                  'no mailbox',
                  'Recipient not allowed',
                  'not allowed to receive mail'
                ],
                'type' => 'UnknownRecipient'
              },
              {
                'pattern' => [
                  'malformed address'
                ],
                'type' => 'SyntaxError'
              },
              {
                'pattern' => [
                  'host not found',
                  'bad destination',
                  'unknown subdomain'
                ],
                'type' => 'UnknownDomain'
              },
              {
                'pattern' => [
                  'mailbox has been suspended',
                  'mail-address is no longer valid'
                ],
                'type' => 'MailboxSuspended'
              },
              {
                'pattern' => [
                  'Virus'
                ],
                'type' => 'VirusAlert'
              },
              {
                'pattern' => [
                  'not listed in',
                  'did not reach the following',
                  'cannot be delivered',
                  'Nachricht nicht empfangen|zugestellt',
                  'konnte nicht ausgeliefert werden',
                  'message? could not be delivered',
                  'nger fehlgeschlagen',
                  'cannot find the path specified',
                  'Error During Delivery',
                  'failure notice',
                  'Undeliverable mail',
                  'undeliverable',
                  'Unzustellbar',
                  'Mailzustellung fehlgeschlagen',
                  'Undelivered Mail',
                  'Delivery failure',
                  'permanent fatal errors',
                  'returning message to sender',
                  'mailbox unavailable',
                  'recipients failed',
                  'does not exist',
                  'Warning: message',
                  '\\berror'
                ],
                'type' => 'UnknownReason'
              }
            ]
          }
        ]
      }
    assert_equal(expected, config.to_hash)
  end
end

