aboutsummaryrefslogtreecommitdiff
path: root/unittest
diff options
context:
space:
mode:
Diffstat (limited to 'unittest')
-rw-r--r--unittest/conftest.py72
-rw-r--r--unittest/requirements.txt3
-rw-r--r--unittest/test_multiple.py29
-rw-r--r--unittest/test_multiple_devices.cc81
-rw-r--r--unittest/test_offline.py39
-rw-r--r--unittest/test_storage.py30
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)