Box large futures
This commit is contained in:
@@ -30,189 +30,178 @@ use types::id::Id;
|
||||
|
||||
pub const NUM_NODES: usize = 3;
|
||||
|
||||
#[test]
|
||||
fn cluster_tests() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn cluster_tests() {
|
||||
println!("Running cluster broadcast tests...");
|
||||
let mut servers = Vec::with_capacity(NUM_NODES);
|
||||
|
||||
let coordinator_id = std::env::var("COORDINATOR").expect(concat!(
|
||||
"Missing coordinator type. Try running `STORE=<store_type> ",
|
||||
"COORDINATOR=<coordinator_type> cargo test`"
|
||||
));
|
||||
let coordinator = match coordinator_id.as_str() {
|
||||
"Nats" => Coordinator::Nats(NatsCoordinator {
|
||||
addresses: Map::new(vec!["127.0.0.1:4222".to_string()]),
|
||||
use_tls: false,
|
||||
..Default::default()
|
||||
}),
|
||||
"Redis" => Coordinator::Redis(RedisStore {
|
||||
url: "redis://127.0.0.1".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
_ => panic!("Unsupported coordinator type: {}", coordinator_id),
|
||||
};
|
||||
|
||||
// Create initial server
|
||||
let test = TestServerBuilder::new("cluster_test_0")
|
||||
.await
|
||||
.with_object(coordinator)
|
||||
.await
|
||||
.with_listener(NetworkListenerProtocol::Http, "http_0", 11000, true)
|
||||
.await
|
||||
.with_imap_listener(12000)
|
||||
.await
|
||||
.with_listener(NetworkListenerProtocol::Lmtp, "lmtp_0", 11200, false)
|
||||
.await
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
println!("Running cluster broadcast tests...");
|
||||
let mut servers = Vec::with_capacity(NUM_NODES);
|
||||
.await;
|
||||
let admin = test.account("admin");
|
||||
admin.mta_no_auth().await;
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
"jdoe@example.com",
|
||||
"this is john's secret",
|
||||
"John's account",
|
||||
&[],
|
||||
vec![],
|
||||
)
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
|
||||
let coordinator_id = std::env::var("COORDINATOR").expect(concat!(
|
||||
"Missing coordinator type. Try running `STORE=<store_type> ",
|
||||
"COORDINATOR=<coordinator_type> cargo test`"
|
||||
));
|
||||
let coordinator = match coordinator_id.as_str() {
|
||||
"Nats" => Coordinator::Nats(NatsCoordinator {
|
||||
addresses: Map::new(vec!["127.0.0.1:4222".to_string()]),
|
||||
use_tls: false,
|
||||
..Default::default()
|
||||
// Create listeners
|
||||
let mut listeners = vec![
|
||||
test.server
|
||||
.registry()
|
||||
.query::<Vec<Id>>(RegistryQuery::new(ObjectType::NetworkListener))
|
||||
.await
|
||||
.unwrap(),
|
||||
];
|
||||
for node_id in 1..NUM_NODES {
|
||||
let http_listener_id = admin
|
||||
.registry_create_object(NetworkListener {
|
||||
name: format!("http_{}", node_id),
|
||||
bind: Map::new(vec![
|
||||
SocketAddr::from_str(&format!("127.0.0.1:1100{node_id}")).unwrap(),
|
||||
]),
|
||||
protocol: NetworkListenerProtocol::Http,
|
||||
tls_implicit: true,
|
||||
use_tls: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
let imap_listener_id = admin
|
||||
.registry_create_object(NetworkListener {
|
||||
name: format!("imap_{}", node_id),
|
||||
bind: Map::new(vec![
|
||||
SocketAddr::from_str(&format!("127.0.0.1:1200{node_id}")).unwrap(),
|
||||
]),
|
||||
protocol: NetworkListenerProtocol::Imap,
|
||||
tls_implicit: false,
|
||||
use_tls: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
listeners.push(vec![http_listener_id, imap_listener_id]);
|
||||
}
|
||||
|
||||
// Create node roles
|
||||
for (role_id, listener_ids) in listeners.into_iter().enumerate() {
|
||||
admin
|
||||
.registry_create_object(ClusterRole {
|
||||
name: format!("role_{role_id}"),
|
||||
listeners: ClusterListenerGroup::EnableSome(ClusterListenerGroupProperties {
|
||||
listener_ids: Map::new(listener_ids),
|
||||
}),
|
||||
"Redis" => Coordinator::Redis(RedisStore {
|
||||
url: "redis://127.0.0.1".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
_ => panic!("Unsupported coordinator type: {}", coordinator_id),
|
||||
};
|
||||
tasks: ClusterTaskGroup::EnableAll,
|
||||
description: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
servers.push(test);
|
||||
|
||||
// Create initial server
|
||||
let test = TestServerBuilder::new("cluster_test_0")
|
||||
.await
|
||||
.with_object(coordinator)
|
||||
.await
|
||||
.with_listener(NetworkListenerProtocol::Http, "http_0", 11000, true)
|
||||
.await
|
||||
.with_imap_listener(12000)
|
||||
.await
|
||||
.with_listener(NetworkListenerProtocol::Lmtp, "lmtp_0", 11200, false)
|
||||
.await
|
||||
.build()
|
||||
.await;
|
||||
let admin = test.account("admin");
|
||||
admin.mta_no_auth().await;
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
"jdoe@example.com",
|
||||
"this is john's secret",
|
||||
"John's account",
|
||||
&[],
|
||||
vec![],
|
||||
)
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
// Build additional servers
|
||||
for node_id in 1..NUM_NODES {
|
||||
let test = TestServerBuilder::new_with_role(
|
||||
&format!("cluster_test_{node_id}"),
|
||||
format!("mail-{node_id}.example.com"),
|
||||
Some(format!("role_{node_id}")),
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.build_with_opts(false)
|
||||
.await;
|
||||
|
||||
// Create listeners
|
||||
let mut listeners = vec![
|
||||
test.server
|
||||
.registry()
|
||||
.query::<Vec<Id>>(RegistryQuery::new(ObjectType::NetworkListener))
|
||||
.await
|
||||
.unwrap(),
|
||||
];
|
||||
for node_id in 1..NUM_NODES {
|
||||
let http_listener_id = admin
|
||||
.registry_create_object(NetworkListener {
|
||||
name: format!("http_{}", node_id),
|
||||
bind: Map::new(vec![
|
||||
SocketAddr::from_str(&format!("127.0.0.1:1100{node_id}")).unwrap(),
|
||||
]),
|
||||
protocol: NetworkListenerProtocol::Http,
|
||||
tls_implicit: true,
|
||||
use_tls: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
let imap_listener_id = admin
|
||||
.registry_create_object(NetworkListener {
|
||||
name: format!("imap_{}", node_id),
|
||||
bind: Map::new(vec![
|
||||
SocketAddr::from_str(&format!("127.0.0.1:1200{node_id}")).unwrap(),
|
||||
]),
|
||||
protocol: NetworkListenerProtocol::Imap,
|
||||
tls_implicit: false,
|
||||
use_tls: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
listeners.push(vec![http_listener_id, imap_listener_id]);
|
||||
}
|
||||
// Verify that the server was assigned the correct node id
|
||||
assert_eq!(test.server.registry().node_id(), node_id as u16);
|
||||
servers.push(test);
|
||||
}
|
||||
|
||||
// Create node roles
|
||||
for (role_id, listener_ids) in listeners.into_iter().enumerate() {
|
||||
admin
|
||||
.registry_create_object(ClusterRole {
|
||||
name: format!("role_{role_id}"),
|
||||
listeners: ClusterListenerGroup::EnableSome(
|
||||
ClusterListenerGroupProperties {
|
||||
listener_ids: Map::new(listener_ids),
|
||||
},
|
||||
),
|
||||
tasks: ClusterTaskGroup::EnableAll,
|
||||
description: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
servers.push(test);
|
||||
// Verify cross-cluster cache invalidations
|
||||
let admin = servers[0].account("admin");
|
||||
let server1 = &servers[1].server;
|
||||
let server2 = &servers[2].server;
|
||||
let account_id = account.id().document_id();
|
||||
assert_eq!(
|
||||
server1
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John's account")
|
||||
);
|
||||
assert_eq!(
|
||||
server2
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John's account")
|
||||
);
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
account.id(),
|
||||
json!({
|
||||
Property::Description: "John Doe"
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
|
||||
assert_eq!(
|
||||
server1
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John Doe")
|
||||
);
|
||||
assert_eq!(
|
||||
server2
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John Doe")
|
||||
);
|
||||
|
||||
// Build additional servers
|
||||
for node_id in 1..NUM_NODES {
|
||||
let test = TestServerBuilder::new_with_role(
|
||||
&format!("cluster_test_{node_id}"),
|
||||
format!("mail-{node_id}.example.com"),
|
||||
Some(format!("role_{node_id}")),
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.build_with_opts(false)
|
||||
.await;
|
||||
|
||||
// Verify that the server was assigned the correct node id
|
||||
assert_eq!(test.server.registry().node_id(), node_id as u16);
|
||||
servers.push(test);
|
||||
}
|
||||
|
||||
// Verify cross-cluster cache invalidations
|
||||
let admin = servers[0].account("admin");
|
||||
let server1 = &servers[1].server;
|
||||
let server2 = &servers[2].server;
|
||||
let account_id = account.id().document_id();
|
||||
assert_eq!(
|
||||
server1
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John's account")
|
||||
);
|
||||
assert_eq!(
|
||||
server2
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John's account")
|
||||
);
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
account.id(),
|
||||
json!({
|
||||
Property::Description: "John Doe"
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
|
||||
assert_eq!(
|
||||
server1
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John Doe")
|
||||
);
|
||||
assert_eq!(
|
||||
server2
|
||||
.account(account_id)
|
||||
.await
|
||||
.unwrap()
|
||||
.description
|
||||
.as_deref(),
|
||||
Some("John Doe")
|
||||
);
|
||||
|
||||
// Run IMAP idle tests across nodes
|
||||
let mut node1_client =
|
||||
imap_client("jdoe@example.com", "this is john's secret", 1).await;
|
||||
let mut node2_client =
|
||||
imap_client("jdoe@example.com", "this is john's secret", 2).await;
|
||||
idle::test(&mut node1_client, &mut node2_client, true).await;
|
||||
});
|
||||
// Run IMAP idle tests across nodes
|
||||
let mut node1_client = imap_client("jdoe@example.com", "this is john's secret", 1).await;
|
||||
let mut node2_client = imap_client("jdoe@example.com", "this is john's secret", 2).await;
|
||||
idle::test(&mut node1_client, &mut node2_client, true).await;
|
||||
}
|
||||
|
||||
async fn imap_client(login: &str, secret: &str, node_id: u32) -> ImapConnection {
|
||||
|
||||
@@ -41,251 +41,244 @@ use serde_json::json;
|
||||
use std::{path::PathBuf, time::Instant};
|
||||
use utils::map::vec_map::VecMap;
|
||||
|
||||
#[test]
|
||||
fn imap_tests() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn imap_tests() {
|
||||
let mut test = TestServerBuilder::new("imap_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let mut test = TestServerBuilder::new("imap_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.await;
|
||||
.await;
|
||||
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"jdoe@example.com",
|
||||
"12345 + extra safety",
|
||||
"John Doe",
|
||||
&["john.doe@example.com"][..],
|
||||
),
|
||||
(
|
||||
"jane.smith@example.com",
|
||||
"abcde + extra safety",
|
||||
"Jane Smith",
|
||||
&["jane@example.com"][..],
|
||||
),
|
||||
(
|
||||
"foobar@example.com",
|
||||
"098765 + extra safety",
|
||||
"Bill Foobar",
|
||||
&["bill.foobar@example.com"][..],
|
||||
),
|
||||
(
|
||||
"popper@example.com",
|
||||
"a_pop3_safe_secret_with_extra_safety",
|
||||
"Karl Popper",
|
||||
&["karl.popper@example.com"][..],
|
||||
),
|
||||
(
|
||||
"sgd@example.com",
|
||||
"secret2 + extra safety",
|
||||
"Sigmund Gudmund Dudmundsson",
|
||||
&[][..],
|
||||
),
|
||||
(
|
||||
"spamtrap@example.com",
|
||||
"secret3 + extra safety",
|
||||
"Spam Trap",
|
||||
&[][..],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads],
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"jdoe@example.com",
|
||||
"12345 + extra safety",
|
||||
"John Doe",
|
||||
&["john.doe@example.com"][..],
|
||||
),
|
||||
(
|
||||
"jane.smith@example.com",
|
||||
"abcde + extra safety",
|
||||
"Jane Smith",
|
||||
&["jane@example.com"][..],
|
||||
),
|
||||
(
|
||||
"foobar@example.com",
|
||||
"098765 + extra safety",
|
||||
"Bill Foobar",
|
||||
&["bill.foobar@example.com"][..],
|
||||
),
|
||||
(
|
||||
"popper@example.com",
|
||||
"a_pop3_safe_secret_with_extra_safety",
|
||||
"Karl Popper",
|
||||
&["karl.popper@example.com"][..],
|
||||
),
|
||||
(
|
||||
"sgd@example.com",
|
||||
"secret2 + extra safety",
|
||||
"Sigmund Gudmund Dudmundsson",
|
||||
&[][..],
|
||||
),
|
||||
(
|
||||
"spamtrap@example.com",
|
||||
"secret3 + extra safety",
|
||||
"Spam Trap",
|
||||
&[][..],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads],
|
||||
)
|
||||
.await;
|
||||
test.insert_account(account);
|
||||
}
|
||||
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("support@example.com", "Support Group", &[])
|
||||
.await,
|
||||
);
|
||||
|
||||
// Add Jane to the Support group
|
||||
let support_id = test.account("support@example.com").id();
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
test.account("jane.smith@example.com").id(),
|
||||
json!({
|
||||
"memberGroupIds": { support_id: true },
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_create_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamClassifier {
|
||||
min_ham_samples: 10,
|
||||
min_spam_samples: 10,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Email {
|
||||
default_folders: VecMap::from_iter(
|
||||
[
|
||||
(SpecialUse::Inbox, "Inbox"),
|
||||
(SpecialUse::Sent, "Sent Items"),
|
||||
(SpecialUse::Trash, "Deleted Items"),
|
||||
(SpecialUse::Junk, "Junk Mail"),
|
||||
(SpecialUse::Drafts, "Drafts"),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(use_, name)| {
|
||||
(
|
||||
use_,
|
||||
EmailFolder {
|
||||
name: name.into(),
|
||||
subscribe: false,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await;
|
||||
test.insert_account(account);
|
||||
}
|
||||
}),
|
||||
),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageData {
|
||||
add_delivered_to_header: false,
|
||||
enable_spam_filter: Expression {
|
||||
else_: "recipients[0] != 'popper@example.com'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(10.0),
|
||||
tag: "PROB_SPAM_LOW".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(10.0),
|
||||
tag: "PROB_SPAM_HIGH".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(100.0),
|
||||
tag: "SPAM_TRAP".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MemoryLookupKey {
|
||||
is_glob_pattern: true,
|
||||
key: "spamtrap@*".into(),
|
||||
namespace: "spam-traps".into(),
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
admin.reload_lookup_stores().await;
|
||||
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("support@example.com", "Support Group", &[])
|
||||
.await,
|
||||
);
|
||||
test.insert_account(admin);
|
||||
|
||||
// Add Jane to the Support group
|
||||
let support_id = test.account("support@example.com").id();
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
test.account("jane.smith@example.com").id(),
|
||||
json!({
|
||||
"memberGroupIds": { support_id: true },
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let start_time = Instant::now();
|
||||
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_create_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamClassifier {
|
||||
min_ham_samples: 10,
|
||||
min_spam_samples: 10,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Email {
|
||||
default_folders: VecMap::from_iter(
|
||||
[
|
||||
(SpecialUse::Inbox, "Inbox"),
|
||||
(SpecialUse::Sent, "Sent Items"),
|
||||
(SpecialUse::Trash, "Deleted Items"),
|
||||
(SpecialUse::Junk, "Junk Mail"),
|
||||
(SpecialUse::Drafts, "Drafts"),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(use_, name)| {
|
||||
(
|
||||
use_,
|
||||
EmailFolder {
|
||||
name: name.into(),
|
||||
subscribe: false,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
}),
|
||||
),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageData {
|
||||
add_delivered_to_header: false,
|
||||
enable_spam_filter: Expression {
|
||||
else_: "recipients[0] != 'popper@example.com'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(10.0),
|
||||
tag: "PROB_SPAM_LOW".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(10.0),
|
||||
tag: "PROB_SPAM_HIGH".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SpamTag::Score(SpamTagScore {
|
||||
score: Float::new(100.0),
|
||||
tag: "SPAM_TRAP".into(),
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MemoryLookupKey {
|
||||
is_glob_pattern: true,
|
||||
key: "spamtrap@*".into(),
|
||||
namespace: "spam-traps".into(),
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
admin.reload_lookup_stores().await;
|
||||
// Body structure tests
|
||||
body_structure::test();
|
||||
|
||||
test.insert_account(admin);
|
||||
// Connect to IMAP server
|
||||
let mut imap_check = ImapConnection::connect(b"_y ").await;
|
||||
let mut imap = ImapConnection::connect(b"_x ").await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.assert_read(Type::Untagged, ResponseType::Ok).await;
|
||||
}
|
||||
|
||||
let start_time = Instant::now();
|
||||
// Unauthenticated tests
|
||||
basic::test(&mut imap, &mut imap_check).await;
|
||||
|
||||
// Body structure tests
|
||||
body_structure::test();
|
||||
// Login
|
||||
let account = test.account("jdoe@example.com");
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.authenticate(account.name(), account.secret()).await;
|
||||
}
|
||||
|
||||
// Connect to IMAP server
|
||||
let mut imap_check = ImapConnection::connect(b"_y ").await;
|
||||
let mut imap = ImapConnection::connect(b"_x ").await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.assert_read(Type::Untagged, ResponseType::Ok).await;
|
||||
}
|
||||
// Delete folders
|
||||
for mailbox in ["Drafts", "Junk Mail", "Sent Items"] {
|
||||
imap.send(&format!("DELETE \"{}\"", mailbox)).await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
}
|
||||
|
||||
// Unauthenticated tests
|
||||
basic::test(&mut imap, &mut imap_check).await;
|
||||
mailbox::test(&mut imap, &mut imap_check, &test).await;
|
||||
append::test(&mut imap, &mut imap_check, &test).await;
|
||||
search::test(&mut imap, &mut imap_check, &test).await;
|
||||
fetch::test(&mut imap, &mut imap_check).await;
|
||||
store::test(&mut imap, &mut imap_check, &test).await;
|
||||
copy_move::test(&mut imap, &mut imap_check).await;
|
||||
thread::test(&mut imap, &mut imap_check, &test).await;
|
||||
idle::test(&mut imap, &mut imap_check, false).await;
|
||||
condstore::test(&mut imap, &mut imap_check).await;
|
||||
acl::test(&mut imap, &mut imap_check, &test).await;
|
||||
|
||||
// Login
|
||||
let account = test.account("jdoe@example.com");
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.authenticate(account.name(), account.secret()).await;
|
||||
}
|
||||
// Logout
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("UNAUTHENTICATE").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Delete folders
|
||||
for mailbox in ["Drafts", "Junk Mail", "Sent Items"] {
|
||||
imap.send(&format!("DELETE \"{}\"", mailbox)).await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
}
|
||||
imap.send("LOGOUT").await;
|
||||
imap.assert_read(Type::Untagged, ResponseType::Bye).await;
|
||||
}
|
||||
|
||||
mailbox::test(&mut imap, &mut imap_check, &test).await;
|
||||
append::test(&mut imap, &mut imap_check, &test).await;
|
||||
search::test(&mut imap, &mut imap_check, &test).await;
|
||||
fetch::test(&mut imap, &mut imap_check).await;
|
||||
store::test(&mut imap, &mut imap_check, &test).await;
|
||||
copy_move::test(&mut imap, &mut imap_check).await;
|
||||
thread::test(&mut imap, &mut imap_check, &test).await;
|
||||
idle::test(&mut imap, &mut imap_check, false).await;
|
||||
condstore::test(&mut imap, &mut imap_check).await;
|
||||
acl::test(&mut imap, &mut imap_check, &test).await;
|
||||
// Antispam training
|
||||
antispam::test(&test).await;
|
||||
|
||||
// Logout
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("UNAUTHENTICATE").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
// Run ManageSieve tests
|
||||
managesieve::test(&test).await;
|
||||
|
||||
imap.send("LOGOUT").await;
|
||||
imap.assert_read(Type::Untagged, ResponseType::Bye).await;
|
||||
}
|
||||
// Run POP3 tests
|
||||
pop::test(&test).await;
|
||||
|
||||
// Antispam training
|
||||
antispam::test(&test).await;
|
||||
// Print elapsed time
|
||||
let elapsed = start_time.elapsed();
|
||||
println!(
|
||||
"Elapsed: {}.{:03}s",
|
||||
elapsed.as_secs(),
|
||||
elapsed.subsec_millis()
|
||||
);
|
||||
|
||||
// Run ManageSieve tests
|
||||
managesieve::test(&test).await;
|
||||
|
||||
// Run POP3 tests
|
||||
pop::test(&test).await;
|
||||
|
||||
// Print elapsed time
|
||||
let elapsed = start_time.elapsed();
|
||||
println!(
|
||||
"Elapsed: {}.{:03}s",
|
||||
elapsed.as_secs(),
|
||||
elapsed.subsec_millis()
|
||||
);
|
||||
|
||||
// Remove test data
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
});
|
||||
// Remove test data
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_uid_list(list: &str) -> AHashSet<u32> {
|
||||
|
||||
@@ -23,201 +23,194 @@ pub mod files;
|
||||
pub mod mail;
|
||||
pub mod principal;
|
||||
|
||||
#[test]
|
||||
fn jmap_tests() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn jmap_tests() {
|
||||
let mut test = TestServerBuilder::new("jmap_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let mut test = TestServerBuilder::new("jmap_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.await;
|
||||
.await;
|
||||
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"jdoe@example.com",
|
||||
"12345 + extra safety",
|
||||
"John Doe",
|
||||
&["john.doe@example.com"][..],
|
||||
),
|
||||
(
|
||||
"jane.smith@example.com",
|
||||
"abcde + extra safety",
|
||||
"Jane Smith",
|
||||
&["jane@example.com"],
|
||||
),
|
||||
(
|
||||
"bill@example.com",
|
||||
"098765 + extra safety",
|
||||
"Bill Foobar",
|
||||
&["bill.foobar@example.com"],
|
||||
),
|
||||
(
|
||||
"robert@example.com",
|
||||
"aabbcc + extra safety",
|
||||
"Robert Foobar",
|
||||
&[][..],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads],
|
||||
)
|
||||
.await;
|
||||
test.insert_account(account);
|
||||
}
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"jdoe@example.com",
|
||||
"12345 + extra safety",
|
||||
"John Doe",
|
||||
&["john.doe@example.com"][..],
|
||||
),
|
||||
(
|
||||
"jane.smith@example.com",
|
||||
"abcde + extra safety",
|
||||
"Jane Smith",
|
||||
&["jane@example.com"],
|
||||
),
|
||||
(
|
||||
"bill@example.com",
|
||||
"098765 + extra safety",
|
||||
"Bill Foobar",
|
||||
&["bill.foobar@example.com"],
|
||||
),
|
||||
(
|
||||
"robert@example.com",
|
||||
"aabbcc + extra safety",
|
||||
"Robert Foobar",
|
||||
&[][..],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![Permission::UnlimitedRequests, Permission::UnlimitedUploads],
|
||||
)
|
||||
.await;
|
||||
test.insert_account(account);
|
||||
}
|
||||
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("sales@example.com", "Sales Group", &[])
|
||||
.await,
|
||||
);
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("sales@example.com", "Sales Group", &[])
|
||||
.await,
|
||||
);
|
||||
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_create_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Jmap {
|
||||
set_max_objects: 100_000,
|
||||
get_max_results: 100_000,
|
||||
event_source_throttle: 500u64.into(),
|
||||
push_throttle: 500u64.into(),
|
||||
websocket_throttle: 500u64.into(),
|
||||
push_attempt_wait: 500u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_create_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Jmap {
|
||||
set_max_objects: 100_000,
|
||||
get_max_results: 100_000,
|
||||
event_source_throttle: 500u64.into(),
|
||||
push_throttle: 500u64.into(),
|
||||
websocket_throttle: 500u64.into(),
|
||||
push_attempt_wait: 500u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarAlarm {
|
||||
min_trigger_interval: 1000u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Sharing {
|
||||
allow_directory_queries: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaOutboundStrategy {
|
||||
route: Expression {
|
||||
match_: List::from_iter([
|
||||
ExpressionMatch {
|
||||
if_: "rcpt_domain == 'example.com'".into(),
|
||||
then: "'local'".into(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarAlarm {
|
||||
min_trigger_interval: 1000u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Sharing {
|
||||
allow_directory_queries: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaOutboundStrategy {
|
||||
route: Expression {
|
||||
match_: List::from_iter([
|
||||
ExpressionMatch {
|
||||
if_: "rcpt_domain == 'example.com'".into(),
|
||||
then: "'local'".into(),
|
||||
},
|
||||
ExpressionMatch {
|
||||
if_: concat!(
|
||||
"contains(['remote.org', 'foobar.com', ",
|
||||
"'test.com', 'other_domain.com'], rcpt_domain)"
|
||||
)
|
||||
.into(),
|
||||
then: "'mock-smtp'".into(),
|
||||
},
|
||||
]),
|
||||
else_: "'mx'".to_string(),
|
||||
ExpressionMatch {
|
||||
if_: concat!(
|
||||
"contains(['remote.org', 'foobar.com', ",
|
||||
"'test.com', 'other_domain.com'], rcpt_domain)"
|
||||
)
|
||||
.into(),
|
||||
then: "'mock-smtp'".into(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaRoute::Relay(MtaRouteRelay {
|
||||
address: "127.0.0.1".into(),
|
||||
port: 9999,
|
||||
allow_invalid_certs: true,
|
||||
implicit_tls: false,
|
||||
name: "mock-smtp".into(),
|
||||
protocol: MtaProtocol::Smtp,
|
||||
..Default::default()
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaExtensions {
|
||||
future_release: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "!is_empty(authenticated_as)".into(),
|
||||
then: "99999999d".into(),
|
||||
}]),
|
||||
else_: "false".to_string(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
]),
|
||||
else_: "'mx'".to_string(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaRoute::Relay(MtaRouteRelay {
|
||||
address: "127.0.0.1".into(),
|
||||
port: 9999,
|
||||
allow_invalid_certs: true,
|
||||
implicit_tls: false,
|
||||
name: "mock-smtp".into(),
|
||||
protocol: MtaProtocol::Smtp,
|
||||
..Default::default()
|
||||
}))
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaExtensions {
|
||||
future_release: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "!is_empty(authenticated_as)".into(),
|
||||
then: "99999999d".into(),
|
||||
}]),
|
||||
else_: "false".to_string(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
|
||||
test.insert_account(admin);
|
||||
test.insert_account(admin);
|
||||
|
||||
/*mail::get::test(&test).await;
|
||||
mail::set::test(&test).await;
|
||||
mail::parse::test(&test).await;
|
||||
mail::query::test(&test).await;
|
||||
mail::search_snippet::test(&test).await;
|
||||
mail::changes::test(&test).await;
|
||||
mail::query_changes::test(&test).await;
|
||||
mail::copy::test(&test).await;
|
||||
mail::thread_get::test(&test).await;*/
|
||||
mail::thread_merge::test(&test).await;
|
||||
mail::mailbox::test(&test).await;
|
||||
mail::acl::test(&test).await;
|
||||
mail::sieve_script::test(&test).await;
|
||||
mail::vacation_response::test(&test).await;
|
||||
mail::submission::test(&test).await;
|
||||
mail::get::test(&test).await;
|
||||
mail::set::test(&test).await;
|
||||
mail::parse::test(&test).await;
|
||||
mail::query::test(&test).await;
|
||||
mail::search_snippet::test(&test).await;
|
||||
mail::changes::test(&test).await;
|
||||
mail::query_changes::test(&test).await;
|
||||
mail::copy::test(&test).await;
|
||||
mail::thread_get::test(&test).await;
|
||||
mail::thread_merge::test(&test).await;
|
||||
mail::mailbox::test(&test).await;
|
||||
mail::acl::test(&test).await;
|
||||
mail::sieve_script::test(&test).await;
|
||||
mail::vacation_response::test(&test).await;
|
||||
mail::submission::test(&test).await;
|
||||
|
||||
core::event_source::test(&test).await;
|
||||
core::websocket::test(&test).await;
|
||||
core::push_subscription::test(&test).await;
|
||||
core::blob::test(&test).await;
|
||||
core::event_source::test(&test).await;
|
||||
core::websocket::test(&test).await;
|
||||
core::push_subscription::test(&test).await;
|
||||
core::blob::test(&test).await;
|
||||
|
||||
contacts::addressbook::test(&test).await;
|
||||
contacts::contact::test(&test).await;
|
||||
contacts::acl::test(&test).await;
|
||||
contacts::addressbook::test(&test).await;
|
||||
contacts::contact::test(&test).await;
|
||||
contacts::acl::test(&test).await;
|
||||
|
||||
files::node::test(&test).await;
|
||||
files::acl::test(&test).await;
|
||||
files::node::test(&test).await;
|
||||
files::acl::test(&test).await;
|
||||
|
||||
calendar::calendars::test(&test).await;
|
||||
calendar::event::test(&test).await;
|
||||
calendar::notification::test(&test).await;
|
||||
calendar::alarm::test(&test).await;
|
||||
calendar::calendars::test(&test).await;
|
||||
calendar::event::test(&test).await;
|
||||
calendar::notification::test(&test).await;
|
||||
calendar::alarm::test(&test).await;
|
||||
|
||||
calendar::identity::test(&test).await;
|
||||
calendar::acl::test(&test).await;
|
||||
calendar::identity::test(&test).await;
|
||||
calendar::acl::test(&test).await;
|
||||
|
||||
principal::get::test(&test).await;
|
||||
principal::availability::test(&test).await;
|
||||
principal::get::test(&test).await;
|
||||
principal::availability::test(&test).await;
|
||||
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
});
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_values(string: &str, name: &str) -> Vec<String> {
|
||||
|
||||
@@ -27,49 +27,43 @@ if allof( envelope :localpart :contains "to" ".",
|
||||
}
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn address_rewrite() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn address_rewrite() {
|
||||
let mut test = TestServerBuilder::new("smtp_rewrite_test")
|
||||
.await
|
||||
.with_http_listener(19007)
|
||||
.await
|
||||
.disable_services()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let mut test = TestServerBuilder::new("smtp_rewrite_test")
|
||||
.await
|
||||
.with_http_listener(19007)
|
||||
.await
|
||||
.disable_services()
|
||||
.build()
|
||||
.await;
|
||||
.await;
|
||||
|
||||
// Add test settings
|
||||
let admin = test.account("admin");
|
||||
admin.mta_no_auth().await;
|
||||
admin
|
||||
.registry_create_object(MtaStageMail {
|
||||
rewrite: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: concat!(
|
||||
"ends_with(sender_domain, '.foobar.net') & ",
|
||||
"matches('^([^.]+)@([^.]+)\\.(.+)$', sender)"
|
||||
)
|
||||
.into(),
|
||||
then: "$1 + '+' + $2 + '@' + $3".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
script: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "sender_domain = 'foobar.org'".into(),
|
||||
then: "'mail'".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
// Add test settings
|
||||
let admin = test.account("admin");
|
||||
admin.mta_no_auth().await;
|
||||
admin
|
||||
.registry_create_object(MtaStageMail {
|
||||
rewrite: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: concat!(
|
||||
"ends_with(sender_domain, '.foobar.net') & ",
|
||||
"matches('^([^.]+)@([^.]+)\\.(.+)$', sender)"
|
||||
)
|
||||
.into(),
|
||||
then: "$1 + '+' + $2 + '@' + $3".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
script: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "sender_domain = 'foobar.org'".into(),
|
||||
then: "'mail'".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageRcpt {
|
||||
rewrite: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
@@ -93,81 +87,80 @@ fn address_rewrite() {
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SieveSystemInterpreter {
|
||||
default_from_address: Expression {
|
||||
else_: "'sieve@foobar.org'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
admin
|
||||
.registry_create_object(SieveSystemInterpreter {
|
||||
default_from_address: Expression {
|
||||
else_: "'sieve@foobar.org'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
default_from_name: Expression {
|
||||
else_: "'Sieve Daemon'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
default_return_path: Expression {
|
||||
else_: "''".into(),
|
||||
..Default::default()
|
||||
},
|
||||
message_id_hostname: Some("'mx.foobar.org'".into()),
|
||||
duplicate_expiry: (86_400u64 * 100 * 7).into(),
|
||||
max_cpu_cycles: 10000,
|
||||
max_nested_includes: 5,
|
||||
max_out_messages: 5,
|
||||
max_received_headers: 50,
|
||||
max_redirects: 3,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
for (name, contents) in [("mail", MAIL_SCRIPT), ("rcpt", MAIL_RCPT)] {
|
||||
admin
|
||||
.registry_create_object(SieveSystemScript {
|
||||
name: name.to_string(),
|
||||
contents: contents.to_string(),
|
||||
is_active: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
}
|
||||
admin.reload_settings().await;
|
||||
test.reload_core();
|
||||
default_from_name: Expression {
|
||||
else_: "'Sieve Daemon'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
default_return_path: Expression {
|
||||
else_: "''".into(),
|
||||
..Default::default()
|
||||
},
|
||||
message_id_hostname: Some("'mx.foobar.org'".into()),
|
||||
duplicate_expiry: (86_400u64 * 100 * 7).into(),
|
||||
max_cpu_cycles: 10000,
|
||||
max_nested_includes: 5,
|
||||
max_out_messages: 5,
|
||||
max_received_headers: 50,
|
||||
max_redirects: 3,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
for (name, contents) in [("mail", MAIL_SCRIPT), ("rcpt", MAIL_RCPT)] {
|
||||
admin
|
||||
.registry_create_object(SieveSystemScript {
|
||||
name: name.to_string(),
|
||||
contents: contents.to_string(),
|
||||
is_active: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
}
|
||||
admin.reload_settings().await;
|
||||
test.reload_core();
|
||||
|
||||
// Init session
|
||||
let mut session = test.new_mta_session();
|
||||
session.data.remote_ip_str = "10.0.0.1".into();
|
||||
session.eval_session_params().await;
|
||||
session.ehlo("mx.doe.org").await;
|
||||
// Init session
|
||||
let mut session = test.new_mta_session();
|
||||
session.data.remote_ip_str = "10.0.0.1".into();
|
||||
session.eval_session_params().await;
|
||||
session.ehlo("mx.doe.org").await;
|
||||
|
||||
// Sender rewrite using regex
|
||||
session.mail_from("bill@doe.foobar.net", "250").await;
|
||||
assert_eq!(
|
||||
session.data.mail_from.as_ref().unwrap().address,
|
||||
"bill+doe@foobar.net"
|
||||
);
|
||||
session.reset();
|
||||
// Sender rewrite using regex
|
||||
session.mail_from("bill@doe.foobar.net", "250").await;
|
||||
assert_eq!(
|
||||
session.data.mail_from.as_ref().unwrap().address,
|
||||
"bill+doe@foobar.net"
|
||||
);
|
||||
session.reset();
|
||||
|
||||
// Sender rewrite using sieve
|
||||
session.mail_from("this_is_admin@foobar.org", "250").await;
|
||||
assert_eq!(
|
||||
session.data.mail_from.as_ref().unwrap().address_lcase,
|
||||
"mailer-daemon@foobar.org"
|
||||
);
|
||||
// Sender rewrite using sieve
|
||||
session.mail_from("this_is_admin@foobar.org", "250").await;
|
||||
assert_eq!(
|
||||
session.data.mail_from.as_ref().unwrap().address_lcase,
|
||||
"mailer-daemon@foobar.org"
|
||||
);
|
||||
|
||||
// Recipient rewrite using regex
|
||||
session.rcpt_to("mary.smith@foobar.net", "250").await;
|
||||
assert_eq!(
|
||||
session.data.rcpt_to.last().unwrap().address,
|
||||
"mary+smith@foobar.net"
|
||||
);
|
||||
// Recipient rewrite using regex
|
||||
session.rcpt_to("mary.smith@foobar.net", "250").await;
|
||||
assert_eq!(
|
||||
session.data.rcpt_to.last().unwrap().address,
|
||||
"mary+smith@foobar.net"
|
||||
);
|
||||
|
||||
// Remove duplicates
|
||||
session.rcpt_to("mary.smith@foobar.net", "250").await;
|
||||
assert_eq!(session.data.rcpt_to.len(), 1);
|
||||
// Remove duplicates
|
||||
session.rcpt_to("mary.smith@foobar.net", "250").await;
|
||||
assert_eq!(session.data.rcpt_to.len(), 1);
|
||||
|
||||
// Recipient rewrite using sieve
|
||||
session.rcpt_to("m.a.r.y.s.m.i.t.h@foobar.org", "250").await;
|
||||
assert_eq!(
|
||||
session.data.rcpt_to.last().unwrap().address,
|
||||
"marysmith@foobar.org"
|
||||
);
|
||||
});
|
||||
// Recipient rewrite using sieve
|
||||
session.rcpt_to("m.a.r.y.s.m.i.t.h@foobar.org", "250").await;
|
||||
assert_eq!(
|
||||
session.data.rcpt_to.last().unwrap().address,
|
||||
"marysmith@foobar.org"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,65 +21,58 @@ pub mod tenant;
|
||||
use crate::utils::server::TestServerBuilder;
|
||||
use registry::schema::structs::{Expression, Imap, MtaStageAuth};
|
||||
|
||||
#[test]
|
||||
fn system_tests() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn system_tests() {
|
||||
let mut test = TestServerBuilder::new("system_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.with_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.with_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let mut test = TestServerBuilder::new("system_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.with_object(Imap {
|
||||
allow_plain_text_auth: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.with_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.build()
|
||||
.await;
|
||||
.await;
|
||||
|
||||
// Create admin account
|
||||
let admin = test
|
||||
.create_user_account(
|
||||
"admin",
|
||||
"admin@example.org",
|
||||
"these_pretzels_are_making_me_thirsty",
|
||||
&[],
|
||||
"Admin",
|
||||
)
|
||||
.await;
|
||||
test.account("admin")
|
||||
.assign_roles_to_account(admin.id(), &["user", "system"])
|
||||
.await;
|
||||
test.insert_account(admin);
|
||||
// Create admin account
|
||||
let admin = test
|
||||
.create_user_account(
|
||||
"admin",
|
||||
"admin@example.org",
|
||||
"these_pretzels_are_making_me_thirsty",
|
||||
&[],
|
||||
"Admin",
|
||||
)
|
||||
.await;
|
||||
test.account("admin")
|
||||
.assign_roles_to_account(admin.id(), &["user", "system"])
|
||||
.await;
|
||||
test.insert_account(admin);
|
||||
|
||||
directory::test(&test).await;
|
||||
authentication::test(&test).await;
|
||||
oidc::test(&mut test).await;
|
||||
authorization::test(&mut test).await;
|
||||
tenant::test(&mut test).await;
|
||||
security::test(&mut test).await;
|
||||
quota::test(&mut test).await;
|
||||
purge::test(&mut test).await;
|
||||
delivery::test(&mut test).await;
|
||||
crypto::test(&mut test).await;
|
||||
antispam::test(&mut test).await;
|
||||
archiving::test(&mut test).await;
|
||||
task::test(&mut test).await;
|
||||
directory::test(&test).await;
|
||||
authentication::test(&test).await;
|
||||
oidc::test(&mut test).await;
|
||||
authorization::test(&mut test).await;
|
||||
tenant::test(&mut test).await;
|
||||
security::test(&mut test).await;
|
||||
quota::test(&mut test).await;
|
||||
purge::test(&mut test).await;
|
||||
delivery::test(&mut test).await;
|
||||
crypto::test(&mut test).await;
|
||||
antispam::test(&mut test).await;
|
||||
archiving::test(&mut test).await;
|
||||
task::test(&mut test).await;
|
||||
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
});
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,180 +40,173 @@ pub mod prop;
|
||||
pub mod put_get;
|
||||
pub mod sync;
|
||||
|
||||
#[test]
|
||||
fn webdav_tests() {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.thread_stack_size(8 * 1024 * 1024) // 8MB stack
|
||||
.enable_all()
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
pub async fn webdav_tests() {
|
||||
// Prepare settings
|
||||
let assisted_discovery = std::env::var("ASSISTED_DISCOVERY").unwrap_or_default() == "1";
|
||||
|
||||
let mut test = TestServerBuilder::new("webdav_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
// Prepare settings
|
||||
let assisted_discovery = std::env::var("ASSISTED_DISCOVERY").unwrap_or_default() == "1";
|
||||
.await;
|
||||
|
||||
let mut test = TestServerBuilder::new("webdav_tests")
|
||||
.await
|
||||
.with_default_listeners()
|
||||
.await
|
||||
.build()
|
||||
.await;
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
|
||||
// Create admin account
|
||||
let admin = test.create_admin_account("admin@example.com").await;
|
||||
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"john@example.com",
|
||||
"secret2 + some more text",
|
||||
"John Doe",
|
||||
&["jdoe@example.com"],
|
||||
),
|
||||
(
|
||||
"jane@example.com",
|
||||
"secret3 + some more text",
|
||||
"Jane Doe-Smith",
|
||||
&["jane.smith@example.com"],
|
||||
),
|
||||
(
|
||||
"bill@example.com",
|
||||
"secret4 + some more text",
|
||||
"Bill Foobar",
|
||||
&["bill@example.com"],
|
||||
),
|
||||
(
|
||||
"mike@example.com",
|
||||
"secret5 + some more text",
|
||||
"Mike Noquota",
|
||||
&["mike@example.com"],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![
|
||||
Permission::UnlimitedRequests,
|
||||
Permission::UnlimitedUploads,
|
||||
Permission::DavPrincipalList,
|
||||
Permission::DavPrincipalSearch,
|
||||
],
|
||||
)
|
||||
.await;
|
||||
if name == "mike@example.com" {
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
account.id(),
|
||||
json!({
|
||||
Property::Quotas: { StorageQuota::MaxDiskQuota.as_str(): 1024}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
test.insert_account(account);
|
||||
}
|
||||
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("support@example.com", "Support Group", &[])
|
||||
.await,
|
||||
);
|
||||
|
||||
// Add Jane to the Support group
|
||||
let support_id = test.account("support@example.com").id();
|
||||
// Create test users
|
||||
for (name, secret, description, aliases) in [
|
||||
(
|
||||
"john@example.com",
|
||||
"secret2 + some more text",
|
||||
"John Doe",
|
||||
&["jdoe@example.com"],
|
||||
),
|
||||
(
|
||||
"jane@example.com",
|
||||
"secret3 + some more text",
|
||||
"Jane Doe-Smith",
|
||||
&["jane.smith@example.com"],
|
||||
),
|
||||
(
|
||||
"bill@example.com",
|
||||
"secret4 + some more text",
|
||||
"Bill Foobar",
|
||||
&["bill@example.com"],
|
||||
),
|
||||
(
|
||||
"mike@example.com",
|
||||
"secret5 + some more text",
|
||||
"Mike Noquota",
|
||||
&["mike@example.com"],
|
||||
),
|
||||
] {
|
||||
let account = admin
|
||||
.create_user_account(
|
||||
name,
|
||||
secret,
|
||||
description,
|
||||
aliases,
|
||||
vec![
|
||||
Permission::UnlimitedRequests,
|
||||
Permission::UnlimitedUploads,
|
||||
Permission::DavPrincipalList,
|
||||
Permission::DavPrincipalSearch,
|
||||
],
|
||||
)
|
||||
.await;
|
||||
if name == "mike@example.com" {
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
test.account("jane@example.com").id(),
|
||||
account.id(),
|
||||
json!({
|
||||
"memberGroupIds": { support_id: true },
|
||||
Property::Quotas: { StorageQuota::MaxDiskQuota.as_str(): 1024}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_update_setting(
|
||||
SystemSettings {
|
||||
default_hostname: "webdav.example.org".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
&[Property::DefaultHostname],
|
||||
)
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarAlarm {
|
||||
min_trigger_interval: 1000u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Sharing {
|
||||
allow_directory_queries: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarScheduling {
|
||||
auto_add_invitations: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(WebDav {
|
||||
enable_assisted_discovery: assisted_discovery,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
test.insert_account(account);
|
||||
}
|
||||
|
||||
test.insert_account(admin);
|
||||
// Create test group
|
||||
test.insert_account(
|
||||
admin
|
||||
.create_group_account("support@example.com", "Support Group", &[])
|
||||
.await,
|
||||
);
|
||||
|
||||
let start_time = Instant::now();
|
||||
//test_build_itip_templates(&test).await;
|
||||
basic::test(&test).await;
|
||||
put_get::test(&test).await;
|
||||
mkcol::test(&test).await;
|
||||
copy_move::test(&test, assisted_discovery).await;
|
||||
prop::test(&test, assisted_discovery).await;
|
||||
multiget::test(&test).await;
|
||||
sync::test(&test).await;
|
||||
lock::test(&test).await;
|
||||
principals::test(&test, assisted_discovery).await;
|
||||
acl::test(&test).await;
|
||||
card_query::test(&test).await;
|
||||
cal_query::test(&test).await;
|
||||
cal_alarm::test(&test).await;
|
||||
cal_itip::test();
|
||||
cal_scheduling::test(&test).await;
|
||||
// Add Jane to the Support group
|
||||
let support_id = test.account("support@example.com").id();
|
||||
admin
|
||||
.registry_update_object(
|
||||
ObjectType::Account,
|
||||
test.account("jane@example.com").id(),
|
||||
json!({
|
||||
"memberGroupIds": { support_id: true },
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Print elapsed time
|
||||
let elapsed = start_time.elapsed();
|
||||
println!(
|
||||
"Elapsed: {}.{:03}s",
|
||||
elapsed.as_secs(),
|
||||
elapsed.subsec_millis()
|
||||
);
|
||||
// Add test settings
|
||||
admin
|
||||
.registry_update_setting(
|
||||
SystemSettings {
|
||||
default_hostname: "webdav.example.org".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
&[Property::DefaultHostname],
|
||||
)
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageAuth {
|
||||
require: Expression {
|
||||
else_: "false".to_string(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarAlarm {
|
||||
min_trigger_interval: 1000u64.into(),
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(Sharing {
|
||||
allow_directory_queries: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(CalendarScheduling {
|
||||
auto_add_invitations: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(WebDav {
|
||||
enable_assisted_discovery: assisted_discovery,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
|
||||
// Remove test data
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
});
|
||||
test.insert_account(admin);
|
||||
|
||||
let start_time = Instant::now();
|
||||
//test_build_itip_templates(&test).await;
|
||||
basic::test(&test).await;
|
||||
put_get::test(&test).await;
|
||||
mkcol::test(&test).await;
|
||||
copy_move::test(&test, assisted_discovery).await;
|
||||
prop::test(&test, assisted_discovery).await;
|
||||
multiget::test(&test).await;
|
||||
sync::test(&test).await;
|
||||
lock::test(&test).await;
|
||||
principals::test(&test, assisted_discovery).await;
|
||||
acl::test(&test).await;
|
||||
card_query::test(&test).await;
|
||||
cal_query::test(&test).await;
|
||||
cal_alarm::test(&test).await;
|
||||
cal_itip::test();
|
||||
cal_scheduling::test(&test).await;
|
||||
|
||||
// Print elapsed time
|
||||
let elapsed = start_time.elapsed();
|
||||
println!(
|
||||
"Elapsed: {}.{:03}s",
|
||||
elapsed.as_secs(),
|
||||
elapsed.subsec_millis()
|
||||
);
|
||||
|
||||
// Remove test data
|
||||
if test.is_reset() {
|
||||
test.temp_dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DavResourcesTest {
|
||||
|
||||
Reference in New Issue
Block a user