Skip to content

Commit 5adb7ba

Browse files
authored
Merge pull request #17 from cuteolaf/test/core
Unit tests for `platform-core`
2 parents 138fbf9 + f4594fe commit 5adb7ba

File tree

8 files changed

+728
-0
lines changed

8 files changed

+728
-0
lines changed

crates/core/src/challenge.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,13 @@ mod tests {
230230
assert_eq!(meta.name, challenge.name);
231231
assert_eq!(meta.code_hash, challenge.code_hash);
232232
}
233+
234+
#[test]
235+
fn test_challenge_config_with_mechanism() {
236+
let config = ChallengeConfig::with_mechanism(5);
237+
assert_eq!(config.mechanism_id, 5);
238+
assert_eq!(config.timeout_secs, 300); // Should have other defaults
239+
assert_eq!(config.max_memory_mb, 512);
240+
assert_eq!(config.emission_weight, 1.0);
241+
}
233242
}

crates/core/src/crypto.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,110 @@ mod tests {
333333
let ss58 = kp.ss58_address();
334334
assert_eq!(ss58, "5GziQCcRpN8NCJktX343brnfuVe3w6gUYieeStXPD1Dag2At");
335335
}
336+
337+
#[test]
338+
fn test_keypair_seed_method() {
339+
let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
340+
let keypair = Keypair::from_mnemonic(mnemonic).unwrap();
341+
let seed = keypair.seed();
342+
assert_eq!(seed.len(), 32);
343+
}
344+
345+
#[test]
346+
fn test_sign_bytes() {
347+
let keypair = Keypair::generate();
348+
let message = b"test message";
349+
let signature = keypair.sign_bytes(message).unwrap();
350+
assert_eq!(signature.len(), 64);
351+
352+
// Verify signature works
353+
let signed_msg = SignedMessage {
354+
message: message.to_vec(),
355+
signature,
356+
signer: keypair.hotkey(),
357+
};
358+
assert!(signed_msg.verify().unwrap());
359+
}
360+
361+
#[test]
362+
fn test_signed_message_debug() {
363+
let keypair = Keypair::generate();
364+
let message = b"test";
365+
let signature = keypair.sign_bytes(message).unwrap();
366+
let signed_msg = SignedMessage {
367+
message: message.to_vec(),
368+
signature,
369+
signer: keypair.hotkey(),
370+
};
371+
let debug_str = format!("{:?}", signed_msg);
372+
assert!(debug_str.contains("SignedMessage"));
373+
}
374+
375+
#[test]
376+
fn test_keypair_seed_fallback() {
377+
// Force the fallback branch by creating a keypair and removing mini_seed
378+
let mut keypair = Keypair::generate();
379+
keypair.mini_seed = None;
380+
381+
// Call seed() which should hit the fallback path
382+
let seed = keypair.seed();
383+
assert_eq!(seed.len(), 32);
384+
385+
// Verify the fallback extracts from raw_vec
386+
let raw = keypair.pair.to_raw_vec();
387+
if raw.len() >= 32 {
388+
let mut expected = [0u8; 32];
389+
expected.copy_from_slice(&raw[..32]);
390+
assert_eq!(seed, expected);
391+
}
392+
}
393+
394+
#[test]
395+
fn test_sign_data_serialization_error() {
396+
// Test that sign_data properly handles serialization errors
397+
let keypair = Keypair::generate();
398+
399+
// Create a type that always fails to serialize
400+
struct FailSerialize;
401+
impl serde::Serialize for FailSerialize {
402+
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
403+
where
404+
S: serde::Serializer,
405+
{
406+
Err(serde::ser::Error::custom(
407+
"intentional serialization failure",
408+
))
409+
}
410+
}
411+
412+
let result = keypair.sign_data(&FailSerialize);
413+
assert!(result.is_err());
414+
assert!(matches!(
415+
result.unwrap_err(),
416+
MiniChainError::Serialization(_)
417+
));
418+
}
419+
420+
#[test]
421+
fn test_hash_data_serialization_error() {
422+
// Test hash_data with a type that fails to serialize
423+
struct FailSerialize;
424+
impl serde::Serialize for FailSerialize {
425+
fn serialize<S>(&self, _serializer: S) -> std::result::Result<S::Ok, S::Error>
426+
where
427+
S: serde::Serializer,
428+
{
429+
Err(serde::ser::Error::custom(
430+
"intentional serialization failure",
431+
))
432+
}
433+
}
434+
435+
let result = hash_data(&FailSerialize);
436+
assert!(result.is_err());
437+
assert!(matches!(
438+
result.unwrap_err(),
439+
MiniChainError::Serialization(_)
440+
));
441+
}
336442
}

