diff options
Diffstat (limited to 'unittest')
-rw-r--r-- | unittest/conftest.py | 72 | ||||
-rw-r--r-- | unittest/requirements.txt | 3 | ||||
-rw-r--r-- | unittest/test_multiple.py | 29 | ||||
-rw-r--r-- | unittest/test_multiple_devices.cc | 81 | ||||
-rw-r--r-- | unittest/test_offline.py | 39 | ||||
-rw-r--r-- | unittest/test_storage.py | 30 |
6 files changed, 233 insertions, 21 deletions
diff --git a/unittest/conftest.py b/unittest/conftest.py index 253e1d8..a9f46c6 100644 --- a/unittest/conftest.py +++ b/unittest/conftest.py @@ -21,10 +21,17 @@ SPDX-License-Identifier: LGPL-3.0 import pytest -from misc import ffi +from misc import ffi, gs device_type = None +from logging import getLogger, basicConfig, DEBUG + +basicConfig(format='* %(relativeCreated)6d %(filename)s:%(lineno)d %(message)s',level=DEBUG) +log = getLogger('conftest') +print = log.debug + + def skip_if_device_version_lower_than(allowed_devices): global device_type model, version = device_type @@ -33,8 +40,45 @@ def skip_if_device_version_lower_than(allowed_devices): pytest.skip('This device model is not applicable to run this test') +class AtrrCallProx(object): + def __init__(self, C, name): + self.C = C + self.name = name + + def __call__(self, *args, **kwargs): + print('Calling {}{}'.format(self.name, args)) + res = self.C(*args, **kwargs) + res_s = res + try: + res_s = '{} => '.format(res) + '{}'.format(gs(res)) + except Exception as e: + pass + print('Result of {}: {}'.format(self.name, res_s)) + return res + + +class AttrProxy(object): + def __init__(self, C, name): + self.C = C + self.name = name + + def __getattr__(self, attr): + return AtrrCallProx(getattr(self.C, attr), attr) + + +@pytest.fixture(scope="module") +def C_offline(request=None): + print("Getting library without initializing connection") + return get_library(request, allow_offline=True) + + @pytest.fixture(scope="module") def C(request=None): + print("Getting library with connection initialized") + return get_library(request) + + +def get_library(request, allow_offline=False): fp = '../NK_C_API.h' declarations = [] @@ -44,13 +88,13 @@ def C(request=None): cnt = 0 a = iter(declarations) for declaration in a: - if declaration.strip().startswith('NK_C_API'): + if declaration.strip().startswith('NK_C_API') \ + or declaration.strip().startswith('struct'): declaration = declaration.replace('NK_C_API', '').strip() - while ';' not in declaration: - declaration += (next(a)).strip() - # print(declaration) + while ');' not in declaration and '};' not in declaration: + declaration += (next(a)).strip()+'\n' ffi.cdef(declaration, override=True) - cnt +=1 + cnt += 1 print('Imported {} declarations'.format(cnt)) C = None @@ -82,12 +126,13 @@ def C(request=None): nk_login = C.NK_login_auto() if nk_login != 1: print('No devices detected!') - assert nk_login != 0 # returns 0 if not connected or wrong model or 1 when connected - global device_type - firmware_version = C.NK_get_minor_firmware_version() - model = 'P' if firmware_version < 20 else 'S' - device_type = (model, firmware_version) - print('Connected device: {} {}'.format(model, firmware_version)) + if not allow_offline: + assert nk_login != 0 # returns 0 if not connected or wrong model or 1 when connected + global device_type + firmware_version = C.NK_get_minor_firmware_version() + model = 'P' if firmware_version < 20 else 'S' + device_type = (model, firmware_version) + print('Connected device: {} {}'.format(model, firmware_version)) # assert C.NK_first_authenticate(DefaultPasswords.ADMIN, DefaultPasswords.ADMIN_TEMP) == DeviceErrorCode.STATUS_OK # assert C.NK_user_authenticate(DefaultPasswords.USER, DefaultPasswords.USER_TEMP) == DeviceErrorCode.STATUS_OK @@ -104,4 +149,5 @@ def C(request=None): # C.NK_set_debug(True) C.NK_set_debug_level(int(os.environ.get('LIBNK_DEBUG', 3))) - return C + return AttrProxy(C, "libnitrokey C") + diff --git a/unittest/requirements.txt b/unittest/requirements.txt index 5c0110b..6d718ad 100644 --- a/unittest/requirements.txt +++ b/unittest/requirements.txt @@ -1,4 +1,5 @@ cffi pytest-repeat pytest-randomly -oath
\ No newline at end of file +tqdm +oath diff --git a/unittest/test_multiple.py b/unittest/test_multiple.py index 3f1d2d5..821a3b7 100644 --- a/unittest/test_multiple.py +++ b/unittest/test_multiple.py @@ -29,13 +29,40 @@ from tqdm import tqdm from conftest import skip_if_device_version_lower_than from constants import DefaultPasswords, DeviceErrorCode, bb -from misc import gs, wait +from misc import gs, wait, ffi pprint = pprint.PrettyPrinter(indent=4).pprint @pytest.mark.other @pytest.mark.info +def test_list_devices(C): + infos = C.NK_list_devices() + assert infos != ffi.NULL + C.NK_free_device_info(infos) + + +@pytest.mark.other +@pytest.mark.info +def test_connect_with_path(C): + ids = gs(C.NK_list_devices_by_cpuID()) + # NK_list_devices_by_cpuID already opened the devices, so we have to close + # them before trying to reconnect + assert C.NK_logout() == 0 + + devices_list = ids.split(b';') + for value in devices_list: + parts = value.split(b'_p_') + assert len(parts) < 3 + if len(parts) == 2: + path = parts[1] + else: + path = parts[0] + assert C.NK_connect_with_path(path) == 1 + + +@pytest.mark.other +@pytest.mark.info def test_get_status_storage_multiple(C): ids = gs(C.NK_list_devices_by_cpuID()) print(ids) diff --git a/unittest/test_multiple_devices.cc b/unittest/test_multiple_devices.cc index cd78681..4b1e2c1 100644 --- a/unittest/test_multiple_devices.cc +++ b/unittest/test_multiple_devices.cc @@ -29,15 +29,40 @@ const char * RFC_SECRET = "12345678901234567890"; #include <iostream> #include <NitrokeyManager.h> #include <stick20_commands.h> +#include "../NK_C_API.h" using namespace nitrokey; TEST_CASE("List devices", "[BASIC]") { + auto v = Device::enumerate(); + REQUIRE(v.size() > 0); + for (auto i : v){ + auto d = Device::create(i.m_deviceModel); + if (!d) { + std::cout << "Could not create device with model " << i.m_deviceModel << "\n"; + continue; + } + std::cout << i.m_deviceModel << " " << i.m_path << " " + << i.m_serialNumber << " |"; + d->set_path(i.m_path); + d->connect(); + auto res = GetStatus::CommandTransaction::run(d); + std::cout << " " << res.data().card_serial_u32 << " " + << res.data().get_card_serial_hex() + << std::endl; + d->disconnect(); + } +} + +TEST_CASE("List Storage devices", "[BASIC]") { shared_ptr<Stick20> d = make_shared<Stick20>(); - auto v = d->enumerate(); + auto v = Device::enumerate(); REQUIRE(v.size() > 0); - for (auto a : v){ + for (auto i : v){ + if (i.m_deviceModel != DeviceModel::STORAGE) + continue; + auto a = i.m_path; std::cout << a; d->set_path(a); d->connect(); @@ -53,11 +78,14 @@ TEST_CASE("List devices", "[BASIC]") { TEST_CASE("Regenerate AES keys", "[BASIC]") { shared_ptr<Stick20> d = make_shared<Stick20>(); - auto v = d->enumerate(); + auto v = Device::enumerate(); REQUIRE(v.size() > 0); std::vector<shared_ptr<Stick20>> devices; - for (auto a : v){ + for (auto i : v){ + if (i.m_deviceModel != DeviceModel::STORAGE) + continue; + auto a = i.m_path; std::cout << a << endl; d = make_shared<Stick20>(); d->set_path(a); @@ -81,14 +109,57 @@ TEST_CASE("Regenerate AES keys", "[BASIC]") { } +TEST_CASE("Use C API", "[BASIC]") { + auto ptr = NK_list_devices(); + auto first_ptr = ptr; + REQUIRE(ptr != nullptr); + + while (ptr) { + std::cout << "Connect with: " << ptr->model << " " << ptr->path << " " + << ptr->serial_number << " | " << NK_connect_with_path(ptr->path) << " | "; + auto status = NK_status(); + std::cout << status << std::endl; + free(status); + ptr = ptr->next; + } + + NK_free_device_info(first_ptr); +} + + TEST_CASE("Use API", "[BASIC]") { auto nm = NitrokeyManager::instance(); nm->set_loglevel(2); auto v = nm->list_devices(); REQUIRE(v.size() > 0); + for (auto i : v) { + std::cout << "Connect with: " << i.m_deviceModel << " " << i.m_path << " " + << i.m_serialNumber << " | " << std::boolalpha << nm->connect_with_path(i.m_path) << " |"; + try { + auto status = nm->get_status(); + std::cout << " " << status.card_serial_u32 << " " + << status.get_card_serial_hex() + << std::endl; + } catch (const LongOperationInProgressException &e) { + std::cout << "long operation in progress on " << i.m_path + << " " << std::to_string(e.progress_bar_value) << std::endl; + } + } +} + + +TEST_CASE("Use Storage API", "[BASIC]") { + auto nm = NitrokeyManager::instance(); + nm->set_loglevel(2); + auto v = nm->list_devices(); + REQUIRE(v.size() > 0); + for (int i=0; i<10; i++){ - for (auto a : v) { + for (auto i : v) { + if (i.m_deviceModel != DeviceModel::STORAGE) + continue; + auto a = i.m_path; std::cout <<"Connect with: " << a << " " << std::boolalpha << nm->connect_with_path(a) << " "; try{ diff --git a/unittest/test_offline.py b/unittest/test_offline.py new file mode 100644 index 0000000..51fe67d --- /dev/null +++ b/unittest/test_offline.py @@ -0,0 +1,39 @@ +""" +Copyright (c) 2019 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 +""" + +from misc import gs +import re + + +def test_offline(C_offline): + C_offline.NK_set_debug(False) + C_offline.NK_set_debug_level(4) + assert C_offline.NK_get_major_library_version() == 3 + assert C_offline.NK_get_minor_library_version() >= 3 + assert C_offline.NK_login_auto() == 0 + + libnk_version = gs(C_offline.NK_get_library_version()) + assert libnk_version + print(libnk_version) + + # v3.4.1-29-g1f3d + search = re.search(b'v\d\.\d(\.\d)?', libnk_version) + assert search is not None
\ No newline at end of file diff --git a/unittest/test_storage.py b/unittest/test_storage.py index 2aa8441..04b0581 100644 --- a/unittest/test_storage.py +++ b/unittest/test_storage.py @@ -24,7 +24,8 @@ import pytest from conftest import skip_if_device_version_lower_than from constants import DefaultPasswords, DeviceErrorCode, bb -from misc import gs, wait +from misc import gs, wait, ffi + pprint = pprint.PrettyPrinter(indent=4).pprint @@ -367,3 +368,30 @@ def test_send_startup(C): skip_if_device_version_lower_than({'S': 43}) time_seconds_from_epoch = 0 # FIXME set proper date assert C.NK_send_startup(time_seconds_from_epoch) == DeviceErrorCode.STATUS_OK + + +@pytest.mark.other +def test_struct_multiline_prodtest(C): + info_st = ffi.new('struct NK_storage_ProductionTest *') + if info_st is None: raise Exception('Invalid value') + err = C.NK_get_storage_production_info(info_st) + assert err == 0 + assert info_st.SD_Card_ManufacturingYear_u8 != 0 + assert info_st.SD_Card_ManufacturingMonth_u8 != 0 + assert info_st.SD_Card_Size_u8 != 0 + assert info_st.FirmwareVersion_au8[0] == 0 + assert info_st.FirmwareVersion_au8[1] >= 50 + + info = 'CPU:{CPU},SC:{SC},SD:{SD},' \ + 'SCM:{SCM},SCO:{SCO},DAT:{DAT},Size:{size},Firmware:{fw} - {fwb}'.format( + CPU='0x{:08x}'.format(info_st.CPU_CardID_u32), + SC='0x{:08x}'.format(info_st.SmartCardID_u32), + SD='0x{:08x}'.format(info_st.SD_CardID_u32), + SCM='0x{:02x}'.format(info_st.SD_Card_Manufacturer_u8), + SCO='0x{:04x}'.format(info_st.SD_Card_OEM_u16), + DAT='20{}.{}'.format(info_st.SD_Card_ManufacturingYear_u8, info_st.SD_Card_ManufacturingMonth_u8), + size=info_st.SD_Card_Size_u8, + fw='{}.{}'.format(info_st.FirmwareVersion_au8[0], info_st.FirmwareVersion_au8[1]), + fwb=info_st.FirmwareVersionInternal_u8 + ) + print(info) |