Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/core/src/challenge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,4 +230,13 @@ mod tests {
assert_eq!(meta.name, challenge.name);
assert_eq!(meta.code_hash, challenge.code_hash);
}

#[test]
fn test_challenge_config_with_mechanism() {
let config = ChallengeConfig::with_mechanism(5);
assert_eq!(config.mechanism_id, 5);
assert_eq!(config.timeout_secs, 300); // Should have other defaults
assert_eq!(config.max_memory_mb, 512);
assert_eq!(config.emission_weight, 1.0);
}
}
106 changes: 106 additions & 0 deletions crates/core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,4 +333,110 @@ mod tests {
let ss58 = kp.ss58_address();
assert_eq!(ss58, "5GziQCcRpN8NCJktX343brnfuVe3w6gUYieeStXPD1Dag2At");
}

#[test]
fn test_keypair_seed_method() {
let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
let keypair = Keypair::from_mnemonic(mnemonic).unwrap();
let seed = keypair.seed();
assert_eq!(seed.len(), 32);
}

#[test]
fn test_sign_bytes() {
let keypair = Keypair::generate();
let message = b"test message";
let signature = keypair.sign_bytes(message).unwrap();
assert_eq!(signature.len(), 64);

// Verify signature works
let signed_msg = SignedMessage {
message: message.to_vec(),
signature,
signer: keypair.hotkey(),
};
assert!(signed_msg.verify().unwrap());
}

#[test]
fn test_signed_message_debug() {
let keypair = Keypair::generate();
let message = b"test";
let signature = keypair.sign_bytes(message).unwrap();
let signed_msg = SignedMessage {
message: message.to_vec(),
signature,
signer: keypair.hotkey(),
};
let debug_str = format!("{:?}", signed_msg);
assert!(debug_str.contains("SignedMessage"));
}

#[test]
fn test_keypair_seed_fallback() {
// Force the fallback branch by creating a keypair and removing mini_seed
let mut keypair = Keypair::generate();
keypair.mini_seed = None;

// Call seed() which should hit the fallback path
let seed = keypair.seed();
assert_eq!(seed.len(), 32);

// Verify the fallback extracts from raw_vec
let raw = keypair.pair.to_raw_vec();
if raw.len() >= 32 {
let mut expected = [0u8; 32];
expected.copy_from_slice(&raw[..32]);
assert_eq!(seed, expected);
}
}

#[test]
fn test_sign_data_serialization_error() {
// Test that sign_data properly handles serialization errors
let keypair = Keypair::generate();

// Create a type that always fails to serialize
struct FailSerialize;
impl serde::Serialize for FailSerialize {
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Err(serde::ser::Error::custom(
"intentional serialization failure",
))
}
}

let result = keypair.sign_data(&FailSerialize);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
MiniChainError::Serialization(_)
));
}

#[test]
fn test_hash_data_serialization_error() {
// Test hash_data with a type that fails to serialize
struct FailSerialize;
impl serde::Serialize for FailSerialize {
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Err(serde::ser::Error::custom(
"intentional serialization failure",
))
}
}

let result = hash_data(&FailSerialize);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
MiniChainError::Serialization(_)
));
}
}
43 changes: 43 additions & 0 deletions crates/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,46 @@ impl From<serde_json::Error> for MiniChainError {
MiniChainError::Serialization(err.to_string())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_from_io_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let chain_err: MiniChainError = io_err.into();
assert!(matches!(chain_err, MiniChainError::Internal(_)));
assert!(chain_err.to_string().contains("file not found"));
}

#[test]
fn test_from_bincode_error() {
// Create a bincode serialization error by writing to a fixed-size buffer that's too small
let mut buffer = [0u8; 2]; // Fixed small buffer
let large_data = vec![0u8; 1000]; // Data too large for buffer
let result = bincode::serialize_into(&mut buffer[..], &large_data);
let bincode_err = result.unwrap_err();
let chain_err: MiniChainError = bincode_err.into();
assert!(matches!(chain_err, MiniChainError::Serialization(_)));
}

#[test]
fn test_from_serde_json_error() {
let json_err = serde_json::from_str::<serde_json::Value>("{invalid json").unwrap_err();
let chain_err: MiniChainError = json_err.into();
assert!(matches!(chain_err, MiniChainError::Serialization(_)));
}