crates/core/src/error.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,46 @@ impl From<serde_json::Error> for MiniChainError {
6565
MiniChainError::Serialization(err.to_string())
6666
}
6767
}
68+
69+
#[cfg(test)]
70+
mod tests {
71+
use super::*;
72+
73+
#[test]
74+
fn test_from_io_error() {
75+
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
76+
let chain_err: MiniChainError = io_err.into();
77+
assert!(matches!(chain_err, MiniChainError::Internal(_)));
78+
assert!(chain_err.to_string().contains("file not found"));
79+
}
80+
81+
#[test]
82+
fn test_from_bincode_error() {
83+
// Create a bincode serialization error by writing to a fixed-size buffer that's too small
84+
let mut buffer = [0u8; 2]; // Fixed small buffer
85+
let large_data = vec![0u8; 1000]; // Data too large for buffer
86+
let result = bincode::serialize_into(&mut buffer[..], &large_data);
87+
let bincode_err = result.unwrap_err();
88+
let chain_err: MiniChainError = bincode_err.into();
89+
assert!(matches!(chain_err, MiniChainError::Serialization(_)));
90+
}
91+
92+
#[test]
93+
fn test_from_serde_json_error() {
94+
let json_err = serde_json::from_str::<serde_json::Value>("{invalid json").unwrap_err();
95+
let chain_err: MiniChainError = json_err.into();
96+
assert!(matches!(chain_err, MiniChainError::Serialization(_)));
97+
}
98+
99+
#[test]
100+
fn test_error_display() {
101+
let err = MiniChainError::Crypto("bad key".to_string());
102+
assert_eq!(err.to_string(), "Cryptographic error: bad key");
103+
104+
let err = MiniChainError::InvalidSignature;
105+
assert_eq!(err.to_string(), "Invalid signature");
106+
107+
let err = MiniChainError::NotFound("block 123".to_string());
108+
assert_eq!(err.to_string(), "Not found: block 123");
109+
}
110+
}

