added tests that are currently failing

This commit is contained in:
ghe0 2024-08-22 23:09:58 +03:00
parent 3c2137f224
commit b3498b8e1e
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
3 changed files with 268 additions and 6 deletions

1
.gitignore vendored

@ -3,3 +3,4 @@ build
detee_challenge_nodes detee_challenge_nodes
.cargo .cargo
.idea .idea
.tmp

@ -49,7 +49,7 @@ impl std::fmt::Display for SigningError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let error_message = match self { let error_message = match self {
SigningError::CorruptedKey => "The public key is corrupted", SigningError::CorruptedKey => "The public key is corrupted",
SigningError::KeyNotFound => "Did not find the public key", SigningError::KeyNotFound => "Did not find the private key",
}; };
write!(f, "{}", error_message) write!(f, "{}", error_message)
} }
@ -280,3 +280,125 @@ impl Store {
.find(|k| !self.conns.contains(k)) .find(|k| !self.conns.contains(k))
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use dashmap::DashMap;
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
use std::time::{SystemTime, UNIX_EPOCH};
#[test]
fn test_node_info_creation() {
let keypair = SigningKey::generate(&mut OsRng);
let node_info = NodeInfo {
pubkey: keypair.verifying_key(),
updated_at: SystemTime::now(),
public: true,
};
assert_eq!(node_info.pubkey, keypair.verifying_key());
assert!(node_info.updated_at >= UNIX_EPOCH);
assert!(node_info.public);
}
#[test]
fn test_store_creation() {
let store = Store {
nodes: DashMap::new(),
conns: DashSet::new(),
keys: DashMap::new(),
};
assert!(store.nodes.is_empty());
assert!(store.conns.is_empty());
assert!(store.keys.is_empty());
}
#[test]
fn test_signing_error_from_hex_error() {
let hex_error: Result<(), hex::FromHexError> =
Err(hex::FromHexError::InvalidHexCharacter { c: 'a', index: 0 });
let signing_error: SigningError = hex_error.unwrap_err().into();
match signing_error {
SigningError::CorruptedKey => assert!(true),
_ => assert!(false, "Expected SigningError::CorruptedKey"),
}
}
#[tokio::test]
async fn test_sign_message_with_key() {
let keypair = SigningKey::generate(&mut OsRng);
let pubkey_hex = hex::encode(keypair.verifying_key().as_bytes());
let store = Store {
nodes: DashMap::new(),
conns: DashSet::new(),
keys: DashMap::new(),
};
store.keys.insert(keypair.verifying_key(), keypair);
let message = "Test message";
let result = store.sign_message_with_key(message, &pubkey_hex).await;
assert!(result.is_ok());
if let Ok(signature) = result {
assert!(!signature.is_empty());
}
}
#[tokio::test]
async fn test_process_node_update() {
let keypair = SigningKey::generate(&mut OsRng);
let node_update = NodeUpdate {
ip: "127.0.0.1".to_string(),
keypair: hex::encode(keypair.as_bytes()),
updated_at: Some(prost_types::Timestamp {
seconds: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64,
nanos: 0,
}),
public: true,
};
let store = Store {
nodes: DashMap::new(),
conns: DashSet::new(),
keys: DashMap::new(),
};
let result = store.process_node_update(node_update).await;
assert!(result);
assert!(store.nodes.contains_key("127.0.0.1"));
}
#[tokio::test]
async fn test_get_full_node_list() {
let keypair = SigningKey::generate(&mut OsRng);
let node_info = NodeInfo {
pubkey: keypair.verifying_key(),
updated_at: SystemTime::now(),
public: true,
};
let store = Store {
nodes: DashMap::new(),
conns: DashSet::new(),
keys: DashMap::new(),
};
store.nodes.insert("127.0.0.1".to_string(), node_info);
store.keys.insert(keypair.verifying_key(), keypair.clone());
let node_list = store.get_full_node_list().await;
assert_eq!(node_list.len(), 1);
assert_eq!(node_list[0].ip, "127.0.0.1");
assert_eq!(node_list[0].keypair, hex::encode(keypair.as_bytes()));
assert!(node_list[0].public);
}
}

