rpc-window: code style adjustments

QubesOS/qubes-issues#910
This commit is contained in:
Marek Marczykowski-Górecki 2017-03-22 16:27:14 +01:00
parent b3ceb2d7fa
commit ab1bd77b45
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
5 changed files with 178 additions and 141 deletions

View File

@ -19,14 +19,16 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import qubes import gi
import gi, os import os
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GObject, GLib from gi.repository import Gtk, Gdk, GdkPixbuf, GObject, GLib
from . qubesutils import sanitize_domain_name import qubes
from qubespolicy.utils import sanitize_domain_name
glade_directory = os.path.join(os.path.dirname(__file__), "glade") glade_directory = os.path.join(os.path.dirname(__file__), "glade")
class GtkIconGetter: class GtkIconGetter:
def __init__(self, size): def __init__(self, size):
self._icons = {} self._icons = {}
@ -44,6 +46,7 @@ class GtkIconGetter:
return self._icons[name] return self._icons[name]
class VMListModeler: class VMListModeler:
def __init__(self): def __init__(self):
self._icon_getter = GtkIconGetter(16) self._icon_getter = GtkIconGetter(16)
@ -68,7 +71,7 @@ class VMListModeler:
def _create_entries(self): def _create_entries(self):
for vm in self._get_list(): for vm in self._get_list():
sanitize_domain_name(vm.name, assert_sanitized = True) sanitize_domain_name(vm.name, assert_sanitized=True)
icon = self._get_icon(vm) icon = self._get_icon(vm)
@ -120,13 +123,13 @@ class VMListModeler:
if name: if name:
activation_trigger(entry_box) activation_trigger(entry_box)
def apply_model(self, destination_object, vm_filter_list = None, def apply_model(self, destination_object, vm_filter_list=None,
selection_trigger = None, activation_trigger = None): selection_trigger=None, activation_trigger=None):
if isinstance(destination_object, Gtk.ComboBox): if isinstance(destination_object, Gtk.ComboBox):
list_store = Gtk.ListStore(int, str, GdkPixbuf.Pixbuf) list_store = Gtk.ListStore(int, str, GdkPixbuf.Pixbuf)
exclusions = [] exclusions = []
for vm_name in sorted(self._entries.iterkeys()): for vm_name in sorted(self._entries.keys()):
entry = self._entries[vm_name] entry = self._entries[vm_name]
matches = True matches = True
@ -223,6 +226,7 @@ class VMListModeler:
def matches(self, vm): def matches(self, vm):
return vm.name in self._allowed_names_list return vm.name in self._allowed_names_list
class GtkOneTimerHelper: class GtkOneTimerHelper:
def __init__(self, wait_seconds): def __init__(self, wait_seconds):
self._wait_seconds = wait_seconds self._wait_seconds = wait_seconds
@ -254,8 +258,9 @@ class GtkOneTimerHelper:
def _timer_has_completed(self): def _timer_has_completed(self):
return self._timer_completed return self._timer_completed
class FocusStealingHelper(GtkOneTimerHelper): class FocusStealingHelper(GtkOneTimerHelper):
def __init__(self, window, target_button, wait_seconds = 1): def __init__(self, window, target_button, wait_seconds=1):
GtkOneTimerHelper.__init__(self, wait_seconds) GtkOneTimerHelper.__init__(self, wait_seconds)
self._window = window self._window = window
self._target_button = target_button self._target_button = target_button
@ -298,4 +303,3 @@ class FocusStealingHelper(GtkOneTimerHelper):
def can_perform_action(self): def can_perform_action(self):
return self._timer_has_completed() return self._timer_has_completed()

View File

