def test_focus_on_function_using_tuples(self):
        recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(helper.monitor._code_trackers, {})
    def test_focus_on_function_using_tuples(self):

        # local import to avoid errors when the optional depedency psutils is
        # not available
        from pikos.cymonitors.focused_function_memory_monitor import (
            FocusedFunctionMemoryMonitor)

        recorder = ListRecorder(
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedFunctionMemoryMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, recorder)
        self.assertEqual(helper.monitor._code_trackers, {})
    def setUp(self):
        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedLineMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = TextStreamRecorder(
            text_stream=self.stream)
    def test_focus_on_function_using_tuples(self):
        recorder = ListRecorder()

        def monitor_factory(functions=[]):
            from pikos.cymonitors.focused_line_memory_monitor import (
                FocusedLineMemoryMonitor)
            return FocusedLineMemoryMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, recorder)
    def test_focus_on_function_with_tuple(self):
        recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedLineMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, self.stream)
    def setUp(self):
        self.check_for_psutils()
        from pikos.monitors.focused_line_memory_monitor import (
            FocusedLineMemoryMonitor)

        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedLineMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder()
    def setUp(self):
        self.check_for_psutils()
        self.maxDiff = None

        # local import to avoid errors when the optional depedency psutils is
        # not available
        from pikos.monitors.focused_function_memory_monitor import (
            FocusedFunctionMemoryMonitor)

        def monitor_factory(functions=[]):
            return FocusedFunctionMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder(
            filter_=OnValue('filename', self.filename))
    def setUp(self):
        self.check_for_psutils()
        try:
            from pikos.cymonitors.focused_function_memory_monitor import (
                FocusedFunctionMemoryMonitor)
        except ImportError:
            self.skipTest(
                'Cython FocusedFunctionMemoryMonitor is not available')
        self.maxDiff = None

        def monitor_factory(functions=[]):
            return FocusedFunctionMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder(
            filter_=OnValue('filename', self.filename))
    def setUp(self):
        self.check_for_psutils()
        try:
            from pikos.cymonitors.focused_line_memory_monitor import (
                FocusedLineMemoryMonitor)
        except ImportError:
            self.skipTest('Cython LineMemoryMonitor is not available')

        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedLineMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder()
    def setUp(self):
        try:
            from pikos.cymonitors.focused_function_monitor import (
                FocusedFunctionMonitor)
        except ImportError:
            self.skipTest('Cython FocusedFunctionMonitor is not available')
        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=OnValue('filename', self.filename))
