mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Fixing tests
This commit is contained in:
@@ -1,22 +0,0 @@
|
|||||||
[database]
|
|
||||||
path="./oott.db"
|
|
||||||
|
|
||||||
[networking]
|
|
||||||
interface = "wlp3s0" # Network interface to use for scans
|
|
||||||
|
|
||||||
[log]
|
|
||||||
level = "debug" # off, error, warn, info, debug, trace
|
|
||||||
|
|
||||||
[timings]
|
|
||||||
wait_between_scans="30m" # Wait time between scans. This does not include the scan time
|
|
||||||
arp_sender_timeout="1m" # If the ARP sender process takes longer than this it will be stopped (for a class C network - 254 IPs - it should take less than a minute)
|
|
||||||
arp_scan_duration="2m" # How long to wait for response packets on each scan (5m to 10m is a good timeframe for a class B or C network)
|
|
||||||
|
|
||||||
[notifications]
|
|
||||||
# method="pushover" # For now just pushover, you can set this to "none" to avoid sending notifications (it will just log)
|
|
||||||
method="none"
|
|
||||||
notify_when_not_seen_for="1w" # Send a notification if a device comes back online after not being seen for this timeframe
|
|
||||||
|
|
||||||
[notifications.pushover]
|
|
||||||
token="a7vxi8b24ncdmuyt65x7zytkxaozi3" # Your pushover token goes here, just copy&paste from their website after creating the app
|
|
||||||
user_key="u872udy8xc8ceys9ee6iur229xs3fj" # User key goes here, this is the account wide code for pushover
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod devices;
|
pub mod devices;
|
||||||
|
pub mod error;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
|
|
||||||
use include_dir::{Dir, include_dir};
|
use include_dir::{Dir, include_dir};
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
use std::{error, fmt};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DbError {
|
||||||
|
Parse(rusqlite::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DbError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
DbError::Parse(..) => write!(f, "Database access error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for DbError {
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
match *self {
|
||||||
|
DbError::Parse(ref e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<rusqlite::Error> for DbError {
|
||||||
|
fn from(err: rusqlite::Error) -> DbError {
|
||||||
|
DbError::Parse(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
+112
-17
@@ -1,32 +1,127 @@
|
|||||||
use chrono::Local;
|
use crate::db;
|
||||||
|
use crate::db::error::DbError;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::model::{self, notifications::Notification};
|
use crate::model::notifications::Notification;
|
||||||
|
|
||||||
pub fn list() -> Vec<model::notifications::Notification> {
|
pub fn list() -> Result<Vec<Notification>, DbError> {
|
||||||
debug!("Listing notifications");
|
debug!("Listing notifications");
|
||||||
let mut result = Vec::new();
|
let conn = db::get_db_connection();
|
||||||
result.push(Notification {
|
|
||||||
id: 1,
|
|
||||||
created_on: Local::now().to_utc(),
|
|
||||||
is_new: true,
|
|
||||||
notification_type: model::notifications::NotificationType::NewDeviceFound,
|
|
||||||
title: "title".to_string(),
|
|
||||||
body: "body".to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
result
|
let mut stmt = conn.prepare(
|
||||||
|
"SELECT id, created_on, notification_type, title, body FROM notifications WHERE is_new=1",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let notifications: Vec<Notification> = stmt
|
||||||
|
.query_map([], |row| {
|
||||||
|
Ok(Notification {
|
||||||
|
id: row.get(0)?,
|
||||||
|
created_on: row.get(1)?,
|
||||||
|
notification_type: row.get(2)?,
|
||||||
|
title: row.get(3)?,
|
||||||
|
body: row.get(4)?,
|
||||||
|
is_new: true,
|
||||||
|
})
|
||||||
|
})?
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
Ok(notifications)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use chrono::TimeZone;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tests_common;
|
use crate::{model::notifications::NotificationType, tests_common};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn list_default() {
|
async fn test_list_default() {
|
||||||
tests_common::setup().await;
|
tests_common::setup().await;
|
||||||
let notifications = list();
|
let notifications = list().unwrap();
|
||||||
assert_eq!(notifications.len(), 1);
|
|
||||||
|
// There should be 3 unread notifications
|
||||||
|
assert_eq!(
|
||||||
|
notifications.len(),
|
||||||
|
3,
|
||||||
|
"There should be 3 notifications in the list"
|
||||||
|
);
|
||||||
|
|
||||||
|
// All notifications must be unread/new
|
||||||
|
for notification in notifications.iter() {
|
||||||
|
assert!(
|
||||||
|
notification.is_new,
|
||||||
|
"Notification {} is not new and there should only be new notifications in the list",
|
||||||
|
notification.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There should be only one of each type
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.notification_type == NotificationType::Other)
|
||||||
|
.count(),
|
||||||
|
"There should be only one notification of type Other"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.notification_type
|
||||||
|
== NotificationType::DeviceOnlineAfterTime)
|
||||||
|
.count(),
|
||||||
|
"There should be only one notification of type Other"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.notification_type
|
||||||
|
== NotificationType::NewDeviceFound)
|
||||||
|
.count(),
|
||||||
|
"There should be only one notification of type Other"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check date of notification 1
|
||||||
|
let notification1 = notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.id == 1)
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// 2026-01-03 14:13:12
|
||||||
|
assert_eq!(
|
||||||
|
notification1.created_on,
|
||||||
|
Local.with_ymd_and_hms(2026, 1, 3, 14, 13, 12).unwrap(),
|
||||||
|
"Incorrect created_on date/time for notification 1."
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check title of notification 3
|
||||||
|
let notification3 = notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.id == 3)
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
notification3.title, "Unread device online after time",
|
||||||
|
"Notification 3 title incorrect: {}",
|
||||||
|
notification3.title
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check body of notification 5
|
||||||
|
let notification5 = notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|notification| notification.id == 5)
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
notification5.body, "Body other",
|
||||||
|
"Notification 5 body incorrect: {}",
|
||||||
|
notification5.body
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{error::Error, fmt, str::FromStr};
|
|||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct Notification {
|
pub struct Notification {
|
||||||
pub id: u64,
|
pub id: i64,
|
||||||
#[serde(with = "ts_seconds")]
|
#[serde(with = "ts_seconds")]
|
||||||
pub created_on: DateTime<Utc>,
|
pub created_on: DateTime<Utc>,
|
||||||
pub notification_type: NotificationType,
|
pub notification_type: NotificationType,
|
||||||
@@ -24,7 +24,13 @@ impl fmt::Display for Notification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
impl PartialEq for Notification {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.id == other.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum NotificationType {
|
pub enum NotificationType {
|
||||||
NewDeviceFound,
|
NewDeviceFound,
|
||||||
DeviceOnlineAfterTime,
|
DeviceOnlineAfterTime,
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (1, '2026-01-03 14:13:12', 'NewDeviceFound', 'Title new device found', 'Body new device found', 1);
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (1, '2026-01-03 14:13:12', 'NewDeviceFound', 'Unread new device found', 'Body unread new device found', 1);
|
||||||
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (2, '2026-01-04 08:10:13', 'NewDeviceFound', 'Read new device found', 'Body read new device found', 0);
|
||||||
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (3, '2026-01-05 17:20:01', 'DeviceOnlineAfterTime', 'Unread device online after time', 'Body unread device online after time', 1);
|
||||||
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (4, '2026-01-06 02:11:12', 'DeviceOnlineAfterTime', 'Read device online after time', 'Body read device online after time', 0);
|
||||||
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (5, '2026-02-01 11:11:11', 'Other', 'Unread other', 'Body other', 1);
|
||||||
|
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (6, '2026-02-03 13:13:13', 'Other', 'Read other', 'Body other', 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user