Merge lp:~canonical-platform-qa/autopilot/fixing_pid_search_1569079 into lp:autopilot

Proposed by Christopher Lee
Status: Merged
Approved by: Christopher Lee
Approved revision: 579
Merged at revision: 577
Proposed branch: lp:~canonical-platform-qa/autopilot/fixing_pid_search_1569079
Merge into: lp:autopilot
Diff against target: 155 lines (+119/-1)
2 files modified
autopilot/introspection/_search.py (+42/-0)
autopilot/tests/unit/test_introspection_search.py (+77/-1)
To merge this branch: bzr merge lp:~canonical-platform-qa/autopilot/fixing_pid_search_1569079
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Thomi Richards (community) Approve
platform-qa-bot continuous-integration Approve
Autopilot Hackers Pending
Review via email: mp+291568@code.launchpad.net

Commit message

Add a final filter that ignores any children processes if the parent process matches and the supplied pid is the parents.

Description of the change

It's possible that a parent process spawns a child process that will match an attempt to get a proxy object for the parent.

Add a final filter that ignores any children processes if the parent process matches and the supplied pid is the parents.

To post a comment you must log in.
Revision history for this message
Max Brustkern (nuclearbob) wrote :

Seems reasonable to me, once we get a good test of it.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Needs Fixing (continuous-integration)
578. By Christopher Lee

Fix minor flake8 issue.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
579. By Christopher Lee

Refactor to remove mock in test and potentially reduce calls to get pid details.

Revision history for this message
platform-qa-bot (platform-qa-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'autopilot/introspection/_search.py'
--- autopilot/introspection/_search.py 2016-01-22 17:21:36 +0000
+++ autopilot/introspection/_search.py 2016-04-12 03:02:16 +0000
@@ -171,6 +171,16 @@
171 process171 process
172 )172 )
173173
174 if pid is not None:
175 # Due to the filtering including children parents, if there exists a
176 # top-level pid, take that instead of any children that may have
177 # matched.
178 connections = _filter_parent_pids_from_children(
179 pid,
180 connections,
181 dbus_bus
182 )
183
174 _raise_if_not_single_result(184 _raise_if_not_single_result(
175 connections,185 connections,
176 _get_search_criteria_string_representation(**kwargs)186 _get_search_criteria_string_representation(**kwargs)
@@ -184,6 +194,38 @@
184 )194 )
185195
186196
197def _map_connection_to_pid(connection, dbus_bus):
198 try:
199 return _get_bus_connections_pid(dbus_bus, connection)
200 except dbus.DBusException as e:
201 logger.info(
202 "dbus.DBusException while attempting to get PID for %s: %r" %
203 (connection, e))
204
205
206def _filter_parent_pids_from_children(
207 pid, connections, dbus_bus, _connection_pid_fn=_map_connection_to_pid):
208 """Return any connections that have an actual pid matching the requested
209 and aren't just a child of that requested pid.
210
211 :param pid: Pid passed in for matching
212 :param connections: List of connections to filter
213 :param dbus_bus: Dbus object that the connections are contained.
214 :param _connection_pid_fn: Function that takes 2 args 'connection' 'dbus
215 object' that returns the pid (or None if not found) of the connection on
216 that dbus bus.
217 (Note: Useful for testing.)
218 :returns: List of suitable connections (e.g. returns what was passed if no
219 connections match the pid (i.e. all matches are children)).
220
221 """
222 for conn in connections:
223 if pid == _connection_pid_fn(conn, dbus_bus):
224 logger.info('Found the parent pid, ignoring any others.')
225 return [conn]
226 return connections
227
228
187def _get_dbus_bus_from_string(dbus_string):229def _get_dbus_bus_from_string(dbus_string):
188 if dbus_string == 'session':230 if dbus_string == 'session':
189 return dbus_handler.get_session_bus()231 return dbus_handler.get_session_bus()
190232
=== modified file 'autopilot/tests/unit/test_introspection_search.py'
--- autopilot/tests/unit/test_introspection_search.py 2015-06-16 02:39:23 +0000
+++ autopilot/tests/unit/test_introspection_search.py 2016-04-12 03:02:16 +0000
@@ -19,7 +19,7 @@
1919
20from dbus import DBusException20from dbus import DBusException
21import os21import os
22from unittest.mock import patch, Mock22from unittest.mock import call, patch, Mock
23from testtools import TestCase23from testtools import TestCase
24from testtools.matchers import (24from testtools.matchers import (
25 Contains,25 Contains,
@@ -581,6 +581,82 @@
581 self.assertEqual(fake_process.pid, observed)581 self.assertEqual(fake_process.pid, observed)
582582
583583
584class FilterParentPidsFromChildrenTests(TestCase):
585
586 def test_returns_all_connections_with_no_parent_match(self):
587 search_pid = 123
588 connections = ['1:0', '1:3']
589 dbus_bus = Mock()
590 pid_mapping = Mock(side_effect=[111, 222])
591 self.assertThat(
592 _s._filter_parent_pids_from_children(
593 search_pid,
594 connections,
595 dbus_bus,
596 _connection_pid_fn=pid_mapping
597 ),
598 Equals(connections)
599 )
600
601 def test_calls_connection_pid_fn_in_order(self):
602 search_pid = 123
603 connections = ['1:3', '1:0']
604 dbus_bus = Mock()
605 pid_mapping = Mock(side_effect=[222, 123])
606 _s._filter_parent_pids_from_children(
607 search_pid,
608 connections,
609 dbus_bus,
610 _connection_pid_fn=pid_mapping
611 )
612
613 self.assertTrue(
614 pid_mapping.call_args_list == [
615 call('1:3', dbus_bus),
616 call('1:0', dbus_bus)
617 ]
618 )
619
620 def test_returns_just_parent_connection_with_pid_match(self):
621 search_pid = 123
622 # connection '1.0' has pid 123.
623 connections = ['1:3', '1:0']
624 dbus_bus = Mock()
625 # Mapping returns parent pid on second call.
626 pid_mapping = Mock(side_effect=[222, 123])
627 self.assertThat(
628 _s._filter_parent_pids_from_children(
629 search_pid,
630 connections,
631 dbus_bus,
632 _connection_pid_fn=pid_mapping
633 ),
634 Equals(['1:0'])
635 )
636
637 self.assertTrue(
638 pid_mapping.call_args_list == [
639 call('1:3', dbus_bus),
640 call('1:0', dbus_bus)
641 ]
642 )
643
644 def test_returns_all_connections_with_no_pids_returned_in_search(self):
645 search_pid = 123
646 connections = ['1:3', '1:0']
647 dbus_bus = Mock()
648 pid_mapping = Mock(side_effect=[None, None])
649 self.assertThat(
650 _s._filter_parent_pids_from_children(
651 search_pid,
652 connections,
653 dbus_bus,
654 _connection_pid_fn=pid_mapping
655 ),
656 Equals(connections)
657 )
658
659
584class ProcessSearchErrorStringRepTests(TestCase):660class ProcessSearchErrorStringRepTests(TestCase):
585661
586 """Various tests for the _get_search_criteria_string_representation662 """Various tests for the _get_search_criteria_string_representation

Subscribers

People subscribed via source and target branches