class TestFocusedCFunctionMemoryMonitor(TestCase):

    def setUp(self):
        self.check_for_psutils()
        try:
            from pikos.cymonitors.focused_function_memory_monitor import (
                FocusedFunctionMemoryMonitor)
        except ImportError:
            self.skipTest(
                'Cython FocusedFunctionMemoryMonitor is not available')
        self.maxDiff = None

        def monitor_factory(functions=[]):
            return FocusedFunctionMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder(
            filter_=OnValue('filename', self.filename))

    def test_focus_on_function(self):
        result = self.helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.recorder)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_functions(self):
        result = self.helper.run_on_functions()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 62 {0}",
            "1 call internal 67 {0}",
            "2 return internal 68 {0}",
            "3 call internal 67 {0}",
            "4 return internal 68 {0}",
            "5 return gcd 65 {0}",
            "6 call foo 73 {0}",
            "7 call boo 70 {0}",
            "8 return boo 71 {0}",
            "9 call boo 70 {0}",
            "10 return boo 71 {0}",
            "11 return foo 75 {0}",
        ]
        self.check_records(template, self.recorder)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_recursive(self):
        result = self.helper.run_on_recursive_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 96 {0}",
            "1 call foo 103 {0}",
            "2 return foo 104 {0}",
            "3 call gcd 96 {0}",
            "4 call foo 103 {0}",
            "5 return foo 104 {0}",
            "6 return gcd 98 {0}",
            "7 return gcd 98 {0}"]
        self.check_records(template, self.recorder)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_function(self):
        result = self.helper.run_on_decorated()
        self.assertEqual(result, 3)
        template = [
            "0 call container 137 {0}",
            "1 call gcd 123 {0}",
            "2 call internal 128 {0}",
            "3 call boo 132 {0}",
            "4 return boo 133 {0}",
            "5 return internal 130 {0}",
            "6 call internal 128 {0}",
            "7 call boo 132 {0}",
            "8 return boo 133 {0}",
            "9 return internal 130 {0}",
            "10 return gcd 126 {0}",
            "11 call boo 132 {0}",
            "12 return boo 133 {0}",
            "13 return container 141 {0}"]
        self.check_records(template, self.recorder)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_recursive(self):
        result = self.helper.run_on_decorated_recursive()
        self.assertEqual(result, 3)
        if sys.version_info[:2] == (2, 6):
            # Python 2.6 __enter__ is called through the CALL_FUNCTION
            # bytecode and thus the c __enter__ methods appear in the
            # function events while in 2.7 the behaviour has changed.
            template = [
                "0 call gcd 157 {0}",
                "1 call foo 152 {0}",
                "2 return foo 153 {0}",
                "8 call gcd 157 {0}",
                "9 call foo 152 {0}",
                "10 return foo 153 {0}",
                "11 return gcd 160 {0}",
                "15 return gcd 160 {0}"]
        else:
            template = [
                "0 call gcd 157 {0}",
                "1 call foo 152 {0}",
                "2 return foo 153 {0}",
                "6 call gcd 157 {0}",
                "7 call foo 152 {0}",
                "8 return foo 153 {0}",
                "9 return gcd 160 {0}",
                "13 return gcd 160 {0}"]
        self.check_records(template, self.recorder)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_function_using_tuples(self):

        # local import to avoid errors when the optional depedency psutils is
        # not available
        from pikos.cymonitors.focused_function_memory_monitor import (
            FocusedFunctionMemoryMonitor)

        recorder = ListRecorder(
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedFunctionMemoryMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, recorder)
        self.assertEqual(helper.monitor._code_trackers, {})

    def get_records(self, recorder):
        """ Remove the memory related fields.
        """
        records = []
        for record in recorder.records:
            filtered = record[:3] + record[5:]
            records.append(' '.join([str(item) for item in filtered]))
        return records

    def check_records(self, template, recorder):
        expected = [line.format(self.filename) for line in template]
        records = self.get_records(recorder)
        self.assertEqual(records, expected)

    def check_for_psutils(self):
        try:
            import psutil
            psutil
        except ImportError:
            self.skipTest('Could not import psutils, skipping test.')
