From 28c7ce368ca4a4ff55686b24ee6df77c65025668 Mon Sep 17 00:00:00 2001 From: matan Date: Thu, 3 Mar 2022 16:28:25 +0200 Subject: [PATCH] Preferences: refactor cf tests. --- .../rpcclient/darwin/cfpreferences.py | 18 ++- src/rpcclient/tests/test_preferences.py | 136 +++++++++++++++--- 2 files changed, 134 insertions(+), 20 deletions(-) diff --git a/src/rpcclient/rpcclient/darwin/cfpreferences.py b/src/rpcclient/rpcclient/darwin/cfpreferences.py index eb807d83..5fc2a67d 100644 --- a/src/rpcclient/rpcclient/darwin/cfpreferences.py +++ b/src/rpcclient/rpcclient/darwin/cfpreferences.py @@ -1,6 +1,7 @@ +from contextlib import suppress import typing -from rpcclient.exceptions import RpcClientException +from rpcclient.exceptions import RpcClientException, NoSuchPreferenceError kCFPreferencesCurrentUser = 'kCFPreferencesCurrentUser' kCFPreferencesAnyUser = 'kCFPreferencesAnyUser' @@ -25,7 +26,10 @@ def get_keys(self, application_id: str, username: str = kCFPreferencesCurrentUse application_id = self._client.cf(application_id) username = self._client.cf(username) hostname = self._client.cf(hostname) - return self._client.symbols.CFPreferencesCopyKeyList(application_id, username, hostname).py + keys = self._client.symbols.CFPreferencesCopyKeyList(application_id, username, hostname).py + if keys is None: + raise NoSuchPreferenceError() + return keys def get_value(self, key: str, application_id: str, username: str = kCFPreferencesCurrentUser, hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[str]: @@ -35,8 +39,8 @@ def get_value(self, key: str, application_id: str, username: str = kCFPreference hostname = self._client.cf(hostname) return self._client.symbols.CFPreferencesCopyValue(key, application_id, username, hostname).py - def get_values(self, application_id: str, username: str = kCFPreferencesCurrentUser, - hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[typing.Mapping]: + def get_dict(self, application_id: str, username: str = kCFPreferencesCurrentUser, + hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[typing.Mapping]: result = {} key_list = self.get_keys(application_id, username, hostname) if not key_list: @@ -59,6 +63,12 @@ def remove(self, key: str, application_id: str, username: str = kCFPreferencesCu def set_dict(self, d: typing.Mapping, application_id: str, username: str = kCFPreferencesCurrentUser, hostname: str = kCFPreferencesCurrentHost): + with suppress(NoSuchPreferenceError): + self.clear(application_id, username, hostname) + self.update_dict(d, application_id, username, hostname) + + def update_dict(self, d: typing.Mapping, application_id: str, username: str = kCFPreferencesCurrentUser, + hostname: str = kCFPreferencesCurrentHost): for k, v in d.items(): self.set(k, v, application_id, username, hostname) diff --git a/src/rpcclient/tests/test_preferences.py b/src/rpcclient/tests/test_preferences.py index d8e5b63c..edb1d143 100644 --- a/src/rpcclient/tests/test_preferences.py +++ b/src/rpcclient/tests/test_preferences.py @@ -1,25 +1,129 @@ +from contextlib import suppress + +import pytest + +from rpcclient.exceptions import NoSuchPreferenceError + DOMAIN = 'rpcserver' -def test_cf_preferences(client): - if client.preferences.cf.get_keys(DOMAIN) is not None: - # if from some reason this domain already exist, empty it - client.preferences.cf.clear(DOMAIN) - assert client.preferences.cf.get_keys(DOMAIN) is None +def test_cf_get_keys(client): + """ + :param rpcclient.client.Client client: + """ + assert 'uuid-mappings' in client.preferences.cf.get_keys('com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + + +def test_cf_get_keys_invalid_preference(client): + """ + :param rpcclient.client.Client client: + """ + with pytest.raises(NoSuchPreferenceError): + client.preferences.cf.get_keys('com.apple.invalid_preference_for_sure', 'kCFPreferencesAnyUser') + + +def test_cf_get_value(client): + """ + :param rpcclient.client.Client client: + """ + assert 'com.apple.system.diagnostics' in client.preferences.cf.get_value('uuid-mappings', + 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + + +def test_cf_get_dict(client): + """ + :param rpcclient.client.Client client: + """ + assert 'com.apple.system.diagnostics' in client.preferences.cf.get_dict('com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser')['uuid-mappings'] + + +def test_cf_set(client): + """ + :param rpcclient.client.Client client: + """ + uuid_mapping = client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + client.preferences.cf.set('uuid-mappings', {'hey': 'you'}, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + try: + assert client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') == {'hey': 'you'} + finally: + client.preferences.cf.set('uuid-mappings', uuid_mapping, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + - # test set a full dictionary - test_dict = {'KEY1': 'VALUE1', 'KEY2': 'VALUE2'} - client.preferences.cf.set_dict(test_dict, DOMAIN) - assert test_dict == client.preferences.cf.get_values(DOMAIN) +def test_cf_remove(client): + uuid_mapping = client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + client.preferences.cf.remove('uuid-mappings', 'com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') + try: + assert client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') is None + finally: + client.preferences.cf.set('uuid-mappings', uuid_mapping, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') - # test set remove a single value - client.preferences.cf.remove('KEY2', DOMAIN) - test_dict.pop('KEY2') - assert test_dict == client.preferences.cf.get_values(DOMAIN) - # remove out test data and verify it works - client.preferences.cf.clear(DOMAIN) - assert client.preferences.cf.get_keys(DOMAIN) is None +def test_cf_set_dict(client): + uuid_mapping = client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + client.preferences.cf.set_dict({'a': 5}, 'com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') + try: + client.preferences.cf.get_dict('com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') == {'a': 5} + finally: + client.preferences.cf.set_dict({'uuid-mappings': uuid_mapping}, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + + +def test_cf_update_dict(client): + uuid_mapping = client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + client.preferences.cf.set_dict({'a': 5}, 'com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') + try: + client.preferences.cf.get_dict('com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') == { + 'a': 5, + 'uuid-mappings': uuid_mapping + } + finally: + client.preferences.cf.set_dict({'uuid-mappings': uuid_mapping}, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + + +def test_cf_clear(client): + uuid_mapping = client.preferences.cf.get_value('uuid-mappings', 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + client.preferences.cf.clear('com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') + try: + with pytest.raises(NoSuchPreferenceError): + assert not client.preferences.cf.get_dict('com.apple.networkextension.uuidcache', 'kCFPreferencesAnyUser') + finally: + client.preferences.cf.set('uuid-mappings', uuid_mapping, 'com.apple.networkextension.uuidcache', + 'kCFPreferencesAnyUser') + + +class TestCustomDomain: + @pytest.fixture(autouse=True) + def clear_domain(self, client): + with suppress(NoSuchPreferenceError): + # if from some reason this domain already exist, empty it + client.preferences.cf.clear(DOMAIN) + assert client.preferences.cf.get_keys(DOMAIN) is None + + def test_set_dict(self, client): + test_dict = {'KEY1': 'VALUE1', 'KEY2': 'VALUE2'} + client.preferences.cf.set_dict(test_dict, DOMAIN) + assert test_dict == client.preferences.cf.get_dict(DOMAIN) + + def test_remove(self, client): + test_dict = {'KEY1': 'VALUE1', 'KEY2': 'VALUE2'} + client.preferences.cf.set_dict(test_dict, DOMAIN) + client.preferences.cf.remove('KEY2', DOMAIN) + test_dict.pop('KEY2') + assert test_dict == client.preferences.cf.get_dict(DOMAIN) def test_sc_preferences(client):