use std::{process::exit, sync::Arc, time::Duration};
use brume::{concrete::local::LocalDir, filesystem::FileSystem};
use env_logger::Builder;
use brume_daemon_proto::{AnyFsCreationInfo, LocalDirCreationInfo, NextcloudFsCreationInfo};
use brume_daemon::{
daemon::{Daemon, DaemonConfig, ErrorMode},
db::DatabaseConfig,
};
use log::{LevelFilter, info};
use tarpc::context;
#[path = "utils.rs"]
mod utils;
use utils::{
connect_to_daemon, get_random_port, get_random_sock_name, start_nextcloud, stop_nextcloud,
wait_full_sync,
};
#[tokio::test]
async fn main() {
let mut logs_builder = Builder::new();
logs_builder
.filter_level(LevelFilter::Info)
.filter(Some("tarpc"), LevelFilter::Error)
.init();
let sock_name = get_random_sock_name();
info!("using sock name {sock_name}");
let sync_interval = Duration::from_secs(2);
let config = DaemonConfig::default()
.with_sync_interval(sync_interval)
.with_error_mode(ErrorMode::Exit)
.with_db_config(DatabaseConfig::InMemory)
.with_sock_name(&sock_name);
let daemon = Daemon::new(config).await.unwrap();
let daemon = Arc::new(daemon);
let daemon_task = daemon.spawn().await;
let dir_a = tempfile::tempdir().unwrap();
let dir_b = tempfile::tempdir().unwrap();
info!("dir_a: {:?}", dir_a.path());
info!("dir_b: {:?}", dir_b.path());
let nextcloud_port = get_random_port();
let nextcloud_url = format!("http://localhost:{}", nextcloud_port);
info!("nextcloud url: {}", &nextcloud_url);
let container = start_nextcloud(nextcloud_port, &nextcloud_url).await;
info!("container started: {}", container.id());
let local_a = AnyFsCreationInfo::LocalDir(LocalDirCreationInfo::new(dir_a.path()));
let remote = AnyFsCreationInfo::Nextcloud(NextcloudFsCreationInfo::new(
&nextcloud_url,
"admin",
"admin",
));
let rpc = connect_to_daemon(&sock_name).await.unwrap();
rpc.new_synchro(context::current(), local_a, remote.clone(), None)
.await
.unwrap()
.unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
let list = rpc.list_synchros(context::current()).await.unwrap();
assert_eq!(list.len(), 1);
let local_b = AnyFsCreationInfo::LocalDir(LocalDirCreationInfo::new(dir_b.path()));
rpc.new_synchro(context::current(), local_b, remote, None)
.await
.unwrap()
.unwrap();
wait_full_sync(sync_interval, &rpc).await;
let list = rpc.list_synchros(context::current()).await.unwrap();
assert_eq!(list.len(), 2);
let concrete_a: LocalDir = LocalDirCreationInfo::new(dir_a.path()).try_into().unwrap();
let mut fs_a = FileSystem::new(concrete_a);
let concrete_b: LocalDir = LocalDirCreationInfo::new(dir_b.path()).try_into().unwrap();
let mut fs_b = FileSystem::new(concrete_b);
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
std::fs::remove_file(dir_a.path().to_path_buf().join("Documents/Example.md")).unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
let content_a = b"This is a test";
std::fs::write(
dir_a.path().to_path_buf().join("Templates/Readme.md"),
content_a,
)
.unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
let content_b = std::fs::read(dir_a.path().to_path_buf().join("Templates/Readme.md")).unwrap();
assert_eq!(content_a, content_b.as_slice());
std::fs::create_dir(dir_a.path().to_path_buf().join("testdir")).unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
let content_a = b"Hello, world";
std::fs::write(
dir_a.path().to_path_buf().join("testdir/testfile"),
content_a,
)
.unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
let content_b = std::fs::read(dir_a.path().to_path_buf().join("testdir/testfile")).unwrap();
assert_eq!(content_a, content_b.as_slice());
std::fs::remove_dir_all(dir_a.path().to_path_buf().join("testdir")).unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
fs_a.diff_vfs().await.unwrap();
fs_b.diff_vfs().await.unwrap();
assert!(fs_a.vfs().structural_eq(fs_b.vfs()));
let first_sync = list.keys().collect::<Vec<_>>()[0];
rpc.delete_synchro(context::current(), *first_sync)
.await
.unwrap()
.unwrap();
wait_full_sync(sync_interval, &rpc).await;
if !daemon.is_running() {
stop_nextcloud(container).await;
exit(1)
}
let list = rpc.list_synchros(context::current()).await.unwrap();
assert_eq!(list.len(), 1);
daemon.stop();
daemon_task.await.unwrap().unwrap();
}