Update tests

pull/3/head
lambda 1 week ago
parent b187811649
commit a979f5dda7
No known key found for this signature in database
GPG Key ID: CF45A8EE158BBCB6

@ -7,3 +7,36 @@ pub fn normalize_uuid(u: &str) -> String {
}
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_strips_standard_base_suffix() {
assert_eq!(normalize_uuid("00001816-0000-1000-8000-00805f9b34fb"), "1816");
}
#[test]
fn test_short_uuid_is_unchanged() {
assert_eq!(normalize_uuid("1816"), "1816");
}
#[test]
fn test_trims_whitespace() {
assert_eq!(normalize_uuid(" 1816 "), "1816");
}
#[test]
fn test_lowercases_input() {
assert_eq!(normalize_uuid("181D"), "181d");
}
#[test]
fn test_custom_128bit_uuid_is_left_untouched() {
assert_eq!(
normalize_uuid("f0001816-0451-4000-b000-000000000000"),
"f0001816-0451-4000-b000-000000000000"
);
}
}

@ -93,6 +93,23 @@ pub fn get_device_types(device: &Device) -> Vec<DeviceType> {
mod tests {
use super::*;
/// Test helper: builds a Device from service UUIDs and characteristics,
/// with all other fields stubbed. Tests only exercise classification.
fn dev(services: &[&str], characteristics: &[&str]) -> Device {
Device {
id: "test-device".into(),
address: "00:00:00:00:00:00".into(),
display_name: None,
rssi: None,
service_uuids: services.iter().map(|s| s.to_string()).collect(),
characteristics: characteristics.iter().map(|s| s.to_string()).collect(),
manufacturer_data: None,
metadata: None,
}
}
// Real-device fixture: Magene speed/cadence sensor advertising the CSC
// service (0x1816) as a full 128-bit UUID.
#[test]
fn test_service_types_for_magene_speedcadence() {
let magene = Device {
@ -108,4 +125,101 @@ mod tests {
assert_eq!(get_device_types(&magene), [DeviceType::CadSensor]);
}
// Heart rate
#[test]
fn test_hr_sensor_by_service() {
assert_eq!(get_device_types(&dev(&["180d"], &[])), [DeviceType::HrSensor]);
}
#[test]
fn test_hr_sensor_by_characteristic() {
assert_eq!(get_device_types(&dev(&[], &["2a37"])), [DeviceType::HrSensor]);
}
#[test]
fn test_hr_sensor_by_full_128bit_uuid() {
assert_eq!(
get_device_types(&dev(&["0000180d-0000-1000-8000-00805f9b34fb"], &[])),
[DeviceType::HrSensor]
);
}
// Cadence / speed
#[test]
fn test_cadence_by_service() {
assert_eq!(get_device_types(&dev(&["1816"], &[])), [DeviceType::CadSensor]);
}
#[test]
fn test_cadence_by_characteristic() {
assert_eq!(get_device_types(&dev(&[], &["2a5b"])), [DeviceType::CadSensor]);
}
// Trainer / cycling power / FTMS
#[test]
fn test_trainer_by_ftms_service() {
assert_eq!(get_device_types(&dev(&["1826"], &[])), [DeviceType::Trainer]);
}
#[test]
fn test_trainer_by_power_service() {
assert_eq!(get_device_types(&dev(&["1818"], &[])), [DeviceType::Trainer]);
}
#[test]
fn test_trainer_by_power_characteristic() {
assert_eq!(get_device_types(&dev(&[], &["2a63"])), [DeviceType::Trainer]);
}
#[test]
fn test_trainer_by_fitness_machine_characteristic() {
assert_eq!(get_device_types(&dev(&[], &["2acc"])), [DeviceType::Trainer]);
}
// Indoor bike data (2ADx): a trainer characteristic that also implies cadence.
#[test]
fn test_indoor_bike_data_is_trainer_and_cadence() {
// 2ad2 is both a trainer characteristic and an indoor-bike marker.
assert_eq!(
get_device_types(&dev(&[], &["2ad2"])),
[DeviceType::Trainer, DeviceType::CadSensor]
);
}
#[test]
fn test_indoor_bike_variant_is_cadence_only() {
// 2ad5 is an indoor-bike marker but not in the trainer list.
assert_eq!(get_device_types(&dev(&[], &["2ad5"])), [DeviceType::CadSensor]);
}
// "service::characteristic" strings produced by the scanner.
#[test]
fn test_characteristic_split_on_double_colon() {
assert_eq!(get_device_types(&dev(&[], &["1816::2a5b"])), [DeviceType::CadSensor]);
}
// Combined and negative cases
#[test]
fn test_hr_and_cadence_combo() {
assert_eq!(
get_device_types(&dev(&["180d", "1816"], &[])),
[DeviceType::HrSensor, DeviceType::CadSensor]
);
}
#[test]
fn test_battery_service_is_ignored() {
assert!(get_device_types(&dev(&["180f"], &[])).is_empty());
}
#[test]
fn test_empty_device_has_no_types() {
assert!(get_device_types(&dev(&[], &[])).is_empty());
}
#[test]
fn test_uuid_case_and_whitespace_are_normalized() {
assert_eq!(get_device_types(&dev(&[" 180D "], &[])), [DeviceType::HrSensor]);
}
}

@ -60,6 +60,20 @@ pub fn repo_from_devices(devices: Vec<Device>) -> Repo {
mod tests {
use super::*;
/// Helper: a cadence device (CSC service 0x1816) with the given RSSI.
fn cadence_device(rssi: Option<i16>) -> Device {
Device {
id: format!("cad-{rssi:?}"),
address: "00:00:00:00:00:00".into(),
display_name: None,
rssi,
service_uuids: vec!["1816".into()],
characteristics: vec![],
manufacturer_data: None,
metadata: None,
}
}
#[test]
fn test_repo_classifies_magene_as_cadence_sensor() {
let magene = Device {
@ -79,4 +93,42 @@ mod tests {
assert!(repo.hr_sensors.is_empty());
assert!(repo.trainers.is_empty());
}
#[test]
fn test_sorts_devices_by_rssi_descending() {
let devices = vec![
cadence_device(Some(-80)),
cadence_device(Some(-42)),
cadence_device(Some(-60)),
];
let repo = repo_from_devices(devices);
let rssis: Vec<_> = repo.cad_sensors.iter().map(|d| d.rssi).collect();
assert_eq!(rssis, vec![Some(-42), Some(-60), Some(-80)]);
}
#[test]
fn test_devices_without_rssi_go_last() {
let devices = vec![cadence_device(None), cadence_device(Some(-50))];
let repo = repo_from_devices(devices);
assert_eq!(repo.cad_sensors[0].rssi, Some(-50));
assert_eq!(repo.cad_sensors[1].rssi, None);
}
#[test]
fn test_indoor_bike_lands_in_trainer_and_cadence_buckets() {
let indoor_bike = Device {
id: "indoor-bike".into(),
address: "00:00:00:00:00:00".into(),
display_name: None,
rssi: Some(-70),
service_uuids: vec![],
characteristics: vec!["2ad2".into()],
manufacturer_data: None,
metadata: None,
};
let repo = repo_from_devices(vec![indoor_bike]);
assert_eq!(repo.trainers.len(), 1);
assert_eq!(repo.cad_sensors.len(), 1);
assert!(repo.hr_sensors.is_empty());
}
}

Loading…
Cancel
Save