Skip to content

Commit 7c173fc

Browse files
simo5Gemini
andcommitted
Add multi-backend support to integration tests
The test setup helper functions in `rc_common` are refactored to simplify testing against multiple database backends. The `setup_token` function now dynamically generates the configuration required for sqlite, nssdb, and memory backends. This allows for more comprehensive integration testing. A new test is added to verify that token state is correctly preserved after a `C_Finalize` and `C_Initialize` sequence. This new, higher-level test replaces the previous C-style re-initialization tests. Existing tests are updated to use the new, unified setup function. Co-authored-by: Gemini <gemini@google.com> Signed-off-by: Simo Sorce <simo@redhat.com>
1 parent 4f3904b commit 7c173fc

File tree

7 files changed

+131
-82
lines changed

7 files changed

+131
-82
lines changed

cdylib/tests/rc_common.rs

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use cryptoki::slot::Slot;
77
use cryptoki::types::AuthPin;
88
use std::env;
99
use std::fs;
10-
use std::path::{Path, PathBuf};
10+
use std::path::PathBuf;
1111

1212
fn _setup_common() -> (Pkcs11, Slot) {
1313
let module = env::var("TEST_PKCS11_MODULE").unwrap_or_else(|_| {
@@ -72,40 +72,57 @@ fn setup_test_dir(name: &str) -> PathBuf {
7272
testdir
7373
}
7474

75-
pub fn setup_token(name: &str) -> (Pkcs11, Slot) {
76-
let testdir = setup_test_dir(name);
77-
let confname = testdir.join(format!("{}.sql", name));
78-
79-
// Set KRYOPTIC_CONF for the C library. Using `std::env::set_var` is not thread-safe.
80-
unsafe {
81-
env::set_var("KRYOPTIC_CONF", confname);
82-
}
83-
84-
_setup_common()
85-
}
86-
87-
pub fn setup(name: &str, common_config_lines: &[&str]) -> (Pkcs11, Slot) {
75+
pub fn setup_token(name: &str, common_config_lines: &[&str]) -> (Pkcs11, Slot) {
8876
let testdir = setup_test_dir(name);
8977
let confname = testdir.join(format!("{}.conf", name));
90-
let sql_path = testdir.join(format!("{}.sql", name));
9178

9279
let mut config_content = String::new();
80+
let mut dbtype = "sqlite".to_string();
9381

94-
// Add common section lines
82+
let mut final_config_lines = Vec::new();
9583
for line in common_config_lines {
84+
let line_str = *line;
85+
if line_str.starts_with("dbtype=") {
86+
dbtype = line_str.splitn(2, '=').nth(1).unwrap().trim().to_string();
87+
} else {
88+
final_config_lines.push(line_str);
89+
}
90+
}
91+
92+
match dbtype.as_str() {
93+
"sqlite" | "nssdb" | "memory" => {}
94+
_ => panic!("Unsupported dbtype: {}", dbtype),
95+
}
96+
97+
// Add common section lines
98+
for line in final_config_lines {
9699
config_content.push_str(line);
97100
config_content.push('\n');
98101
}
99102

100-
// Add slot configuration pointing to the sqlite db
103+
// Add slot configuration
104+
let dbargs = match dbtype.as_str() {
105+
"sqlite" => {
106+
let sql_path = testdir.join(format!("{}.sql", name));
107+
sql_path.to_str().unwrap().replace('\\', "\\\\")
108+
}
109+
"nssdb" => format!(
110+
"configDir={}",
111+
testdir.to_str().unwrap().replace('\\', "\\\\")
112+
),
113+
"memory" => "flags=encrypt".to_string(),
114+
_ => unreachable!(),
115+
};
116+
101117
let slot_config = format!(
102118
r#"
103119
[[slots]]
104120
slot = 0
105-
dbtype = "sqlite"
121+
dbtype = "{}"
106122
dbargs = "{}"
107123
"#,
108-
sql_path.to_str().unwrap().replace('\\', "\\\\")
124+
dbtype,
125+
dbargs.replace('\\', "\\\\")
109126
);
110127
config_content.push_str(&slot_config);
111128

@@ -119,6 +136,7 @@ pub fn setup(name: &str, common_config_lines: &[&str]) -> (Pkcs11, Slot) {
119136
_setup_common()
120137
}
121138

139+
#[allow(dead_code)]
122140
pub fn modify_setup(
123141
name: &str,
124142
common_config_lines: &[&str],
@@ -130,25 +148,53 @@ pub fn modify_setup(
130148
)
131149
.join(name);
132150
let confname = testdir.join(format!("{}.conf", name));
133-
let sql_path = testdir.join(format!("{}.sql", name));
134151

135152
let mut config_content = String::new();
153+
let mut dbtype = "sqlite".to_string();
136154

137-
// Add common section lines
155+
let mut final_config_lines = Vec::new();
138156
for line in common_config_lines {
157+
let line_str = *line;
158+
if line_str.starts_with("dbtype=") {
159+
dbtype = line_str.splitn(2, '=').nth(1).unwrap().trim().to_string();
160+
} else {
161+
final_config_lines.push(line_str);
162+
}
163+
}
164+
165+
match dbtype.as_str() {
166+
"sqlite" | "nssdb" | "memory" => {}
167+
_ => panic!("Unsupported dbtype: {}", dbtype),
168+
}
169+
170+
// Add common section lines
171+
for line in final_config_lines {
139172
config_content.push_str(line);
140173
config_content.push('\n');
141174
}
142175

143-
// Add slot configuration pointing to the sqlite db
176+
// Add slot configuration
177+
let dbargs = match dbtype.as_str() {
178+
"sqlite" => {
179+
let sql_path = testdir.join(format!("{}.sql", name));
180+
sql_path.to_str().unwrap().replace('\\', "\\\\")
181+
}
182+
"nssdb" => format!(
183+
"configDir={}",
184+
testdir.to_str().unwrap().replace('\\', "\\\\")
185+
),
186+
"memory" => "flags=encrypt".to_string(),
187+
_ => unreachable!(),
188+
};
189+
144190
let slot_config = format!(
145191
r#"
146192
[[slots]]
147193
slot = 0
148-
dbtype = "sqlite"
194+
dbtype = "{}"
149195
dbargs = "{}"
150196
"#,
151-
sql_path.to_str().unwrap().replace('\\', "\\\\")
197+
dbtype, dbargs
152198
);
153199
config_content.push_str(&slot_config);
154200

cdylib/tests/rc_ecdh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn ecdh_reimport_loop_test() -> Result<(), Box<dyn std::error::Error>> {
1212
use cryptoki::types::AuthPin;
1313
use std::env;
1414

15-
let (pkcs11, slot) = rc_common::setup_token("ecdh_reimport_loop_test");
15+
let (pkcs11, slot) = rc_common::setup_token("ecdh_reimport_loop_test", &[]);
1616

1717
let user_pin = AuthPin::new("12345678".into());
1818
let session = pkcs11.open_rw_session(slot)?;

cdylib/tests/rc_eddsa_compat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use cryptoki::types::AuthPin;
1111
#[cfg(feature = "integration_tests")]
1212
fn rc_eddsa_compat() -> Result<(), Box<dyn std::error::Error>> {
1313
// Setup with default configuration
14-
let (pkcs11, slot) = rc_common::setup("rc_eddsa_compat", &[]);
14+
let (pkcs11, slot) = rc_common::setup_token("rc_eddsa_compat", &[]);
1515

1616
// Test Vectors for Ed25519ctx from C_CreateObject
1717
let point: Vec<u8> = vec![

cdylib/tests/rc_login.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
mod rc_common;
55

66
use cryptoki::session::UserType;
7-
use cryptoki::slot::Slot;
87
use cryptoki::types::AuthPin;
98

109
#[test]
@@ -14,7 +13,7 @@ fn test_login() -> Result<(), Box<dyn std::error::Error>> {
1413
use cryptoki::error::{Error, RvError};
1514
use cryptoki::session::SessionState;
1615

17-
let (pkcs11, slot) = rc_common::setup_token("test_login");
16+
let (pkcs11, slot) = rc_common::setup_token("test_login", &[]);
1817

1918
let ro_session = pkcs11.open_ro_session(slot)?;
2019
let info = ro_session.get_session_info()?;

cdylib/tests/rc_re_initialize.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2024 Simo Sorce
2+
// See LICENSE.txt file for terms
3+
4+
mod rc_common;
5+
6+
use cryptoki::context::{CInitializeArgs, CInitializeFlags, Pkcs11};
7+
use cryptoki::session::UserType;
8+
use cryptoki::types::AuthPin;
9+
use std::env;
10+
11+
fn test_re_initialize_common(
12+
dbtype: &str,
13+
) -> Result<(), Box<dyn std::error::Error>> {
14+
let test_name = format!("test_re_initialize_{}", dbtype);
15+
let config_dbtype = format!("dbtype={}", dbtype);
16+
let (pkcs11, slot) = rc_common::setup_token(&test_name, &[&config_dbtype]);
17+
18+
// Check the token info and get label
19+
let token_info = pkcs11.get_token_info(slot)?;
20+
let expected_label = token_info.label();
21+
22+
// Now finalize the token
23+
pkcs11.finalize()?;
24+
25+
// Re-initialize and check that we can still access data
26+
let module = env::var("TEST_PKCS11_MODULE").unwrap_or_else(|_| {
27+
"../target/debug/libkryoptic_pkcs11.so".to_string()
28+
});
29+
let pkcs11 = Pkcs11::new(&module).expect("Failed to load PKCS#11 module");
30+
pkcs11
31+
.initialize(CInitializeArgs::new(CInitializeFlags::OS_LOCKING_OK))
32+
.expect("Failed to re-initialize PKCS#11");
33+
34+
// Check the token info to see if state was preserved.
35+
let token_info = pkcs11.get_token_info(slot)?;
36+
assert_eq!(token_info.label(), expected_label);
37+
38+
// We should be able to log in.
39+
let session = pkcs11.open_rw_session(slot)?;
40+
let user_pin = AuthPin::new("12345678".into());
41+
session.login(UserType::User, Some(&user_pin))?;
42+
session.logout()?;
43+
44+
Ok(())
45+
}
46+
47+
#[test]
48+
fn test_re_initialize() -> Result<(), Box<dyn std::error::Error>> {
49+
#[cfg(all(feature = "integration_tests", feature = "default"))]
50+
test_re_initialize_common("sqlite")?;
51+
52+
#[cfg(all(feature = "integration_tests", feature = "nssdb"))]
53+
test_re_initialize_common("nssdb")?;
54+
55+
Ok(())
56+
}

cdylib/tests/rust_cryptoki.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn basic_example() -> Result<(), Box<dyn std::error::Error>> {
1111
use cryptoki::session::UserType;
1212
use cryptoki::types::AuthPin;
1313

14-
let (pkcs11, slot) = rc_common::setup_token("basic_example");
14+
let (pkcs11, slot) = rc_common::setup_token("basic_example", &[]);
1515

1616
let user_pin = AuthPin::new("12345678".into());
1717

src/tests/init.rs

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use crate::fips::indicators::KRF_FIPS;
66
use crate::tests::*;
77

8-
use serial_test::{parallel, serial};
8+
use serial_test::parallel;
99

1010
#[test]
1111
#[parallel]
@@ -261,55 +261,3 @@ fn test_init_token() {
261261

262262
testtokn.finalize();
263263
}
264-
265-
fn test_re_init_token_common(dbtype: String, dbargs: String) {
266-
let mut testtokn =
267-
TestToken::new_type(dbtype, dbargs, String::from("test_reinit_token"));
268-
269-
let mut args = TestToken::make_init_args(Some(testtokn.make_init_string()));
270-
let args_ptr = &mut args as *mut CK_C_INITIALIZE_ARGS;
271-
let mut ret = fn_initialize(args_ptr as *mut std::ffi::c_void);
272-
assert_in!(ret, [CKR_OK, CKR_CRYPTOKI_ALREADY_INITIALIZED]);
273-
274-
/* init once */
275-
let pin_value = "SO Pin Value";
276-
ret = fn_init_token(
277-
testtokn.get_slot(),
278-
CString::new(pin_value).unwrap().into_raw() as *mut u8,
279-
pin_value.len() as CK_ULONG,
280-
std::ptr::null_mut(),
281-
);
282-
assert_eq!(ret, CKR_OK);
283-
284-
let ret = fn_finalize(std::ptr::null_mut() as *mut std::ffi::c_void);
285-
assert_eq!(ret, CKR_OK);
286-
287-
let ret = fn_initialize(args_ptr as *mut std::ffi::c_void);
288-
assert_eq!(ret, CKR_OK);
289-
290-
testtokn.finalize();
291-
}
292-
293-
#[cfg(feature = "sqlitedb")]
294-
#[test]
295-
#[serial]
296-
fn test_re_init_token_sql() {
297-
let dbargs = format!("{}/{}", TESTDIR, "test_reinit_token.sql");
298-
test_re_init_token_common(String::from("sqlite"), dbargs)
299-
}
300-
301-
#[cfg(feature = "nssdb")]
302-
#[test]
303-
#[serial]
304-
fn test_re_init_token_nss() {
305-
let dbargs = format!("configDir={}/{}", TESTDIR, "test_reinit_token");
306-
test_re_init_token_common(String::from("nssdb"), dbargs)
307-
}
308-
309-
#[cfg(feature = "memorydb")]
310-
#[test]
311-
#[serial]
312-
fn test_re_init_token_memory() {
313-
let dbargs = "flags=encrypt".to_string();
314-
test_re_init_token_common(String::from("memory"), dbargs)
315-
}

0 commit comments

Comments
 (0)