Fixed tests

This commit is contained in:
mdecimus
2023-12-22 10:27:43 +01:00
parent 7ff851e350
commit 8ff0d3ff9c
9 changed files with 112 additions and 47 deletions

View File

@@ -35,7 +35,7 @@ pub mod set;
pub const INBOX_ID: u32 = 0;
pub const TRASH_ID: u32 = 1;
pub const JUNK_ID: u32 = 1;
pub const JUNK_ID: u32 = 2;
#[derive(Debug, Clone, Copy)]
pub struct UidMailbox {

View File

@@ -32,7 +32,7 @@ jemallocator = "0.5.0"
[features]
#default = ["sqlite", "foundationdb", "postgres", "mysql", "rocks", "elastic", "s3", "redis"]
default = ["rocks"]
default = ["sqlite", "foundationdb", "postgres", "mysql", "rocks", "elastic", "s3", "redis"]
sqlite = ["store/sqlite"]
foundationdb = ["store/foundation"]
postgres = ["store/postgres"]

View File

@@ -24,7 +24,7 @@
use rusqlite::{params, OptionalExtension, TransactionBehavior};
use crate::{
write::{Batch, Operation, ValueOp},
write::{Batch, BitmapClass, Operation, ValueClass, ValueOp},
BitmapKey, IndexKey, Key, LogKey, ValueKey,
};
@@ -95,6 +95,26 @@ impl SqliteStore {
table
))?
.execute([&key, value])?;
if matches!(class, ValueClass::ReservedId) {
// Make sure the reserved id is not already in use
let key = BitmapKey {
account_id,
collection,
class: BitmapClass::DocumentIds,
block_num: document_id,
}
.serialize(0);
if trx
.prepare_cached("SELECT 1 FROM b WHERE k = ?")?
.query_row([&key], |_| Ok(true))
.optional()?
.unwrap_or(false)
{
trx.rollback()?;
return Err(crate::Error::AssertValueFailed);
}
}
} else {
trx.prepare_cached(&format!("DELETE FROM {} WHERE k = ?", table))?
.execute([&key])?;
@@ -171,6 +191,7 @@ impl SqliteStore {
.optional()?
.unwrap_or_else(|| assert_value.is_none());
if !matches {
trx.rollback()?;
return Err(crate::Error::AssertValueFailed);
}
}

View File

@@ -6,7 +6,7 @@ resolver = "2"
[features]
#default = ["sqlite", "foundationdb", "postgres", "mysql", "rocks", "elastic", "s3", "redis"]
default = ["rocks"]
default = ["sqlite", "foundationdb", "postgres", "mysql", "rocks", "elastic", "s3", "redis"]
sqlite = ["store/sqlite"]
foundationdb = ["store/foundation"]
postgres = ["store/postgres"]

View File

@@ -43,6 +43,22 @@ use tokio_rustls::TlsAcceptor;
use crate::store::TempDir;
const CONFIG: &str = r#"
[directory."rocksdb"]
type = "internal"
store = "rocksdb"
[directory."rocksdb".options]
catch-all = true
subaddressing = true
[directory."foundationdb"]
type = "internal"
store = "foundationdb"
[directory."foundationdb".options]
catch-all = true
subaddressing = true
[directory."sqlite"]
type = "sql"
store = "sqlite"
@@ -288,7 +304,9 @@ impl DirectoryTest {
let mut config_file = CONFIG.replace("{TMP}", &temp_dir.path.to_string_lossy());
if id_store.is_some() {
// Disable foundationdb store for SQL tests (the fdb select api version can only be run once per process)
config_file = config_file.replace("foundationdb", "ignore");
config_file = config_file
.replace("type = \"foundationdb\"", "type = \"ignore\"")
.replace("store = \"foundationdb\"", "disable = true");
}
let config = utils::config::Config::new(&config_file).unwrap();
let stores = config.parse_stores().await.unwrap();

View File

@@ -325,7 +325,7 @@ impl DirectoryStore {
),
"INSERT INTO accounts (name, secret, type) VALUES ('admin', 'secret', 'admin')",
] {
let query = if matches!(self.store, LookupStore::Store(Store::MySQL(_))) {
let query = if self.is_mysql() {
query.replace("TEXT", "VARCHAR(255)")
} else {
query.to_string()
@@ -346,12 +346,12 @@ impl DirectoryStore {
};
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
concat!(
"INSERT INTO accounts (name, secret, description, ",
"type, active) VALUES ($1, $2, $3, $4, true) ON CONFLICT (name) DO NOTHING"
)
} else if matches!(self.store, LookupStore::Store(Store::MySQL(_))) {
} else if self.is_mysql() {
concat!(
"INSERT IGNORE INTO accounts (name, secret, description, ",
"type, active) VALUES (?, ?, ?, ?, true)"
@@ -381,12 +381,12 @@ impl DirectoryStore {
pub async fn create_test_group(&self, login: &str, name: &str) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
concat!(
"INSERT INTO accounts (name, description, ",
"type, active) VALUES ($1, $2, $3, $4) ON CONFLICT (name) DO NOTHING"
)
} else if matches!(self.store, LookupStore::Store(Store::MySQL(_))) {
} else if self.is_mysql() {
concat!(
"INSERT IGNORE INTO accounts (name, description, ",
"type, active) VALUES (?, ?, ?, ?)"
@@ -411,9 +411,9 @@ impl DirectoryStore {
pub async fn link_test_address(&self, login: &str, address: &str, typ: &str) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
"INSERT INTO emails (name, address, type) VALUES ($1, $2, $3) ON CONFLICT (name, address) DO NOTHING"
} else if matches!(self.store, LookupStore::Store(Store::MySQL(_))) {
} else if self.is_mysql() {
"INSERT IGNORE INTO emails (name, address, type) VALUES (?, ?, ?)"
} else {
"INSERT OR IGNORE INTO emails (name, address, type) VALUES (?, ?, ?)"
@@ -427,7 +427,7 @@ impl DirectoryStore {
pub async fn set_test_quota(&self, login: &str, quota: u32) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
"UPDATE accounts SET quota = $1 where name = $2"
} else {
"UPDATE accounts SET quota = ? where name = ?"
@@ -441,7 +441,7 @@ impl DirectoryStore {
pub async fn add_to_group(&self, login: &str, group: &str) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
"INSERT INTO group_members (name, member_of) VALUES ($1, $2)"
} else {
"INSERT INTO group_members (name, member_of) VALUES (?, ?)"
@@ -455,7 +455,7 @@ impl DirectoryStore {
pub async fn remove_from_group(&self, login: &str, group: &str) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
"DELETE FROM group_members WHERE name = $1 AND member_of = $2"
} else {
"DELETE FROM group_members WHERE name = ? AND member_of = ?"
@@ -469,7 +469,7 @@ impl DirectoryStore {
pub async fn remove_test_alias(&self, login: &str, alias: &str) {
self.store
.query::<usize>(
if matches!(self.store, LookupStore::Store(Store::PostgreSQL(_))) {
if self.is_postgresql() {
"DELETE FROM emails WHERE name = $1 AND address = $2"
} else {
"DELETE FROM emails WHERE name = ? AND address = ?"
@@ -479,4 +479,38 @@ impl DirectoryStore {
.await
.unwrap();
}
fn is_mysql(&self) -> bool {
#[cfg(feature = "mysql")]
{
matches!(self.store, LookupStore::Store(Store::MySQL(_)))
}
#[cfg(not(feature = "mysql"))]
{
false
}
}
fn is_postgresql(&self) -> bool {
#[cfg(feature = "postgres")]
{
matches!(self.store, LookupStore::Store(Store::PostgreSQL(_)))
}
#[cfg(not(feature = "postgres"))]
{
false
}
}
#[allow(dead_code)]
fn is_sqlite(&self) -> bool {
#[cfg(feature = "sqlite")]
{
matches!(self.store, LookupStore::Store(Store::SQLite(_)))
}
#[cfg(not(feature = "sqlite"))]
{
false
}
}
}

View File

@@ -164,6 +164,7 @@ url = "https://localhost:9200"
user = "elastic"
password = "RtQ-Lu6+o4rxx=XJplVJ"
allow-invalid-certs = true
disable = true # Elastic is disabled by default
[certificate.default]
cert = "file://{CERT}"
@@ -286,10 +287,8 @@ pub async fn jmap_tests() {
delete,
)
.await;
//assert_is_empty(params.server.clone()).await;
let coco = 1;
/*email_query::test(&mut params, delete).await;
email_query::test(&mut params, delete).await;
email_get::test(&mut params).await;
email_set::test(&mut params).await;
email_parse::test(&mut params).await;
@@ -300,7 +299,7 @@ pub async fn jmap_tests() {
thread_get::test(&mut params).await;
thread_merge::test(&mut params).await;
mailbox::test(&mut params).await;
delivery::test(&mut params).await;*/
delivery::test(&mut params).await;
auth_acl::test(&mut params).await;
auth_limits::test(&mut params).await;
auth_oauth::test(&mut params).await;

View File

@@ -38,9 +38,9 @@ pub async fn blob_tests() {
Config::new(&CONFIG.replace("{TMP}", temp_dir.path.as_path().to_str().unwrap())).unwrap();
let stores = config.parse_stores().await.unwrap();
for (store_id, blob_store) in stores.blob_stores {
for (store_id, blob_store) in &stores.blob_stores {
println!("Testing blob store {}...", store_id);
test_store(blob_store).await;
test_store(blob_store.clone()).await;
}
for (store_id, store) in stores.stores {

View File

@@ -39,15 +39,25 @@ pub async fn lookup_tests() {
store.destroy().await;
}
// Test value expiry
// Test key
let key = "xyz".as_bytes().to_vec();
assert_eq!(
LookupValue::None,
store
.key_get::<String>(LookupKey::Key(key.clone()))
.await
.unwrap()
);
store
.key_set(
key.clone(),
LookupValue::Value {
value: "world".to_string().into_bytes(),
expires: 0,
},
)
.await
.unwrap();
store.purge_expired().await.unwrap();
assert!(matches!(store
.key_get::<String>(LookupKey::Key(key.clone()))
.await
.unwrap(), LookupValue::Value { value,.. } if value == "world"));
// Test value expiry
store
.key_set(
key.clone(),
@@ -76,23 +86,6 @@ pub async fn lookup_tests() {
store.assert_is_empty(store.clone().into()).await;
}
// Test key
store
.key_set(
key.clone(),
LookupValue::Value {
value: "world".to_string().into_bytes(),
expires: 0,
},
)
.await
.unwrap();
store.purge_expired().await.unwrap();
assert!(matches!(store
.key_get::<String>(LookupKey::Key(key.clone()))
.await
.unwrap(), LookupValue::Value { value,.. } if value == "world"));
// Test counter
let key = "abc".as_bytes().to_vec();
store