crates/core/src/message.rs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,4 +1544,170 @@ mod tests {
15441544
let result2 = config.validate();
15451545
assert!(result2.is_err());
15461546
}
1547+
1548+
#[test]
1549+
fn test_task_progress_message_new() {
1550+
let msg = TaskProgressMessage::new(
1551+
"test-challenge".to_string(),
1552+
"agent-hash".to_string(),
1553+
"eval-123".to_string(),
1554+
"task-1".to_string(),
1555+
1,
1556+
10,
1557+
true,
1558+
0.95,
1559+
1500,
1560+
0.002,
1561+
None,
1562+
"validator-key".to_string(),
1563+
);
1564+
assert_eq!(msg.challenge_id, "test-challenge");
1565+
assert_eq!(msg.task_index, 1);
1566+
assert_eq!(msg.total_tasks, 10);
1567+
assert!(msg.passed);
1568+
assert_eq!(msg.score, 0.95);
1569+
assert!(msg.timestamp > 0);
1570+
}
1571+
1572+
#[test]
1573+
fn test_challenge_container_config_with_resources() {
1574+
let config =
1575+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5)
1576+
.with_resources(4.0, 8192, true);
1577+
1578+
assert_eq!(config.cpu_cores, 4.0);
1579+
assert_eq!(config.memory_mb, 8192);
1580+
assert!(config.gpu_required);
1581+
}
1582+
1583+
#[test]
1584+
fn test_challenge_container_config_with_timeout() {
1585+
let config =
1586+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5)
1587+
.with_timeout(7200);
1588+
1589+
assert_eq!(config.timeout_secs, 7200);
1590+
}
1591+
1592+
#[test]
1593+
fn test_mechanism_weight_config_new() {
1594+
let config = MechanismWeightConfig::new(5);
1595+
assert_eq!(config.mechanism_id, 5);
1596+
assert_eq!(config.base_burn_rate, 0.0);
1597+
assert!(config.equal_distribution);
1598+
assert!(config.active);
1599+
}
1600+
1601+
#[test]
1602+
fn test_mechanism_weight_config_with_burn_rate() {
1603+
let config = MechanismWeightConfig::new(1).with_burn_rate(0.15);
1604+
assert_eq!(config.base_burn_rate, 0.15);
1605+
}
1606+
1607+
#[test]
1608+
fn test_mechanism_weight_config_with_max_cap() {
1609+
let config = MechanismWeightConfig::new(1).with_max_cap(0.8);
1610+
assert_eq!(config.max_weight_cap, 0.8);
1611+
}
1612+
1613+
#[test]
1614+
fn test_challenge_weight_allocation_new() {
1615+
let challenge_id = ChallengeId::new();
1616+
let allocation = ChallengeWeightAllocation::new(challenge_id.clone(), 1, 0.7);
1617+
assert_eq!(allocation.challenge_id, challenge_id);
1618+
assert_eq!(allocation.mechanism_id, 1);
1619+
assert_eq!(allocation.weight_ratio, 0.7);
1620+
assert!(allocation.active);
1621+
}
1622+
1623+
#[test]
1624+
fn test_challenge_config_validate_empty_docker_image() {
1625+
let config = ChallengeContainerConfig::new(
1626+
"Test", "", // Empty docker image
1627+
1, 0.5,
1628+
);
1629+
let result = config.validate();
1630+
assert!(result.is_err());
1631+
assert!(result.unwrap_err().contains("Docker image cannot be empty"));
1632+
}
1633+
1634+
#[test]
1635+
fn test_challenge_config_validate_timeout_too_short() {
1636+
let mut config =
1637+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
1638+
config.timeout_secs = 30; // Less than 60
1639+
let result = config.validate();
1640+
assert!(result.is_err());
1641+
assert!(result.unwrap_err().contains("at least 60 seconds"));
1642+
}
1643+
1644+
#[test]
1645+
fn test_challenge_config_validate_timeout_too_long() {
1646+
let mut config =
1647+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
1648+
config.timeout_secs = 90000; // More than 86400
1649+
let result = config.validate();
1650+
assert!(result.is_err());
1651+
assert!(result.unwrap_err().contains("cannot exceed 24 hours"));
1652+
}
1653+
1654+
#[test]
1655+
fn test_challenge_config_validate_cpu_cores_invalid() {
1656+
let mut config =
1657+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
1658+
config.cpu_cores = 0.1; // Less than 0.5
1659+
let result = config.validate();
1660+
assert!(result.is_err());
1661+
assert!(result.unwrap_err().contains("CPU cores"));
1662+
1663+
config.cpu_cores = 100.0; // More than 64
1664+
let result = config.validate();
1665+
assert!(result.is_err());
1666+
assert!(result.unwrap_err().contains("CPU cores"));
1667+
}
1668+
1669+
#[test]
1670+
fn test_challenge_config_validate_memory_invalid() {
1671+
let mut config =
1672+
ChallengeContainerConfig::new("Test", "ghcr.io/platformnetwork/test:v1", 1, 0.5);
1673+
config.memory_mb = 256; // Less than 512
1674+
let result = config.validate();
1675+
assert!(result.is_err());
1676+
assert!(result.unwrap_err().contains("Memory"));
1677+
1678+
config.memory_mb = 200000; // More than 131072
1679+
let result = config.validate();
1680+
assert!(result.is_err());
1681+
assert!(result.unwrap_err().contains("Memory"));
1682+
}
1683+
1684+
#[test]
1685+
fn test_is_development_mode() {
1686+
// Test the development mode check
1687+
// Save current state and test both paths
1688+
let original = std::env::var("DEVELOPMENT_MODE").ok();
1689+
1690+
// Test with DEVELOPMENT_MODE unset
1691+
std::env::remove_var("DEVELOPMENT_MODE");
1692+
assert!(!is_development_mode());
1693+
1694+
// Test with DEVELOPMENT_MODE set
1695+
std::env::set_var("DEVELOPMENT_MODE", "1");
1696+
assert!(is_development_mode());
1697+
1698+
// Restore original state
1699+
match original {
1700+
Some(val) => std::env::set_var("DEVELOPMENT_MODE", val),
1701+
None => std::env::remove_var("DEVELOPMENT_MODE"),
1702+
}
1703+
}
1704+
1705+
#[test]
1706+
fn test_mechanism_weight_config_default() {
1707+
let config = MechanismWeightConfig::default();
1708+
assert_eq!(config.mechanism_id, 0);
1709+
assert_eq!(config.base_burn_rate, 0.0);
1710+
assert!(config.equal_distribution);
1711+
assert!(config.active);
1712+
}
15471713
}

0 commit comments

Comments
 (0)