| @@ -0,0 +1 @@ | ||
| +*.pyc |
| @@ -0,0 +1,40 @@ | ||
| +# | ||
| +# Copyright (c) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +TOPDIR = ../../.. | ||
| +include $(TOPDIR)/src/include/builddefs | ||
| + | ||
| +TARGET = pcp-pidstat | ||
| +MAN_SECTION = 1 | ||
| +MAN_PAGES = $(TARGET).$(MAN_SECTION) | ||
| +MAN_DEST = $(PCP_MAN_DIR)/man$(MAN_SECTION) | ||
| + | ||
| +default: $(TARGET).py $(MAN_PAGES) | ||
| + | ||
| +include $(BUILDRULES) | ||
| + | ||
| +install: default | ||
| +ifeq "$(HAVE_PYTHON)" "true" | ||
| + $(INSTALL) -m 755 $(TARGET).py $(PCP_BINADM_DIR)/$(TARGET) | ||
| + @$(INSTALL_MAN) | ||
| +endif | ||
| + | ||
| +default_pcp : default | ||
| + | ||
| +install_pcp : install | ||
| + | ||
| +check :: check_pcp | ||
| + | ||
| +check_pcp: | ||
| + python -m unittest discover -s test -p '*_test.py' |
| @@ -0,0 +1,148 @@ | ||
| +.TH PCP-PIDSTAT 1 "PCP" "Performance Co-Pilot" | ||
| +.SH NAME | ||
| +\f3 pcp-pidstat\f1 \- Report statistics for Linux tasks. | ||
| +.SH SYNOPSIS | ||
| +\f3pcp\f1 \f3pidstat\f1 [\f3\-s\f1 N] [\f3\-t\f1 DELTA] [\f3\-I \f1] [\f3\-a\f1 FILE] [\f3\-G\f1 NAME] [\f3\-U\f1[USERNAME]] [\f3\-p\f1 PID1,PID2..] [\f3\-R\f1/\f3\-r/\f3\-k\f1] [\f3\-V\f1] [\f3\-?\f1] | ||
| +.SH DESCRIPTION | ||
| +.B pcp-pidstat | ||
| +command is used for monitoring individual tasks currently being managed by the Linux kernel. Using various options it helps user to see useful information related with the processes. This information can include percentage CPU, memory and stack usages, scheduling and priority information. | ||
| +.BR pcp-pidstat | ||
| +fetches the data to be analysed from PMCD unless provided \-a option. (See below) | ||
| + | ||
| +.SH OPTIONS | ||
| +Output control options: | ||
| +.TP | ||
| +.BR \-s \ N ", " \fB\-\-samples =\fIN\fR | ||
| +Set the number of samples to be displayed. | ||
| +Default is continous. | ||
| + | ||
| +.TP | ||
| +.BR \-t \ DELTA ", " \fB\-\-interval =\fIDELTA\fR | ||
| +Set the interval between two samples. | ||
| +Default is one second. | ||
| + | ||
| +.PP | ||
| +General Options: | ||
| + | ||
| +.TP | ||
| +.BR \-I \fR | ||
| +In an SMP environment, indicates that tasks CPU usage should be divided by the total number of processors. | ||
| + | ||
| +.TP | ||
| +.BR \-a \ FILE ", " \fB\-\-archive =\fIFILE\fR | ||
| +Causes pcp\-pidstat to use the specified archive than connecting to PMCD. The argument to -a is a comma-separated | ||
| +list of names, each of which may be the base name of an archive or the name of a directory containing one or more archives. Archives can be created using | ||
| +.BR pmlogger (1)\. | ||
| + | ||
| +.TP | ||
| +.BR \-R \fR | ||
| +Report realtime priority and scheduling policy information. The following values may be displayed: | ||
| + | ||
| +UID | ||
| + The real user identification number of the task being monitored. | ||
| + | ||
| +USER | ||
| + The name of the real user owning the task being monitored. | ||
| + | ||
| +PID | ||
| + The identification number of the task being monitored. | ||
| + | ||
| +prio | ||
| + The realtime priority of the task being monitored. | ||
| + | ||
| +policy | ||
| + The scheduling policy of the task being monitored. | ||
| + | ||
| +Command | ||
| + The command name of the task. | ||
| + | ||
| +.TP | ||
| +.BR \-r \fR | ||
| +Report page faults and memory utilization. The following values may be displayed: | ||
| + | ||
| +UID | ||
| + The real user identification number of the task being monitored. | ||
| + | ||
| +USER | ||
| + The name of the real user owning the task being monitored. | ||
| + | ||
| +PID | ||
| + The identification number of the task being monitored. | ||
| + | ||
| +minflt/s | ||
| + Total number of minor faults the task has made per second, those which have not required loading a memory page from disk. | ||
| + | ||
| +majflt/s | ||
| + Total number of major faults the task has made per second, those which have required loading a memory page from disk. | ||
| + | ||
| +VSZ | ||
| + Virtual Size: The virtual memory usage of entire task in kilobytes. | ||
| + | ||
| +RSS | ||
| + Resident Set Size: The non-swapped physical memory used by the task in kilobytes. | ||
| + | ||
| +%MEM | ||
| + The tasks's currently used share of available physical memory. | ||
| + | ||
| +Command | ||
| + The command name of the task. | ||
| + | ||
| +.TP | ||
| +.BR \-k \fR | ||
| +Report stack utilization. The following values may be displayed: | ||
| + | ||
| +UID | ||
| + The real user identification number of the task being monitored. | ||
| + | ||
| +USER | ||
| + The name of the real user owning the task being monitored. | ||
| + | ||
| +PID | ||
| + The identification number of the task being monitored. | ||
| + | ||
| +StkSize | ||
| + The amount of memory in kilobytes reserved for the task as stack, but not necessarily used. | ||
| + | ||
| +StkRef | ||
| + The amount of memory in kilobytes used as stack, referenced by the task. | ||
| + | ||
| +Command | ||
| + The command name of the task. | ||
| + | ||
| +.TP | ||
| +.BR \-V \fR | ||
| +Display version and exit | ||
| + | ||
| +.TP | ||
| +.BR \-? " , " \fB\-\-help\fR | ||
| +Display help and exit | ||
| + | ||
| +.PP | ||
| +Ouput Filter Options | ||
| + | ||
| +.TP | ||
| +.BR \-G \ NAME ", " \fB\-\-process-name =\fINAME\fR | ||
| +Display only processes whose command name includes the string \fINAME\fR. This string can be a regular expression. | ||
| + | ||
| +.TP | ||
| +.BR \-U\fI[USERNAME] ", " \fB\-\-user\-name =\fI[USERNAME]\fR | ||
| +Display the real user name of the tasks being monitored instead of the UID. If \fIusername\fR is specified, then only tasks belonging to the specified user are displayed. | ||
| + | ||
| +.TP | ||
| +.BR \-p \ \fIPID1,PID2 .. " , " \fB\-\-pid-list =\fIPID1,PID2 ..\fR | ||
| +Display only processes whose PID belongs to the given Pid List. | ||
| + | ||
| +.SH NOTES | ||
| +.B pcp-pidstat | ||
| +is inspired by the | ||
| +.BR pidstat (1) | ||
| +command and aims to be command line and output compatible with it. | ||
| + | ||
| +.PP | ||
| +.SH "SEE ALSO" | ||
| +.BR pcp (1), | ||
| +.BR pidstat(1), | ||
| +.BR PCPIntro (1), | ||
| +.BR pmParseInterval (3) | ||
| +and | ||
| +.BR environ (7). |
| @@ -0,0 +1,38 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import mock | ||
| +import unittest | ||
| +from pcp_pidstat import CpuProcessMemoryUtil | ||
| + | ||
| + | ||
| +class TestCpuProcessMemoryUtil(unittest.TestCase): | ||
| + | ||
| + def current_values_side_effect(self, metric): | ||
| + if metric == 'proc.psinfo.pid': | ||
| + return {1: 1, 2: 2, 5: 5, 10: 10} | ||
| + | ||
| + def test_get_processes(self): | ||
| + metric_repository = mock.Mock() | ||
| + cpu_process_memory_util = CpuProcessMemoryUtil(metric_repository) | ||
| + metric_repository.current_values = mock.Mock(side_effect=self.current_values_side_effect) | ||
| + | ||
| + processes_list = cpu_process_memory_util.get_processes(1.34) | ||
| + | ||
| + self.assertEquals(len(processes_list),4) | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,38 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import unittest | ||
| +from mock import Mock | ||
| +import mock | ||
| +from pcp_pidstat import CpuProcessPriorities | ||
| + | ||
| + | ||
| +class TestCpuProcessPriorities(unittest.TestCase): | ||
| + | ||
| + def current_values_side_effect(self, metric): | ||
| + if metric == 'proc.psinfo.pid': | ||
| + return {1: 1, 2: 2, 5: 5, 10: 10} | ||
| + | ||
| + def test_get_processes(self): | ||
| + metric_repository = mock.Mock() | ||
| + cpu_process_priorities = CpuProcessPriorities(metric_repository) | ||
| + metric_repository.current_values = mock.Mock(side_effect=self.current_values_side_effect) | ||
| + | ||
| + processes_list = cpu_process_priorities.get_processes() | ||
| + | ||
| + self.assertEquals(len(processes_list),4) | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,38 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import unittest | ||
| +from mock import Mock | ||
| +import mock | ||
| +from pcp_pidstat import CpuProcessStackUtil | ||
| + | ||
| + | ||
| +class TestCpuProcessStackUtil(unittest.TestCase): | ||
| + | ||
| + def current_values_side_effect(self, metric): | ||
| + if metric == 'proc.psinfo.pid': | ||
| + return {1: 1, 2: 2, 5: 5, 10: 10} | ||
| + | ||
| + def test_get_processes(self): | ||
| + metric_repository = mock.Mock() | ||
| + cpu_process_stack_util = CpuProcessStackUtil(metric_repository) | ||
| + metric_repository.current_values = mock.Mock(side_effect=self.current_values_side_effect) | ||
| + | ||
| + processes_list = cpu_process_stack_util.get_processes() | ||
| + | ||
| + self.assertEquals(len(processes_list),4) | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,122 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import unittest | ||
| +from pcp_pidstat import CpuUsageReporter | ||
| + | ||
| +class TestCpuUsageReporter(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.options = Mock( | ||
| + per_processor_usage = False, | ||
| + show_process_user = None) | ||
| + | ||
| + process_1 = Mock(pid = Mock(return_value = 1), | ||
| + process_name = Mock(return_value = "process_1"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + user_id = Mock(return_value=1000), | ||
| + user_percent = Mock(return_value=2.43), | ||
| + system_percent = Mock(return_value=1.24), | ||
| + guest_percent = Mock(return_value=0.00), | ||
| + total_percent = Mock(return_value=3.67), | ||
| + cpu_number = Mock(return_value=1),) | ||
| + | ||
| + self.processes = [process_1] | ||
| + | ||
| + def test_print_report_without_filtering(self): | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t2.43\t1.24\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_user_name(self): | ||
| + self.options.show_process_user = 'pcp' | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\tpcp\t1\t2.43\t1.24\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_per_processor_usage(self): | ||
| + self.options.per_processor_usage = True | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t2.43\t1.24\t0.0\t0.92\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_user_percent_none(self): | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].user_percent = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\tNone\t1.24\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_guest_percent_none(self): | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].guest_percent = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t2.43\t1.24\tNone\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_system_percent_none(self): | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].system_percent = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t2.43\tNone\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_total_percent_none(self): | ||
| + cpu_usage = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].total_percent = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuUsageReporter(cpu_usage, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123, 4) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t2.43\t1.24\t0.0\tNone\t1\tprocess_1") | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,38 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import unittest | ||
| +from mock import Mock | ||
| +import mock | ||
| +from pcp_pidstat import CpuUsage | ||
| + | ||
| + | ||
| +class TestUserCpuUsage(unittest.TestCase): | ||
| + | ||
| + def current_values_side_effect(self, metric): | ||
| + if metric == 'proc.psinfo.pid': | ||
| + return {1: 1, 2: 2, 5: 5, 10: 10} | ||
| + | ||
| + def test_get_processes(self): | ||
| + metric_repository = mock.Mock() | ||
| + cpu_usage = CpuUsage(metric_repository) | ||
| + metric_repository.current_values = mock.Mock(side_effect=self.current_values_side_effect) | ||
| + | ||
| + processes_list = cpu_usage.get_processes(1.34) | ||
| + | ||
| + self.assertEquals(len(processes_list),4) | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,151 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import unittest | ||
| +from mock import Mock,MagicMock | ||
| +import mock | ||
| +from pcp_pidstat import ReportingMetricRepository | ||
| + | ||
| +class ReportingMetricRepositoryTest(unittest.TestCase): | ||
| + | ||
| + def test_returns_the_current_value_for_a_metric_that_has_instances(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.current_value('proc.psinfo.utime',111) | ||
| + | ||
| + self.assertEquals(c_utime,12345) | ||
| + | ||
| + def test_returns_the_current_value_for_a_metric_that_has_no_instances(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [('NULL',None,12345)], | ||
| + netPrevValues = [('NULL',None,12354)] | ||
| + ) | ||
| + group = {'kernel.all.cpu.user':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.current_value('kernel.all.cpu.user',None) | ||
| + | ||
| + self.assertEquals(c_utime,12345) | ||
| + | ||
| + def test_returns_none_if_a_metric_does_not_exist_for_an_instance(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.current_value('proc.psinfo.time',111) | ||
| + | ||
| + self.assertIsNone(c_utime) | ||
| + | ||
| + def test_returns_none_if_a_metric_does_not_exist_for_a_metric_that_has_no_instance(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [('NULL',None,12345)], | ||
| + netPrevValues = [('NULL',None,12354)] | ||
| + ) | ||
| + group = {'kernel.all.cpu.user':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.current_value('kernel.all.cpu.guest',None) | ||
| + | ||
| + self.assertIsNone(c_utime) | ||
| + | ||
| + def test_returns_the_previous_value_for_a_metric_that_has_instances(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.previous_value('proc.psinfo.utime',111) | ||
| + | ||
| + self.assertEquals(c_utime,12354) | ||
| + | ||
| + def test_returns_the_previous_value_for_a_metric_that_has_no_instances(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [('NULL',None,12345)], | ||
| + netPrevValues = [('NULL',None,12354)] | ||
| + ) | ||
| + group = {'kernel.all.cpu.user':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.previous_value('kernel.all.cpu.user',None) | ||
| + | ||
| + self.assertEquals(c_utime,12354) | ||
| + | ||
| + def test_returns_none_if_a_metric_for_previous_value_does_not_exist_for_an_instance(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.previous_value('proc.psinfo.time',111) | ||
| + | ||
| + self.assertIsNone(c_utime) | ||
| + | ||
| + def test_returns_none_if_a_metric_for_previous_value_does_not_exist_for_a_metric_that_has_no_instance(self): | ||
| + utime_mock = Mock( | ||
| + netValues = [('NULL',None,12345)], | ||
| + netPrevValues = [('NULL',None,12354)] | ||
| + ) | ||
| + group = {'kernel.all.cpu.user':utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + | ||
| + c_utime = m_repo.previous_value('kernel.all.cpu.guest',None) | ||
| + | ||
| + self.assertIsNone(c_utime) | ||
| + | ||
| + def test_checks_if_metric_values_are_fetched_only_once_if_not_available(self): | ||
| + proc_utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':proc_utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + fetch_call_count = 0 | ||
| + | ||
| + with mock.patch.object(m_repo,'_ReportingMetricRepository__fetch_current_values',return_value={111:12345}) as method: | ||
| + c_ptime = m_repo.current_value('proc.psinfo.utime',111) | ||
| + fetch_call_count = method.call_count | ||
| + | ||
| + self.assertEquals(fetch_call_count,1) | ||
| + | ||
| + def test_checks_if_metric_values_are_not_fetched_if_already_available(self): | ||
| + proc_utime_mock = Mock( | ||
| + netValues = [(Mock(inst=111),'dummyprocess',12345)], | ||
| + netPrevValues = [(Mock(inst=111),'dummyprocess',12354)] | ||
| + ) | ||
| + group = {'proc.psinfo.utime':proc_utime_mock} | ||
| + m_repo = ReportingMetricRepository(group) | ||
| + m_repo.current_cached_values = {'proc.psinfo.utime':{111:12354}} | ||
| + fetch_call_count = 0 | ||
| + | ||
| + with mock.patch.object(m_repo,'_ReportingMetricRepository__fetch_current_values',return_value={111:12345}) as method: | ||
| + c_ptime = m_repo.current_value('proc.psinfo.utime',111) | ||
| + fetch_call_count = method.call_count | ||
| + | ||
| + self.assertEquals(fetch_call_count,0) | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,40 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import unittest | ||
| +from mock import Mock | ||
| +from pcp_pidstat import NoneHandlingPrinterDecorator | ||
| +class TestNoneHandlingPrinterDecorator(unittest.TestCase): | ||
| + | ||
| + def test_print_report_without_none_values(self): | ||
| + printer = Mock() | ||
| + printer.Print = Mock() | ||
| + printer_decorator = NoneHandlingPrinterDecorator(printer) | ||
| + | ||
| + printer_decorator.Print("123\t1000\t1\t2.43\t1.24\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + printer.Print.assert_called_with("123\t1000\t1\t2.43\t1.24\t0.0\t3.67\t1\tprocess_1") | ||
| + | ||
| + def test_print_report_with_none_values(self): | ||
| + printer = Mock() | ||
| + printer.Print = Mock() | ||
| + printer_decorator = NoneHandlingPrinterDecorator(printer) | ||
| + | ||
| + printer_decorator.Print("123\t1000\t1\tNone\t1.24\t0.0\tNone\t1\tprocess_1") | ||
| + | ||
| + printer.Print.assert_called_with("123\t1000\t1\t?\t1.24\t0.0\t?\t1\tprocess_1") | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,43 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +log mandatory on 1 sec { | ||
| + pmda.uname | ||
| + hinv.ncpu | ||
| + proc.psinfo.pid | ||
| + proc.nprocs | ||
| + proc.psinfo.utime | ||
| + proc.psinfo.stime | ||
| + proc.psinfo.guest_time | ||
| + proc.psinfo.processor | ||
| + proc.id.uid | ||
| + proc.psinfo.cmd | ||
| + kernel.all.cpu.user | ||
| + kernel.all.cpu.vuser | ||
| + kernel.all.cpu.sys | ||
| + kernel.all.cpu.guest | ||
| + kernel.all.cpu.nice | ||
| + kernel.all.cpu.idle | ||
| + proc.id.uid_nm | ||
| + proc.psinfo.rt_priority | ||
| + proc.psinfo.policy | ||
| + proc.psinfo.minflt | ||
| + proc.psinfo.maj_flt | ||
| + proc.psinfo.vsize | ||
| + proc.psinfo.rss mem.physmem | ||
| + proc.psinfo.cmin_flt | ||
| + proc.psinfo.cmaj_flt | ||
| + proc.memory.vmstack | ||
| +} |
| @@ -0,0 +1 @@ | ||
| +../pcp-pidstat.py |
| @@ -0,0 +1,217 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import mock | ||
| +import unittest | ||
| +from pcp_pidstat import ProcessCpuUsage | ||
| + | ||
| +class TestProcessCpuUsage(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.__metric_repository = mock.Mock() | ||
| + self.__metric_repository.current_value = mock.Mock(side_effect=self.metric_repo_current_value_side_effect) | ||
| + self.__metric_repository.previous_value = mock.Mock(side_effect=self.metric_repo_previous_value_side_effect) | ||
| + | ||
| + def metric_repo_current_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.psinfo.utime' and instance == 1: | ||
| + return 112233 | ||
| + if metric_name == 'proc.psinfo.guest_time' and instance == 1: | ||
| + return 112213 | ||
| + if metric_name == 'proc.psinfo.stime' and instance == 1: | ||
| + return 112243 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 1: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.processor' and instance == 1: | ||
| + return 0 | ||
| + if metric_name == 'proc.id.uid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.id.uid_nm' and instance == 1: | ||
| + return "pcp" | ||
| + if metric_name == 'proc.psinfo.utime' and instance == 2: | ||
| + return 112233 | ||
| + if metric_name == 'proc.psinfo.guest_time' and instance == 2: | ||
| + return 112213 | ||
| + if metric_name == 'proc.psinfo.stime' and instance == 2: | ||
| + return 112243 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 2: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 2: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.processor' and instance == 2: | ||
| + return 0 | ||
| + if metric_name == 'proc.id.uid' and instance == 2: | ||
| + return 1 | ||
| + if metric_name == 'proc.id.uid_nm' and instance == 2: | ||
| + return "pcp" | ||
| + return None | ||
| + | ||
| + def metric_repo_previous_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.psinfo.utime' and instance == 1: | ||
| + return 112223 | ||
| + if metric_name == 'proc.psinfo.guest_time' and instance == 1: | ||
| + return 112203 | ||
| + if metric_name == 'proc.psinfo.stime' and instance == 1: | ||
| + return 112233 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 1: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.processor' and instance == 1: | ||
| + return 0 | ||
| + if metric_name == 'proc.id.uid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.id.uid_nm' and instance == 1: | ||
| + return "pcp" | ||
| + if metric_name == 'proc.psinfo.utime' and instance == 3: | ||
| + return 112223 | ||
| + if metric_name == 'proc.psinfo.guest_time' and instance == 3: | ||
| + return 112203 | ||
| + if metric_name == 'proc.psinfo.stime' and instance == 3: | ||
| + return 112233 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 3: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 3: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.processor' and instance == 3: | ||
| + return 0 | ||
| + if metric_name == 'proc.id.uid' and instance == 3: | ||
| + return 1 | ||
| + if metric_name == 'proc.id.uid_nm' and instance == 3: | ||
| + return "pcp" | ||
| + return None | ||
| + | ||
| + def test_user_percent(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + user_percent = process_cpu_usage.user_percent() | ||
| + | ||
| + self.assertEquals(user_percent, 0.75) | ||
| + | ||
| + def test_user_percent_if_current_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(3,1.34,self.__metric_repository) | ||
| + | ||
| + user_percent = process_cpu_usage.user_percent() | ||
| + | ||
| + self.assertIsNone(user_percent) | ||
| + | ||
| + def test_user_percent_if_previous_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(2,1.34,self.__metric_repository) | ||
| + | ||
| + user_percent = process_cpu_usage.user_percent() | ||
| + | ||
| + self.assertIsNone(user_percent) | ||
| + | ||
| + def test_guest_percent(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + guest_percent = process_cpu_usage.guest_percent() | ||
| + | ||
| + self.assertEquals(guest_percent, 0.75) | ||
| + | ||
| + def test_guest_percent_if_current_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(3,1.34,self.__metric_repository) | ||
| + | ||
| + guest_percent = process_cpu_usage.guest_percent() | ||
| + | ||
| + self.assertIsNone(guest_percent) | ||
| + | ||
| + def test_guest_percent_if_previous_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(2,1.34,self.__metric_repository) | ||
| + | ||
| + guest_percent = process_cpu_usage.guest_percent() | ||
| + | ||
| + self.assertIsNone(guest_percent) | ||
| + | ||
| + def test_system_percent(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + system_percent = process_cpu_usage.system_percent() | ||
| + | ||
| + self.assertEquals(system_percent, 0.75) | ||
| + | ||
| + def test_system_percent_if_current_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(3,1.34,self.__metric_repository) | ||
| + | ||
| + system_percent = process_cpu_usage.system_percent() | ||
| + | ||
| + self.assertIsNone(system_percent, None) | ||
| + | ||
| + def test_system_percent_if_previous_value_is_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(2,1.34,self.__metric_repository) | ||
| + | ||
| + system_percent = process_cpu_usage.system_percent() | ||
| + | ||
| + self.assertIsNone(system_percent, None) | ||
| + | ||
| + def test_total_percent(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + total_percent = process_cpu_usage.total_percent() | ||
| + | ||
| + self.assertEquals(total_percent, 2.25) | ||
| + | ||
| + def test_total_percent_if_current_value_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(3,1.34,self.__metric_repository) | ||
| + | ||
| + total_percent = process_cpu_usage.total_percent() | ||
| + | ||
| + self.assertIsNone(total_percent, None) | ||
| + | ||
| + def test_total_percent_if_previous_value_None(self): | ||
| + process_cpu_usage = ProcessCpuUsage(2,1.34,self.__metric_repository) | ||
| + | ||
| + total_percent = process_cpu_usage.total_percent() | ||
| + | ||
| + self.assertIsNone(total_percent, None) | ||
| + | ||
| + def test_pid(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + pid = process_cpu_usage.pid() | ||
| + | ||
| + self.assertEqual(pid,1) | ||
| + | ||
| + def test_process_name(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + name = process_cpu_usage.process_name() | ||
| + | ||
| + self.assertEqual(name,'test') | ||
| + | ||
| + def test_cpu_number(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + number = process_cpu_usage.cpu_number() | ||
| + | ||
| + self.assertEqual(number,0) | ||
| + | ||
| + def test_user_id(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + user_id = process_cpu_usage.user_id() | ||
| + | ||
| + self.assertEqual(user_id,1) | ||
| + | ||
| + def test_user_name(self): | ||
| + process_cpu_usage = ProcessCpuUsage(1,1.34,self.__metric_repository) | ||
| + | ||
| + user_name = process_cpu_usage.user_name() | ||
| + | ||
| + self.assertEqual(user_name,'pcp') | ||
| + | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,109 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import unittest | ||
| +from pcp_pidstat import ProcessFilter | ||
| + | ||
| +class TestProcessFilter(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.options = Mock(process_name = None, | ||
| + show_process_memory_util = False, | ||
| + show_process_priority = False, | ||
| + show_process_stack_util = False, | ||
| + per_processor_usage = False, | ||
| + show_process_user = False, | ||
| + filtered_process_user = None, | ||
| + pid_filter = None, | ||
| + pid_list = []) | ||
| + | ||
| + self.process_1 = Mock(pid = Mock(return_value = 1), | ||
| + process_name = Mock(return_value = "process_1"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + vsize = Mock(return_value=136), | ||
| + priority = Mock(return_value=99), | ||
| + stack_size = Mock(return_value=123),) | ||
| + self.process_2 = Mock(pid = Mock(return_value = 2), | ||
| + process_name = Mock(return_value = "process_two"), | ||
| + user_name = Mock(return_value='pcp1'), | ||
| + vsize = Mock(return_value=136), | ||
| + priority = Mock(return_value=0), | ||
| + stack_size = Mock(return_value=0),) | ||
| + self.process_3 = Mock(pid = Mock(return_value = 3), | ||
| + process_name = Mock(return_value = "proc_3"), | ||
| + user_name = Mock(return_value='pcp1'), | ||
| + vsize = Mock(return_value=0), | ||
| + priority = Mock(return_value=99), | ||
| + stack_size = Mock(return_value=0),) | ||
| + self.process_4 = Mock(pid = Mock(return_value = 4), | ||
| + process_name = Mock(return_value = "a_short_process"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + vsize = Mock(return_value=0), | ||
| + priority = Mock(return_value=0), | ||
| + stack_size = Mock(return_value=50),) | ||
| + | ||
| + self.processes = [self.process_1, self.process_2, self.process_3, self.process_4] | ||
| + | ||
| + def test_filter_processes_for_given_user_name(self): | ||
| + self.options.filtered_process_user = 'pcp1' | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_2,self.process_3]) | ||
| + | ||
| + def test_filter_processes_for_given_process_name(self): | ||
| + self.options.process_name = 'process' | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_1, self.process_2, self.process_4]) | ||
| + | ||
| + def test_filter_processes_for_given_pid_list(self): | ||
| + self.options.pid_filter = 'ALL' | ||
| + self.options.pid_list = [1,4] | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_1,self.process_4]) | ||
| + | ||
| + def test_filter_processes_for_process_vsize(self): | ||
| + self.options.show_process_memory_util = True | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_1,self.process_2]) | ||
| + | ||
| + def test_filter_processes_for_process_priority(self): | ||
| + self.options.show_process_priority = True | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_1,self.process_3]) | ||
| + | ||
| + def test_filter_processes_for_process_stack_size(self): | ||
| + self.options.show_process_stack_util = True | ||
| + processs_filter = ProcessFilter(self.options) | ||
| + | ||
| + test_filtered_processes = processs_filter.filter_processes(self.processes) | ||
| + | ||
| + self.assertEqual(test_filtered_processes,[self.process_1,self.process_4]) | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,85 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import unittest | ||
| +from pcp_pidstat import CpuProcessMemoryUtilReporter | ||
| + | ||
| +class TestProcessMemoryUtilReporter(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.options = Mock( | ||
| + show_process_user = None) | ||
| + | ||
| + process_1 = Mock(pid = Mock(return_value = 1), | ||
| + process_name = Mock(return_value = "process_1"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + user_id = Mock(return_value=1000), | ||
| + minflt = Mock(return_value=9.10), | ||
| + majflt = Mock(return_value=5.34), | ||
| + vsize = Mock(return_value=100), | ||
| + rss = Mock(return_value=200), | ||
| + mem = Mock(return_value=1.23)) | ||
| + | ||
| + self.processes = [process_1] | ||
| + | ||
| + def test_print_report_without_filtering(self): | ||
| + process_memory_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessMemoryUtilReporter(process_memory_util, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t9.1\t\t5.34\t\t100\t200\t1.23\tprocess_1") | ||
| + | ||
| + def test_print_report_with_min_flt_None(self): | ||
| + process_memory_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].minflt = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessMemoryUtilReporter(process_memory_util, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\tNone\t\t5.34\t\t100\t200\t1.23\tprocess_1") | ||
| + | ||
| + def test_print_report_with_maj_flt_None(self): | ||
| + process_memory_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + self.processes[0].majflt = Mock(return_value=None) | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessMemoryUtilReporter(process_memory_util, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t9.1\t\tNone\t\t100\t200\t1.23\tprocess_1") | ||
| + | ||
| + def test_print_report_with_user_name(self): | ||
| + self.options.show_process_user = 'pcp' | ||
| + process_memory_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessMemoryUtilReporter(process_memory_util, process_filter, 1, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with('123\tpcp\t1\t9.1\t\t5.34\t\t100\t200\t1.23\tprocess_1') | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,162 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import mock | ||
| +import unittest | ||
| +from pcp_pidstat import ProcessMemoryUtil | ||
| + | ||
| +class TestProcessMemoryUtil(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.__metric_repository = mock.Mock() | ||
| + self.__metric_repository.current_value = mock.Mock(side_effect=self.metric_repo_current_value_side_effect) | ||
| + self.__metric_repository.previous_value = mock.Mock(side_effect=self.metric_repo_previous_value_side_effect) | ||
| + | ||
| + def metric_repo_current_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.psinfo.vsize' and instance == 1: | ||
| + return 120084 | ||
| + if metric_name == 'proc.psinfo.rss' and instance == 1: | ||
| + return 6272 | ||
| + if metric_name == 'proc.psinfo.minflt' and instance == 1: | ||
| + return 14509 | ||
| + if metric_name == 'proc.psinfo.maj_flt' and instance == 1: | ||
| + return 54 | ||
| + if metric_name == 'mem.physmem': | ||
| + return 3794764 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 1: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.processor' and instance == 1: | ||
| + return 0 | ||
| + if metric_name == 'proc.id.uid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.vsize' and instance == 2: | ||
| + return 120084 | ||
| + if metric_name == 'proc.psinfo.rss' and instance == 2: | ||
| + return 6272 | ||
| + if metric_name == 'proc.psinfo.minflt' and instance == 2: | ||
| + return 14509 | ||
| + if metric_name == 'proc.psinfo.maj_flt' and instance == 2: | ||
| + return 54 | ||
| + return None | ||
| + | ||
| + def metric_repo_previous_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.psinfo.cmin_flt' and instance == 1: | ||
| + return 573930 | ||
| + if metric_name == 'proc.psinfo.minflt' and instance == 1: | ||
| + return 14500 | ||
| + if metric_name == 'proc.psinfo.cmaj_flt' and instance == 1: | ||
| + return 645 | ||
| + if metric_name == 'proc.psinfo.maj_flt' and instance == 1: | ||
| + return 50 | ||
| + if metric_name == 'proc.psinfo.cmin_flt' and instance == 3: | ||
| + return 573930 | ||
| + if metric_name == 'proc.psinfo.minflt' and instance == 3: | ||
| + return 14500 | ||
| + if metric_name == 'proc.psinfo.cmaj_flt' and instance == 3: | ||
| + return 645 | ||
| + if metric_name == 'proc.psinfo.maj_flt' and instance == 3: | ||
| + return 50 | ||
| + return None | ||
| + | ||
| + def test_vsize(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + vsize = process_memory_usage.vsize() | ||
| + | ||
| + self.assertEquals(vsize, 120084) | ||
| + | ||
| + def test_rss(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + rss = process_memory_usage.rss() | ||
| + | ||
| + self.assertEquals(rss, 6272) | ||
| + | ||
| + def test_mem(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + mem = process_memory_usage.mem() | ||
| + | ||
| + self.assertEquals(mem, 0.17) | ||
| + | ||
| + def test_min_flt(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + min_flt = process_memory_usage.minflt() | ||
| + | ||
| + self.assertEquals(min_flt, 6.72) | ||
| + | ||
| + def test_min_flt_if_current_value_is_None(self): | ||
| + process_memory_usage = ProcessMemoryUtil(3,1.34,self.__metric_repository) | ||
| + | ||
| + min_flt = process_memory_usage.minflt() | ||
| + | ||
| + self.assertIsNone(min_flt) | ||
| + | ||
| + def test_min_flt_if_previous_value_is_None(self): | ||
| + process_memory_usage = ProcessMemoryUtil(2,1.34,self.__metric_repository) | ||
| + | ||
| + min_flt = process_memory_usage.minflt() | ||
| + | ||
| + self.assertIsNone(min_flt) | ||
| + | ||
| + def test_maj_flt(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + maj_flt = process_memory_usage.majflt() | ||
| + | ||
| + self.assertEquals(maj_flt, 2.99) | ||
| + | ||
| + def test_maj_flt_if_current_value_is_None(self): | ||
| + process_memory_usage = ProcessMemoryUtil(3,1.34,self.__metric_repository) | ||
| + | ||
| + maj_flt = process_memory_usage.majflt() | ||
| + | ||
| + self.assertIsNone(maj_flt) | ||
| + | ||
| + | ||
| + def test_maj_flt_if_previous_value_is_None(self): | ||
| + process_memory_usage = ProcessMemoryUtil(2,1.34,self.__metric_repository) | ||
| + | ||
| + maj_flt = process_memory_usage.majflt() | ||
| + | ||
| + self.assertIsNone(maj_flt) | ||
| + | ||
| + def test_pid(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + pid = process_memory_usage.pid() | ||
| + | ||
| + self.assertEqual(pid,1) | ||
| + | ||
| + def test_process_name(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + name = process_memory_usage.process_name() | ||
| + | ||
| + self.assertEqual(name,'test') | ||
| + | ||
| + | ||
| + def test_user_id(self): | ||
| + process_memory_usage = ProcessMemoryUtil(1,1.34,self.__metric_repository) | ||
| + | ||
| + user_id = process_memory_usage.user_id() | ||
| + | ||
| + self.assertEqual(user_id,1) | ||
| + | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,58 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import unittest | ||
| +from pcp_pidstat import CpuProcessPrioritiesReporter | ||
| + | ||
| +class TestProcessPriorityReporter(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.options = Mock( | ||
| + show_process_user = None) | ||
| + | ||
| + process_1 = Mock(pid = Mock(return_value = 1), | ||
| + process_name = Mock(return_value = "process_1"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + user_id = Mock(return_value=1000), | ||
| + priority = Mock(return_value=99), | ||
| + policy = Mock(return_value='FIFO')) | ||
| + | ||
| + self.processes = [process_1] | ||
| + | ||
| + def test_print_report_without_filtering(self): | ||
| + process_priority = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessPrioritiesReporter(process_priority, process_filter, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t99\tFIFO\tprocess_1") | ||
| + | ||
| + def test_print_report_with_user_name(self): | ||
| + self.options.show_process_user = 'pcp' | ||
| + process_priority = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessPrioritiesReporter(process_priority, process_filter, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\tpcp\t1\t99\tFIFO\tprocess_1") | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,73 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import mock | ||
| +import unittest | ||
| +from pcp_pidstat import ProcessPriority | ||
| + | ||
| +class TestProcessPriority(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.__metric_repository = mock.Mock() | ||
| + self.__metric_repository.current_value = mock.Mock(side_effect=self.metric_repo_current_value_side_effect) | ||
| + | ||
| + def metric_repo_current_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.id.uid' and instance == 1: | ||
| + return 0 | ||
| + if metric_name == 'proc.psinfo.rt_priority' and instance == 1: | ||
| + return 99 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 1: | ||
| + return "test" | ||
| + if metric_name == 'proc.psinfo.policy' and instance == 1: | ||
| + return 1 | ||
| + | ||
| + def test_pid(self): | ||
| + process_priority = ProcessPriority(1,self.__metric_repository) | ||
| + | ||
| + pid = process_priority.pid() | ||
| + | ||
| + self.assertEqual(pid,1) | ||
| + | ||
| + def test_process_name(self): | ||
| + process_priority = ProcessPriority(1,self.__metric_repository) | ||
| + | ||
| + name = process_priority.process_name() | ||
| + | ||
| + self.assertEqual(name,'test') | ||
| + | ||
| + def test_policy(self): | ||
| + process_priority = ProcessPriority(1,self.__metric_repository) | ||
| + | ||
| + policy = process_priority.policy() | ||
| + | ||
| + self.assertEqual(policy,'FIFO') | ||
| + | ||
| + def test_user_id(self): | ||
| + process_priority = ProcessPriority(1,self.__metric_repository) | ||
| + | ||
| + user_id = process_priority.user_id() | ||
| + | ||
| + self.assertEqual(user_id,0) | ||
| + | ||
| + def test_priority(self): | ||
| + process_priority = ProcessPriority(1,self.__metric_repository) | ||
| + | ||
| + priority = process_priority.priority() | ||
| + | ||
| + self.assertEqual(priority,99) | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |
| @@ -0,0 +1,57 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +from mock import Mock | ||
| +import unittest | ||
| +from pcp_pidstat import CpuProcessStackUtilReporter | ||
| + | ||
| +class TestProcessStackUtilReporter(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.options = Mock( | ||
| + show_process_user = None) | ||
| + | ||
| + process_1 = Mock(pid = Mock(return_value = 1), | ||
| + process_name = Mock(return_value = "process_1"), | ||
| + user_name = Mock(return_value='pcp'), | ||
| + user_id = Mock(return_value=1000), | ||
| + stack_size = Mock(return_value=136)) | ||
| + | ||
| + self.processes = [process_1] | ||
| + | ||
| + def test_print_report_without_filtering(self): | ||
| + process_stack_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessStackUtilReporter(process_stack_util, process_filter, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\t1000\t1\t136\tprocess_1") | ||
| + | ||
| + def test_print_report_with_user_name(self): | ||
| + self.options.show_process_user = 'pcp' | ||
| + process_stack_util = Mock() | ||
| + process_filter = Mock() | ||
| + printer = Mock() | ||
| + process_filter.filter_processes = Mock(return_value=self.processes) | ||
| + reporter = CpuProcessStackUtilReporter(process_stack_util, process_filter, printer, self.options) | ||
| + | ||
| + reporter.print_report(123) | ||
| + | ||
| + printer.assert_called_with("123\tpcp\t1\t136\tprocess_1") | ||
| + | ||
| +if __name__ == "__main__": | ||
| + unittest.main() |
| @@ -0,0 +1,69 @@ | ||
| +#!/usr/bin/env pmpython | ||
| +# | ||
| +# Copyright (C) 2016 Sitaram Shelke. | ||
| +# | ||
| +# This program is free software; you can redistribute it and/or modify it | ||
| +# under the terms of the GNU General Public License as published by the | ||
| +# Free Software Foundation; either version 2 of the License, or (at your | ||
| +# option) any later version. | ||
| +# | ||
| +# This program 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 General Public License | ||
| +# for more details. | ||
| +# | ||
| + | ||
| +import mock | ||
| +import unittest | ||
| +from pcp_pidstat import ProcessStackUtil | ||
| + | ||
| +class TestProcessStackUtil(unittest.TestCase): | ||
| + def setUp(self): | ||
| + self.__metric_repository = mock.Mock() | ||
| + self.__metric_repository.current_value = mock.Mock(side_effect=self.metric_repo_current_value_side_effect) | ||
| + | ||
| + def metric_repo_current_value_side_effect(self, metric_name,instance): | ||
| + if metric_name == 'proc.memory.vmstack' and instance == 1: | ||
| + return 136 | ||
| + if metric_name == 'proc.psinfo.cmd' and instance == 1: | ||
| + return "test" | ||
| + if metric_name == 'proc.id.uid' and instance == 1: | ||
| + return 1 | ||
| + if metric_name == 'proc.psinfo.pid' and instance == 1: | ||
| + return 1 | ||
| + | ||
| + def test_stack_size(self): | ||
| + process_stack_usage = ProcessStackUtil(1,self.__metric_repository) | ||
| + | ||
| + stack_size = process_stack_usage.stack_size() | ||
| + | ||
| + self.assertEquals(stack_size, 136) | ||
| + | ||
| + def test_stack_referenced_size(self): | ||
| + self.skipTest(reason="Implement when suitable metric is found") | ||
| + | ||
| + def test_pid(self): | ||
| + process_stack_usage = ProcessStackUtil(1,self.__metric_repository) | ||
| + | ||
| + pid = process_stack_usage.pid() | ||
| + | ||
| + self.assertEqual(pid,1) | ||
| + | ||
| + def test_process_name(self): | ||
| + process_stack_usage = ProcessStackUtil(1,self.__metric_repository) | ||
| + | ||
| + name = process_stack_usage.process_name() | ||
| + | ||
| + self.assertEqual(name,'test') | ||
| + | ||
| + | ||
| + def test_user_id(self): | ||
| + process_stack_usage = ProcessStackUtil(1,self.__metric_repository) | ||
| + | ||
| + user_id = process_stack_usage.user_id() | ||
| + | ||
| + self.assertEqual(user_id,1) | ||
| + | ||
| + | ||
| +if __name__ == '__main__': | ||
| + unittest.main() |