Add unit tests for core components
Some checks failed
Makefile CI / Release - Linux-x86_64 (push) Has been cancelled
Makefile CI / Release - Windows-x86_64 (push) Has been cancelled

This commit is contained in:
2025-04-10 13:44:35 -04:00
parent 2bb5ce0327
commit c9f8325da9
4 changed files with 348 additions and 30 deletions

92
Cargo.lock generated
View File

@@ -377,7 +377,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -412,7 +412,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -565,7 +565,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -701,7 +701,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -889,7 +889,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -1073,7 +1073,7 @@ checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -1228,7 +1228,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -1279,7 +1279,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -1682,7 +1682,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -1937,6 +1937,26 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "mock-it"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c79f6245a4564f117ae4e640a829a7b425e641ca3e6ea279d74a9caf05d2daf"
dependencies = [
"mock-it_codegen",
]
[[package]]
name = "mock-it_codegen"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a887ee7c909093b773c59ee57412f0fd29d2f262905eeea721cfc31a38e18f"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "naga"
version = "23.1.0"
@@ -2043,7 +2063,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2370,7 +2390,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2401,7 +2421,7 @@ checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2704,7 +2724,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2727,7 +2747,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2764,6 +2784,7 @@ dependencies = [
"fast_config",
"hidapi",
"log",
"mock-it",
"serde",
]
@@ -2890,6 +2911,17 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.96"
@@ -2909,7 +2941,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2961,7 +2993,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -2972,7 +3004,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -3046,7 +3078,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -3193,7 +3225,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"wasm-bindgen-shared",
]
@@ -3228,7 +3260,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -3560,7 +3592,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -3571,7 +3603,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -3979,7 +4011,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"synstructure",
]
@@ -4039,7 +4071,7 @@ checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"zbus-lockstep",
"zbus_xml",
"zvariant",
@@ -4054,7 +4086,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"zvariant_utils",
]
@@ -4100,7 +4132,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -4120,7 +4152,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"synstructure",
]
@@ -4143,7 +4175,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]
[[package]]
@@ -4168,7 +4200,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
"zvariant_utils",
]
@@ -4180,5 +4212,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.96",
]

View File

@@ -5,6 +5,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "shift_tool"
path = "src/main.rs"
[lib]
name = "vpc_shift_tool"
path = "src/lib.rs"
[dependencies]
clap = { version = "4.5.4", features = ["derive"] }
eframe = "0.30.0"
@@ -21,3 +29,6 @@ chrono = "0.4.40"
logging = []
default = ["logging"]
[dev-dependencies]
mock-it = "0.9.0"

78
src/lib.rs Normal file
View File

@@ -0,0 +1,78 @@
// Export modules for testing
pub mod about;
pub mod config;
pub mod device;
pub mod hid_worker;
pub mod state;
pub mod ui;
pub mod util;
// Re-export main struct and types for testing
pub use crate::config::ConfigData;
pub use crate::device::VpcDevice;
pub use crate::state::State;
// Constants
pub const PROGRAM_TITLE: &str = "OpenVPC - Shift Tool";
pub const INITIAL_WIDTH: f32 = 740.0;
pub const INITIAL_HEIGHT: f32 = 260.0;
// Type aliases for shared state
pub use std::sync::{Arc, Condvar, Mutex};
pub type SharedStateFlag = Arc<(Mutex<bool>, Condvar)>;
pub type SharedDeviceState = Arc<Mutex<u16>>;
// Args struct for command line parsing
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
#[arg(short, long, default_value_t = false)]
pub skip_firmware: bool,
}
// Wrapper for ConfigData to match the actual structure
pub use fast_config::Config;
// The main application struct
pub struct ShiftTool {
// State
pub state: State,
pub thread_state: SharedStateFlag, // Is the worker thread running?
// Device Data
pub device_list: Vec<VpcDevice>, // List of discovered compatible devices
// Shared state between UI and Worker Thread
pub shift_state: SharedDeviceState, // Current shift state
pub source_states: Vec<SharedDeviceState>, // Current state of each source device
pub receiver_states: Vec<SharedDeviceState>, // Current state of each receiver device
// Configuration
pub config: Config<ConfigData>,
pub selected_source: usize,
pub selected_receiver: usize,
}
// Implementations for ShiftTool
impl ShiftTool {
// Add a new source state tracking object
pub fn add_source_state(&mut self) {
self.source_states.push(Arc::new(Mutex::new(0)));
}
// Add a new receiver state tracking object
pub fn add_receiver_state(&mut self) {
self.receiver_states.push(Arc::new(Mutex::new(0)));
}
// Get the current thread status
pub fn get_thread_status(&self) -> bool {
let &(ref lock, _) = &*self.thread_state;
match lock.lock() {
Ok(guard) => *guard,
Err(_) => false, // Return false if the mutex is poisoned
}
}
}

197
tests/basic_tests.rs Normal file
View File

