[autotest]: Add HermesErrorScenarios test
Do repeat actions like install, enable, disable on a profile and
uninstall already enabled profile, validate dbus errors and if any
unexpected hermes behaviour
BUG=None
TEST=Done on test esim and tmobile prod esim:
test_that -b trogdor <esim_dut_ip> --fast
cellular_HermesErrorScenarios.testci
Change-Id: If4e1826ffe54c5774d592a80917de1f1a5f89933
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2723412
Reviewed-by: Srikanth Oruganti <srikanthkumar@google.com>
Reviewed-by: Pavan Holla <pholla@google.com>
Tested-by: Srikanth Oruganti <srikanthkumar@google.com>
Commit-Queue: Srikanth Oruganti <srikanthkumar@google.com>
diff --git a/client/site_tests/cellular_HermesErrorScenarios/cellular_HermesErrorScenarios.py b/client/site_tests/cellular_HermesErrorScenarios/cellular_HermesErrorScenarios.py
new file mode 100644
index 0000000..c434da3
--- /dev/null
+++ b/client/site_tests/cellular_HermesErrorScenarios/cellular_HermesErrorScenarios.py
@@ -0,0 +1,214 @@
+# Copyright (c) 2021 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import dbus
+import logging
+
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.cros.cellular import cellular_logging
+from autotest_lib.client.cros.cellular import hermes_constants
+from autotest_lib.client.cros.cellular import hermes_utils
+
+log = cellular_logging.SetupCellularLogging('HermesErrorScenariosTest')
+
+class cellular_HermesErrorScenarios(test.test):
+ """
+ Tests Hermes Error Scenarios on active Euicc
+
+ This test fails when not able to do error validation
+
+ Prerequisites
+
+ 1) For test CI:
+ Before running this test on test CI, a profile needs to be created on
+ go/stork-profile. The profile needs to be linked to the EID of the dut.
+ Profiles with class=operational and type=Android GTS test are known to work
+ well with this test.
+
+ We rely on the SMDS event to find the activation code for the test.
+ There is a limit of 99 downloads before the profile needs to be deleted and
+ recreated.(b/181723689)
+
+ 2) For prod CI:
+ Install a production profile before running the test.
+
+ """
+ version = 1
+
+ def install_invalid_profile_test(self, euicc_path):
+ """
+ Install a profile with incorrect activation code
+ Check expected error, also validates InstallProfileFromActivationCode
+ api on test euicc
+
+ @param euicc_path: esim path based on testci/prodci
+ @return raise error.TestFail if expected error not resulted
+
+ """
+ expected_exception = 'org.chromium.Hermes.Error.InvalidActivationCode'
+ try:
+ logging.info('install_invalid_profile_test start')
+ euicc, _ = hermes_utils.request_installed_profiles(
+ euicc_path, self.hermes_manager)
+
+ # Incorrect activation code
+ activation_code = 'W567-EQ7A-TEST-CODE'
+
+ logging.info('Installing activation_code:%s conf_code:%s',
+ activation_code, '')
+
+ # Install and check for expected error
+ euicc.install_profile_from_activation_code(activation_code, '')
+ raise error.TestFail(expected_exception, ' not raised while '
+ 'installing a profile with an invalid activation code.')
+ except dbus.DBusException as e:
+ self.check_exception(expected_exception, e.get_dbus_name())
+ logging.info('===install_invalid_profile_test done===\n')
+
+ def enable_uninstall_profile_test(self, euicc_path):
+ """
+ Attempt to uninstall an enabled profile, and check that an error is
+ received.
+
+ @param euicc_path: esim path based on testci/prodci
+ @return raise error.TestFail if expected error not resulted
+
+ """
+ expected_exception = 'org.chromium.Hermes.Error.Unknown'
+ try:
+ logging.info('enable_uninstall_profile_test start')
+ # Get a profile to enable which is not active
+ installed_iccid = self.get_installed_profile(euicc_path, False)
+ hermes_utils.set_profile_state(
+ True, euicc_path, self.hermes_manager, installed_iccid, None)
+
+ # Uninstall already enabled profile
+ euicc = self.hermes_manager.get_euicc(euicc_path)
+ profile = euicc.get_profile_from_iccid(installed_iccid)
+ if (hermes_constants.ProfileClassToString(profile.profileclass) !=
+ 'TESTING'):
+ euicc.uninstall_profile(profile.path)
+ logging.info('enable_uninstall_profile_test success')
+ except dbus.DBusException as e:
+ self.check_exception(expected_exception, e.get_dbus_name())
+ logging.info('===enable_uninstall_profile_test done===\n')
+
+ def get_installed_profile(self, euicc_path, is_active):
+ """
+ Attempts to get an active/inactive profile. If a profile in the desired
+ state is not found, installs a profile and enables/disables the profile
+
+ @param euicc_path: esim path based on testci/prodci
+ @param is_active: true to get active profile, false to get inactive one
+
+ """
+ logging.info('get_installed_profile start')
+ installed_iccid = hermes_utils.get_profile(
+ euicc_path, self.hermes_manager, is_active)
+
+ if (installed_iccid is None and not self.is_prod_ci):
+ logging.info('Could not find an installed profile with '
+ 'state==%s. Will attempt to install a profile and set it to the '
+ 'desired state.', is_active)
+ installed_iccid = hermes_utils.install_pending_profile_test(
+ euicc_path, self.hermes_manager)
+
+ hermes_utils.enable_or_disable_profile_test(
+ euicc_path, self.hermes_manager, installed_iccid, is_active)
+
+ if not installed_iccid:
+ raise error.TestFail('get_installed_profile failed - no profile')
+ logging.info('get_installed_profile done')
+ return installed_iccid
+
+ def check_exception(self, expected_exception, received_exception):
+ """
+ Checks the exception is an expected one or not
+
+ @param expected_exception: DBus expected exception
+ @param received_exception: DBus resulted exception
+
+ """
+ if received_exception in expected_exception:
+ logging.info('Received exception %s as expected.',
+ expected_exception)
+ else:
+ raise error.TestFail('Expected exception:' + expected_exception +
+ '. Got exception:' + received_exception)
+
+ def enable_active_profile_test(self, euicc_path):
+ """
+ Check that an exception is raised upon re-enabling an active profile.
+
+ @param euicc_path: esim path based on testci/prodci
+ @return raise error.TestFail if expected error not resulted
+
+ """
+ expected_exception = 'org.chromium.Hermes.Error.AlreadyEnabled'
+ try:
+ logging.info('===enable_active_profile_test start===')
+ installed_iccid = self.get_installed_profile(euicc_path, True)
+ hermes_utils.set_profile_state(
+ True, euicc_path, self.hermes_manager, installed_iccid, None)
+ raise error.TestFail(expected_exception, ' not raised while '
+ 'enabling a profile which is already in enabled state.')
+ except dbus.DBusException as e:
+ self.check_exception(expected_exception, e.get_dbus_name())
+ logging.info('===enable_active_profile_test done===\n')
+
+ def disable_inactive_profile_test(self, euicc_path):
+ """
+ Validate expected result after disabling already disabled profile
+
+ @param euicc_path: esim path based on testci/prodci
+ @return raise error.TestFail if expected error not resulted
+
+ """
+ expected_exception = 'org.chromium.Hermes.Error.AlreadyDisabled'
+ try:
+ logging.info('===disable_inactive_profile_test start===')
+ installed_iccid = self.get_installed_profile(euicc_path, False)
+ hermes_utils.set_profile_state(
+ False, euicc_path, self.hermes_manager, installed_iccid, None)
+ raise error.TestFail(expected_exception, ' not raised while '
+ 'disabling a profile which is already in disabled state.')
+ except dbus.DBusException as e:
+ self.check_exception(expected_exception, e.get_dbus_name())
+ logging.info('===disable_inactive_profile_test done===\n')
+
+ def run_once(self, is_prod_ci=False):
+ """
+ Validated error scenarios on Profile
+
+ @param is_prod: is_prod_ci true if prod sim dut & false for test sim dut
+ @return raise error.TestFail if expected error not resulted
+
+ expected_exceptions are
+ 'org.chromium.Hermes.Error.AlreadyEnabled',
+ 'org.chromium.Hermes.Error.AlreadyDisabled',
+ 'org.chromium.Hermes.Error.InvalidActivationCode'
+ 'org.chromium.Hermes.Error.Unknown'
+
+ """
+ self.is_prod_ci = is_prod_ci
+
+ self.mm_proxy, self.hermes_manager, euicc_path = \
+ hermes_utils.initialize_test(is_prod_ci)
+
+ # Error cases: Do operations that can result expected dbus errors
+ # Install an invalid profile(wrong activation code)
+ self.install_invalid_profile_test(euicc_path)
+
+ # Enable a previously enabled profile
+ self.enable_active_profile_test(euicc_path)
+
+ # Disable a previously disabled profile
+ self.disable_inactive_profile_test(euicc_path)
+
+ if not self.is_prod_ci:
+ # Do Enable->Uninstall same profile
+ self.enable_uninstall_profile_test(euicc_path)
+
+ logging.info('HermesErrorScenariosTest Completed')
diff --git a/client/site_tests/cellular_HermesErrorScenarios/control.testci b/client/site_tests/cellular_HermesErrorScenarios/control.testci
new file mode 100644
index 0000000..2eed831
--- /dev/null
+++ b/client/site_tests/cellular_HermesErrorScenarios/control.testci
@@ -0,0 +1,30 @@
+# Copyright (c) 2021 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+AUTHOR = "ChromeOS Team"
+NAME = "cellular_HermesErrorScenarios.testci"
+PURPOSE = "Verify that a failed hermes connect attempt reported"
+CRITERIA = """
+This test will fail if not resulted in expected error from Hermes daemon
+"""
+ATTRIBUTES = "suite:cellular_ota_flaky"
+TIME = "SHORT"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "network"
+TEST_TYPE = "client"
+DEPENDENCIES = "testesim"
+DOC = """
+ Tests that Hermes Profile/Euicc error validation scenarios
+
+ This test will fail if failed to if not resulted in expected error OR
+ could not able to find and connect to Hermes dbus daemon
+ It requires a dut with a modem and euicc
+"""
+
+from autotest_lib.client.cros.cellular import test_environment
+
+test_env = test_environment.CellularESIMTestEnvironment()
+job.run_test('cellular_HermesErrorScenarios', test_env=test_env,
+ is_prod_ci=False)
+