forked from projectmoon/tenebrous-dicebot
Compare commits
19 Commits
Author | SHA1 | Date |
---|---|---|
projectmoon | 125f3d0cee | |
projectmoon | a4c3d34a97 | |
projectmoon | 86fbb05e54 | |
projectmoon | 661a943672 | |
projectmoon | d65715dee6 | |
projectmoon | 55a3bfb861 | |
projectmoon | 0050810182 | |
projectmoon | 3ba546d4a4 | |
projectmoon | ffded7b572 | |
projectmoon | cf93d14913 | |
projectmoon | cf6dd96b34 | |
projectmoon | c8c6f4d6f0 | |
projectmoon | 2488429edb | |
projectmoon | f68d5ffcc1 | |
projectmoon | 473e899275 | |
projectmoon | 1f03837bfe | |
projectmoon | 0059e3d133 | |
matthew | 915b82d0aa | |
projectmoon | cab856241d |
|
@ -14,8 +14,9 @@ steps:
|
||||||
- name: docker
|
- name: docker
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
when:
|
when:
|
||||||
branch:
|
ref:
|
||||||
- master
|
- refs/tags/v*
|
||||||
|
- refs/heads/master
|
||||||
settings:
|
settings:
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
username:
|
username:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"dicebot",
|
"dicebot",
|
||||||
"rpc",
|
"rpc"
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,7 +9,7 @@ RUN rustup-init -qy
|
||||||
ENV TINI_VERSION v0.19.0
|
ENV TINI_VERSION v0.19.0
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/local/bin/tini
|
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/local/bin/tini
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc /tini.asc
|
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc /tini.asc
|
||||||
RUN gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \
|
RUN gpg --batch --keyserver hkp://keyserver.ubuntu.com --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \
|
||||||
&& gpg --batch --verify /tini.asc /usr/local/bin/tini
|
&& gpg --batch --verify /tini.asc /usr/local/bin/tini
|
||||||
RUN chmod +x /usr/local/bin/tini
|
RUN chmod +x /usr/local/bin/tini
|
||||||
|
|
||||||
|
|
35
README.md
35
README.md
|
@ -1,6 +1,7 @@
|
||||||
# Tenebrous Dicebot
|
# Tenebrous Dicebot
|
||||||
|
|
||||||
[![Build Status](https://drone.agnos.is/api/badges/projectmoon/tenebrous-dicebot/status.svg)](https://drone.agnos.is/projectmoon/tenebrous-dicebot)
|
[![Build Status](https://drone.agnos.is/api/badges/projectmoon/tenebrous-dicebot/status.svg)](https://drone.agnos.is/projectmoon/tenebrous-dicebot)
|
||||||
|
[![Matrix Chat](https://img.shields.io/matrix/tenebrous:agnos.is?label=matrix&server_fqdn=matrix.org)][matrix-room]
|
||||||
|
|
||||||
_This repository is hosted on [Agnos.is Git][main-repo] and mirrored
|
_This repository is hosted on [Agnos.is Git][main-repo] and mirrored
|
||||||
to [GitHub][github-repo]._
|
to [GitHub][github-repo]._
|
||||||
|
@ -24,6 +25,23 @@ System.
|
||||||
* Works in encrypted or unencrypted Matrix rooms.
|
* Works in encrypted or unencrypted Matrix rooms.
|
||||||
* Storing variables created by the user.
|
* Storing variables created by the user.
|
||||||
|
|
||||||
|
## Support and Community
|
||||||
|
|
||||||
|
The project has a Matrix room at [#tenebrous:agnos.is][matrix-room].
|
||||||
|
It is also possible to make a post in [GitHub
|
||||||
|
Discussions][github-discussions].
|
||||||
|
|
||||||
|
For reporting bugs, we prefer that you open an issue on
|
||||||
|
[git.agnos.is][agnosis-git-issues]. However, you may also open an
|
||||||
|
issue on [GitHub][github-issues].
|
||||||
|
|
||||||
|
### Development and Contributions
|
||||||
|
|
||||||
|
All development occurs on [git.agnos.is][main-repo]. If you wish to
|
||||||
|
contribute, please open a pull request there. In some cases, pull
|
||||||
|
requests from GitHub may be accepted. All contributions must be
|
||||||
|
licensed under [AGPL 3.0 or later][agpl] to be accepted.
|
||||||
|
|
||||||
## Building and Installation
|
## Building and Installation
|
||||||
|
|
||||||
### Docker Image
|
### Docker Image
|
||||||
|
@ -46,6 +64,17 @@ root of the repository.
|
||||||
After pulling or building the image, see [instructions on how to use
|
After pulling or building the image, see [instructions on how to use
|
||||||
the Docker image](#running-the-bot).
|
the Docker image](#running-the-bot).
|
||||||
|
|
||||||
|
### Install from crates.io
|
||||||
|
|
||||||
|
The project can be from [crates.io][crates-io]. To install it, execute
|
||||||
|
`cargo install tenebrous-dicebot`. This will make the following
|
||||||
|
executables available on your system:
|
||||||
|
|
||||||
|
* `dicebot`: Main dicebot executable.
|
||||||
|
* `dicebot-cmd`: Run dicebot commands from the command line.
|
||||||
|
* `dicebot_migrate`: Standalone database migrator (not required).
|
||||||
|
* `tonic_client`: Test client for the gRPC connection (not required).
|
||||||
|
|
||||||
### Build from Source
|
### Build from Source
|
||||||
|
|
||||||
Precompiled executables are not yet available. Clone this repository
|
Precompiled executables are not yet available. Clone this repository
|
||||||
|
@ -254,3 +283,9 @@ support added for Chronicles of Darkness and Call of Cthulhu.
|
||||||
[main-repo]: https://git.agnos.is/projectmoon/tenebrous-dicebot
|
[main-repo]: https://git.agnos.is/projectmoon/tenebrous-dicebot
|
||||||
[github-repo]: https://github.com/ProjectMoon/matrix-dicebot
|
[github-repo]: https://github.com/ProjectMoon/matrix-dicebot
|
||||||
[roadmap]: https://git.agnos.is/projectmoon/tenebrous-dicebot/wiki/Roadmap
|
[roadmap]: https://git.agnos.is/projectmoon/tenebrous-dicebot/wiki/Roadmap
|
||||||
|
[crates-io]: https://crates.io/crates/tenebrous-dicebot
|
||||||
|
[matrix-room]: https://matrix.to/#/#tenebrous:agnos.is
|
||||||
|
[agnosis-git-issues]: https://git.agnos.is/projectmoon/tenebrous-dicebot/issues
|
||||||
|
[github-discussions]: https://github.com/ProjectMoon/matrix-dicebot/discussions
|
||||||
|
[github-issues]: https://github.com/ProjectMoon/matrix-dicebot/issues
|
||||||
|
[agpl]: https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tenebrous-dicebot"
|
name = "tenebrous-dicebot"
|
||||||
version = "0.10.0"
|
version = "0.13.1"
|
||||||
authors = ["Taylor C. Richberger <taywee@gmx.com>", "projectmoon <projectmoon@agnos.is>"]
|
authors = ["projectmoon <projectmoon@agnos.is>", "Taylor C. Richberger <taywee@gmx.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = 'AGPL-3.0-or-later'
|
license = 'AGPL-3.0-or-later'
|
||||||
description = 'An async Matrix dice bot for role-playing games'
|
description = 'An async Matrix dice bot for role-playing games'
|
||||||
readme = 'README.md'
|
readme = '../README.md'
|
||||||
repository = 'https://git.agnos.is/projectmoon/matrix-dicebot'
|
repository = 'https://git.agnos.is/projectmoon/matrix-dicebot'
|
||||||
keywords = ["games", "dice", "matrix", "bot"]
|
keywords = ["games", "dice", "matrix", "bot"]
|
||||||
categories = ["games"]
|
categories = ["games"]
|
||||||
|
@ -14,6 +14,8 @@ categories = ["games"]
|
||||||
tonic-build = "0.4"
|
tonic-build = "0.4"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# indexmap version locked fixes a dependency cycle.
|
||||||
|
indexmap = "=1.6.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tracing-subscriber = "0.2"
|
tracing-subscriber = "0.2"
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
|
@ -30,15 +32,15 @@ combine = "4.5"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
html2text = "0.2"
|
html2text = "0.2"
|
||||||
phf = { version = "0.8", features = ["macros"] }
|
phf = { version = "0.8", features = ["macros"] }
|
||||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }
|
matrix-sdk = { version = "0.3" }
|
||||||
refinery = { version = "0.5", features = ["rusqlite"]}
|
refinery = { version = "0.6", features = ["rusqlite"]}
|
||||||
barrel = { version = "0.6", features = ["sqlite3"] }
|
barrel = { version = "0.6", features = ["sqlite3"] }
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
substring = "1.4"
|
substring = "1.4"
|
||||||
fuse-rust = "0.2"
|
fuse-rust = "0.2"
|
||||||
tonic = "0.4"
|
tonic = "0.4"
|
||||||
prost = "0.7"
|
prost = "0.7"
|
||||||
tenebrous-rpc = { path = "../rpc" }
|
tenebrous-rpc = { path = "../rpc", version = "0.1.0" }
|
||||||
|
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.5"
|
version = "0.5"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use tenebrous_rpc::protos::dicebot::UserIdRequest;
|
use tenebrous_rpc::protos::dicebot::UserIdRequest;
|
||||||
use tenebrous_rpc::protos::dicebot::{dicebot_client::DicebotClient, GetVariableRequest};
|
use tenebrous_rpc::protos::dicebot::{dicebot_client::DicebotClient};
|
||||||
use tonic::{metadata::MetadataValue, transport::Channel, Request};
|
use tonic::{metadata::MetadataValue, transport::Channel, Request};
|
||||||
|
|
||||||
async fn create_client(
|
async fn create_client(
|
||||||
|
@ -23,21 +23,11 @@ async fn create_client(
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut client = create_client("example-key").await?;
|
let mut client = create_client("example-key").await?;
|
||||||
|
|
||||||
// let request = tonic::Request::new(GetVariableRequest {
|
|
||||||
// user_id: "@projectmoon:agnos.is".into(),
|
|
||||||
// room_id: "!agICWvldGfuCywUVUM:agnos.is".into(),
|
|
||||||
// variable_name: "stuff".into(),
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let response = client.get_variable(request).await?.into_inner();
|
|
||||||
|
|
||||||
let request = tonic::Request::new(UserIdRequest {
|
let request = tonic::Request::new(UserIdRequest {
|
||||||
user_id: "@projectmoon:agnos.is".into(),
|
user_id: "@projectmoon:agnos.is".into(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let response = client.rooms_for_user(request).await?.into_inner();
|
let response = client.rooms_for_user(request).await?.into_inner();
|
||||||
// println!("RESPONSE={:?}", response);
|
|
||||||
// println!("User friendly response is: {:?}", response.value);
|
|
||||||
println!("Rooms: {:?}", response.rooms);
|
println!("Rooms: {:?}", response.rooms);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,34 +53,41 @@ impl Rooms for Database {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::db::sqlite::Database;
|
use crate::db::sqlite::Database;
|
||||||
use crate::db::Rooms;
|
use crate::db::Rooms;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
async fn create_db() -> Database {
|
async fn with_db<Fut>(f: impl FnOnce(Database) -> Fut)
|
||||||
|
where
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
{
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Database::new(db_path.path().to_str().unwrap())
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
f(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn should_process_test() {
|
async fn should_process_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let first_check = db
|
||||||
|
.should_process("myroom", "myeventid")
|
||||||
|
.await
|
||||||
|
.expect("should_process failed in first insert");
|
||||||
|
|
||||||
let first_check = db
|
assert_eq!(first_check, true);
|
||||||
.should_process("myroom", "myeventid")
|
|
||||||
.await
|
|
||||||
.expect("should_process failed in first insert");
|
|
||||||
|
|
||||||
assert_eq!(first_check, true);
|
let second_check = db
|
||||||
|
.should_process("myroom", "myeventid")
|
||||||
|
.await
|
||||||
|
.expect("should_process failed in first insert");
|
||||||
|
|
||||||
let second_check = db
|
assert_eq!(second_check, false);
|
||||||
.should_process("myroom", "myeventid")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("should_process failed in first insert");
|
|
||||||
|
|
||||||
assert_eq!(second_check, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,54 +37,64 @@ impl DbState for Database {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::db::sqlite::Database;
|
use crate::db::sqlite::Database;
|
||||||
use crate::db::DbState;
|
use crate::db::DbState;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
async fn create_db() -> Database {
|
async fn with_db<Fut>(f: impl FnOnce(Database) -> Fut)
|
||||||
|
where
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
{
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Database::new(db_path.path().to_str().unwrap())
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
f(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn set_and_get_device_id() {
|
async fn set_and_get_device_id() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
db.set_device_id("device_id")
|
||||||
|
.await
|
||||||
|
.expect("Could not set device ID");
|
||||||
|
|
||||||
db.set_device_id("device_id")
|
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
||||||
.await
|
|
||||||
.expect("Could not set device ID");
|
|
||||||
|
|
||||||
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
assert!(device_id.is_some());
|
||||||
|
assert_eq!(device_id.unwrap(), "device_id");
|
||||||
assert!(device_id.is_some());
|
})
|
||||||
assert_eq!(device_id.unwrap(), "device_id");
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn no_device_id_set_returns_none() {
|
async fn no_device_id_set_returns_none() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
||||||
assert!(device_id.is_none());
|
assert!(device_id.is_none());
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_update_device_id() {
|
async fn can_update_device_id() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
db.set_device_id("device_id")
|
||||||
|
.await
|
||||||
|
.expect("Could not set device ID");
|
||||||
|
|
||||||
db.set_device_id("device_id")
|
db.set_device_id("device_id2")
|
||||||
.await
|
.await
|
||||||
.expect("Could not set device ID");
|
.expect("Could not set device ID");
|
||||||
|
|
||||||
db.set_device_id("device_id2")
|
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
||||||
.await
|
|
||||||
.expect("Could not set device ID");
|
|
||||||
|
|
||||||
let device_id = db.get_device_id().await.expect("Could not get device ID");
|
assert!(device_id.is_some());
|
||||||
|
assert_eq!(device_id.unwrap(), "device_id2");
|
||||||
assert!(device_id.is_some());
|
})
|
||||||
assert_eq!(device_id.unwrap(), "device_id2");
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,251 +91,271 @@ mod tests {
|
||||||
use crate::db::sqlite::Database;
|
use crate::db::sqlite::Database;
|
||||||
use crate::db::Users;
|
use crate::db::Users;
|
||||||
use crate::models::AccountStatus;
|
use crate::models::AccountStatus;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
async fn create_db() -> Database {
|
async fn with_db<Fut>(f: impl FnOnce(Database) -> Fut)
|
||||||
|
where
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
{
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Database::new(db_path.path().to_str().unwrap())
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
f(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn create_and_get_full_user_test() {
|
async fn create_and_get_full_user_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("abc".to_string()),
|
||||||
|
account_status: AccountStatus::Registered,
|
||||||
|
active_room: Some("myroom".to_string()),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some("abc".to_string()),
|
|
||||||
account_status: AccountStatus::Registered,
|
|
||||||
active_room: Some("myroom".to_string()),
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
let user = db
|
||||||
|
.get_user("myuser")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.get_user("myuser")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
assert_eq!(user.password, Some("abc".to_string()));
|
||||||
|
assert_eq!(user.account_status, AccountStatus::Registered);
|
||||||
assert!(user.is_some());
|
assert_eq!(user.active_room, Some("myroom".to_string()));
|
||||||
let user = user.unwrap();
|
})
|
||||||
assert_eq!(user.username, "myuser");
|
.await;
|
||||||
assert_eq!(user.password, Some("abc".to_string()));
|
|
||||||
assert_eq!(user.account_status, AccountStatus::Registered);
|
|
||||||
assert_eq!(user.active_room, Some("myroom".to_string()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_get_user_with_no_state_record() {
|
async fn can_get_user_with_no_state_record() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("abc".to_string()),
|
||||||
|
account_status: AccountStatus::AwaitingActivation,
|
||||||
|
active_room: Some("myroom".to_string()),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some("abc".to_string()),
|
|
||||||
account_status: AccountStatus::AwaitingActivation,
|
|
||||||
active_room: Some("myroom".to_string()),
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
sqlx::query("DELETE FROM user_state")
|
||||||
|
.execute(&db.conn)
|
||||||
|
.await
|
||||||
|
.expect("Could not delete from user_state table.");
|
||||||
|
|
||||||
sqlx::query("DELETE FROM user_state")
|
let user = db
|
||||||
.execute(&db.conn)
|
.get_user("myuser")
|
||||||
.await
|
.await
|
||||||
.expect("Could not delete from user_state table.");
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.get_user("myuser")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
assert_eq!(user.password, Some("abc".to_string()));
|
||||||
|
assert_eq!(user.account_status, AccountStatus::AwaitingActivation);
|
||||||
|
|
||||||
assert!(user.is_some());
|
//These should be default values because the state record is missing.
|
||||||
let user = user.unwrap();
|
assert_eq!(user.active_room, None);
|
||||||
assert_eq!(user.username, "myuser");
|
})
|
||||||
assert_eq!(user.password, Some("abc".to_string()));
|
.await;
|
||||||
assert_eq!(user.account_status, AccountStatus::AwaitingActivation);
|
|
||||||
|
|
||||||
//These should be default values because the state record is missing.
|
|
||||||
assert_eq!(user.active_room, None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_insert_without_password() {
|
async fn can_insert_without_password() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: None,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: None,
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
let user = db
|
||||||
|
.get_user("myuser")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.get_user("myuser")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
assert_eq!(user.password, None);
|
||||||
|
})
|
||||||
assert!(user.is_some());
|
.await;
|
||||||
let user = user.unwrap();
|
|
||||||
assert_eq!(user.username, "myuser");
|
|
||||||
assert_eq!(user.password, None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_insert_without_active_room() {
|
async fn can_insert_without_active_room() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
active_room: None,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
active_room: None,
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
let user = db
|
||||||
|
.get_user("myuser")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.get_user("myuser")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
assert_eq!(user.active_room, None);
|
||||||
|
})
|
||||||
assert!(user.is_some());
|
.await;
|
||||||
let user = user.unwrap();
|
|
||||||
assert_eq!(user.username, "myuser");
|
|
||||||
assert_eq!(user.active_room, None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_update_user() {
|
async fn can_update_user() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result1 = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("abc".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result1 = db
|
assert!(insert_result1.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some("abc".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result1.is_ok());
|
let insert_result2 = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("123".to_string()),
|
||||||
|
active_room: Some("room".to_string()),
|
||||||
|
account_status: AccountStatus::AwaitingActivation,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result2 = db
|
assert!(insert_result2.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some("123".to_string()),
|
|
||||||
active_room: Some("room".to_string()),
|
|
||||||
account_status: AccountStatus::AwaitingActivation,
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result2.is_ok());
|
let user = db
|
||||||
|
.get_user("myuser")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.get_user("myuser")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
|
||||||
|
|
||||||
assert!(user.is_some());
|
//From second upsert
|
||||||
let user = user.unwrap();
|
assert_eq!(user.password, Some("123".to_string()));
|
||||||
assert_eq!(user.username, "myuser");
|
assert_eq!(user.active_room, Some("room".to_string()));
|
||||||
|
assert_eq!(user.account_status, AccountStatus::AwaitingActivation);
|
||||||
//From second upsert
|
})
|
||||||
assert_eq!(user.password, Some("123".to_string()));
|
.await;
|
||||||
assert_eq!(user.active_room, Some("room".to_string()));
|
|
||||||
assert_eq!(user.account_status, AccountStatus::AwaitingActivation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn can_delete_user() {
|
async fn can_delete_user() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("abc".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some("abc".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
db.delete_user("myuser")
|
||||||
|
.await
|
||||||
|
.expect("User deletion query failed");
|
||||||
|
|
||||||
db.delete_user("myuser")
|
let user = db
|
||||||
.await
|
.get_user("myuser")
|
||||||
.expect("User deletion query failed");
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_none());
|
||||||
.get_user("myuser")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("User retrieval query failed");
|
|
||||||
|
|
||||||
assert!(user.is_none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn username_not_in_db_returns_none() {
|
async fn username_not_in_db_returns_none() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
let user = db
|
let user = db
|
||||||
.get_user("does not exist")
|
.get_user("does not exist")
|
||||||
.await
|
.await
|
||||||
.expect("Get user query failure");
|
.expect("Get user query failure");
|
||||||
|
|
||||||
assert!(user.is_none());
|
assert!(user.is_none());
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn authenticate_user_is_some_with_valid_password() {
|
async fn authenticate_user_is_some_with_valid_password() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some(
|
||||||
|
crate::logic::hash_password("abc").expect("password hash error!"),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some(crate::logic::hash_password("abc").expect("password hash error!")),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
let user = db
|
||||||
|
.authenticate_user("myuser", "abc")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_some());
|
||||||
.authenticate_user("myuser", "abc")
|
let user = user.unwrap();
|
||||||
.await
|
assert_eq!(user.username, "myuser");
|
||||||
.expect("User retrieval query failed");
|
})
|
||||||
|
.await;
|
||||||
assert!(user.is_some());
|
|
||||||
let user = user.unwrap();
|
|
||||||
assert_eq!(user.username, "myuser");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn authenticate_user_is_none_with_wrong_password() {
|
async fn authenticate_user_is_none_with_wrong_password() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let insert_result = db
|
||||||
|
.upsert_user(&User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some(
|
||||||
|
crate::logic::hash_password("abc").expect("password hash error!"),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
let insert_result = db
|
assert!(insert_result.is_ok());
|
||||||
.upsert_user(&User {
|
|
||||||
username: "myuser".to_string(),
|
|
||||||
password: Some(crate::logic::hash_password("abc").expect("password hash error!")),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
assert!(insert_result.is_ok());
|
let user = db
|
||||||
|
.authenticate_user("myuser", "wrong-password")
|
||||||
|
.await
|
||||||
|
.expect("User retrieval query failed");
|
||||||
|
|
||||||
let user = db
|
assert!(user.is_none());
|
||||||
.authenticate_user("myuser", "wrong-password")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("User retrieval query failed");
|
|
||||||
|
|
||||||
assert!(user.is_none());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,143 +102,156 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::db::sqlite::Database;
|
use crate::db::sqlite::Database;
|
||||||
use crate::db::Variables;
|
use crate::db::Variables;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
async fn create_db() -> Database {
|
async fn with_db<Fut>(f: impl FnOnce(Database) -> Fut)
|
||||||
|
where
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
{
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Database::new(db_path.path().to_str().unwrap())
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
f(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn set_and_get_variable_test() {
|
async fn set_and_get_variable_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
db.set_user_variable("myuser", "myroom", "myvariable", 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
|
||||||
db.set_user_variable("myuser", "myroom", "myvariable", 1)
|
let value = db
|
||||||
.await
|
.get_user_variable("myuser", "myroom", "myvariable")
|
||||||
.expect("Could not set variable");
|
.await
|
||||||
|
.expect("Could not get variable");
|
||||||
|
|
||||||
let value = db
|
assert_eq!(value, 1);
|
||||||
.get_user_variable("myuser", "myroom", "myvariable")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("Could not get variable");
|
|
||||||
|
|
||||||
assert_eq!(value, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn get_missing_variable_test() {
|
async fn get_missing_variable_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let value = db.get_user_variable("myuser", "myroom", "myvariable").await;
|
||||||
|
|
||||||
let value = db.get_user_variable("myuser", "myroom", "myvariable").await;
|
assert!(value.is_err());
|
||||||
|
assert!(matches!(
|
||||||
assert!(value.is_err());
|
value.err().unwrap(),
|
||||||
assert!(matches!(
|
DataError::KeyDoesNotExist(_)
|
||||||
value.err().unwrap(),
|
));
|
||||||
DataError::KeyDoesNotExist(_)
|
})
|
||||||
));
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn get_other_user_variable_test() {
|
async fn get_other_user_variable_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
db.set_user_variable("myuser1", "myroom", "myvariable", 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
|
||||||
db.set_user_variable("myuser1", "myroom", "myvariable", 1)
|
let value = db
|
||||||
.await
|
.get_user_variable("myuser2", "myroom", "myvariable")
|
||||||
.expect("Could not set variable");
|
.await;
|
||||||
|
|
||||||
let value = db
|
assert!(value.is_err());
|
||||||
.get_user_variable("myuser2", "myroom", "myvariable")
|
assert!(matches!(
|
||||||
.await;
|
value.err().unwrap(),
|
||||||
|
DataError::KeyDoesNotExist(_)
|
||||||
assert!(value.is_err());
|
));
|
||||||
assert!(matches!(
|
})
|
||||||
value.err().unwrap(),
|
.await;
|
||||||
DataError::KeyDoesNotExist(_)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn count_variables_test() {
|
async fn count_variables_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
for variable_name in &["var1", "var2", "var3"] {
|
||||||
|
db.set_user_variable("myuser", "myroom", variable_name, 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
}
|
||||||
|
|
||||||
for variable_name in &["var1", "var2", "var3"] {
|
let count = db
|
||||||
db.set_user_variable("myuser", "myroom", variable_name, 1)
|
.get_variable_count("myuser", "myroom")
|
||||||
.await
|
.await
|
||||||
.expect("Could not set variable");
|
.expect("Could not get count.");
|
||||||
}
|
|
||||||
|
|
||||||
let count = db
|
assert_eq!(count, 3);
|
||||||
.get_variable_count("myuser", "myroom")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("Could not get count.");
|
|
||||||
|
|
||||||
assert_eq!(count, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn count_variables_respects_user_id() {
|
async fn count_variables_respects_user_id() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
for variable_name in &["var1", "var2", "var3"] {
|
||||||
|
db.set_user_variable("different-user", "myroom", variable_name, 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
}
|
||||||
|
|
||||||
for variable_name in &["var1", "var2", "var3"] {
|
let count = db
|
||||||
db.set_user_variable("different-user", "myroom", variable_name, 1)
|
.get_variable_count("myuser", "myroom")
|
||||||
.await
|
.await
|
||||||
.expect("Could not set variable");
|
.expect("Could not get count.");
|
||||||
}
|
|
||||||
|
|
||||||
let count = db
|
assert_eq!(count, 0);
|
||||||
.get_variable_count("myuser", "myroom")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("Could not get count.");
|
|
||||||
|
|
||||||
assert_eq!(count, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn count_variables_respects_room_id() {
|
async fn count_variables_respects_room_id() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
for variable_name in &["var1", "var2", "var3"] {
|
||||||
|
db.set_user_variable("myuser", "different-room", variable_name, 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
}
|
||||||
|
|
||||||
for variable_name in &["var1", "var2", "var3"] {
|
let count = db
|
||||||
db.set_user_variable("myuser", "different-room", variable_name, 1)
|
.get_variable_count("myuser", "myroom")
|
||||||
.await
|
.await
|
||||||
.expect("Could not set variable");
|
.expect("Could not get count.");
|
||||||
}
|
|
||||||
|
|
||||||
let count = db
|
assert_eq!(count, 0);
|
||||||
.get_variable_count("myuser", "myroom")
|
})
|
||||||
.await
|
.await;
|
||||||
.expect("Could not get count.");
|
|
||||||
|
|
||||||
assert_eq!(count, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn delete_variable_test() {
|
async fn delete_variable_test() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
for variable_name in &["var1", "var2", "var3"] {
|
||||||
|
db.set_user_variable("myuser", "myroom", variable_name, 1)
|
||||||
|
.await
|
||||||
|
.expect("Could not set variable");
|
||||||
|
}
|
||||||
|
|
||||||
for variable_name in &["var1", "var2", "var3"] {
|
db.delete_user_variable("myuser", "myroom", "var1")
|
||||||
db.set_user_variable("myuser", "myroom", variable_name, 1)
|
|
||||||
.await
|
.await
|
||||||
.expect("Could not set variable");
|
.expect("Could not delete variable.");
|
||||||
}
|
|
||||||
|
|
||||||
db.delete_user_variable("myuser", "myroom", "var1")
|
let count = db
|
||||||
.await
|
.get_variable_count("myuser", "myroom")
|
||||||
.expect("Could not delete variable.");
|
.await
|
||||||
|
.expect("Could not get count");
|
||||||
|
|
||||||
let count = db
|
assert_eq!(count, 2);
|
||||||
.get_variable_count("myuser", "myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not get count");
|
|
||||||
|
|
||||||
assert_eq!(count, 2);
|
let var1 = db.get_user_variable("myuser", "myroom", "var1").await;
|
||||||
|
assert!(var1.is_err());
|
||||||
let var1 = db.get_user_variable("myuser", "myroom", "var1").await;
|
assert!(matches!(var1.err().unwrap(), DataError::KeyDoesNotExist(_)));
|
||||||
assert!(var1.is_err());
|
})
|
||||||
assert!(matches!(var1.err().unwrap(), DataError::KeyDoesNotExist(_)));
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,53 +71,61 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::db::Users;
|
use crate::db::Users;
|
||||||
use crate::models::{AccountStatus, User};
|
use crate::models::{AccountStatus, User};
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
async fn create_db() -> Database {
|
async fn with_db<Fut>(f: impl FnOnce(Database) -> Fut)
|
||||||
|
where
|
||||||
|
Fut: Future<Output = ()>,
|
||||||
|
{
|
||||||
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
let db_path = tempfile::NamedTempFile::new_in(".").unwrap();
|
||||||
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
crate::db::sqlite::migrator::migrate(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Database::new(db_path.path().to_str().unwrap())
|
let db = Database::new(db_path.path().to_str().unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
f(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn get_account_no_user_exists() {
|
async fn get_account_no_user_exists() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let account = get_account(&db, "@test:example.com")
|
||||||
|
.await
|
||||||
|
.expect("Account retrieval didn't work");
|
||||||
|
|
||||||
let account = get_account(&db, "@test:example.com")
|
assert!(matches!(account, Account::Transient(_)));
|
||||||
.await
|
|
||||||
.expect("Account retrieval didn't work");
|
|
||||||
|
|
||||||
assert!(matches!(account, Account::Transient(_)));
|
let user = account.transient_user().unwrap();
|
||||||
|
assert_eq!(user.username, "@test:example.com");
|
||||||
let user = account.transient_user().unwrap();
|
})
|
||||||
assert_eq!(user.username, "@test:example.com");
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
||||||
async fn get_or_create_user_when_user_exists() {
|
async fn get_or_create_user_when_user_exists() {
|
||||||
let db = create_db().await;
|
with_db(|db| async move {
|
||||||
|
let user = User {
|
||||||
|
username: "myuser".to_string(),
|
||||||
|
password: Some("abc".to_string()),
|
||||||
|
account_status: AccountStatus::Registered,
|
||||||
|
active_room: Some("myroom".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
let user = User {
|
let insert_result = db.upsert_user(&user).await;
|
||||||
username: "myuser".to_string(),
|
assert!(insert_result.is_ok());
|
||||||
password: Some("abc".to_string()),
|
|
||||||
account_status: AccountStatus::Registered,
|
|
||||||
active_room: Some("myroom".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let insert_result = db.upsert_user(&user).await;
|
let account = get_account(&db, "myuser")
|
||||||
assert!(insert_result.is_ok());
|
.await
|
||||||
|
.expect("Account retrieval did not work");
|
||||||
|
|
||||||
let account = get_account(&db, "myuser")
|
assert!(matches!(account, Account::Registered(_)));
|
||||||
.await
|
|
||||||
.expect("Account retrieval did not work");
|
|
||||||
|
|
||||||
assert!(matches!(account, Account::Registered(_)));
|
let user_again = account.registered_user().unwrap();
|
||||||
|
assert_eq!(user, *user_again);
|
||||||
let user_again = account.registered_user().unwrap();
|
})
|
||||||
assert_eq!(user, *user_again);
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,10 @@ name = "tenebrous-rpc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["projectmoon <projectmoon@agnos.is>"]
|
authors = ["projectmoon <projectmoon@agnos.is>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
description = "gRPC protobuf models for Tenebrous."
|
||||||
|
homepage = "https://git.agnos.is/projectmoon/tenebrous-dicebot"
|
||||||
|
repository = "https://git.agnos.is/projectmoon/tenebrous-dicebot"
|
||||||
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
Loading…
Reference in New Issue