@ -8,7 +8,7 @@ use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom};
use tokio::sync::Mutex; use tokio::sync::Mutex;
const DATA_SIZE: usize = 78; const DATA_SIZE: usize = 76;
enum Error { enum Error {
CorruptedIP, CorruptedIP,
@ -20,6 +20,7 @@ impl From<AddrParseError> for Error {
} }
} }
#[derive(Clone)]
struct Node { struct Node {
ip: Ipv4Addr, ip: Ipv4Addr,
keypair: SigningKey, keypair: SigningKey,
@ -50,7 +51,7 @@ impl Node {
let mut result = [0; DATA_SIZE]; let mut result = [0; DATA_SIZE];
result[0..4].copy_from_slice(&self.ip.octets()); result[0..4].copy_from_slice(&self.ip.octets());
result[4..68].copy_from_slice(&self.keypair.to_keypair_bytes()); result[4..68].copy_from_slice(&self.keypair.to_keypair_bytes());
result[69..DATA_SIZE].copy_from_slice( result[68..DATA_SIZE].copy_from_slice(
&self &self
.joined_at .joined_at
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)
@ -66,7 +67,7 @@ impl Node {
let ip: Ipv4Addr = ip.into(); let ip: Ipv4Addr = ip.into();
let keypair: [u8; KEYPAIR_LENGTH] = bytes[4..68].try_into().unwrap(); let keypair: [u8; KEYPAIR_LENGTH] = bytes[4..68].try_into().unwrap();
let keypair: SigningKey = SigningKey::from_keypair_bytes(&keypair).unwrap(); let keypair: SigningKey = SigningKey::from_keypair_bytes(&keypair).unwrap();
let joined_at: [u8; 8] = bytes[69..DATA_SIZE].try_into().unwrap(); let joined_at: [u8; 8] = bytes[68..DATA_SIZE].try_into().unwrap();
let joined_at: u64 = u64::from_le_bytes(joined_at); let joined_at: u64 = u64::from_le_bytes(joined_at);
let joined_at = SystemTime::UNIX_EPOCH + Duration::from_secs(joined_at); let joined_at = SystemTime::UNIX_EPOCH + Duration::from_secs(joined_at);
Self { Self {
@ -99,10 +100,148 @@ impl FileManager {
async fn get_node_by_id(&self, id: u64) -> std::io::Result<Node> { async fn get_node_by_id(&self, id: u64) -> std::io::Result<Node> {
let mut file = self.file.lock().await; let mut file = self.file.lock().await;
file.seek(SeekFrom::Start(id.wrapping_mul(DATA_SIZE.try_into().unwrap_or(0)))) file.seek(SeekFrom::Start(
id.wrapping_mul(DATA_SIZE.try_into().unwrap_or(0)),
))
.await?; .await?;
let mut node_bytes = [0; DATA_SIZE]; let mut node_bytes = [0; DATA_SIZE];
file.read_exact(&mut node_bytes).await?; file.read_exact(&mut node_bytes).await?;
Ok(Node::from_bytes(node_bytes)) Ok(Node::from_bytes(node_bytes))
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
use std::io::Result;
use tokio::fs::remove_file;
use tokio::io::AsyncWriteExt;
const TEST_FILE_PREFIX: &str = ".tmp/test_";
fn get_test_file_name(function: &str) -> String {
TEST_FILE_PREFIX.to_string() + function
}
async fn setup_test_file(function: &str) -> Result<FileManager> {
let path = get_test_file_name(function);
let mut file = File::create(path.clone()).await?;
file.flush().await?;
drop(file);
FileManager::init(&path).await
}
#[test]
fn test_node_to_bytes_and_back() {
let keypair = SigningKey::generate(&mut OsRng);
let original_node = Node {
ip: "192.168.1.1".parse().unwrap(),
keypair: keypair.clone(),
joined_at: SystemTime::now(),
};
let node_bytes = original_node.clone().to_bytes();
let restored_node = Node::from_bytes(node_bytes);
assert_eq!(original_node.ip_as_string(), restored_node.ip_as_string());
assert_eq!(
original_node.keypair.to_keypair_bytes(),
restored_node.keypair.to_keypair_bytes()
);
assert_eq!(
original_node
.joined_at
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
restored_node
.joined_at
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
);
}
#[tokio::test]
async fn setup_file_manager() {
match setup_test_file("setup_file_manager").await {
Err(e) => {
panic!("Could not init File Manager: {}", e);
}
_ => {}
}
}
#[tokio::test]
async fn test_file_manager_append_and_retrieve_node() -> Result<()> {
let function_name = "test_file_manager_append_and_retrieve_node";
let manager = setup_test_file(function_name).await?;
let keypair = SigningKey::generate(&mut OsRng);
let node = Node {
ip: "192.168.1.1".parse().unwrap(),
keypair: keypair.clone(),
joined_at: SystemTime::now(),
};
manager.append_node(node.clone()).await.unwrap();
let retrieved_node = manager.get_node_by_id(0).await.unwrap();
assert_eq!(node.ip_as_string(), retrieved_node.ip_as_string());
assert_eq!(
node.keypair.to_keypair_bytes(),
retrieved_node.keypair.to_keypair_bytes()
);
assert_eq!(node.joined_at, retrieved_node.joined_at);
remove_file(get_test_file_name(function_name)).await?;
Ok(())
}
#[tokio::test]
async fn test_file_manager_multiple_nodes() -> Result<()> {
let function_name = "test_file_manager_multiple_nodes";
let manager = setup_test_file(function_name).await?;
let keypair1 = SigningKey::generate(&mut OsRng);
let node1 = Node {
ip: "192.168.1.1".parse().unwrap(),
keypair: keypair1.clone(),
joined_at: SystemTime::now(),
};
let keypair2 = SigningKey::generate(&mut OsRng);
let node2 = Node {
ip: "10.0.0.1".parse().unwrap(),
keypair: keypair2.clone(),
joined_at: SystemTime::now(),
};
manager.append_node(node1.clone()).await.unwrap();
manager.append_node(node2.clone()).await.unwrap();
let retrieved_node1 = manager.get_node_by_id(0).await?;
let retrieved_node2 = manager.get_node_by_id(1).await?;
assert_eq!(node1.ip_as_string(), retrieved_node1.ip_as_string());
assert_eq!(
node1.keypair.to_keypair_bytes(),
retrieved_node1.keypair.to_keypair_bytes()
);
assert_eq!(node2.ip_as_string(), retrieved_node2.ip_as_string());
assert_eq!(
node2.keypair.to_keypair_bytes(),
retrieved_node2.keypair.to_keypair_bytes()
);
remove_file(get_test_file_name(function_name)).await?;
Ok(())
}
}