@ -19,25 +19,29 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
from . gtkhelpers import VMListModeler, FocusStealingHelper, glade_directory
from . qubesutils import sanitize_domain_name, sanitize_service_name
from gi.repository import Gtk, Gdk, GLib from gi.repository import Gtk, Gdk, GLib
import os import os
from qubespolicy.gtkhelpers import VMListModeler, FocusStealingHelper, \
glade_directory
from qubespolicy.utils import sanitize_domain_name, \
sanitize_service_name
class RPCConfirmationWindow():
class RPCConfirmationWindow:
_source_file = os.path.join(glade_directory, "RPCConfirmationWindow.glade") _source_file = os.path.join(glade_directory, "RPCConfirmationWindow.glade")
_source_id = { 'window': "RPCConfirmationWindow", _source_id = {'window': "RPCConfirmationWindow",
'ok': "okButton", 'ok': "okButton",
'cancel': "cancelButton", 'cancel': "cancelButton",
'source': "sourceEntry", 'source': "sourceEntry",
'rpc_label' : "rpcLabel", 'rpc_label': "rpcLabel",
'target': "TargetCombo", 'target': "TargetCombo",
'error_bar': "ErrorBar", 'error_bar': "ErrorBar",
'error_message': "ErrorMessage", 'error_message': "ErrorMessage",
} }
def _clicked_ok(self, source): def _clicked_ok(self, source):
assert source != None, \ assert source is not None, \
'Called the clicked ok callback from no source object' 'Called the clicked ok callback from no source object'
if self._can_perform_action(): if self._can_perform_action():
@ -62,7 +66,7 @@ class RPCConfirmationWindow():
self._close() self._close()
def _update_ok_button_sensitivity(self, data): def _update_ok_button_sensitivity(self, data):
valid = (data != None) valid = (data is not None)
if valid: if valid:
(self._target_qid, self._target_name) = data (self._target_qid, self._target_name) = data
@ -79,12 +83,13 @@ class RPCConfirmationWindow():
def _close_error(self, error_bar, response): def _close_error(self, error_bar, response):
assert error_bar == self._error_bar, \ assert error_bar == self._error_bar, \
'Closed the error bar with the wrong error bar as parameter' 'Closed the error bar with the wrong error bar as parameter'
assert response != None, 'Closed the error bar with None as a response' assert response is not None, \
'Closed the error bar with None as a response'
self._error_bar.set_visible(False) self._error_bar.set_visible(False)
def _set_initial_target(self, source, target): def _set_initial_target(self, source, target):
if target != None: if target is not None:
if target == source: if target == source:
self._show_error( self._show_error(
"Source and target domains must not be the same.") "Source and target domains must not be the same.")
@ -121,15 +126,15 @@ class RPCConfirmationWindow():
return formatted return formatted
def _connect_events(self): def _connect_events(self):
self._rpc_window.connect("key-press-event",self._key_pressed) self._rpc_window.connect("key-press-event", self._key_pressed)
self._rpc_ok_button.connect("clicked", self._clicked_ok) self._rpc_ok_button.connect("clicked", self._clicked_ok)
self._rpc_cancel_button.connect("clicked", self._clicked_cancel) self._rpc_cancel_button.connect("clicked", self._clicked_cancel)
self._error_bar.connect("response", self._close_error) self._error_bar.connect("response", self._close_error)
def __init__(self, source, rpc_operation, name_whitelist, target = None): def __init__(self, source, rpc_operation, name_whitelist, target=None):
sanitize_domain_name(source, assert_sanitized = True) sanitize_domain_name(source, assert_sanitized=True)
sanitize_service_name(source, assert_sanitized = True) sanitize_service_name(source, assert_sanitized=True)
self._gtk_builder = Gtk.Builder() self._gtk_builder = Gtk.Builder()
self._gtk_builder.add_from_file(self._source_file) self._gtk_builder.add_from_file(self._source_file)
@ -162,8 +167,8 @@ class RPCConfirmationWindow():
domain_filters = [VMListModeler.NameWhitelistFilter(name_whitelist)] domain_filters = [VMListModeler.NameWhitelistFilter(name_whitelist)]
list_modeler.apply_model(self._rpc_combo_box, domain_filters, list_modeler.apply_model(self._rpc_combo_box, domain_filters,
selection_trigger = self._update_ok_button_sensitivity, selection_trigger=self._update_ok_button_sensitivity,
activation_trigger = self._clicked_ok ) activation_trigger=self._clicked_ok)
self._source_entry.set_text(source) self._source_entry.set_text(source)
list_modeler.apply_icon(self._source_entry, source) list_modeler.apply_icon(self._source_entry, source)
@ -197,12 +202,13 @@ class RPCConfirmationWindow():
self._show() self._show()
if self._confirmed: if self._confirmed:
return { 'name': self._target_name, 'qid': self._target_qid, return {'name': self._target_name, 'qid': self._target_qid,
'parameters': {} } 'parameters': {}}
else: else:
return False return False
def confirm_rpc(source, rpc_operation, name_whitelist, target = None):
def confirm_rpc(source, rpc_operation, name_whitelist, target=None):
window = RPCConfirmationWindow(source, rpc_operation, name_whitelist, window = RPCConfirmationWindow(source, rpc_operation, name_whitelist,
target) target)

View File