class TestFocusedLineMemoryMonitor(TestCase):

    def setUp(self):
        self.check_for_psutils()
        try:
            from pikos.cymonitors.focused_line_memory_monitor import (
                FocusedLineMemoryMonitor)
        except ImportError:
            self.skipTest('Cython LineMemoryMonitor is not available')

        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedLineMemoryMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = ListRecorder()

    def test_focus_on_function(self):
        result = self.helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, self.recorder)

    def test_focus_on_functions(self):
        result = self.helper.run_on_functions()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 63             while x > 0: {0}",
            "1 gcd 64                 x, y = internal(x, y) {0}",
            "2 gcd 63             while x > 0: {0}",
            "3 gcd 64                 x, y = internal(x, y) {0}",
            "4 gcd 63             while x > 0: {0}",
            "5 gcd 65             return y {0}",
            "6 foo 74             boo() {0}",
            "7 foo 75             boo() {0}"]
        self.check_records(template, self.recorder)

    def test_focus_on_recursive(self):
        result = self.helper.run_on_recursive_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 97             foo() {0}",
            "1 gcd 98             return x if y == 0 else gcd(y, (x % y)) {0}",  # noqa
            "2 gcd 97             foo() {0}",
            "3 gcd 98             return x if y == 0 else gcd(y, (x % y)) {0}"]  # noqa
        self.check_records(template, self.recorder)

    def test_focus_on_decorated_recursive_function(self):
        result = self.helper.run_on_decorated_recursive()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 159             foo() {0}",
            "1 gcd 160             return x if y == 0 else gcd(y, (x % y)) {0}",  # noqa
            "2 gcd 159             foo() {0}",
            "3 gcd 160             return x if y == 0 else gcd(y, (x % y)) {0}"]  # noqa
        self.check_records(template, self.recorder)

    def test_focus_on_decorated_function(self):
        result = self.helper.run_on_decorated()
        self.assertEqual(result, 3)
        template = [
            "0 container 139             result = gcd(x, y) {0}",
            "1 gcd 124             while x > 0: {0}",
            "2 gcd 125                 x, y = internal(x, y) {0}",
            "3 gcd 124             while x > 0: {0}",
            "4 gcd 125                 x, y = internal(x, y) {0}",
            "5 gcd 124             while x > 0: {0}",
            "6 gcd 126             return y {0}",
            "7 container 140             boo() {0}",
            "8 container 141             return result {0}"]
        self.check_records(template, self.recorder)

    def test_focus_on_function_using_tuples(self):
        recorder = ListRecorder()

        def monitor_factory(functions=[]):
            from pikos.cymonitors.focused_line_memory_monitor import (
                FocusedLineMemoryMonitor)
            return FocusedLineMemoryMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, recorder)

    def get_records(self, recorder):
        """ Remove the memory related fields.
        """
        records = []
        for record in recorder.records:
            filtered = record[:3] + record[5:]
            records.append(' '.join([str(item) for item in filtered]))
        return records

    def check_for_psutils(self):
        try:
            import psutil  # noqa
        except ImportError:
            self.skipTest('Could not import psutils, skipping test.')

    def check_records(self, template, recorder):
        expected = [line.format(self.filename) for line in template]
        records = self.get_records(recorder)
        self.assertEqual(records, expected)
class TestFocusedFunctionMonitor(TestCase):

    def setUp(self):
        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=OnValue('filename', self.filename))

    def tearDown(self):
        sys.setprofile(None)

    def test_focus_on_function(self):
        result = self.helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_functions(self):
        result = self.helper.run_on_functions()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 62 {0}",
            "1 call internal 67 {0}",
            "2 return internal 68 {0}",
            "3 call internal 67 {0}",
            "4 return internal 68 {0}",
            "5 return gcd 65 {0}",
            "6 call foo 73 {0}",
            "7 call boo 70 {0}",
            "8 return boo 71 {0}",
            "9 call boo 70 {0}",
            "10 return boo 71 {0}",
            "11 return foo 75 {0}",
        ]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_recursive(self):
        result = self.helper.run_on_recursive_function()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 96 {0}",
            "1 call foo 103 {0}",
            "2 return foo 104 {0}",
            "3 call gcd 96 {0}",
            "4 call foo 103 {0}",
            "5 return foo 104 {0}",
            "6 return gcd 98 {0}",
            "7 return gcd 98 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_function(self):
        result = self.helper.run_on_decorated()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call container 137 {0}",
            "1 call gcd 123 {0}",
            "2 call internal 128 {0}",
            "3 call boo 132 {0}",
            "4 return boo 133 {0}",
            "5 return internal 130 {0}",
            "6 call internal 128 {0}",
            "7 call boo 132 {0}",
            "8 return boo 133 {0}",
            "9 return internal 130 {0}",
            "10 return gcd 126 {0}",
            "11 call boo 132 {0}",
            "12 return boo 133 {0}",
            "13 return container 141 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_recursive(self):
        result = self.helper.run_on_decorated_recursive()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 157 {0}",
            "1 call foo 152 {0}",
            "2 return foo 153 {0}",
            "10 call gcd 157 {0}",
            "11 call foo 152 {0}",
            "12 return foo 153 {0}",
            "13 return gcd 160 {0}",
            "21 return gcd 160 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_function_using_tuples(self):
        recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(helper.monitor._code_trackers, {})

    def check_records(self, template, stream):
        expected = [line.format(self.filename) for line in template]
        records = ''.join(stream.buflist).splitlines()
        self.assertEqual(records, expected)
