Example #1
0
    async def collect(self):
        """ Collect data asynchronously using memleak.py """
        try:
            raw_data = await self._get_raw_data()
        except exceptions.SubprocessedErorred as se:
            logger.error(str(se))
            return data_io.StackData(None, -1, -1, InterfaceTypes.MEMLEAK,
                                     None)

        data = self._get_generator(raw_data)
        data_options = data_io.StackData.DataOptions("kilobytes")
        return data_io.StackData(data, self.start_time, self.end_time,
                                 InterfaceTypes.MEMLEAK, data_options)
Example #2
0
    def test_create_treemap_csv_different_stack_lengths(self):
        """
        Again, tests multidigit weights, now with bigger input

        """
        # The expected output
        expected = self.tmap.data_options.weight_units + ";" + \
                   ';'.join([str(i) for i in
                             range(1, self.tmap.display_options.depth + 1)]) + \
                   '\n' + \
                   "1;pname;call1;call2;call3\n" \
                   "2;pname;call1\n" \
                   "3;pname;call1;call2\n"

        data = iter(("00000" + consts.field_separator
                     + "pname;call1;call2;call3;call4;call5\n",
                     "000000000" + consts.field_separator + "pname;call1;call2\n",
                     "000" + consts.field_separator + "pname;call1;call2;call3"))
        datum_generator = (
            data_io.StackDatum(1, ('pname', 'call1', 'call2', 'call3')),
            data_io.StackDatum(2, ('pname', 'call1')),
            data_io.StackDatum(3, ('pname', 'call1', 'call2'))
        )

        data = data_io.StackData(datum_generator, None, None, None, None)

        out = self._get_output(data)

        # Check that we got the desired output
        self.assertEqual(expected, out)
Example #3
0
    def test_create_treemap_csv_multidigit(self):
        """
        Tests multidigit weight values

        """
        # The expected output
        expected = self.tmap.data_options.weight_units + ";" + \
                   ';'.join([str(i) for i in
                             range(1, self.tmap.display_options.depth + 1)]) + \
                   '\n' + \
                   "1;pname;call1;call2\n" \
                   "2;pname;call3;call4\n"

        # Get the output from a collapsed stack (first line in inpt is the
        # empty header
        datum_generator = (
            data_io.StackDatum(1, ('pname', 'call1', 'call2')),
            data_io.StackDatum(2, ('pname', 'call3', 'call4'))
        )

        data = data_io.StackData(datum_generator, None, None, None, None)

        outpt = self._get_output(data)

        # Check that we got the desired output
        self.assertEqual(expected, outpt)
Example #4
0
    async def collect(self):
        """
        Collect data asynchronously.

        :return:
            A `data_io.StackData` object, encapsulating the collected data.
        """
        try:
            raw_data = await self._get_raw_data()
        except exceptions.SubprocessedErorred as se:
            logger.error(str(se))
            return data_io.StackData(None, -1, -1, InterfaceTypes.MALLOCSTACKS,
                                     None)

        data = self._get_generator(raw_data)
        data_options = data_io.StackData.DataOptions("kilobytes")
        return data_io.StackData(data, self.start_time, self.end_time,
                                 InterfaceTypes.MALLOCSTACKS, data_options)
Example #5
0
    async def collect(self):
        """
        Collect data asynchronously using perf.

        :return
            A `data_io.StackData` object that encapsulates the collected data if
            no subprocesses errored, None otherwise.

        """
        try:
            raw_data = await self._get_raw_data()
        except exceptions.SubprocessedErorred as se:
            logger.error(str(se))
            return data_io.StackData(None, -1, -1, InterfaceTypes.MEMEVENTS,
                                     None)

        data = self._get_generator(raw_data)
        data_options = data_io.StackData.DataOptions("samples")
        return data_io.StackData(data, self.start_time, self.end_time,
                                 InterfaceTypes.MEMEVENTS, data_options)
