use dragonfly_client_request::hashring::VNodeHashRing;
use dragonfly_client_request::id_generator::{IDGenerator, TaskIDParameter};
use siphasher::sip::SipHasher;
use std::hash::Hasher;
fn vnode_hash(id: usize, name: &str) -> u64 {
let mut hasher = SipHasher::new();
hasher.write_usize(id);
hasher.write(name.as_bytes());
hasher.write_u8(0xff);
hasher.finish()
}
fn key_hash(key: &str) -> u64 {
let mut hasher = SipHasher::new();
hasher.write(key.as_bytes());
hasher.write_u8(0xff);
hasher.finish()
}
#[test]
fn test_siphash() {
assert_eq!(vnode_hash(0, "seed-peer-1"), 0x1e5a582b8d945969);
assert_eq!(vnode_hash(1, "seed-peer-1"), 0xb5db98265419376c);
assert_eq!(vnode_hash(0, "seed-peer-2"), 0xf36f748c486b09ef);
assert_eq!(vnode_hash(511, "seed-peer-3"), 0xf0eda07426c5cac1);
assert_eq!(
key_hash("b2c366cce7e68013d5441c6326d5a3e1b12aeb5ed58564d0fd3fa089bc29cb6e"),
0xaa86f08bc4878a68
);
assert_eq!(key_hash("test-task"), 0xa78dd821b4023714);
assert_eq!(key_hash(""), 0x20dd4eb33d9590f2);
}
#[test]
fn test_hashring() {
let mut ring = VNodeHashRing::new(3);
for name in ["seed-peer-1", "seed-peer-2", "seed-peer-3"] {
ring.add(name.to_string());
}
let select = |key: &str, replicas: usize| -> Vec<String> {
ring.get_with_replicas(&key.to_string(), replicas)
.unwrap()
.iter()
.map(|v| v.to_string())
.collect()
};
assert_eq!(
select("task-a", 2),
["seed-peer-3|2", "seed-peer-1|2", "seed-peer-3|0"]
);
assert_eq!(
select("task-b", 2),
["seed-peer-2|0", "seed-peer-2|1", "seed-peer-1|0"]
);
assert_eq!(
select("task-c", 2),
["seed-peer-2|1", "seed-peer-1|0", "seed-peer-3|2"]
);
assert_eq!(
select("task-a", 100),
[
"seed-peer-3|2",
"seed-peer-1|2",
"seed-peer-3|0",
"seed-peer-1|1",
"seed-peer-2|2",
"seed-peer-3|1",
"seed-peer-2|0",
"seed-peer-2|1",
"seed-peer-1|0"
]
);
}
#[test]
fn test_task_id() {
let generator = IDGenerator::new("127.0.0.1".to_string(), "localhost".to_string(), false);
assert_eq!(
generator
.task_id(TaskIDParameter::URLBased {
url: "https://example.com/file.txt?Expires=e1&Signature=s1&foo=bar".to_string(),
piece_length: Some(4194304),
tag: Some("tag1".to_string()),
application: Some("app1".to_string()),
filtered_query_params: vec!["Expires".to_string(), "Signature".to_string()],
revision: None,
})
.unwrap(),
"2a0c4c713d7f2f65f36b78b79c4b78a6bf5d5f67b76730ed13485d3271482f1c"
);
assert_eq!(
generator
.task_id(TaskIDParameter::URLBased {
url: "https://example.com/file.txt".to_string(),
piece_length: None,
tag: None,
application: None,
filtered_query_params: vec![],
revision: None,
})
.unwrap(),
"7fcf06e5f0b1e443065c1a563eed788eb2e168a05c6ad9c4b319f7a976322be0"
);
assert_eq!(
generator
.task_id(TaskIDParameter::Content("This is a test file".to_string()))
.unwrap(),
"e2d0fe1585a63ec6009c8016ff8dda8b17719a637405a4e23c0ff81339148249"
);
assert_eq!(
generator
.task_id(TaskIDParameter::BlobDigestBased(
"http://registry.example.com/v2/library/ubuntu/blobs/sha256:b2c366cce7e68013d5441c6326d5a3e1b12aeb5ed58564d0fd3fa089bc29cb6e"
.to_string(),
))
.unwrap(),
"b2c366cce7e68013d5441c6326d5a3e1b12aeb5ed58564d0fd3fa089bc29cb6e"
);
}