class TestFocusedLineMonitor(TestCase):

    def setUp(self):
        try:
            from pikos.cymonitors.focused_line_monitor import (
                FocusedLineMonitor)
        except ImportError:
            self.skipTest('Cython LineMonitor is not available')
        self.maxDiff = None
        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedLineMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = TextStreamRecorder(
            text_stream=self.stream)

    def test_focus_on_function(self):
        result = self.helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "index function lineNo line filename",
            "-----------------------------------",
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, self.stream)

    def test_focus_on_functions(self):
        result = self.helper.run_on_functions()
        self.assertEqual(result, 3)
        template = [
            "index function lineNo line filename",
            "-----------------------------------",
            "0 gcd 63             while x > 0: {0}",
            "1 gcd 64                 x, y = internal(x, y) {0}",
            "2 gcd 63             while x > 0: {0}",
            "3 gcd 64                 x, y = internal(x, y) {0}",
            "4 gcd 63             while x > 0: {0}",
            "5 gcd 65             return y {0}",
            "6 foo 74             boo() {0}",
            "7 foo 75             boo() {0}"]
        self.check_records(template, self.stream)

    def test_focus_on_recursive(self):
        result = self.helper.run_on_recursive_function()
        self.assertEqual(result, 3)
        template = [
            "index function lineNo line filename",
            "-----------------------------------",
            "0 gcd 97             foo() {0}",
            "1 gcd 98             return x if y == 0 else gcd(y, (x % y)) {0}",  # noqa
            "2 gcd 97             foo() {0}",
            "3 gcd 98             return x if y == 0 else gcd(y, (x % y)) {0}"]  # noqa
        self.check_records(template, self.stream)

    def test_focus_on_decorated_function(self):
        result = self.helper.run_on_decorated()
        self.assertEqual(result, 3)
        template = [
            "index function lineNo line filename",
            "-----------------------------------",
            "0 container 139             result = gcd(x, y) {0}",
            "1 gcd 124             while x > 0: {0}",
            "2 gcd 125                 x, y = internal(x, y) {0}",
            "3 gcd 124             while x > 0: {0}",
            "4 gcd 125                 x, y = internal(x, y) {0}",
            "5 gcd 124             while x > 0: {0}",
            "6 gcd 126             return y {0}",
            "7 container 140             boo() {0}",
            "8 container 141             return result {0}"]
        self.check_records(template, self.stream)

    def test_focus_on_decorated_recursive_function(self):
        result = self.helper.run_on_decorated_recursive()
        self.assertEqual(result, 3)
        template = [
            "index function lineNo line filename",
            "-----------------------------------",
            "0 gcd 159             foo() {0}",
            "1 gcd 160             return x if y == 0 else gcd(y, (x % y)) {0}",  # noqa
            "2 gcd 159             foo() {0}",
            "3 gcd 160             return x if y == 0 else gcd(y, (x % y)) {0}"]  # noqa
        self.check_records(template, self.stream)

    def test_focus_on_function_with_tuple(self):
        from pikos.cymonitors.focused_line_monitor import FocusedLineMonitor

        recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedLineMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 gcd 34             while x > 0: {0}",
            "1 gcd 35                 x, y = internal(x, y) {0}",
            "2 gcd 34             while x > 0: {0}",
            "3 gcd 35                 x, y = internal(x, y) {0}",
            "4 gcd 34             while x > 0: {0}",
            "5 gcd 36             return y {0}"]
        self.check_records(template, self.stream)

    def check_records(self, template, stream):
        template = [line.format(self.filename) for line in template]
        records = ''.join(stream.buflist).splitlines()
        self.assertEqual(records, template)
