diff options
author | Szczepan Zalega <szczepan@nitrokey.com> | 2020-06-15 19:15:17 +0200 |
---|---|---|
committer | Szczepan Zalega <szczepan@nitrokey.com> | 2020-06-15 19:15:17 +0200 |
commit | 3dd267e062a2f3e182d84f15e13b15b6dd4958e0 (patch) | |
tree | 8994b48f6aa359bc52694f1b732c7f1b5ffc4184 /unittest | |
parent | dd0cdcd2130699be8dde5dbadcf18cd9c00ef78f (diff) | |
parent | 89a73d88c9026b6347bea113896d24e419c4370c (diff) | |
download | libnitrokey-3dd267e062a2f3e182d84f15e13b15b6dd4958e0.tar.gz libnitrokey-3dd267e062a2f3e182d84f15e13b15b6dd4958e0.tar.bz2 |
Merge branch 'master' into get_status
Update to latest codebase
Diffstat (limited to 'unittest')
-rw-r--r-- | unittest/conftest.py | 104 | ||||
-rw-r--r-- | unittest/constants.py | 14 | ||||
-rw-r--r-- | unittest/helpers.py | 51 | ||||
-rw-r--r-- | unittest/misc.py | 4 | ||||
-rw-r--r-- | unittest/requirements.txt | 1 | ||||
-rw-r--r-- | unittest/test_memory.c | 63 | ||||
-rw-r--r-- | unittest/test_multiple.py | 4 | ||||
-rw-r--r-- | unittest/test_offline.cc | 4 | ||||
-rw-r--r-- | unittest/test_pro.py | 109 | ||||
-rw-r--r-- | unittest/test_pro_bootloader.py | 71 | ||||
-rw-r--r-- | unittest/test_storage.py | 4 |
11 files changed, 310 insertions, 119 deletions
diff --git a/unittest/conftest.py b/unittest/conftest.py index 49b4f02..17d9ef5 100644 --- a/unittest/conftest.py +++ b/unittest/conftest.py @@ -20,6 +20,7 @@ SPDX-License-Identifier: LGPL-3.0 """ import pytest +import os, sys from misc import ffi, gs @@ -82,47 +83,8 @@ def C(request=None): def get_library(request, allow_offline=False): - fp = '../NK_C_API.h' - - declarations = [] - with open(fp, 'r') as f: - declarations = f.readlines() - - cnt = 0 - a = iter(declarations) - for declaration in a: - if declaration.strip().startswith('NK_C_API') \ - or declaration.strip().startswith('struct'): - declaration = declaration.replace('NK_C_API', '').strip() - while ');' not in declaration and '};' not in declaration: - declaration += (next(a)).strip()+'\n' - ffi.cdef(declaration, override=True) - cnt += 1 - print('Imported {} declarations'.format(cnt)) - - C = None - import os, sys - path_build = os.path.join("..", "build") - paths = [ - os.environ.get('LIBNK_PATH', None), - os.path.join(path_build,"libnitrokey.so"), - os.path.join(path_build,"libnitrokey.dylib"), - os.path.join(path_build,"libnitrokey.dll"), - os.path.join(path_build,"nitrokey.dll"), - ] - for p in paths: - if not p: continue - print("Trying " +p) - p = os.path.abspath(p) - if os.path.exists(p): - print("Found: "+p) - C = ffi.dlopen(p) - break - else: - print("File does not exist: " + p) - if not C: - print("No library file found") - sys.exit(1) + library_read_declarations() + C = library_open_lib() C.NK_set_debug_level(int(os.environ.get('LIBNK_DEBUG', 2))) @@ -155,3 +117,63 @@ def get_library(request, allow_offline=False): return AttrProxy(C, "libnitrokey C") + +def library_open_lib(): + C = None + path_build = os.path.join("..", "build") + paths = [ + os.environ.get('LIBNK_PATH', None), + os.path.join(path_build, "libnitrokey.so"), + os.path.join(path_build, "libnitrokey.dylib"), + os.path.join(path_build, "libnitrokey.dll"), + os.path.join(path_build, "nitrokey.dll"), + ] + for p in paths: + if not p: continue + print("Trying " + p) + p = os.path.abspath(p) + if os.path.exists(p): + print("Found: " + p) + C = ffi.dlopen(p) + break + else: + print("File does not exist: " + p) + if not C: + print("No library file found") + sys.exit(1) + return C + + +def library_read_declarations(): + fp = '../NK_C_API.h' + declarations = [] + with open(fp, 'r') as f: + declarations = f.readlines() + cnt = 0 + a = iter(declarations) + for declaration in a: + if declaration.strip().startswith('NK_C_API') \ + or declaration.strip().startswith('struct'): + declaration = declaration.replace('NK_C_API', '').strip() + while ');' not in declaration and '};' not in declaration: + declaration += (next(a)).strip() + '\n' + ffi.cdef(declaration, override=True) + cnt += 1 + print('Imported {} declarations'.format(cnt)) + + +def pytest_addoption(parser): + parser.addoption("--run-skipped", action="store_true", + help="run the tests skipped by default, e.g. adding side effects") + +def pytest_runtest_setup(item): + if 'skip_by_default' in item.keywords and not item.config.getoption("--run-skipped"): + pytest.skip("need --run-skipped option to run this test") + + +def library_device_reconnect(C): + C.NK_logout() + C = library_open_lib() + C.NK_logout() + assert C.NK_login_auto() == 1, 'Device not found' + return C
\ No newline at end of file diff --git a/unittest/constants.py b/unittest/constants.py index 645ef6a..4047f59 100644 --- a/unittest/constants.py +++ b/unittest/constants.py @@ -18,12 +18,7 @@ along with libnitrokey. If not, see <http://www.gnu.org/licenses/>. SPDX-License-Identifier: LGPL-3.0 """ - -from misc import to_hex - -def bb(x): - return bytes(x, encoding='ascii') - +from misc import to_hex, bb RFC_SECRET_HR = '12345678901234567890' RFC_SECRET = to_hex(RFC_SECRET_HR) # '31323334353637383930...' @@ -39,6 +34,9 @@ class DefaultPasswords: USER_TEMP = b'234234234' UPDATE = b'12345678' UPDATE_TEMP = b'123update123' + UPDATE_LONG = b'1234567890'*2 + UPDATE_TOO_LONG = UPDATE_LONG + b'x' + UPDATE_TOO_SHORT = UPDATE_LONG[:7] class DeviceErrorCode: @@ -49,6 +47,7 @@ class DeviceErrorCode: STATUS_NOT_AUTHORIZED = 5 STATUS_AES_DEC_FAILED = 0xa STATUS_UNKNOWN_ERROR = 100 + STATUS_DISCONNECTED = 255 class LibraryErrors: @@ -59,4 +58,5 @@ class LibraryErrors: HOTP_slot_count = 3 -TOTP_slot_count = 15
\ No newline at end of file +TOTP_slot_count = 15 +PWS_SLOT_COUNT = 16 diff --git a/unittest/helpers.py b/unittest/helpers.py new file mode 100644 index 0000000..90c818e --- /dev/null +++ b/unittest/helpers.py @@ -0,0 +1,51 @@ +from constants import DeviceErrorCode, PWS_SLOT_COUNT, DefaultPasswords +from misc import gs, bb + + +def helper_fill(str_to_fill, target_width): + assert target_width >= len(str_to_fill) + numbers = '1234567890' * 4 + str_to_fill += numbers[:target_width - len(str_to_fill)] + assert len(str_to_fill) == target_width + return bb(str_to_fill) + + +def helper_PWS_get_pass(suffix): + return helper_fill('pass' + suffix, 20) + + +def helper_PWS_get_loginname(suffix): + return helper_fill('login' + suffix, 32) + + +def helper_PWS_get_slotname(suffix): + return helper_fill('slotname' + suffix, 11) + + +def helper_check_device_for_data(C): + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(0, PWS_SLOT_COUNT): + iss = str(i) + assert gs(C.NK_get_password_safe_slot_name(i)) == helper_PWS_get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == helper_PWS_get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == helper_PWS_get_pass(iss) + return True + + +def helper_populate_device(C): + # FIXME use object with random data, and check against it + # FIXME generate OTP as well, and check codes against its secrets + assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK + res = C.NK_enable_password_safe(DefaultPasswords.USER) + if res != DeviceErrorCode.STATUS_OK: + assert C.NK_build_aes_key(DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK + assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK + + for i in range(0, PWS_SLOT_COUNT): + iss = str(i) + assert C.NK_write_password_safe_slot(i, + helper_PWS_get_slotname(iss), helper_PWS_get_loginname(iss), + helper_PWS_get_pass(iss)) == DeviceErrorCode.STATUS_OK + return True diff --git a/unittest/misc.py b/unittest/misc.py index e9e1753..6a0d486 100644 --- a/unittest/misc.py +++ b/unittest/misc.py @@ -72,3 +72,7 @@ def is_long_OTP_secret_handled(C): def has_binary_counter(C): return (not is_storage(C)) or (is_storage(C) and get_devices_firmware_version(C) >= 54) + + +def bb(x): + return bytes(x, encoding='ascii')
\ No newline at end of file diff --git a/unittest/requirements.txt b/unittest/requirements.txt index 6d718ad..d8a7e29 100644 --- a/unittest/requirements.txt +++ b/unittest/requirements.txt @@ -1,4 +1,5 @@ cffi +pytest pytest-repeat pytest-randomly tqdm diff --git a/unittest/test_memory.c b/unittest/test_memory.c new file mode 100644 index 0000000..20b11b2 --- /dev/null +++ b/unittest/test_memory.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 Nitrokey UG + * + * This file is part of libnitrokey. + * + * libnitrokey is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * libnitrokey 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libnitrokey. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-3.0 + */ + +#include <stdlib.h> +#include "../NK_C_API.h" + +// This test should be run with valgrind to make sure that there are no +// memory leaks in the tested functions: +// valgrind ./test_memory +int main() { + int result = NK_login_auto(); + if (result != 1) + return 1; + + int retry_count = NK_get_admin_retry_count(); + if (retry_count != 3) + return 1; + retry_count = NK_get_user_retry_count(); + if (retry_count != 3) + return 1; + + enum NK_device_model model = NK_get_device_model(); + if (model != NK_PRO && model != NK_STORAGE) + return 1; + + uint8_t *config = NK_read_config(); + if (config == NULL) + return 1; + NK_free_config(config); + + result = NK_enable_password_safe("123456"); + if (result != 0) + return 1; + + uint8_t *slot_status = NK_get_password_safe_slot_status(); + if (slot_status == NULL) { + return 1; + } + NK_free_password_safe_slot_status(slot_status); + + NK_logout(); + + return 0; +} + diff --git a/unittest/test_multiple.py b/unittest/test_multiple.py index 821a3b7..96b23d7 100644 --- a/unittest/test_multiple.py +++ b/unittest/test_multiple.py @@ -28,8 +28,8 @@ from collections import defaultdict from tqdm import tqdm from conftest import skip_if_device_version_lower_than -from constants import DefaultPasswords, DeviceErrorCode, bb -from misc import gs, wait, ffi +from constants import DefaultPasswords, DeviceErrorCode +from misc import gs, wait, ffi, bb pprint = pprint.PrettyPrinter(indent=4).pprint diff --git a/unittest/test_offline.cc b/unittest/test_offline.cc index 320ad48..3ca3905 100644 --- a/unittest/test_offline.cc +++ b/unittest/test_offline.cc @@ -67,6 +67,10 @@ TEST_CASE("Test C++ side behaviour in offline", "[fast]") { REQUIRE(serial_number.empty()); REQUIRE_THROWS_AS( + i->get_serial_number_as_u32(), DeviceNotConnected + ); + + REQUIRE_THROWS_AS( i->get_status(), DeviceNotConnected ); diff --git a/unittest/test_pro.py b/unittest/test_pro.py index 203c8b1..30cd5e1 100644 --- a/unittest/test_pro.py +++ b/unittest/test_pro.py @@ -22,9 +22,10 @@ SPDX-License-Identifier: LGPL-3.0 import pytest from conftest import skip_if_device_version_lower_than -from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, bb, bbRFC_SECRET, LibraryErrors, HOTP_slot_count, \ +from constants import DefaultPasswords, DeviceErrorCode, RFC_SECRET, bbRFC_SECRET, LibraryErrors, HOTP_slot_count, \ TOTP_slot_count -from misc import ffi, gs, wait, cast_pointer_to_tuple, has_binary_counter +from helpers import helper_PWS_get_slotname, helper_PWS_get_loginname, helper_PWS_get_pass +from misc import ffi, gs, wait, cast_pointer_to_tuple, has_binary_counter, bb from misc import is_storage @pytest.mark.lock_device @@ -50,37 +51,21 @@ def test_write_password_safe_slot(C): @pytest.mark.PWS @pytest.mark.slowtest def test_write_all_password_safe_slots_and_read_10_times(C): - def fill(s, wid): - assert wid >= len(s) - numbers = '1234567890'*4 - s += numbers[:wid-len(s)] - assert len(s) == wid - return bb(s) - - def get_pass(suffix): - return fill('pass' + suffix, 20) - - def get_loginname(suffix): - return fill('login' + suffix, 32) - - def get_slotname(suffix): - return fill('slotname' + suffix, 11) - assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK PWS_slot_count = 16 for i in range(0, PWS_slot_count): iss = str(i) assert C.NK_write_password_safe_slot(i, - get_slotname(iss), get_loginname(iss), - get_pass(iss)) == DeviceErrorCode.STATUS_OK + helper_PWS_get_slotname(iss), helper_PWS_get_loginname(iss), + helper_PWS_get_pass(iss)) == DeviceErrorCode.STATUS_OK for j in range(0, 10): for i in range(0, PWS_slot_count): iss = str(i) - assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) - assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) - assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + assert gs(C.NK_get_password_safe_slot_name(i)) == helper_PWS_get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == helper_PWS_get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == helper_PWS_get_pass(iss) @pytest.mark.lock_device @@ -88,22 +73,6 @@ def test_write_all_password_safe_slots_and_read_10_times(C): @pytest.mark.slowtest @pytest.mark.xfail(reason="This test should be run directly after test_write_all_password_safe_slots_and_read_10_times") def test_read_all_password_safe_slots_10_times(C): - def fill(s, wid): - assert wid >= len(s) - numbers = '1234567890'*4 - s += numbers[:wid-len(s)] - assert len(s) == wid - return bb(s) - - def get_pass(suffix): - return fill('pass' + suffix, 20) - - def get_loginname(suffix): - return fill('login' + suffix, 32) - - def get_slotname(suffix): - return fill('slotname' + suffix, 11) - assert C.NK_lock_device() == DeviceErrorCode.STATUS_OK assert C.NK_enable_password_safe(DefaultPasswords.USER) == DeviceErrorCode.STATUS_OK PWS_slot_count = 16 @@ -111,9 +80,9 @@ def test_read_all_password_safe_slots_10_times(C): for j in range(0, 10): for i in range(0, PWS_slot_count): iss = str(i) - assert gs(C.NK_get_password_safe_slot_name(i)) == get_slotname(iss) - assert gs(C.NK_get_password_safe_slot_login(i)) == get_loginname(iss) - assert gs(C.NK_get_password_safe_slot_password(i)) == get_pass(iss) + assert gs(C.NK_get_password_safe_slot_name(i)) == helper_PWS_get_slotname(iss) + assert gs(C.NK_get_password_safe_slot_login(i)) == helper_PWS_get_loginname(iss) + assert gs(C.NK_get_password_safe_slot_password(i)) == helper_PWS_get_pass(iss) @pytest.mark.lock_device @@ -678,6 +647,30 @@ def test_read_write_config(C): config = cast_pointer_to_tuple(config_raw_data, 'uint8_t', 5) assert config == (0, 1, 2, True, False) + # use structs: read I + config_st = ffi.new('struct NK_config *') + if not config_st: + raise Exception("Could not allocate config") + assert C.NK_read_config_struct(config_st) == DeviceErrorCode.STATUS_OK + assert config_st.numlock == 0 + assert config_st.capslock == 1 + assert config_st.scrolllock == 2 + assert config_st.enable_user_password + assert not config_st.disable_user_password + + # use structs: write + config_st.numlock = 3 + assert C.NK_write_config_struct(config_st[0], DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK + + # use structs: read II + err = C.NK_read_config_struct(config_st) + assert err == 0 + assert config_st.numlock == 3 + assert config_st.capslock == 1 + assert config_st.scrolllock == 2 + assert config_st.enable_user_password + assert not config_st.disable_user_password + # restore defaults and check assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK assert C.NK_write_config(255, 255, 255, False, True, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK @@ -754,6 +747,13 @@ def test_get_serial_number(C): print(('Serial number of the device: ', sn)) +@pytest.mark.status +def test_get_serial_number_as_u32(C): + sn = C.NK_device_serial_number_as_u32() + assert sn > 0 + print(('Serial number of the device (u32): ', sn)) + + @pytest.mark.otp @pytest.mark.parametrize("secret", ['000001', '00'*10+'ff', '00'*19+'ff', '000102', '00'*29+'ff', '00'*39+'ff', '002EF43F51AFA97BA2B46418768123C9E1809A5B' ]) @@ -996,31 +996,6 @@ def test_get_device_model(C): # assert C.NK_get_device_model() != C.NK_DISCONNECTED -@pytest.mark.firmware -def test_bootloader_password_change_pro(C): - skip_if_device_version_lower_than({'P': 11}) - assert C.NK_change_firmware_password_pro(b'zxcasd', b'zxcasd') == DeviceErrorCode.WRONG_PASSWORD - - assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.STATUS_OK - assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE_TEMP, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK - - -@pytest.mark.firmware -def test_bootloader_run_pro(C): - skip_if_device_version_lower_than({'P': 11}) - assert C.NK_enable_firmware_update_pro(DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.WRONG_PASSWORD - # Not enabled due to lack of side-effect removal at this point - # assert C.NK_enable_firmware_update_pro(DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK - - -@pytest.mark.firmware -def test_bootloader_password_change_pro_too_long(C): - skip_if_device_version_lower_than({'P': 11}) - long_string = b'a' * 100 - assert C.NK_change_firmware_password_pro(long_string, long_string) == LibraryErrors.TOO_LONG_STRING - assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, long_string) == LibraryErrors.TOO_LONG_STRING - - @pytest.mark.otp @pytest.mark.parametrize('counter_mid', [10**3-1, 10**4-1, 10**7-1, 10**8-10, 2**16, 2**31-1, 2**32-1, 2**33, 2**50, 2**60, 2**63]) # 2**64-1 def test_HOTP_counter_getter(C, counter_mid: int): diff --git a/unittest/test_pro_bootloader.py b/unittest/test_pro_bootloader.py new file mode 100644 index 0000000..4cb7470 --- /dev/null +++ b/unittest/test_pro_bootloader.py @@ -0,0 +1,71 @@ +import pytest + +from conftest import skip_if_device_version_lower_than, library_device_reconnect +from constants import DefaultPasswords, DeviceErrorCode, LibraryErrors +from helpers import helper_populate_device, helper_check_device_for_data + + +@pytest.mark.firmware +def test_bootloader_password_change_pro_length(C): + skip_if_device_version_lower_than({'P': 11}) + + # Test whether the correct password is set + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + # Change to the longest possible password + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_LONG) == DeviceErrorCode.STATUS_OK + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE_LONG, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + # Use longer or shorter passwords than possible + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TOO_LONG) == LibraryErrors.TOO_LONG_STRING + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TOO_SHORT) == DeviceErrorCode.WRONG_PASSWORD + + + +@pytest.mark.firmware +def test_bootloader_password_change_pro(C): + skip_if_device_version_lower_than({'P': 11}) + assert C.NK_change_firmware_password_pro(b'zxcasd', b'zxcasd') == DeviceErrorCode.WRONG_PASSWORD + + # Revert effects of broken test run, if needed + C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE_TEMP, DefaultPasswords.UPDATE) + + # Change to the same password + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + # Change password + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.STATUS_OK + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE_TEMP, DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.firmware +def test_bootloader_run_pro_wrong_password(C): + skip_if_device_version_lower_than({'P': 11}) + assert C.NK_enable_firmware_update_pro(DefaultPasswords.UPDATE_TEMP) == DeviceErrorCode.WRONG_PASSWORD + + +@pytest.mark.skip_by_default +@pytest.mark.firmware +def test_bootloader_run_pro_real(C): + skip_if_device_version_lower_than({'P': 11}) + # Not enabled due to lack of side-effect removal at this point + assert C.NK_enable_firmware_update_pro(DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_DISCONNECTED + + +@pytest.mark.firmware +def test_bootloader_password_change_pro_too_long(C): + skip_if_device_version_lower_than({'P': 11}) + long_string = b'a' * 100 + assert C.NK_change_firmware_password_pro(long_string, long_string) == LibraryErrors.TOO_LONG_STRING + assert C.NK_change_firmware_password_pro(DefaultPasswords.UPDATE, long_string) == LibraryErrors.TOO_LONG_STRING + + +@pytest.mark.skip_by_default +@pytest.mark.firmware +def test_bootloader_data_rention(C): + skip_if_device_version_lower_than({'P': 11}) + + assert helper_populate_device(C) + assert C.NK_enable_firmware_update_pro(DefaultPasswords.UPDATE) == DeviceErrorCode.STATUS_DISCONNECTED + input('Please press ENTER after uploading new firmware to the device') + C = library_device_reconnect(C) + assert helper_check_device_for_data(C) + diff --git a/unittest/test_storage.py b/unittest/test_storage.py index 0f960cc..a435a15 100644 --- a/unittest/test_storage.py +++ b/unittest/test_storage.py @@ -23,8 +23,8 @@ import pprint import pytest from conftest import skip_if_device_version_lower_than -from constants import DefaultPasswords, DeviceErrorCode, bb -from misc import gs, wait, ffi +from constants import DefaultPasswords, DeviceErrorCode +from misc import gs, wait, ffi, bb pprint = pprint.PrettyPrinter(indent=4).pprint |