#[test]
fn test_error_display() {
let err = MiniChainError::Crypto("bad key".to_string());
assert_eq!(err.to_string(), "Cryptographic error: bad key");

let err = MiniChainError::InvalidSignature;
assert_eq!(err.to_string(), "Invalid signature");

let err = MiniChainError::NotFound("block 123".to_string());
assert_eq!(err.to_string(), "Not found: block 123");
}
}
166 changes: 166 additions & 0 deletions crates/core/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,4 +1544,170 @@ mod tests {
let result2 = config.validate();
assert!(result2.is_err());
}

#[test]
fn test_task_progress_message_new() {
let msg = TaskProgressMessage::new(
"test-challenge".to_string(),
"agent-hash".to_string(),
"eval-123".to_string(),
"task-1".to_string(),
1,
10,
true,
0.95,
1500,
0.002,
None,
"validator-key".to_string(),
);
assert_eq!(msg.challenge_id, "test-challenge");
assert_eq!(msg.task_index, 1);
assert_eq!(msg.total_tasks, 10);
assert!(msg.passed);
assert_eq!(msg.score, 0.95);
assert!(msg.timestamp > 0);
}

#[test]
fn test_challenge_container_config_with_resources() {
let config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5)
.with_resources(4.0, 8192, true);

assert_eq!(config.cpu_cores, 4.0);
assert_eq!(config.memory_mb, 8192);
assert!(config.gpu_required);
}

#[test]
fn test_challenge_container_config_with_timeout() {
let config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5)
.with_timeout(7200);

assert_eq!(config.timeout_secs, 7200);
}

#[test]
fn test_mechanism_weight_config_new() {
let config = MechanismWeightConfig::new(5);
assert_eq!(config.mechanism_id, 5);
assert_eq!(config.base_burn_rate, 0.0);
assert!(config.equal_distribution);
assert!(config.active);
}

#[test]
fn test_mechanism_weight_config_with_burn_rate() {
let config = MechanismWeightConfig::new(1).with_burn_rate(0.15);
assert_eq!(config.base_burn_rate, 0.15);
}

#[test]
fn test_mechanism_weight_config_with_max_cap() {
let config = MechanismWeightConfig::new(1).with_max_cap(0.8);
assert_eq!(config.max_weight_cap, 0.8);
}

#[test]
fn test_challenge_weight_allocation_new() {
let challenge_id = ChallengeId::new();
let allocation = ChallengeWeightAllocation::new(challenge_id.clone(), 1, 0.7);
assert_eq!(allocation.challenge_id, challenge_id);
assert_eq!(allocation.mechanism_id, 1);
assert_eq!(allocation.weight_ratio, 0.7);
assert!(allocation.active);
}

#[test]
fn test_challenge_config_validate_empty_docker_image() {
let config = ChallengeContainerConfig::new(
"Test", "", // Empty docker image
1, 0.5,
);
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("Docker image cannot be empty"));
}

#[test]
fn test_challenge_config_validate_timeout_too_short() {
let mut config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
config.timeout_secs = 30; // Less than 60
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("at least 60 seconds"));
}

#[test]
fn test_challenge_config_validate_timeout_too_long() {
let mut config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
config.timeout_secs = 90000; // More than 86400
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("cannot exceed 24 hours"));
}

#[test]
fn test_challenge_config_validate_cpu_cores_invalid() {
let mut config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
config.cpu_cores = 0.1; // Less than 0.5
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("CPU cores"));

config.cpu_cores = 100.0; // More than 64
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("CPU cores"));
}

#[test]
fn test_challenge_config_validate_memory_invalid() {
let mut config =
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
config.memory_mb = 256; // Less than 512
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("Memory"));

config.memory_mb = 200000; // More than 131072
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("Memory"));
}

#[test]
fn test_is_development_mode() {
// Test the development mode check
// Save current state and test both paths
let original = std::env::var("DEVELOPMENT_MODE").ok();

// Test with DEVELOPMENT_MODE unset
std::env::remove_var("DEVELOPMENT_MODE");
assert!(!is_development_mode());

// Test with DEVELOPMENT_MODE set
std::env::set_var("DEVELOPMENT_MODE", "1");
assert!(is_development_mode());

// Restore original state
match original {
Some(val) => std::env::set_var("DEVELOPMENT_MODE", val),
None => std::env::remove_var("DEVELOPMENT_MODE"),
}
}

#[test]
fn test_mechanism_weight_config_default() {
let config = MechanismWeightConfig::default();
assert_eq!(config.mechanism_id, 0);
assert_eq!(config.base_burn_rate, 0.0);
assert!(config.equal_distribution);
assert!(config.active);
}
}
Loading