"""test_runloop
"""

import sys
import time
import StringIO
import unittest

from eventlet import runloop


class TestRunloop(unittest.TestCase):
    def test_empty(self):
        r = runloop.RunLoop()
        r.schedule_call(0, r.abort)
        r.run()
        assert not r.running


    def test_timer(self):
        r = runloop.RunLoop()
        r.schedule_call(0.125, r.abort)
        start_time = time.time()
        r.run()
        assert time.time() - start_time >= 0.125
        assert not r.running

    def test_observer(self):
        observed = []
        r = runloop.RunLoop()
        r.add_observer(lambda runloop, activity: observed.append(activity))
        r.schedule_call(0, r.abort)
        r.run()
        assert observed == ['entry', 'before_timers', 'before_waiting', 'after_waiting', 'exit']
        assert not r.running


    def test_remove_observer(self):
        r = runloop.RunLoop()

        observed = []
        def observe(runloop, mode):
            observed.append(mode)
            r.remove_observer(observe)

        looped = []
        def run_loop_twice(runloop, mode):
            if looped:
                r.abort()
            else:
                looped.append(True)

        r.add_observer(observe, 'before_timers')
        r.add_observer(run_loop_twice, 'after_waiting')
        r.run()
        assert len(observed) == 1
        assert not r.running

    def test_observer_exception(self):
        r = runloop.RunLoop()

        observed = []
        def observe(runloop, mode):
            observed.append(mode)
            raise Exception("Squelch me please")

        looped = []
        def run_loop_twice(runloop, mode):
            if looped:
                r.abort()
            else:
                looped.append(True)

        saved = sys.stderr
        sys.stderr = err = StringIO.StringIO()

        r.add_observer(observe, 'before_timers')
        r.add_observer(run_loop_twice, 'after_waiting')
        r.run()

        err.seek(0)
        sys.stderr = saved

        assert len(observed) == 1
        assert err.read()
        assert not r.running

    def test_timer_exception(self):
        r = runloop.RunLoop()

        observed = []
        def timer():
            observed.append(True)
            raise Exception("Squelch me please")

        looped = []
        def run_loop_twice(runloop, mode):
            if looped:
                r.abort()
            else:
                looped.append(True)

        saved = sys.stderr
        sys.stderr = err = StringIO.StringIO()

        r.schedule_call(0, timer)
        r.add_observer(run_loop_twice, 'after_waiting')
        r.run()

        err.seek(0)
        sys.stderr = saved

        assert len(observed) == 1
        assert err.read()
        assert not r.running

    def test_timer_system_exception(self):
        r = runloop.RunLoop()
        def timer():
            raise SystemExit

        r.schedule_call(0, timer)

        caught = []
        try:
            r.run()
        except SystemExit:
            caught.append(True)

        assert caught
        assert not r.running

if __name__ == '__main__':
    unittest.main()