@@ -0,0 +1,197 @@
use vpc_shift_tool::config::{ConfigData, ShiftModifiers, ModifiersArray};
use vpc_shift_tool::device::{SavedDevice, VpcDevice};
use vpc_shift_tool::state::State;
use std::rc::Rc;
#[test]
fn test_config_data_default() {
// Test that the default ConfigData is created correctly
let config = ConfigData::default();
// Check that sources and receivers are empty
assert_eq!(config.sources.len(), 0);
assert_eq!(config.receivers.len(), 0);
// Check that shift_modifiers has the default value (all OR)
for i in 0..8 {
assert_eq!(config.shift_modifiers[i], ShiftModifiers::OR);
}
}
#[test]
fn test_shift_modifiers_display() {
// Test the Display implementation for ShiftModifiers
assert_eq!(format!("{}", ShiftModifiers::OR), "OR");
assert_eq!(format!("{}", ShiftModifiers::AND), "AND");
assert_eq!(format!("{}", ShiftModifiers::XOR), "XOR");
}
#[test]
fn test_saved_device_default() {
// Test that the default SavedDevice is created correctly
let device = SavedDevice::default();
assert_eq!(device.vendor_id, 0);
assert_eq!(device.product_id, 0);
assert_eq!(device.serial_number, "");
assert_eq!(device.state_enabled, [true; 8]); // All bits enabled by default
}
#[test]
fn test_state_enum() {
// Test that the State enum has the expected variants
let initializing = State::Initialising;
let about = State::About;
let running = State::Running;
// Test that the variants are different
assert_ne!(initializing, about);
assert_ne!(initializing, running);
assert_ne!(about, running);
// Test equality with same variant
assert_eq!(initializing, State::Initialising);
assert_eq!(about, State::About);
assert_eq!(running, State::Running);
}
#[test]
fn test_config_with_devices() {
// Test creating a ConfigData with sources and receivers
let mut config = ConfigData::default();
// Create some test devices
let device1 = SavedDevice {
vendor_id: 0x3344,
product_id: 0x0001,
serial_number: "123456".to_string(),
state_enabled: [true, false, true, false, true, false, true, false],
};
let device2 = SavedDevice {
vendor_id: 0x3344,
product_id: 0x0002,
serial_number: "654321".to_string(),
state_enabled: [false, true, false, true, false, true, false, true],
};
// Add devices to sources and receivers
config.sources.push(device1.clone());
config.receivers.push(device2.clone());
// Check that the devices were added correctly
assert_eq!(config.sources.len(), 1);
assert_eq!(config.receivers.len(), 1);
assert_eq!(config.sources[0].vendor_id, 0x3344);
assert_eq!(config.sources[0].product_id, 0x0001);
assert_eq!(config.sources[0].serial_number, "123456");
assert_eq!(config.sources[0].state_enabled, [true, false, true, false, true, false, true, false]);
assert_eq!(config.receivers[0].vendor_id, 0x3344);
assert_eq!(config.receivers[0].product_id, 0x0002);
assert_eq!(config.receivers[0].serial_number, "654321");
assert_eq!(config.receivers[0].state_enabled, [false, true, false, true, false, true, false, true]);
}
#[test]
fn test_modifiers_array() {
// Test the ModifiersArray implementation
let mut modifiers = ModifiersArray::default();
// Check default values
for i in 0..8 {
assert_eq!(modifiers[i], ShiftModifiers::OR);
}
// Test setting values
modifiers[0] = ShiftModifiers::AND;
modifiers[4] = ShiftModifiers::XOR;
// Check the modified values
assert_eq!(modifiers[0], ShiftModifiers::AND);
assert_eq!(modifiers[4], ShiftModifiers::XOR);
// Check that other values remain unchanged
for i in 1..4 {
assert_eq!(modifiers[i], ShiftModifiers::OR);
}
for i in 5..8 {
assert_eq!(modifiers[i], ShiftModifiers::OR);
}
}
#[test]
fn test_vpc_device_default() {
// Test the default VpcDevice implementation
let device = VpcDevice::default();
assert_eq!(device.full_name, "");
assert_eq!(*device.name, "-NO CONNECTION (Select device from list)-");
assert_eq!(*device.firmware, "");
assert_eq!(device.vendor_id, 0);
assert_eq!(device.product_id, 0);
assert_eq!(device.serial_number, "");
assert_eq!(device.usage, 0);
assert_eq!(device.active, false);
}
#[test]
fn test_vpc_device_display() {
// Test the Display implementation for VpcDevice
// Test default device
let device = VpcDevice::default();
assert_eq!(format!("{}", device), "-NO CONNECTION (Select device from list)-");
// Test a real device
let device = VpcDevice {
full_name: "3344:0001:123456".to_string(),
name: Rc::new("VPC MongoosT-50CM3".to_string()),
firmware: Rc::new("VIRPIL Controls 20240101".to_string()),
vendor_id: 0x3344,
product_id: 0x0001,
serial_number: "123456".to_string(),
usage: 0,
active: false,
};
assert_eq!(
format!("{}", device),
"VID:3344 PID:0001 VPC MongoosT-50CM3 (SN:123456 FW:VIRPIL Controls 20240101)"
);
// Test a device with empty serial number
let device = VpcDevice {
full_name: "3344:0001:no_sn".to_string(),
name: Rc::new("VPC MongoosT-50CM3".to_string()),
firmware: Rc::new("VIRPIL Controls 20240101".to_string()),
vendor_id: 0x3344,
product_id: 0x0001,
serial_number: "".to_string(),
usage: 0,
active: false,
};
assert_eq!(
format!("{}", device),
"VID:3344 PID:0001 VPC MongoosT-50CM3 (SN:N/A FW:VIRPIL Controls 20240101)"
);
// Test a device with empty firmware
let device = VpcDevice {
full_name: "3344:0001:123456".to_string(),
name: Rc::new("VPC MongoosT-50CM3".to_string()),
firmware: Rc::new("".to_string()),
vendor_id: 0x3344,
product_id: 0x0001,
serial_number: "123456".to_string(),
usage: 0,
active: false,
};
assert_eq!(
format!("{}", device),
"VID:3344 PID:0001 VPC MongoosT-50CM3 (SN:123456 FW:N/A)"
);
}