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)
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)
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)
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)
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)
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
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)
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)])