Example #6
0
class _FlamegraphBaseTest(unittest.TestCase):
    """ Base class for flamegraph tests """
    coloring = 'test_color'
    weight_units = "kb"

    datum_generator = (
        data_io.StackDatum(1, ('2', '3', '4', '5'))
    )
    data = data_io.StackData(datum_generator, None, None, None, data_io.StackData.DataOptions("kb"))

    outfile = mock.MagicMock()
    outfilename = "test_output"
    outfile.__str__.return_value = outfilename
    file_mock = StringIO("")

    # Set up blank flamegraph
    fg = object.__new__(flamegraph.Flamegraph)

    fg.display_options = flamegraph.Flamegraph.DisplayOptions(coloring)
    fg.data_options = data_io.StackData.DataOptions("kb")
    fg.data = data
Example #7
0
class MakeTest(_FlamegraphBaseTest):
    """ Test the flamegraph creation """

    # Set up test data and expected values
    test_stack_datums = [
        data_io.StackDatum(1, ('A1', 'A2', 'A3')),
        data_io.StackDatum(2, ('B1', 'B2', 'B3', 'B4')),
        data_io.StackDatum(3, ('A1', 'A2', 'A3'))
    ]

    test_stack_data = data_io.StackData(test_stack_datums, None, None, None,
                                        data_io.StackData.DataOptions("kb"))

    expected = collections.Counter({('A1', 'A2', 'A3'): 4,
                                    ('B1', 'B2', 'B3', 'B4'): 2})

    expected_temp_file = "A1;A2;A3 4\n" \
                         "B1;B2;B3;B4 2\n"

    @mock.patch('marple.display.interface.flamegraph.file')
    @mock.patch('builtins.open')
    @mock.patch('marple.display.interface.flamegraph.subprocess')
    def test_no_options(self, subproc_mock, open_mock, temp_file_mock):
        """ Test without display options """
        temp_file_mock.TempFileName.return_value.__str__.return_value = \
            "test_temp_file"

        fg = flamegraph.Flamegraph(self.test_stack_data)

        context_mock1, context_mock2 = mock.MagicMock(), mock.MagicMock()
        file_mock1, file_mock2 = StringIO(""), StringIO("")
        open_mock.side_effect = [context_mock1, context_mock2]
        context_mock1.__enter__.return_value = file_mock1
        context_mock2.__enter__.return_value = file_mock2

        actual = fg._make()

        temp_file_mock.TempFileName.return_value.__str__.\
            assert_has_calls((mock.call(), mock.call()))
        open_mock.assert_has_calls([
            mock.call("test_temp_file", "w"),
            mock.call("test_temp_file", "w")
        ])
        self.assertEqual(file_mock1.getvalue(), self.expected_temp_file)

        subproc_mock.Popen.assert_called_once_with(
            [flamegraph.FLAMEGRAPH_DIR, "--color=hot", "--countname=kb",
             "test_temp_file"],
            stdout=file_mock2
        )
        self.assertEqual(self.expected, actual)

    @mock.patch('marple.display.interface.flamegraph.file')
    @mock.patch('builtins.open')
    @mock.patch('marple.display.interface.flamegraph.subprocess')
    def test_with_coloring(self, subproc_mock, open_mock, temp_file_mock):
        """ Test with a options """
        temp_file_mock.TempFileName.return_value.__str__.return_value = \
            "test_temp_file"

        fg = flamegraph.Flamegraph(self.test_stack_data)

        context_mock1, context_mock2 = mock.MagicMock(), mock.MagicMock()
        file_mock1, file_mock2 = StringIO(""), StringIO("")
        open_mock.side_effect = [context_mock1, context_mock2]
        context_mock1.__enter__.return_value = file_mock1
        context_mock2.__enter__.return_value = file_mock2

        actual = fg._make()

        temp_file_mock.TempFileName.return_value.__str__.\
            assert_has_calls((mock.call(), mock.call()))
        open_mock.assert_has_calls([
            mock.call("test_temp_file", "w"),
            mock.call("test_temp_file", "w")
        ])
        self.assertEqual(file_mock1.getvalue(), self.expected_temp_file)
        subproc_mock.Popen.assert_called_once_with(
            [flamegraph.FLAMEGRAPH_DIR, '--color=hot', '--countname=kb',
             'test_temp_file'], stdout=file_mock2
        )
        self.assertEqual(self.expected, actual)