class TestFocusedCFunctionMonitor(TestCase):

    def setUp(self):
        try:
            from pikos.cymonitors.focused_function_monitor import (
                FocusedFunctionMonitor)
        except ImportError:
            self.skipTest('Cython FocusedFunctionMonitor is not available')
        self.maxDiff = None
        self.stream = StringIO.StringIO()

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions, recorder=self.recorder)

        self.helper = FocusedMonitoringHelper(monitor_factory)
        self.filename = self.helper.filename
        self.recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=OnValue('filename', self.filename))

    def tearDown(self):
        sys.setprofile(None)

    def test_focus_on_function(self):
        result = self.helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_functions(self):
        result = self.helper.run_on_functions()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 62 {0}",
            "1 call internal 67 {0}",
            "2 return internal 68 {0}",
            "3 call internal 67 {0}",
            "4 return internal 68 {0}",
            "5 return gcd 65 {0}",
            "6 call foo 73 {0}",
            "7 call boo 70 {0}",
            "8 return boo 71 {0}",
            "9 call boo 70 {0}",
            "10 return boo 71 {0}",
            "11 return foo 75 {0}",
        ]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_recursive(self):
        result = self.helper.run_on_recursive_function()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call gcd 96 {0}",
            "1 call foo 103 {0}",
            "2 return foo 104 {0}",
            "3 call gcd 96 {0}",
            "4 call foo 103 {0}",
            "5 return foo 104 {0}",
            "6 return gcd 98 {0}",
            "7 return gcd 98 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_function(self):
        result = self.helper.run_on_decorated()
        self.assertEqual(result, 3)
        template = [
            "index type function lineNo filename",
            "-----------------------------------",
            "0 call container 137 {0}",
            "1 call gcd 123 {0}",
            "2 call internal 128 {0}",
            "3 call boo 132 {0}",
            "4 return boo 133 {0}",
            "5 return internal 130 {0}",
            "6 call internal 128 {0}",
            "7 call boo 132 {0}",
            "8 return boo 133 {0}",
            "9 return internal 130 {0}",
            "10 return gcd 126 {0}",
            "11 call boo 132 {0}",
            "12 return boo 133 {0}",
            "13 return container 141 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_decorated_recursive(self):
        result = self.helper.run_on_decorated_recursive()
        self.assertEqual(result, 3)
        if sys.version_info[:2] == (2, 6):
            # Python 2.6 __enter__ is called through the CALL_FUNCTION
            # bytecode and thus the c __enter__ methods appear in the
            # function events while in 2.7 the behaviour has changed.
            template = [
                "index type function lineNo filename",
                "-----------------------------------",
                "0 call gcd 157 {0}",
                "1 call foo 152 {0}",
                "2 return foo 153 {0}",
                "8 call gcd 157 {0}",
                "9 call foo 152 {0}",
                "10 return foo 153 {0}",
                "11 return gcd 160 {0}",
                "15 return gcd 160 {0}"]
        else:
            template = [
                "index type function lineNo filename",
                "-----------------------------------",
                "0 call gcd 157 {0}",
                "1 call foo 152 {0}",
                "2 return foo 153 {0}",
                "6 call gcd 157 {0}",
                "7 call foo 152 {0}",
                "8 return foo 153 {0}",
                "9 return gcd 160 {0}",
                "13 return gcd 160 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(self.helper.monitor._code_trackers, {})

    def test_focus_on_function_using_tuples(self):
        from pikos.cymonitors.focused_function_monitor import (
            FocusedFunctionMonitor)
        recorder = TextStreamRecorder(
            text_stream=self.stream,
            filter_=lambda record: self.filename in record)

        def monitor_factory(functions=[]):
            return FocusedFunctionMonitor(
                functions=functions,
                recorder=recorder,
                record_type=tuple)

        helper = FocusedMonitoringHelper(monitor_factory)
        result = helper.run_on_function()
        self.assertEqual(result, 3)
        template = [
            "0 call gcd 33 {0}",
            "1 call internal 40 {0}",
            "2 call boo 44 {0}",
            "3 return boo 45 {0}",
            "4 return internal 42 {0}",
            "5 call internal 40 {0}",
            "6 call boo 44 {0}",
            "7 return boo 45 {0}",
            "8 return internal 42 {0}",
            "9 return gcd 36 {0}"]
        self.check_records(template, self.stream)
        self.assertEqual(helper.monitor._code_trackers, {})

    def check_records(self, template, stream):
        expected = [line.format(self.filename) for line in template]
        records = ''.join(stream.buflist).splitlines()
        self.assertEqual(records, expected)