@ -19,41 +19,52 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import unittest, time import time
from core.gtkhelpers import VMListModeler, GtkOneTimerHelper, FocusStealingHelper, Gtk import unittest
from gi.repository import Gtk
from qubespolicy.gtkhelpers import VMListModeler, GtkOneTimerHelper, \
FocusStealingHelper
class VMListModelerMock(VMListModeler): class VMListModelerMock(VMListModeler):
def __init__(self): def __init__(self):
VMListModeler.__init__(self) VMListModeler.__init__(self)
def _get_list(self): def _get_list(self):
return [ MockVm(0, "dom0", "black"), return [
MockVm(2, "test-red1", "red"), MockVm(0, "dom0", "black"),
MockVm(4, "test-red2", "red"), MockVm(2, "test-red1", "red"),
MockVm(7, "test-red3", "red"), MockVm(4, "test-red2", "red"),
MockVm(8, "test-source", "green"), MockVm(7, "test-red3", "red"),
MockVm(10, "test-target", "orange"), MockVm(8, "test-source", "green"),
MockVm(15, "test-disp6", "red", True) ] MockVm(10, "test-target", "orange"),
MockVm(15, "test-disp6", "red", True)
]
@staticmethod @staticmethod
def get_name_whitelist(): def get_name_whitelist():
return [ "test-red1", "test-red2", "test-red3", return ["test-red1", "test-red2", "test-red3",
"test-target", "test-disp6" ] "test-target", "test-disp6"]
class MockVmLabel: class MockVmLabel:
def __init__(self, index, color, name, dispvm = False): def __init__(self, index, color, name, dispvm=False):
self.index = index self.index = index
self.color = color self.color = color
self.name = name self.name = name
self.dispvm = dispvm self.dispvm = dispvm
self.icon = "gnome-foot" self.icon = "gnome-foot"
class MockVm: class MockVm:
def __init__(self, qid, name, color, dispvm = False): def __init__(self, qid, name, color, dispvm=False):
self.qid = qid self.qid = qid
self.name = name self.name = name
self.label = MockVmLabel(qid, 0x000000, color, dispvm) self.label = MockVmLabel(qid, 0x000000, color, dispvm)
class MockComboEntry: class MockComboEntry:
def __init__(self, text): def __init__(self, text):
self._text = text self._text = text
@ -64,12 +75,13 @@ class MockComboEntry:
def get_text(self): def get_text(self):
return self._text return self._text
class GtkTestCase(unittest.TestCase): class GtkTestCase(unittest.TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
self._smallest_wait = 0.01 self._smallest_wait = 0.01
def flush_gtk_events(self, wait_seconds = 0): def flush_gtk_events(self, wait_seconds=0):
start = time.time() start = time.time()
iterations = 0 iterations = 0
remaining_wait = wait_seconds remaining_wait = wait_seconds
@ -80,16 +92,17 @@ class GtkTestCase(unittest.TestCase):
while remaining_wait >= 0: while remaining_wait >= 0:
while Gtk.events_pending(): while Gtk.events_pending():
Gtk.main_iteration_do(blocking = False) Gtk.main_iteration_do(blocking=False)
iterations += 1 iterations += 1
time_length = time.time() - start time_length = time.time() - start
remaining_wait = wait_seconds - time_length remaining_wait = wait_seconds - time_length
if (remaining_wait > 0): if remaining_wait > 0:
time.sleep(self._smallest_wait) time.sleep(self._smallest_wait)
return (iterations, time_length) return iterations, time_length
class VMListModelerTest(VMListModelerMock, unittest.TestCase): class VMListModelerTest(VMListModelerMock, unittest.TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -102,8 +115,8 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
def test_valid_qube_name(self): def test_valid_qube_name(self):
self.apply_model(Gtk.ComboBox()) self.apply_model(Gtk.ComboBox())
for name in [ "test-red1", "test-red2", "test-red3", for name in ["test-red1", "test-red2", "test-red3",
"test-target", "test-disp6" ]: "test-target", "test-disp6"]:
mock = MockComboEntry(name) mock = MockComboEntry(name)
self.assertEquals(name, self._get_valid_qube_name(mock, mock, [])) self.assertEquals(name, self._get_valid_qube_name(mock, mock, []))
@ -115,7 +128,7 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
list_exc = ["test-disp6", "test-red2"] list_exc = ["test-disp6", "test-red2"]
self.apply_model(Gtk.ComboBox(), self.apply_model(Gtk.ComboBox(),
[VMListModeler.NameBlacklistFilter([ list_exc[0], list_exc[1] ]) ]) [VMListModeler.NameBlacklistFilter([list_exc[0], list_exc[1]])])
for name in list_exc: for name in list_exc:
mock = MockComboEntry(name) mock = MockComboEntry(name)
@ -126,7 +139,7 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
def test_invalid_qube_name(self): def test_invalid_qube_name(self):
self.apply_model(Gtk.ComboBox()) self.apply_model(Gtk.ComboBox())
for name in [ "test-nonexistant", None, "", 1 ]: for name in ["test-nonexistant", None, "", 1]:
mock = MockComboEntry(name) mock = MockComboEntry(name)
self.assertIsNone(self._get_valid_qube_name(mock, mock, [])) self.assertIsNone(self._get_valid_qube_name(mock, mock, []))
@ -151,7 +164,7 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
self.assertIsNotNone(new_object.get_model()) self.assertIsNotNone(new_object.get_model())
def test_apply_model_only_combobox(self): def test_apply_model_only_combobox(self):
invalid_types = [ 1, "One", u'1', {'1': "one"}, VMListModelerMock()] invalid_types = [1, "One", u'1', {'1': "one"}, VMListModelerMock()]
for invalid_type in invalid_types: for invalid_type in invalid_types:
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
@ -163,19 +176,19 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
self.apply_model(combo) self.apply_model(combo)
self.assertEquals(7, len(combo.get_model())) self.assertEquals(7, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameBlacklistFilter([ self.apply_model(combo, [
self._entries.keys()[0] ]) ]) VMListModeler.NameBlacklistFilter([self._entries.keys()[0]])])
self.assertEquals(6, len(combo.get_model())) self.assertEquals(6, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameBlacklistFilter([ self.apply_model(combo, [
self._entries.keys()[0] ]), VMListModeler.NameBlacklistFilter([self._entries.keys()[0]]),
VMListModeler.NameBlacklistFilter([ VMListModeler.NameBlacklistFilter([self._entries.keys()[1]])])
self._entries.keys()[1] ]) ])
self.assertEquals(5, len(combo.get_model())) self.assertEquals(5, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameBlacklistFilter([ self.apply_model(combo, [VMListModeler.NameBlacklistFilter([
self._entries.keys()[0], self._entries.keys()[0],
self._entries.keys()[1] ]) ]) self._entries.keys()[1]
])])
self.assertEquals(5, len(combo.get_model())) self.assertEquals(5, len(combo.get_model()))
def test_apply_model_whitelist(self): def test_apply_model_whitelist(self):
@ -184,13 +197,13 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
self.apply_model(combo) self.apply_model(combo)
self.assertEquals(7, len(combo.get_model())) self.assertEquals(7, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameWhitelistFilter([ self.apply_model(combo, [
self._entries.keys()[0] ]) ]) VMListModeler.NameWhitelistFilter([self._entries.keys()[0]])])
self.assertEquals(1, len(combo.get_model())) self.assertEquals(1, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameWhitelistFilter([ self.apply_model(combo, [VMListModeler.NameWhitelistFilter([
self._entries.keys()[0], self._entries.keys()[0],
self._entries.keys()[1] ]) ]) self._entries.keys()[1]])])
self.assertEquals(2, len(combo.get_model())) self.assertEquals(2, len(combo.get_model()))
def test_apply_model_multiple_filters(self): def test_apply_model_multiple_filters(self):
@ -199,15 +212,15 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
self.apply_model(combo) self.apply_model(combo)
self.assertEquals(7, len(combo.get_model())) self.assertEquals(7, len(combo.get_model()))
self.apply_model(combo, [ VMListModeler.NameWhitelistFilter([ self.apply_model(combo, [VMListModeler.NameWhitelistFilter([
self._entries.keys()[0], self._entries.keys()[0],
self._entries.keys()[1], self._entries.keys()[1],
self._entries.keys()[2], self._entries.keys()[2],
self._entries.keys()[3], self._entries.keys()[3],
self._entries.keys()[4] ]), self._entries.keys()[4]]),
VMListModeler.NameBlacklistFilter([ VMListModeler.NameBlacklistFilter([
self._entries.keys()[0], self._entries.keys()[0],
self._entries.keys()[1] ]) ]) self._entries.keys()[1]])])
self.assertEquals(3, len(combo.get_model())) self.assertEquals(3, len(combo.get_model()))
def test_apply_icon(self): def test_apply_icon(self):
@ -222,7 +235,7 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
new_object.get_icon_pixbuf(Gtk.EntryIconPosition.PRIMARY)) new_object.get_icon_pixbuf(Gtk.EntryIconPosition.PRIMARY))
def test_apply_icon_only_entry(self): def test_apply_icon_only_entry(self):
invalid_types = [ 1, "One", u'1', {'1': "one"}, Gtk.ComboBox()] invalid_types = [1, "One", u'1', {'1': "one"}, Gtk.ComboBox()]
for invalid_type in invalid_types: for invalid_type in invalid_types:
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
@ -231,14 +244,15 @@ class VMListModelerTest(VMListModelerMock, unittest.TestCase):
def test_apply_icon_only_existing(self): def test_apply_icon_only_existing(self):
new_object = Gtk.Entry() new_object = Gtk.Entry()
for name in [ "test-red1", "test-red2", "test-red3", for name in ["test-red1", "test-red2", "test-red3",
"test-target", "test-disp6" ]: "test-target", "test-disp6"]:
self.apply_icon(new_object, name) self.apply_icon(new_object, name)
for name in [ "test-nonexistant", None, "", 1 ]: for name in ["test-nonexistant", None, "", 1]:
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
self.apply_icon(new_object, name) self.apply_icon(new_object, name)
class GtkOneTimerHelperTest(GtkOneTimerHelper, GtkTestCase): class GtkOneTimerHelperTest(GtkOneTimerHelper, GtkTestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
GtkTestCase.__init__(self, *args, **kwargs) GtkTestCase.__init__(self, *args, **kwargs)
@ -293,7 +307,7 @@ class GtkOneTimerHelperTest(GtkOneTimerHelper, GtkTestCase):
def test_more_tasks(self): def test_more_tasks(self):
num = 0 num = 0
for num in range(1,10): for num in range(1, 10):
self._timer_schedule() self._timer_schedule()
self.flush_gtk_events(self._test_time/4) self.flush_gtk_events(self._test_time/4)
self.flush_gtk_events(self._test_time*1.75) self.flush_gtk_events(self._test_time*1.75)
@ -303,46 +317,48 @@ class GtkOneTimerHelperTest(GtkOneTimerHelper, GtkTestCase):
def test_more_tasks_cancel(self): def test_more_tasks_cancel(self):
num = 0 num = 0
for num in range(1,10): for num in range(1, 10):
self._timer_schedule() self._timer_schedule()
self.flush_gtk_events(self._test_time/4) self.flush_gtk_events(self._test_time/4)
self._invalidate_current_timer() self._invalidate_current_timer()
self.flush_gtk_events(self._test_time*1.75) self.flush_gtk_events(int(self._test_time*1.75))
self.assertEquals([], self._run_timers) self.assertEquals([], self._run_timers)
self.assertEquals(num+1, self._current_timer_id) self.assertEquals(num+1, self._current_timer_id)
self.assertFalse(self._timer_has_completed()) self.assertFalse(self._timer_has_completed())
def test_subsequent_tasks(self): def test_subsequent_tasks(self):
self._timer_schedule() #1 self._timer_schedule() # 1
self.flush_gtk_events(self._test_time*2) self.flush_gtk_events(self._test_time*2)
self.assertEquals([1], self._run_timers) self.assertEquals([1], self._run_timers)
self.assertEquals(1, self._current_timer_id) self.assertEquals(1, self._current_timer_id)
self.assertTrue(self._timer_has_completed()) self.assertTrue(self._timer_has_completed())
self._timer_schedule() #2 self._timer_schedule() # 2
self.flush_gtk_events(self._test_time*2) self.flush_gtk_events(self._test_time*2)
self.assertEquals([1,2], self._run_timers) self.assertEquals([1, 2], self._run_timers)
self.assertEquals(2, self._current_timer_id) self.assertEquals(2, self._current_timer_id)
self.assertTrue(self._timer_has_completed()) self.assertTrue(self._timer_has_completed())
self._invalidate_timer_completed() self._invalidate_timer_completed()
self._timer_schedule() #3 self._timer_schedule() # 3
self._invalidate_current_timer() #4 self._invalidate_current_timer() # 4
self.flush_gtk_events(self._test_time*2) self.flush_gtk_events(self._test_time*2)
self.assertEquals([1,2], self._run_timers) self.assertEquals([1, 2], self._run_timers)
self.assertEquals(4, self._current_timer_id) self.assertEquals(4, self._current_timer_id)
self.assertFalse(self._timer_has_completed()) self.assertFalse(self._timer_has_completed())
self._timer_schedule() #5 self._timer_schedule() # 5
self.flush_gtk_events(self._test_time*2) self.flush_gtk_events(self._test_time*2)
self.assertEquals([1,2,5], self._run_timers) self.assertEquals([1, 2, 5], self._run_timers)
self.assertEquals(5, self._current_timer_id) self.assertEquals(5, self._current_timer_id)
self.assertTrue(self._timer_has_completed()) self.assertTrue(self._timer_has_completed())
class FocusStealingHelperMock(FocusStealingHelper): class FocusStealingHelperMock(FocusStealingHelper):
def simulate_focus(self): def simulate_focus(self):
self._window_changed_focus(True) self._window_changed_focus(True)
class FocusStealingHelperTest(FocusStealingHelperMock, GtkTestCase): class FocusStealingHelperTest(FocusStealingHelperMock, GtkTestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
GtkTestCase.__init__(self, *args, **kwargs) GtkTestCase.__init__(self, *args, **kwargs)
@ -352,7 +368,7 @@ class FocusStealingHelperTest(FocusStealingHelperMock, GtkTestCase):
self._test_window = Gtk.Window() self._test_window = Gtk.Window()
FocusStealingHelperMock.__init__(self, self._test_window, FocusStealingHelperMock.__init__(self, self._test_window,
self._test_button, self._test_time) self._test_button, self._test_time)
def test_nothing_runs_automatically(self): def test_nothing_runs_automatically(self):
self.assertFalse(self.can_perform_action()) self.assertFalse(self.can_perform_action())
@ -440,5 +456,5 @@ class FocusStealingHelperTest(FocusStealingHelperMock, GtkTestCase):
self.assertTrue(self.can_perform_action()) self.assertTrue(self.can_perform_action())
self.assertFalse(self._test_button.get_sensitive()) self.assertFalse(self._test_button.get_sensitive())
if __name__=='__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -19,9 +19,14 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# #
import unittest, sys import sys
from core.rpcconfirmation import RPCConfirmationWindow import unittest
from gtkhelpers import VMListModelerMock, GtkTestCase, FocusStealingHelperMock
from qubespolicy.tests.gtkhelpers import VMListModelerMock, GtkTestCase, \
FocusStealingHelperMock
from qubespolicy.rpcconfirmation import RPCConfirmationWindow
class MockRPCConfirmationWindow(RPCConfirmationWindow): class MockRPCConfirmationWindow(RPCConfirmationWindow):
def _new_VM_list_modeler(self): def _new_VM_list_modeler(self):
@ -34,8 +39,8 @@ class MockRPCConfirmationWindow(RPCConfirmationWindow):
self._focus_stealing_seconds) self._focus_stealing_seconds)
def __init__(self, source, rpc_operation, def __init__(self, source, rpc_operation,
name_whitelist = VMListModelerMock.get_name_whitelist(), name_whitelist=VMListModelerMock.get_name_whitelist(),
target = None, focus_stealing_seconds = 1): target=None, focus_stealing_seconds=1):
self._focus_stealing_seconds = focus_stealing_seconds self._focus_stealing_seconds = focus_stealing_seconds
RPCConfirmationWindow.__init__(self, source, rpc_operation, RPCConfirmationWindow.__init__(self, source, rpc_operation,
@ -49,20 +54,21 @@ class MockRPCConfirmationWindow(RPCConfirmationWindow):
model_iter = model.get_iter_first() model_iter = model.get_iter_first()
domains = [] domains = []
while model_iter != None: while model_iter is not None:
domain_name = model.get_value(model_iter, 1) domain_name = model.get_value(model_iter, 1)
domains = domains + [domain_name] domains += [domain_name]
model_iter = model.iter_next(model_iter) model_iter = model.iter_next(model_iter)
return domains return domains
class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase): class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
def __init__(self, test_method, source_name = "test-source", def __init__(self, test_method, source_name="test-source",
rpc_operation = "test.Operation", rpc_operation="test.Operation",
name_whitelist = VMListModelerMock.get_name_whitelist(), name_whitelist=VMListModelerMock.get_name_whitelist(),
target_name = None): target_name=None):
GtkTestCase.__init__(self, test_method) GtkTestCase.__init__(self, test_method)
self.test_source_name = source_name self.test_source_name = source_name
self.test_rpc_operation = rpc_operation self.test_rpc_operation = rpc_operation
@ -81,7 +87,7 @@ class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
self.test_rpc_operation, self.test_rpc_operation,
name_whitelist, name_whitelist,
self.test_target_name, self.test_target_name,
focus_stealing_seconds = self._test_time) focus_stealing_seconds=self._test_time)
def _can_perform_action(self): def _can_perform_action(self):
return True return True
@ -111,12 +117,10 @@ class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
self.assertIsNotNone(self._error_message) self.assertIsNotNone(self._error_message)
def test_is_showing_source(self): def test_is_showing_source(self):
self.assertTrue(self.test_source_name in self.assertTrue(self.test_source_name in self._source_entry.get_text())
self._source_entry.get_text())
def test_is_showing_operation(self): def test_is_showing_operation(self):
self.assertTrue(self.test_rpc_operation in self.assertTrue(self.test_rpc_operation in self._rpc_label.get_text())
self._rpc_label.get_text())
def test_escape_and_format_rpc_text(self): def test_escape_and_format_rpc_text(self):
self.assertEquals("qubes.<b>Test</b>", self.assertEquals("qubes.<b>Test</b>",
@ -137,24 +141,24 @@ class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
self._escape_and_format_rpc_text("<script>.inject")) self._escape_and_format_rpc_text("<script>.inject"))
def test_lifecycle_open_select_ok(self): def test_lifecycle_open_select_ok(self):
self._lifecycle_start(select_target = True) self._lifecycle_start(select_target=True)
self._lifecycle_click(click_type = "ok") self._lifecycle_click(click_type="ok")
def test_lifecycle_open_select_cancel(self): def test_lifecycle_open_select_cancel(self):
self._lifecycle_start(select_target = True) self._lifecycle_start(select_target=True)
self._lifecycle_click(click_type = "cancel") self._lifecycle_click(click_type="cancel")
def test_lifecycle_open_select_exit(self): def test_lifecycle_open_select_exit(self):
self._lifecycle_start(select_target = True) self._lifecycle_start(select_target=True)
self._lifecycle_click(click_type = "exit") self._lifecycle_click(click_type="exit")
def test_lifecycle_open_cancel(self): def test_lifecycle_open_cancel(self):
self._lifecycle_start(select_target = False) self._lifecycle_start(select_target=False)
self._lifecycle_click(click_type = "cancel") self._lifecycle_click(click_type="cancel")
def test_lifecycle_open_exit(self): def test_lifecycle_open_exit(self):
self._lifecycle_start(select_target = False) self._lifecycle_start(select_target=False)
self._lifecycle_click(click_type = "exit") self._lifecycle_click(click_type="exit")
def _lifecycle_click(self, click_type): def _lifecycle_click(self, click_type):
if click_type == "ok": if click_type == "ok":
@ -198,7 +202,7 @@ class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
try: try:
# We expect the call to exit immediately, since no window is opened # We expect the call to exit immediately, since no window is opened
self.confirm_rpc() self.confirm_rpc()
except BaseException: except Exception:
pass pass
self.assertFalse(self.test_called_close) self.assertFalse(self.test_called_close)
@ -234,15 +238,16 @@ class RPCConfirmationWindowTestBase(MockRPCConfirmationWindow, GtkTestCase):
else: else:
self.assertFalse(self._focus_helper.can_perform_action()) self.assertFalse(self._focus_helper.can_perform_action())
class RPCConfirmationWindowTestWithTarget(RPCConfirmationWindowTestBase): class RPCConfirmationWindowTestWithTarget(RPCConfirmationWindowTestBase):
def __init__(self, test_method): def __init__(self, test_method):
RPCConfirmationWindowTestBase.__init__(self, test_method, RPCConfirmationWindowTestBase.__init__(self, test_method,
source_name = "test-source", rpc_operation = "test.Operation", source_name="test-source", rpc_operation="test.Operation",
target_name = "test-target") target_name="test-target")
def test_lifecycle_open_ok(self): def test_lifecycle_open_ok(self):
self._lifecycle_start(select_target = False) self._lifecycle_start(select_target=False)
self._lifecycle_click(click_type = "ok") self._lifecycle_click(click_type="ok")
def assert_initial_state(self, after_focus_timer): def assert_initial_state(self, after_focus_timer):
self.assertIsNotNone(self._target_qid) self.assertIsNotNone(self._target_qid)
@ -262,6 +267,7 @@ class RPCConfirmationWindowTestWithTarget(RPCConfirmationWindowTestBase):
self.assertIsNotNone(self._target_qid) self.assertIsNotNone(self._target_qid)
self.assertIsNotNone(self._target_name) self.assertIsNotNone(self._target_name)
class RPCConfirmationWindowTestWithTargetInvalid(unittest.TestCase): class RPCConfirmationWindowTestWithTargetInvalid(unittest.TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
@ -280,32 +286,34 @@ class RPCConfirmationWindowTestWithTargetInvalid(unittest.TestCase):
target=target) target=target)
self.assertEquals(expect, rpcWindow.is_error_visible()) self.assertEquals(expect, rpcWindow.is_error_visible())
class RPCConfirmationWindowTestWhitelist(unittest.TestCase): class RPCConfirmationWindowTestWhitelist(unittest.TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
def test_no_domains(self): def test_no_domains(self):
self._assert_whitelist([],[]) self._assert_whitelist([], [])
def test_all_red_domains(self): def test_all_red_domains(self):
self._assert_whitelist(["test-red1", "test-red2", "test-red3"], self._assert_whitelist(["test-red1", "test-red2", "test-red3"],
["test-red1", "test-red2", "test-red3"]) ["test-red1", "test-red2", "test-red3"])
def test_all_red_domains_plus_nonexistent(self): def test_all_red_domains_plus_nonexistent(self):
self._assert_whitelist(["test-red1", "test-red2", "test-red3", self._assert_whitelist(
"test-blue1", "test-blue2", "test-blue3"], ["test-red1", "test-red2", "test-red3",
["test-red1", "test-red2", "test-red3"]) "test-blue1", "test-blue2", "test-blue3"],
["test-red1", "test-red2", "test-red3"])
def test_all_allowed_domains(self): def test_all_allowed_domains(self):
self._assert_whitelist(["test-red1", "test-red2", "test-red3", self._assert_whitelist(
"test-target", "test-disp6", "test-source", ["test-red1", "test-red2", "test-red3",
"dom0"], ["test-red1", "test-red2", "test-red3", "test-target", "test-disp6", "test-source", "dom0"],
"test-target", "test-disp6", "test-source", ["test-red1", "test-red2", "test-red3",
"dom0"]) "test-target", "test-disp6", "test-source", "dom0"])
def _assert_whitelist(self, whitelist, expected): def _assert_whitelist(self, whitelist, expected):
rpcWindow = MockRPCConfirmationWindow("test-source", "test.Operation", rpcWindow = MockRPCConfirmationWindow(
whitelist) "test-source", "test.Operation", whitelist)
domains = rpcWindow.get_shown_domains() domains = rpcWindow.get_shown_domains()
@ -314,7 +322,7 @@ class RPCConfirmationWindowTestWhitelist(unittest.TestCase):
self.assertEquals(len(expected), len(domains)) self.assertEquals(len(expected), len(domains))
if __name__=='__main__': if __name__ == '__main__':
test = False test = False
window = False window = False
@ -323,12 +331,12 @@ if __name__=='__main__':
elif sys.argv[1] == '-w': elif sys.argv[1] == '-w':
window = True window = True
else: else:
print "Usage: " + __file__ + " [-t|-w]" print("Usage: " + __file__ + " [-t|-w]")
if window: if window:
print MockRPCConfirmationWindow("test-source", print(MockRPCConfirmationWindow("test-source",
"qubes.Filecopy", "qubes.Filecopy",
VMListModelerMock.get_name_whitelist(), VMListModelerMock.get_name_whitelist(),
"test-red1").confirm_rpc() "test-red1").confirm_rpc())
elif test: elif test:
unittest.main(argv = [sys.argv[0]]) unittest.main(argv=[sys.argv[0]])

View File

@ -21,25 +21,26 @@
def _sanitize_char(input_char, extra_allowed_characters): def _sanitize_char(input_char, extra_allowed_characters):
input_char_ord = ord(input_char) input_char_ord = ord(input_char)
if (input_char_ord >= ord('a') and input_char_ord <= ord('z')) \ if (ord('a') <= input_char_ord <= ord('z')) \
or (input_char_ord >= ord('A') and input_char_ord <= ord('Z')) \ or (ord('A') <= input_char_ord <= ord('Z')) \
or (input_char_ord >= ord('0') and input_char_ord <= ord('9')) \ or (ord('0') <= input_char_ord <= ord('9')) \
or (input_char in ['$', '_', '-', '.']) \ or (input_char in ['$', '_', '-', '.']) \
or (extra_allowed_characters != None or (input_char in extra_allowed_characters):
and input_char in extra_allowed_characters):
result = input_char result = input_char
else: else:
result = '_' result = '_'
return result return result
# This function needs to be synchronized with qrexec-daemon.c's sanitize_name() # This function needs to be synchronized with qrexec-daemon.c's sanitize_name()
# from the qubes-core-admin-linux repository. # from the qubes-core-admin-linux repository.
# #
# See https://github.com/QubesOS/qubes-core-admin-linux/blob/4f0878ccbf8a95f8264b54d2b6f4dc433ca0793a/qrexec/qrexec-daemon.c#L627-L646 # See https://github.com/QubesOS/qubes-core-admin-linux/blob/
# 4f0878ccbf8a95f8264b54d2b6f4dc433ca0793a/qrexec/qrexec-daemon.c#L627-L646
# #
def _sanitize_name(input_string, extra_allowed_characters, assert_sanitized): def _sanitize_name(input_string, extra_allowed_characters, assert_sanitized):
result = ''.join(_sanitize_char(character, extra_allowed_characters) \ result = ''.join(_sanitize_char(character, extra_allowed_characters)
for character in input_string) for character in input_string)
if assert_sanitized: if assert_sanitized:
@ -48,9 +49,11 @@ def _sanitize_name(input_string, extra_allowed_characters, assert_sanitized):
else: else:
return result return result
def sanitize_domain_name(input_string, assert_sanitized = False):
return _sanitize_name(input_string, None, assert_sanitized)
def sanitize_service_name(input_string, assert_sanitized = False): def sanitize_domain_name(input_string, assert_sanitized=False):
return _sanitize_name(input_string, {}, assert_sanitized)
def sanitize_service_name(input_string, assert_sanitized=False):
return _sanitize_name(input_string, {'+'}, assert_sanitized) return _sanitize_name(input_string, {'+'}, assert_sanitized)