Example #8
0
class TreemapTest(unittest.TestCase):
    """Class for testing the treemap module and its helper functions"""
    _TEST_DIR = "/tmp/marple-test/"

    # Set up blank treemap
    tmap = object.__new__(treemap.Treemap)

    tmap.display_options = treemap.Treemap.DisplayOptions(25)
    tmap.data_options = data_io.StackData.DataOptions("kb")
    tmap.data = iter(())

    tmap.data_obj = data_io.StackData(
        tmap.data, None, None, 'callstack', tmap.data_options)

    def setUp(self):
        """Per-test set-up"""
        os.makedirs(self._TEST_DIR, exist_ok=True)

    def tearDown(self):
        """Per-test tear-down"""
        shutil.rmtree(self._TEST_DIR)

    def _get_output(self, data):
        csv = self._TEST_DIR + "csv"

        self.tmap.data = data
        self.tmap._generate_csv(csv)

        with open(csv, "r") as file_:
            return file_.read()

    def test_create_treemap_csv_multidigit(self):
        """
        Tests multidigit weight values

        """
        # The expected output
        expected = self.tmap.data_options.weight_units + ";" + \
                   ';'.join([str(i) for i in
                             range(1, self.tmap.display_options.depth + 1)]) + \
                   '\n' + \
                   "1;pname;call1;call2\n" \
                   "2;pname;call3;call4\n"

        # Get the output from a collapsed stack (first line in inpt is the
        # empty header
        datum_generator = (
            data_io.StackDatum(1, ('pname', 'call1', 'call2')),
            data_io.StackDatum(2, ('pname', 'call3', 'call4'))
        )

        data = data_io.StackData(datum_generator, None, None, None, None)

        outpt = self._get_output(data)

        # Check that we got the desired output
        self.assertEqual(expected, outpt)

    def test_create_treemap_csv_different_stack_lengths(self):
        """
        Again, tests multidigit weights, now with bigger input

        """
        # The expected output
        expected = self.tmap.data_options.weight_units + ";" + \
                   ';'.join([str(i) for i in
                             range(1, self.tmap.display_options.depth + 1)]) + \
                   '\n' + \
                   "1;pname;call1;call2;call3\n" \
                   "2;pname;call1\n" \
                   "3;pname;call1;call2\n"

        data = iter(("00000" + consts.field_separator
                     + "pname;call1;call2;call3;call4;call5\n",
                     "000000000" + consts.field_separator + "pname;call1;call2\n",
                     "000" + consts.field_separator + "pname;call1;call2;call3"))
        datum_generator = (
            data_io.StackDatum(1, ('pname', 'call1', 'call2', 'call3')),
            data_io.StackDatum(2, ('pname', 'call1')),
            data_io.StackDatum(3, ('pname', 'call1', 'call2'))
        )

        data = data_io.StackData(datum_generator, None, None, None, None)

        out = self._get_output(data)

        # Check that we got the desired output
        self.assertEqual(expected, out)

    @mock.patch("builtins.open")
    @mock.patch("os.environ")
    @mock.patch("marple.display.interface.treemap.Treemap._generate_csv")
    @mock.patch("marple.display.tools.d3plus.d3IpyPlus.from_csv", return_value="")
    @mock.patch("subprocess.Popen")
    @mock.patch("marple.display.tools.d3plus.d3IpyPlus.TreeMap.dump_html",
                return_value="")
    def test_show_function(self, mock_dump, mock_popen, mock_from_csv,
                           mock_gen_csv, os_mock, mock_open):
        """
        Tests the right parameters for various functions used by the show
        function

        :param mock_dump: mock for dump_html
        :param mock_popen: mock for popen
        :param mock_from_csv: mock for csv
        :param mock_gen_csv: mock for _generate_csv
        :param os_mock: mock for environ
        :return:
        # """
        self.tmap.show()

        # Right columns, also implies right ids (since they are the same
        # but without the 'value' field
        self.assertEqual(mock_from_csv.call_args[1]['columns'],
                         [self.tmap.data_options.weight_units] +
                         [str(x) for x in
                          range(1, self.tmap.display_options.depth + 1)])