aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2018-12-29 11:52:42 -0800
committerRobin Krahl <robin.krahl@ireas.org>2019-01-05 10:26:16 +0100
commit65bff57e6139cc126191d4faabbcf74118932dd2 (patch)
treee67bf4ec413c7d0a6459b5ac4df8f40198441858
parent3593df8844b80741e2d33c8e5af80e65760dc058 (diff)
downloadnitrokey-rs-65bff57e6139cc126191d4faabbcf74118932dd2.tar.gz
nitrokey-rs-65bff57e6139cc126191d4faabbcf74118932dd2.tar.bz2
Use nitrokey-test for nitrokey device tests
This change is the first in a series to migrate the existing tests to using the nitrokey-test crate. The crate provides a couple of benefits over the existing way testing works: - test execution is automatically serialized (i.e., no more need for --test-threads) - available devices are detected at runtime (i.e., no more need for --features test-pro) - tests capable of running only on a specific device are automatically skipped if this device is not present In addition to that, the crate also offers selection of particular groups of tests by virtue of the NITROKEY_TEST_GROUP environment variable. If set (valid values are "nodev", "pro", and "storage") only tests of the particular group are run (those tests will fail if a required precondition is not met, i.e., if a device is present but "nodev" is set, or if the "pro" group is run but no device or a storage device is present). Unfortunately, it has some limitations as well. Most importantly Rust does not allow us to indicate whether a test has been skipped or not. While it has #[ignore] support, that strictly is a compile-time feature and, hence, not usable. This patch in particular pulls in the nitrokey-test crate and adjusts the existing device tests to make use of it.
-rw-r--r--CHANGELOG.md3
-rw-r--r--Cargo.toml3
-rw-r--r--tests/device.rs157
3 files changed, 54 insertions, 109 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae49683..4e2efb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# Unreleased
+- Use `nitrokey-test` to select and execute the unit tests.
+
# v0.3.0 (2019-01-04)
- Add a `force` argument to `ConfigureOtp::set_time`.
- Remove the obsolete `CommandError::RngError`.
diff --git a/Cargo.toml b/Cargo.toml
index b8f30db..3712dbe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,3 +20,6 @@ test-storage = []
libc = "0.2"
nitrokey-sys = "3.4"
rand = "0.6"
+
+[dev-dependencies]
+nitrokey-test = {version = "0.1"}
diff --git a/tests/device.rs b/tests/device.rs
index 0ad4987..0c8bb26 100644
--- a/tests/device.rs
+++ b/tests/device.rs
@@ -6,10 +6,11 @@ use std::{thread, time};
use nitrokey::{
Authenticate, CommandError, Config, ConfigureOtp, Device, GenerateOtp, GetPasswordSafe,
- OtpMode, OtpSlotData, Storage,
+ OtpMode, OtpSlotData,
};
+use nitrokey_test::test as test_device;
-use crate::util::{Target, ADMIN_PASSWORD, UPDATE_PIN, USER_PASSWORD};
+use crate::util::{ADMIN_PASSWORD, UPDATE_PIN, USER_PASSWORD};
static ADMIN_NEW_PASSWORD: &str = "1234567890";
static UPDATE_NEW_PIN: &str = "87654321";
@@ -27,36 +28,29 @@ fn count_nitrokey_block_devices() -> usize {
.count()
}
-#[test]
-#[cfg_attr(any(feature = "test-pro", feature = "test-storage"), ignore)]
+#[test_device]
fn connect_no_device() {
assert!(nitrokey::connect().is_err());
assert!(nitrokey::Pro::connect().is_err());
assert!(nitrokey::Storage::connect().is_err());
}
-#[test]
-#[cfg_attr(not(feature = "test-pro"), ignore)]
-fn connect_pro() {
+#[test_device]
+fn connect_pro(device: Pro) {
+ assert_eq!(device.get_model(), nitrokey::Model::Pro);
+ drop(device);
+
assert!(nitrokey::connect().is_ok());
assert!(nitrokey::Pro::connect().is_ok());
- assert!(nitrokey::Storage::connect().is_err());
- match nitrokey::connect().unwrap() {
- nitrokey::DeviceWrapper::Pro(_) => assert!(true),
- nitrokey::DeviceWrapper::Storage(_) => assert!(false),
- };
}
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn connect_storage() {
+#[test_device]
+fn connect_storage(device: Storage) {
+ assert_eq!(device.get_model(), nitrokey::Model::Storage);
+ drop(device);
+
assert!(nitrokey::connect().is_ok());
- assert!(nitrokey::Pro::connect().is_err());
assert!(nitrokey::Storage::connect().is_ok());
- match nitrokey::connect().unwrap() {
- nitrokey::DeviceWrapper::Pro(_) => assert!(false),
- nitrokey::DeviceWrapper::Storage(_) => assert!(true),
- };
}
fn assert_empty_serial_number() {
@@ -68,54 +62,22 @@ fn assert_empty_serial_number() {
}
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn disconnect() {
- Target::connect().unwrap();
- assert_empty_serial_number();
- Target::connect()
- .unwrap()
- .authenticate_admin(ADMIN_PASSWORD)
- .unwrap();
- assert_empty_serial_number();
- Target::connect()
- .unwrap()
- .authenticate_user(USER_PASSWORD)
- .unwrap();
+#[test_device]
+fn disconnect(device: DeviceWrapper) {
+ drop(device);
assert_empty_serial_number();
}
-fn require_model(model: nitrokey::Model) {
- assert_eq!(model, nitrokey::connect().unwrap().get_model());
- assert_eq!(model, Target::connect().unwrap().get_model());
-}
-
-#[test]
-#[cfg_attr(not(feature = "test-pro"), ignore)]
-fn get_model_pro() {
- require_model(nitrokey::Model::Pro);
-}
-
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn get_model_storage() {
- require_model(nitrokey::Model::Storage);
-}
-
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn get_serial_number() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn get_serial_number(device: DeviceWrapper) {
let result = device.get_serial_number();
assert!(result.is_ok());
let serial_number = result.unwrap();
assert!(serial_number.is_ascii());
assert!(serial_number.chars().all(|c| c.is_ascii_hexdigit()));
}
-#[test]
-#[cfg_attr(not(feature = "test-pro"), ignore)]
-fn get_firmware_version() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn get_firmware_version(device: Pro) {
assert_eq!(0, device.get_major_firmware_version());
let minor = device.get_minor_firmware_version();
assert!(minor > 0);
@@ -141,11 +103,8 @@ fn user_retry<T: Authenticate + Device>(device: T, suffix: &str, count: u8) -> T
return device;
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn get_retry_count() {
- let device = Target::connect().unwrap();
-
+#[test_device]
+fn get_retry_count(device: DeviceWrapper) {
let device = admin_retry(device, "", 3);
let device = admin_retry(device, "123", 2);
let device = admin_retry(device, "456", 1);
@@ -157,10 +116,8 @@ fn get_retry_count() {
user_retry(device, "", 3);
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn config() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn config(device: DeviceWrapper) {
let admin = device.authenticate_admin(ADMIN_PASSWORD).unwrap();
let config = Config::new(None, None, None, true);
assert!(admin.write_config(config).is_ok());
@@ -181,10 +138,8 @@ fn config() {
assert_eq!(config, get_config);
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn change_user_pin() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn change_user_pin(device: DeviceWrapper) {
let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
let device = device.authenticate_user(USER_NEW_PASSWORD).unwrap_err().0;
@@ -209,10 +164,8 @@ fn change_user_pin() {
assert!(device.authenticate_user(USER_NEW_PASSWORD).is_err());
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn change_admin_pin() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn change_admin_pin(device: DeviceWrapper) {
let device = device.authenticate_admin(ADMIN_PASSWORD).unwrap().device();
let device = device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err().0;
@@ -239,7 +192,11 @@ fn change_admin_pin() {
device.authenticate_admin(ADMIN_NEW_PASSWORD).unwrap_err();
}
-fn require_failed_user_login(device: Target, password: &str, error: CommandError) -> Target {
+fn require_failed_user_login<D>(device: D, password: &str, error: CommandError) -> D
+where
+ D: Device + Authenticate,
+ nitrokey::User<D>: std::fmt::Debug,
+{
let result = device.authenticate_user(password);
assert!(result.is_err());
let err = result.unwrap_err();
@@ -247,10 +204,8 @@ fn require_failed_user_login(device: Target, password: &str, error: CommandError
err.0
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn unlock_user_pin() {
- let device = Target::connect().unwrap();
+#[test_device]
+fn unlock_user_pin(device: DeviceWrapper) {
let device = device.authenticate_user(USER_PASSWORD).unwrap().device();
assert!(device
.unlock_user_pin(ADMIN_PASSWORD, USER_PASSWORD)
@@ -298,11 +253,8 @@ fn unlock_user_pin() {
.is_ok());
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn factory_reset() {
- let device = Target::connect().unwrap();
-
+#[test_device]
+fn factory_reset(device: DeviceWrapper) {
assert_eq!(
Ok(()),
device.change_user_pin(USER_PASSWORD, USER_NEW_PASSWORD)
@@ -348,11 +300,8 @@ fn factory_reset() {
assert_eq!(Ok(()), device.build_aes_key(ADMIN_PASSWORD));
}
-#[test]
-#[cfg_attr(not(any(feature = "test-pro", feature = "test-storage")), ignore)]
-fn build_aes_key() {
- let device = Target::connect().unwrap();
-
+#[test_device]
+fn build_aes_key(device: DeviceWrapper) {
let pws = device.get_password_safe(USER_PASSWORD).unwrap();
assert_eq!(Ok(()), pws.write_slot(0, "test", "testlogin", "testpw"));
drop(pws);
@@ -371,11 +320,8 @@ fn build_aes_key() {
assert_ne!("testpw".to_string(), pws.get_slot_password(0).unwrap());
}
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn change_update_pin() {
- let device = Storage::connect().unwrap();
-
+#[test_device]
+fn change_update_pin(device: Storage) {
assert_eq!(
Err(CommandError::WrongPassword),
device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN)
@@ -384,10 +330,8 @@ fn change_update_pin() {
assert_eq!(Ok(()), device.change_update_pin(UPDATE_NEW_PIN, UPDATE_PIN));
}
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn encrypted_volume() {
- let device = Storage::connect().unwrap();
+#[test_device]
+fn encrypted_volume(device: Storage) {
assert!(device.lock().is_ok());
assert_eq!(1, count_nitrokey_block_devices());
@@ -404,20 +348,15 @@ fn encrypted_volume() {
assert_eq!(1, count_nitrokey_block_devices());
}
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn lock() {
- let device = Storage::connect().unwrap();
-
+#[test_device]
+fn lock(device: Storage) {
assert!(device.enable_encrypted_volume(USER_PASSWORD).is_ok());
assert!(device.lock().is_ok());
assert_eq!(1, count_nitrokey_block_devices());
}
-#[test]
-#[cfg_attr(not(feature = "test-storage"), ignore)]
-fn get_storage_status() {
- let device = Storage::connect().unwrap();
+#[test_device]
+fn get_storage_status(device: Storage) {
let status = device.get_status().unwrap();
assert!(status.serial_number_sd_card > 0);