# -*- coding: utf-8 -*-
# vim:fenc=utf-8

# Copyright (C) 2012-2020 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
#
# X2Go Session Broker is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# X2Go Session Broker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import unittest
import tempfile
import time

# Python X2GoBroker modules
import x2gobroker.brokers.inifile_broker as inifile
import x2gobroker.defaults

class TestX2GoBrokerAgent(unittest.TestCase):

    # TEST INTERPRETATION OF REPLIES FROM (FAKED) BROKER AGENT

    def test_broker_agent_replies(self):
        _save_local_broker_agent_call = x2gobroker.agent._call_local_broker_agent
        _save_remote_broker_agent_call = x2gobroker.agent._call_remote_broker_agent
        _save_portscan = x2gobroker.utils.portscan
        _save_time_sleep = time.sleep

        def _call_testsuite_broker_agent(username, task, cmdline_args=[], remote_agent=None, logger=None):

            if task == 'listsessions':
                list_sessions = []
                if username == 'foo1R':
                    list_sessions = ['30342|foo1R-50-1414759661_stDMATE_dp24|50|host1|R|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1R|34|30003|-1|-1',
                    ]
                elif username == 'foo1S':
                    list_sessions = ['30342|foo1S-50-1414759661_stDMATE_dp24|50|host1|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|34|30003|-1|-1',
                    ]
                elif username == 'foo1N':
                    list_sessions = ['30342|foo1N-50-1414759661_stDMATE_dp24|50|host2|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1N|34|30003|-1|-1',
                    ]
                elif username == 'foo2RS':
                    # the session on host2 is older than the session on host1!!!
                    list_sessions = ['30342|foo2RS-50-1414759789_stDMATE_dp24|50|host2|S|2014-10-31T13:49:51|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:49:51|foo2RS|89|30003|-1|-1',
                                     '23412|foo2RS-50-1414759661_stDMATE_dp24|50|host1|R|2014-10-31T13:47:43|fasd7asd58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo2RS|34|30003|-1|-1',
                    ]
                elif username == 'foo3RS':
                    # the session on host2 is older than the session on host1!!!
                    list_sessions = ['30342|foo3RS-50-1414759789_stDMATE_dp24|50|host2|S|2014-10-31T13:49:51|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:49:51|foo3RS|89|30003|-1|-1',
                                     '23412|foo3RS-50-1414759661_stDMATE_dp24|50|host1|R|2014-10-31T13:47:43|fasd7asd58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo3RS|34|30003|-1|-1',
                    ]
                return True, list_sessions

            elif task == 'suspendsession':
                return True, []

            elif task == 'ping':
                return True, []

            return False, []

        def _fake_portscan(addr, port=22):
            return True

        def _fake_time_sleep(sec):
            pass

        x2gobroker.agent._call_local_broker_agent = _call_testsuite_broker_agent
        x2gobroker.agent._call_remote_broker_agent = _call_testsuite_broker_agent
        x2gobroker.utils.portscan = _fake_portscan
        time.sleep = _fake_time_sleep

        _session_profiles = """
[DEFAULT]
command = MATE
user = foo
broker-agent-query-mode = NONE
broker-use-load-checker = false

[testprofile1]
name = testprofile1
host = host1
broker-agent-query-mode = LOCAL

[testprofile2]
name = testprofile2
host = host1, host2, host3, host4
broker-agent-query-mode = SSH

[testprofile3]
name = testprofile3
host = host1.mydomain, host2.mydomain, host3.mydomain, host4.mydomain, host5.mydomain, host6.mydomain
broker-agent-query-mode = LOCAL

[testprofile4]
name = testprofile4
host = host1.mydomain, host2.yourdomain

[testprofile5]
name = testprofile5
host = host1.mydomain (10.0.2.4), host2.mydomain (10.0.2.5)
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = WarningPolicy

[testprofile6]
name = testprofile6
host = host1.mydomain (10.0.2.4), host2.mydomain (10.0.2.5)
sshport = 23467
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = WarningPolicy

[testprofile7]
name = testprofile7
host = docker-vm-1 (docker-server:22001), docker-vm-2 (docker-server:22002)
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = WarningPolicy

[testprofile8]
name = testprofile8
host = docker-vm-0 (docker-server), docker-vm-1 (docker-server:22001), docker-vm-2 (docker-server:22002)
sshport = 22000
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = WarningPolicy

[testprofile9]
name = testprofile9
host = host1.mydomain (10.0.2.4)
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = AutoAddPolicy

[testprofile10]
name = testprofile10
host = host1.mydomain (10.0.2.4)
broker-agent-query-mode = SSH
broker-agent-hostkey-policy = SomeUnkownPolicy

"""
        tf = tempfile.NamedTemporaryFile(mode='w')
        print(_session_profiles, file=tf)
        tf.seek(0)
        inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name)

        # test with 'testprofile1'

        # the faked broker agent should report a running session
        _list1 = inifile_backend.list_profiles(username='foo1R')
        _profile1 = _list1['testprofile1']
        self.assertTrue( ( _profile1['host'] == ['host1'] ) )
        self.assertTrue( ( 'status' in _profile1 and _profile1['status'] == 'R' ) )
        # here will be a short pause, as we will try to suspend the faked X2Go Session
        _session1 = inifile_backend.select_session('testprofile1', username='foo1R')
        # the session broker has detected the running session on host 1 and changed its status to "S"
        self.assertEqual ( _session1, {'port': 22, 'server': 'host1', 'session_info': '30342|foo1R-50-1414759661_stDMATE_dp24|50|host1|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1R|34|30003|-1|-1', } )

        # the faked broker agent should report a suspended session
        _list1 = inifile_backend.list_profiles(username='foo1S')
        _profile1 = _list1['testprofile1']
        self.assertTrue( ( _profile1['host'] == ['host1'] ) )
        self.assertTrue( ( 'status' in _profile1 and _profile1['status'] == 'S' ) )
        _session1 = inifile_backend.select_session('testprofile1')
        self.assertEqual ( _session1, {'port': 22, 'server': 'host1'} )

        # the faked broker agent should report a suspended session for host2, nothing for host1
        _list1 = inifile_backend.list_profiles(username='foo1N')
        _profile1 = _list1['testprofile1']
        self.assertTrue( ( _profile1['host'] == ['host1'] ) )
        self.assertFalse( ( 'status' in _profile1 ) )
        _session1 = inifile_backend.select_session('testprofile1')
        self.assertEqual ( _session1, {'port': 22, 'server': 'host1'} )

        # test "testprofile2", always resume suspended sessions first

        # the faked broker agent should report a suspended session for host1, a running session for host2
        # we resume host1 (the broker attempts resumption of suspended sessions, then the take-over of running sessions
        _list2 = inifile_backend.list_profiles(username='foo2RS')
        _profile2 = _list2['testprofile2']
        _profile2['host'].sort()
        self.assertTrue( ( _profile2['host'] == ['host2'] ) )
        self.assertTrue( ( 'status' in _profile2 and _profile2['status'] == 'S' ) )
        _session2 = inifile_backend.select_session('testprofile2', 'foo2RS')
        self.assertEqual ( _session2, {'port': 22, 'server': 'host2', 'session_info': '30342|foo2RS-50-1414759789_stDMATE_dp24|50|host2|S|2014-10-31T13:49:51|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:49:51|foo2RS|89|30003|-1|-1', } )

        # test "testprofile3", given host names with a subdomain, but subdomains not in listsessions output

        # the faked broker agent should report a suspended session for host1, a running session for host2
        # we resume host1 (the broker attempts resumption of suspended sessions, then the take-over of running sessions
        _list3 = inifile_backend.list_profiles(username='foo3RS')
        _profile3 = _list3['testprofile3']
        _profile3['host'].sort()
        self.assertTrue( ( _profile3['host'] == ['host2'] ) )
        self.assertTrue( ( 'status' in _profile3 and _profile3['status'] == 'S' ) )
        _session3 = inifile_backend.select_session('testprofile3', 'foo3RS')
        self.assertEqual ( _session3, {'port': 22, 'server': 'host2.mydomain', 'session_info': '30342|foo3RS-50-1414759789_stDMATE_dp24|50|host2|S|2014-10-31T13:49:51|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:49:51|foo3RS|89|30003|-1|-1', } )
        _session3 = inifile_backend.select_session('testprofile3', 'foo3RS')

#        # test "testprofile4"
#        _profile4 = inifile_backend.get_profile('testprofile4')
#        _profile4['host'].sort()
#        self.assertTrue( ( _profile4['host'] == ['host1.mydomain', 'host2.yourdomain'] ) )
#        for key in _profile4.keys():
#            self.assertFalse( (key.startswith('host') and key != 'host' ) )
#        _session4 = inifile_backend.select_session('testprofile4')
#        self.assertTrue ( _session4['port'] == 22 )
#        self.assertTrue ( _session4['server'] in ('host1.mydomain', 'host2.yourdomain') )

        # test "testprofile5", test if canonical hostnames and real hostnames differ

        _list5 = inifile_backend.list_profiles(username='foo5N')
        _profile5 = _list5['testprofile5']
        _profile5['host'].sort()
        self.assertTrue( _profile5['host'][0] in ('host1.mydomain', 'host2.mydomain') )
        self.assertTrue( 'status' not in _profile5 )
        i = 0
        while i < 10:
            _remoteagent5 = inifile_backend.get_remote_agent('testprofile5')
            self.assertTrue( _remoteagent5 == {'hostname': 'host1.mydomain', 'hostaddr': '10.0.2.4', 'port': 22, 'load_factors': {}, 'host_key_policy': 'WarningPolicy'} or _remoteagent5 == {'hostname': 'host2.mydomain', 'hostaddr': '10.0.2.5', 'port': 22, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } )
            _session5 = inifile_backend.select_session('testprofile5', 'foo5N')
            self.assertTrue( _session5 == {'port': 22, 'server': '10.0.2.4', } or _session5 == {'port': 22, 'server': '10.0.2.5', } )
            i += 1

        # test "testprofile6", test if canonical hostnames and real hostnames differ and the default
        # SSH port has been adapted

        _list6 = inifile_backend.list_profiles(username='foo6N')
        _profile6 = _list6['testprofile6']
        _profile6['host'].sort()
        self.assertTrue( _profile6['host'][0] in ('host1.mydomain', 'host2.mydomain') )
        self.assertTrue( 'status' not in _profile6 )
        _remoteagent6 = inifile_backend.get_remote_agent('testprofile6')
        self.assertTrue( _remoteagent6 == {'hostname': 'host1.mydomain', 'hostaddr': '10.0.2.4', 'port': 23467, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } or _remoteagent6 == {'hostname': 'host2.mydomain', 'hostaddr': '10.0.2.5', 'port': 23467, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } )
        _session6 = inifile_backend.select_session('testprofile6', 'foo6N')
        self.assertTrue( _session6 == {'port': 23467, 'server': '10.0.2.4', } or _session6 == {'port': 23467, 'server': '10.0.2.5', } )

        _list7 = inifile_backend.list_profiles(username='foo7N')
        _profile7 = _list7['testprofile7']
        _profile7['host'].sort()
        self.assertTrue( _profile7['host'][0] in ('docker-vm-1', 'docker-vm-2') )
        self.assertTrue( 'status' not in _profile7 )
        i = 0
        while i < 10:
            _remoteagent7 = inifile_backend.get_remote_agent('testprofile7')
            self.assertTrue( _remoteagent7 == {'hostname': 'docker-vm-1', 'hostaddr': 'docker-server', 'port': 22001, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } or _remoteagent7 == {'hostname': 'docker-vm-2', 'hostaddr': 'docker-server', 'port': 22002, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } )
            _session7 = inifile_backend.select_session('testprofile7', 'foo7N')
            self.assertTrue( _session7 == {'port': 22001, 'server': 'docker-server', } or _session7 == {'port': 22001, 'server': 'docker-server', } )
            i += 1

        _list8 = inifile_backend.list_profiles(username='foo8N')
        _profile8 = _list8['testprofile8']
        _profile8['host'].sort()
        self.assertTrue( _profile8['host'][0] in ('docker-vm-0', 'docker-vm-1', 'docker-vm-2') )
        self.assertTrue( 'status' not in _profile8 )
        i = 0
        while i < 10:
            _remoteagent8 = inifile_backend.get_remote_agent('testprofile8')
            self.assertTrue( _remoteagent8 == {'hostname': 'docker-vm-0', 'hostaddr': 'docker-server', 'port': 22000, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } or _remoteagent8 == {'hostname': 'docker-vm-1', 'hostaddr': 'docker-server', 'port': 22001, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } or _remoteagent8 == {'hostname': 'docker-vm-2', 'hostaddr': 'docker-server', 'port': 22002, 'load_factors': {}, 'host_key_policy': 'WarningPolicy', } )
            _session8 = inifile_backend.select_session('testprofile8', 'foo8N')
            self.assertTrue( _session8 == {'port': 22000, 'server': 'docker-server', } or _session8 == {'port': 22001, 'server': 'docker-server', } or _session8 == {'port': 22001, 'server': 'docker-server', } )
            i += 1

        # test "testprofile9", test if hostkey policy is propagated from session profile config to remote agent settings

        _list9 = inifile_backend.list_profiles(username='foo9N')
        _profile9 = _list9['testprofile9']
        _profile9['host'].sort()
        self.assertTrue( _profile9['host'][0] in ('host1.mydomain') )
        self.assertTrue( 'status' not in _profile9 )
        _remoteagent9 = inifile_backend.get_remote_agent('testprofile9')
        self.assertTrue( _remoteagent9 == {'hostname': 'host1.mydomain', 'hostaddr': '10.0.2.4', 'port': 22, 'load_factors': {}, 'host_key_policy': 'AutoAddPolicy'})

        # test "testprofile10", test if an invalid hostkey policy is propagated from session profile config to remote agent settings and ignored with RejectPolicy as fallback

        _list10 = inifile_backend.list_profiles(username='foo10N')
        _profile10 = _list10['testprofile10']
        _profile10['host'].sort()
        self.assertTrue( _profile10['host'][0] in ('host1.mydomain') )
        self.assertTrue( 'status' not in _profile10 )
        _remoteagent10 = inifile_backend.get_remote_agent('testprofile10')
        self.assertTrue( _remoteagent10 == {'hostname': 'host1.mydomain', 'hostaddr': '10.0.2.4', 'port': 22, 'load_factors': {}, 'host_key_policy': 'RejectPolicy'})

        x2gobroker.agent._call_local_broker_agent = _save_local_broker_agent_call
        x2gobroker.agent._call_remote_broker_agent = _save_remote_broker_agent_call
        x2gobroker.utils.portscan = _save_portscan
        time.sleep = _save_time_sleep

    def test_broker_agent_replies_with_offline_servers(self):

        _save_local_broker_agent_call = x2gobroker.agent._call_local_broker_agent
        _save_remote_broker_agent_call = x2gobroker.agent._call_remote_broker_agent
        _save_portscan = x2gobroker.utils.portscan
        _save_time_sleep = time.sleep
        self.tbarwos_session_suspended = False

        def _call_testsuite_broker_agent(username, task, cmdline_args=[], remote_agent=None, logger=None):

            if task == 'listsessions':
                list_sessions = []
                if username == 'foo4BS1':
                    list_sessions = ['30342|foo4BS1-50-1414759661_stDMATE_dp24|50|host3-with-session|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo4BS1|34|30003|-1|-1',
                    ]
                elif username == 'foo4BS2':
                    list_sessions = ['30342|foo4BS2-50-1414759661_stDMATE_dp24|50|downhost1-with-session|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo4BS2|34|30003|-1|-1',
                    ]
                elif username == 'foo4BS3':
                    list_sessions = ['30342|foo1S-50-1414759661_stDMATE_dp24|50|downhost1-with-session|R|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|34|30003|-1|-1',
                                     '30342|foo1S-50-1414759661_stDMATE_dp24|50|host3-with-session|S|2014-10-30T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|1474|30003|-1|-1',
                    ]
                elif username == 'foo4BS4':
                    list_sessions = ['30342|foo1S-50-1414759661_stDMATE_dp24|50|downhost1-with-session|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|34|30003|-1|-1',
                                     '30342|foo1S-50-1414759661_stDMATE_dp24|50|host3-with-session|R|2014-10-30T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|1474|30003|-1|-1',
                    ]
                return True, list_sessions

            elif task == 'suspendsession':
                self.tbarwos_session_suspended = True
                return True, []

            elif task == 'findbusyservers':
                busy_servers = []
                if username == 'fooBS1':
                    busy_servers = [
                        '7:host1.internal',
                        '2:host2.internal',
                        '1:host3.internal',
                    ]
                elif username in ('foo4BS1', 'foo4BS2', 'foo4BS3'):
                    busy_servers = [
                        '2:downhost1-with-session.internal',
                        '1:host2.internal',
                        '3:host3-with-session.internal',
                    ]
                elif username in ('foo5BS1'):
                    busy_servers = [
                        '2:downhost1-with-session.internal',
                        '1:host2.internal',
                        '3:host3-with-session.internal',
                        '0:host4.internal',
                    ]
                return True, busy_servers

            elif task == 'ping':
                return True, []

            return False, []

        def _fake_portscan(addr, port=22):
            if addr == 'host3.internal':
                return False
            if addr.startswith('downhost'):
                return False
            return True

        def _fake_time_sleep(sec):
            pass

        x2gobroker.agent._call_local_broker_agent = _call_testsuite_broker_agent
        x2gobroker.agent._call_remote_broker_agent = _call_testsuite_broker_agent
        x2gobroker.utils.portscan = _fake_portscan
        time.sleep = _fake_time_sleep

        _session_profiles = """
[DEFAULT]
command = MATE
user = foo
broker-agent-query-mode = NONE
broker-use-load-checker = false

[testprofile1]
name = testprofile1
host = host1.internal, host2.internal, host3.internal
broker-agent-query-mode = LOCAL
broker-portscan-x2goservers = false

[testprofile2]
name = testprofile1
host = host1.internal, host2.internal, host3.internal
broker-agent-query-mode = LOCAL
broker-portscan-x2goservers = true

[testprofile3]
name = testprofile3
host = downhost1.internal, downhost2.internal, downhost3.internal
broker-agent-query-mode = LOCAL
broker-portscan-x2goservers = true

[testprofile4]
name = testprofile4
host = downhost1-with-session.internal, host2.internal, host3-with-session.internal
broker-agent-query-mode = LOCAL
broker-portscan-x2goservers = true

[testprofile5]
name = testprofile5
host = downhost1-with-session.internal, host2.internal, host3-with-session.internal, host4.internal
broker-agent-query-mode = SSH
broker-portscan-x2goservers = true
broker-autologin = true

"""
        tf = tempfile.NamedTemporaryFile(mode='w')
        print(_session_profiles, file=tf)
        tf.seek(0)
        inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name)

        i = 0
        while i < 10:
            _session1 = inifile_backend.select_session('testprofile1', username='fooBS1')
            self.assertTrue ( _session1['server'] == 'host3.internal')
            i += 1

        i = 0
        while i < 10:
            _session2 = inifile_backend.select_session('testprofile2', username='fooBS1')
            self.assertTrue ( _session2['server'] == 'host2.internal')
            i += 1

        i = 0
        while i < 10:
            _session3 = inifile_backend.select_session('testprofile3', username='fooBS1')
            self.assertTrue ( _session3['server'] == 'no-X2Go-Server-available')
            i += 1

        i = 0
        while i < 10:
            _session4 = inifile_backend.select_session('testprofile4', username='foo4BS1')
            self.assertTrue ( _session4['server'] == 'host3-with-session.internal')
            self.assertTrue ( _session4['session_info'] == '30342|foo4BS1-50-1414759661_stDMATE_dp24|50|host3-with-session|S|2014-10-31T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo4BS1|34|30003|-1|-1' )
            i += 1

        i = 0
        while i < 10:
            _session4 = inifile_backend.select_session('testprofile4', username='foo4BS2')
            self.assertTrue ( _session4['server'] == 'host2.internal')
            self.assertFalse ( 'session_info' in _session4 )
            i += 1

        i = 0
        while i < 10:
            _session4 = inifile_backend.select_session('testprofile4', username='foo4BS3')
            self.assertTrue ( _session4['server'] == 'host3-with-session.internal')
            self.assertTrue ( _session4['session_info'] == '30342|foo1S-50-1414759661_stDMATE_dp24|50|host3-with-session|S|2014-10-30T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|1474|30003|-1|-1' )
            i += 1

        i = 0
        while i < 10:
            _session4 = inifile_backend.select_session('testprofile4', username='foo4BS4')
            self.assertTrue ( _session4['server'] == 'host3-with-session.internal')
            self.assertTrue ( _session4['session_info'] == '30342|foo1S-50-1414759661_stDMATE_dp24|50|host3-with-session|S|2014-10-30T13:47:41|c02c7bbe58677a2726f7e456cb398ae4|127.0.0.1|30001|30002|2014-10-31T13:47:43|foo1S|1474|30003|-1|-1' )
            self.assertTrue ( self.tbarwos_session_suspended )
            self.tbarwos_session_suspended = False
            i += 1

        i = 0
        while i < 10:
            _session5 = inifile_backend.select_session('testprofile5', username='foo5BS1')
            self.assertTrue ( _session5['server'] == 'host4.internal')
            self.assertFalse ( 'session_info' in _session5 )
            i += 1

        x2gobroker.agent._call_local_broker_agent = _save_local_broker_agent_call
        x2gobroker.agent._call_remote_broker_agent = _save_remote_broker_agent_call
        x2gobroker.utils.portscan = _save_portscan
        time.sleep = _save_time_sleep

    def test_get_remote_agent_with_offline_servers(self):

        _save_local_broker_agent_call = x2gobroker.agent._call_local_broker_agent
        _save_remote_broker_agent_call = x2gobroker.agent._call_remote_broker_agent
        _save_portscan = x2gobroker.utils.portscan

        def _call_testsuite_broker_agent(username, task, cmdline_args=[], remote_agent=None, logger=None):

            if task == 'ping':
                return True, []

            return False, []

        def _fake_portscan(addr, port=22):
            if addr == 'host3.internal':
                return False
            elif addr.startswith('downhost'):
                return False
            elif addr == '10.0.2.11':
                return False
            elif addr.endswith('.local'):
                return True
            elif addr.endswith('.external'):
                return False
            return True

        def _fake_time_sleep(sec):
            pass

        x2gobroker.agent._call_local_broker_agent = _call_testsuite_broker_agent
        x2gobroker.agent._call_remote_broker_agent = _call_testsuite_broker_agent
        x2gobroker.utils.portscan = _fake_portscan
        time.sleep = _fake_time_sleep

        _session_profiles = """
[DEFAULT]
command = MATE
user = foo
broker-agent-query-mode = NONE
broker-use-load-checker = false

[testprofile1]
name = testprofile1
host = downhost1.internal (10.0.2.11), host2.internal (10.0.2.12), host3.internal (10.0.2.13)
broker-agent-query-mode = SSH
broker-portscan-x2goservers = true

[testprofile2]
name = testprofile2
host = downhost1.local (downhost1.external), host2.local (host2.external), host3.local (host3.external)
broker-agent-query-mode = SSH
broker-portscan-x2goservers = true

"""
        tf = tempfile.NamedTemporaryFile(mode='w')
        print(_session_profiles, file=tf)
        tf.seek(0)
        inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name)

        i = 0
        while i < 50:
            remote_agent = inifile_backend.get_remote_agent('testprofile1')
            self.assertTrue ( remote_agent['hostaddr'] != '10.0.2.11')
            i += 1

        i = 0
        while i < 50:
            remote_agent = inifile_backend.get_remote_agent('testprofile2')
            self.assertTrue ( bool(remote_agent) )
            self.assertTrue ( remote_agent['hostaddr'] != 'downhost1.external')
            i += 1

        x2gobroker.agent._call_local_broker_agent = _save_local_broker_agent_call
        x2gobroker.agent._call_remote_broker_agent = _save_remote_broker_agent_call
        x2gobroker.utils.portscan = _save_portscan

def test_suite():
    from unittest import TestSuite, makeSuite
    suite = TestSuite()
    suite.addTest(makeSuite(TestX2GoBrokerAgent))
    return suite
