diff --git a/.gitignore b/.gitignore index 753e9e3..f9caba1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ szurubooru-integration-test/szurubooru/data/* szurubooru-integration-test/szurubooru/pgsql/* szurubooru-integration-test/szurubooru/server/* **/.DS_Store +**/target diff --git a/Cargo.lock b/Cargo.lock index 98904d4..623e2bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,6 +1268,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust-test" +version = "0.1.0" +dependencies = [ + "chrono", + "sha1", + "szurubooru-client", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1379,9 +1392,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] @@ -1398,9 +1411,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", @@ -1539,9 +1552,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1602,19 +1615,6 @@ dependencies = [ "urlencoding", ] -[[package]] -name = "szurubooru-integration-test" -version = "0.1.0" -dependencies = [ - "chrono", - "sha1", - "szurubooru-client", - "tempfile", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "target-lexicon" version = "0.12.16" diff --git a/Cargo.toml b/Cargo.toml index 541148b..af1c440 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ "szurubooru-client", - "szurubooru-integration-test" + #"szurubooru-integration-test", + "tests/rust-test" ] default-members = ["szurubooru-client"] diff --git a/szurubooru-integration-test/Cargo.toml b/szurubooru-integration-test/Cargo.toml deleted file mode 100644 index 6226773..0000000 --- a/szurubooru-integration-test/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "szurubooru-integration-test" -version = "0.1.0" -edition = "2021" - -[dependencies] -chrono = "0.4.38" -sha1 = "0.10.6" -szurubooru-client = { path = "../szurubooru-client" } -tempfile = "3.12.0" -tokio = { version = "1.39.2", features = ["full", "test-util", "tracing"] } -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/szurubooru-integration-test/avatar.jpg b/szurubooru-integration-test/avatar.jpg deleted file mode 100644 index 708d879..0000000 Binary files a/szurubooru-integration-test/avatar.jpg and /dev/null differ diff --git a/szurubooru-integration-test/docker-compose.yml b/szurubooru-integration-test/docker-compose.yml deleted file mode 100644 index a51c8a7..0000000 --- a/szurubooru-integration-test/docker-compose.yml +++ /dev/null @@ -1,51 +0,0 @@ -## Example Docker Compose configuration -## -## Use this as a template to set up docker-compose, or as guide to set up other -## orchestration services -version: '2' - -services: - - server: - image: szurubooru/server:latest - depends_on: - - sql - environment: - ## These should be the names of the dependent containers listed below, - ## or FQDNs/IP addresses if these services are running outside of Docker - POSTGRES_HOST: sql - ## Credentials for database: - POSTGRES_USER: pguser - POSTGRES_PASSWORD: pgpassword - ## Commented Values are Default: - #POSTGRES_DB: defaults to same as POSTGRES_USER - #POSTGRES_PORT: 5432 - #LOG_SQL: 0 (1 for verbose SQL logs) - THREADS: - volumes: - - "sz-data:/data" - - "${SERVER_MOUNT}/config.yaml:/opt/app/config.yaml" - - client: - image: szurubooru/client:latest - depends_on: - - server - environment: - BACKEND_HOST: server - BASE_URL: ${BASE_URL} - volumes: - - "sz-data:/data:ro" - ports: - - "${PORT}:80" - - sql: - image: postgres:11-alpine - restart: unless-stopped - environment: - POSTGRES_USER: pguser - POSTGRES_PASSWORD: pgpassword - #volumes: - # - "${MOUNT_SQL}/sqldata:/var/lib/postgresql/data" - -volumes: - sz-data: diff --git a/szurubooru-integration-test/folly.jpg b/szurubooru-integration-test/folly.jpg deleted file mode 100644 index 39ea1c7..0000000 Binary files a/szurubooru-integration-test/folly.jpg and /dev/null differ diff --git a/szurubooru-integration-test/folly1.jpg b/szurubooru-integration-test/folly1.jpg deleted file mode 100644 index ff83e59..0000000 Binary files a/szurubooru-integration-test/folly1.jpg and /dev/null differ diff --git a/szurubooru-integration-test/folly2.jpg b/szurubooru-integration-test/folly2.jpg deleted file mode 100644 index c01f08d..0000000 Binary files a/szurubooru-integration-test/folly2.jpg and /dev/null differ diff --git a/szurubooru-integration-test/folly3.jpg b/szurubooru-integration-test/folly3.jpg deleted file mode 100644 index a5d0609..0000000 Binary files a/szurubooru-integration-test/folly3.jpg and /dev/null differ diff --git a/szurubooru-integration-test/folly3_thumb.jpg b/szurubooru-integration-test/folly3_thumb.jpg deleted file mode 100644 index 96e52bf..0000000 Binary files a/szurubooru-integration-test/folly3_thumb.jpg and /dev/null differ diff --git a/szurubooru-integration-test/folly4.jpg b/szurubooru-integration-test/folly4.jpg deleted file mode 100644 index 08ca156..0000000 Binary files a/szurubooru-integration-test/folly4.jpg and /dev/null differ diff --git a/szurubooru-integration-test/src/main.rs b/szurubooru-integration-test/src/main.rs deleted file mode 100644 index 072e6ec..0000000 --- a/szurubooru-integration-test/src/main.rs +++ /dev/null @@ -1,941 +0,0 @@ -use chrono::Months; -use sha1::{Digest, Sha1}; -use std::error::Error; -use std::fs::File; -use std::io::{Seek, SeekFrom}; -use std::path::Path; -use std::process::Stdio; -use std::time::Duration; -use szurubooru_client::models::*; -use szurubooru_client::tokens::{CommentNamedToken, QueryToken}; -use szurubooru_client::*; -use tempfile::tempfile; -use tokio::process::Command; -use tracing::level_filters::LevelFilter; -use tracing::{info, instrument}; -use tracing_subscriber::filter::EnvFilter; - -#[tokio::main] -#[tracing::instrument] -async fn main() -> Result<(), Box> { - let ev = EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) - .from_env_lossy(); - tracing_subscriber::fmt() - .compact() - //.with_span_events(FmtSpan::ACTIVE) - .with_target(false) - .with_level(false) - .with_env_filter(ev) - .init(); - - //info!("Starting Szurubooru instance..."); - let anon_client = start_instance().await; - - let create_user = CreateUpdateUserBuilder::default() - .name("integration_user".to_string()) - .password("integration_password".to_string()) - .rank(UserRank::Administrator) - .avatar_style(UserAvatarStyle::Gravatar) - .build() - .expect("Unable to create CreateUser object"); - let _user = anon_client - .request() - .create_user(&create_user) - .await - .expect("Error creating user"); - - let auth_client = SzurubooruClient::new_with_basic_auth( - "http://localhost:9801", - "integration_user", - "integration_password", - true, - )?; - - test_tag_categories(&auth_client).await; - test_tags(&auth_client).await; - test_creating_posts(&auth_client).await; - test_pool_categories(&auth_client).await; - test_pools(&auth_client).await; - test_comments(&auth_client).await; - test_users(&auth_client).await; - test_snapshots(&auth_client).await; - test_downloads(&auth_client).await; - - Command::new("sh") - .current_dir(env!("CARGO_MANIFEST_DIR")) - .arg("-c") - .arg("./stop_szurubooru.sh") - .stderr(Stdio::null()) - .stdout(Stdio::null()) - .stdin(Stdio::null()) - .status() - .await - .expect("Failed to stop szurubooru"); - Ok(()) -} - -#[tracing::instrument] -async fn start_instance() -> SzurubooruClient { - info!("Starting Szurubooru instance..."); - let anon_client = SzurubooruClient::new_anonymous("http://localhost:9801", true) - .expect("Can't create anonymous client"); - - Command::new("sh") - .current_dir(env!("CARGO_MANIFEST_DIR")) - .arg("-c") - .arg("./start_szurubooru.sh") - .stderr(Stdio::null()) - .stdout(Stdio::null()) - .stdin(Stdio::null()) - .status() - .await - .expect("Failed to start szurubooru"); - - let mut connected = false; - let mut error = None; - - for _ in 0..5 { - let info = anon_client.request().get_global_info().await; - if info.is_ok() { - connected = true; - break; - } else if let Err(e) = info { - error = Some(e); - } - tokio::time::sleep(Duration::from_secs(5)).await; - } - if !connected { - panic!( - "{}", - format!("Unable to connect to instance. Last error: {error:?}") - ); - } - - anon_client -} - -#[tracing::instrument(skip(client), level = "INFO")] -async fn test_tag_categories(client: &SzurubooruClient) { - info!("Testing tag categories"); - let tag_cats = client - .request() - .list_tag_categories() - .await - .expect("Could not list tag categories"); - assert_eq!(tag_cats.results.len(), 1); - - info!("Creating tag category"); - let create_tag_cat = CreateUpdateTagCategoryBuilder::default() - .name("my_tag_cat".to_string()) - .color("purple".to_string()) - .order(1) - .build() - .expect("Unable to build create_tag_cat object"); - let result_tag_cat = client - .request() - .create_tag_category(&create_tag_cat) - .await - .expect("Unable to create tag category"); - assert_eq!(result_tag_cat.name, Some("my_tag_cat".to_string())); - let tag_cats = client - .request() - .list_tag_categories() - .await - .expect("Could not list tag categories again"); - assert_eq!(tag_cats.results.len(), 2); - - info!("GETting tag category"); - let tag_res = client - .request() - .get_tag_category("my_tag_cat") - .await - .expect("Could not fetch tag category"); - assert_eq!(result_tag_cat.color, tag_res.color); - - info!("Updating tag category"); - let update_tag_cat = CreateUpdateTagCategoryBuilder::default() - .version(tag_res.version) - .color("red".to_string()) - .build() - .expect("Could not create update for tag category"); - let update_res = client - .request() - .update_tag_category("my_tag_cat", &update_tag_cat) - .await - .expect("Unable to update tag category"); - assert_eq!(update_res.color, Some("red".to_string())); - - info!("Deleting tag category"); - client - .request() - .delete_tag_category("my_tag_cat", update_res.version) - .await - .expect("Could not delete tag category"); - let tag_cats = client - .request() - .list_tag_categories() - .await - .expect("Could not list tag categories again"); - assert_eq!(tag_cats.results.len(), 1); -} - -#[instrument(skip(client))] -async fn test_tags(client: &SzurubooruClient) { - info!("Testing tag functions"); - - info!("Listing tags"); - let tag_list = client - .request() - .list_tags(None) - .await - .expect("Could not list tags"); - assert_eq!(tag_list.total, 0); - - info!("Creating tag"); - let cutag = CreateUpdateTagBuilder::default() - .names(vec!["foo".to_string(), "foo2".to_string()]) - .category("default".to_string()) - .description("The foo tag".to_string()) - .build() - .expect("Could not build the CreateUpdateTag"); - let tag_res = client - .request() - .create_tag(&cutag) - .await - .expect("Could not create tag"); - - assert_eq!( - tag_res.names, - Some(vec!["foo".to_string(), "foo2".to_string()]) - ); - assert!(tag_res.description.is_some()); - - let tag_list = client - .request() - .list_tags(None) - .await - .expect("Could not list tags"); - assert_eq!(tag_list.total, 1); - - info!("Testing field selection"); - let tag_list = client - .with_fields(vec!["version", "names", "category"]) - .list_tags(None) - .await - .expect("Could not list tags"); - assert_eq!(tag_list.total, 1); - assert!(tag_list.results.first().unwrap().description.is_none()); - - info!("Updating tag"); - let utag = CreateUpdateTagBuilder::default() - .version(tag_res.version) - .description("The foo2 tag".to_string()) - .build() - .expect("Could not build the CreateUpdateTag"); - let tag_res2 = client - .request() - .update_tag("foo", &utag) - .await - .expect("Could not update tag"); - assert_ne!(tag_res.description, tag_res2.description); - - info!("Getting tag"); - let tag_res3 = client - .request() - .get_tag("foo") - .await - .expect("Could not fetch tag"); - assert_eq!(tag_res2.description, tag_res3.description); - - info!("Creating a second tag"); - let cutag = CreateUpdateTagBuilder::default() - .names(vec!["bar".to_string()]) - .category("default".to_string()) - .description("The foo tag".to_string()) - .build() - .expect("Could not build the CreateUpdateTag"); - let bar_tag = client - .request() - .create_tag(&cutag) - .await - .expect("Unable to create second tag"); - let tag_list = client - .request() - .list_tags(None) - .await - .expect("Could not list tags"); - assert_eq!(tag_list.total, 2); - - info!("Merging tags"); - let merge_tag = MergeTagsBuilder::default() - .remove_version(bar_tag.version) - .remove(bar_tag.names.as_ref().unwrap().first().unwrap()) - .merge_to_version(tag_res3.version) - .merge_to(tag_res3.names.as_ref().unwrap().first().unwrap()) - .build() - .expect("Could not create merge tags object"); - let merged_tag = client - .request() - .merge_tag(&merge_tag) - .await - .expect("Could not merge tags"); - assert_eq!(tag_res3.names, merged_tag.names); - let tag_list = client - .request() - .list_tags(None) - .await - .expect("Could not list tags"); - assert_eq!(tag_list.total, 1); - - info!("Deleting tag"); - client - .request() - .delete_tag("foo", merged_tag.version) - .await - .expect("Could not delete tag"); -} - -#[instrument(skip(client))] -async fn test_creating_posts(client: &SzurubooruClient) { - info!("Testing creating posts"); - - info!("Listing posts (should be empty)"); - let post_list = client - .request() - .list_posts(None) - .await - .expect("Could not list posts"); - assert_eq!(post_list.total, 0); - - info!("Testing upload by URL"); - let wiki_post_obj = CreateUpdatePostBuilder::default() - .content_url("https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Maine_Coon_cat_by_Tomitheos.JPG/225px-Maine_Coon_cat_by_Tomitheos.JPG".to_string()) - .tags(vec!["maine_coon".to_string(), "cat".to_string()]) - .safety(PostSafety::Safe) - .build() - .expect("Could not build wiki post object"); - let wiki_post = client - .request() - .create_post_from_url(&wiki_post_obj) - .await - .expect("Unable to create wiki post object"); - - info!("Updating existing post"); - let wiki_post_update = CreateUpdatePostBuilder::default() - .version(wiki_post.version.unwrap()) - .safety(wiki_post.safety.unwrap()) - .source("Wikipedia".to_string()) - .build() - .expect("Could not build wiki post update object"); - let wiki_post = client - .request() - .update_post(wiki_post.id.unwrap(), &wiki_post_update) - .await - .expect("Unable to up wiki post object"); - let post_list = client - .request() - .list_posts(None) - .await - .expect("Could not list posts"); - assert_eq!(post_list.total, 1); - - info!("Deleting wikipedia image"); - client - .request() - .delete_post(wiki_post.id.unwrap(), wiki_post.version.unwrap()) - .await - .expect("Could not delete wiki post"); - - info!("Test upload by File type"); - let folly1_obj = CreateUpdatePostBuilder::default() - .tags(vec![ - "maine_coon".to_string(), - "cat".to_string(), - "folly1".to_string(), - ]) - .safety(PostSafety::Safe) - .build() - .expect("Could not build first upload object"); - let folly1_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly1.jpg"); - let mut folly1_file = - File::open(&folly1_path).expect(&format!("Could not open file {folly1_path:?}")); - let _folly1_post = client - .request() - .create_post_from_file(&mut folly1_file, None, "folly1.jpg", &folly1_obj) - .await - .expect("Could not create post from folly1 file"); - - info!("Test upload by file path"); - let folly2_obj = CreateUpdatePostBuilder::default() - .tags(vec![ - "maine_coon".to_string(), - "cat".to_string(), - "folly2".to_string(), - ]) - .safety(PostSafety::Safe) - .build() - .expect("Could not build second upload object"); - let folly2_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly2.jpg"); - let _folly2_post = client - .request() - .create_post_from_file_path(folly2_path, None::, &folly2_obj) - .await - .expect("Could not create post from folly2 path"); - - info!("Test upload by file path with thumbnail"); - let folly3_obj = CreateUpdatePostBuilder::default() - .tags(vec![ - "maine_coon".to_string(), - "cat".to_string(), - "folly3".to_string(), - ]) - .safety(PostSafety::Safe) - .build() - .expect("Could not build third upload object"); - let folly3_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly3.jpg"); - let folly3_thumbnail = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly3_thumb.jpg"); - let folly3_post = client - .request() - .create_post_from_file_path(&folly3_path, Some(folly3_thumbnail), &folly3_obj) - .await - .expect("Could not create post with thumbnail"); - - info!("Searching for post by image"); - let matching_posts = client - .request() - .posts_for_file_path(&folly3_path) - .await - .expect("Could not search for post by file path"); - assert_eq!(matching_posts.results.first().unwrap(), &folly3_post); - - info!("Reverse searching"); - let matching_posts = client - .request() - .reverse_search_file_path(&folly3_path) - .await - .expect("Could not reverse image search"); - assert!(matching_posts.exact_post.is_some()); - - info!("Testing temporary upload"); - let folly4_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly4.jpg"); - let folly4_temp_upload = client - .request() - .upload_temporary_file_from_path(folly4_path) - .await - .expect("Could not create temporary upload for folly4"); - let folly4_obj = CreateUpdatePostBuilder::default() - .tags(vec![ - "maine_coon".to_string(), - "cat".to_string(), - "folly4".to_string(), - ]) - .content_token(folly4_temp_upload.token) - .safety(PostSafety::Safe) - .build() - .expect("Could not build fourth upload object"); - let folly4_post = client - .request() - .create_post_from_token(&folly4_obj) - .await - .expect("Could not create upload from temporary token"); - - info!("Querying by tag"); - let f4_results = client - .request() - .list_posts(Some(&vec![QueryToken::anonymous("cat")])) - .await - .expect("Could not list posts by tag cat"); - assert_eq!(f4_results.total, 4); - - info!("Testing pagination"); - let post_list = client - .request() - .with_limit(1) - .list_posts(None) - .await - .expect("Could not list posts page 1"); - assert_eq!(post_list.results.len(), 1); - let post_list2 = client - .request() - .with_limit(1) - .with_offset(1) - .list_posts(None) - .await - .expect("Could not list posts page 2"); - assert_ne!(post_list.results, post_list2.results); - - info!("Testing tag siblings"); - let tag_occurrences = client - .request() - .get_tag_siblings("maine_coon") - .await - .expect("Could not fetch tag siblings"); - let occurrences_filtered = tag_occurrences - .results - .iter() - .filter(|oc| { - oc.tag - .names - .as_ref() - .map(|names| names.contains(&"cat".to_string())) - .unwrap_or(false) - }) - .count(); - assert_eq!(occurrences_filtered, 1); - - info!("Rating post"); - let folly3_post = client - .request() - .rate_post(folly3_post.id.unwrap(), 1) - .await - .expect("Could not rate post"); - assert_eq!(folly3_post.own_score, Some(1)); - - info!("Favoriting post"); - let folly3_post = client - .request() - .favorite_post(folly3_post.id.unwrap()) - .await - .expect("Could not favorite post"); - assert_eq!(folly3_post.own_favorite, Some(true)); - - info!("Unfavorite post"); - let folly3_post = client - .request() - .unfavorite_post(folly3_post.id.unwrap()) - .await - .expect("Could not unfavorite post"); - assert_eq!(folly3_post.own_favorite, Some(false)); - - info!("Featuring post"); - let featured_post = client - .request() - .get_featured_post() - .await - .expect("Could not get featured post"); - assert!(featured_post.is_none()); - - client - .request() - .set_featured_post(folly4_post.id.unwrap()) - .await - .expect("Could not set featured post"); - - let featured_post = client - .request() - .get_featured_post() - .await - .expect("Could not get featured post"); - - assert!(featured_post.is_some()); -} - -#[instrument(skip(client))] -async fn test_pool_categories(client: &SzurubooruClient) { - info!("Testing pool categories"); - - info!("Listing pool categories"); - let pool_cats = client - .request() - .list_pool_categories() - .await - .expect("Could not list pool categories"); - assert!(!pool_cats.results.is_empty()); - - info!("Creating pool category"); - let create_cat = CreateUpdatePoolCategoryBuilder::default() - .name("cat_pool_category".to_string()) - .color("purple".to_string()) - .build() - .expect("Could not build pool category object"); - let pool_cat = client - .request() - .create_pool_category(&create_cat) - .await - .expect("Could not create pool category"); - - let create_dog_cat = CreateUpdatePoolCategoryBuilder::default() - .name("dog_category".to_string()) - .color("orange".to_string()) - .build() - .expect("Could not build pool category object"); - let dog_pool_cat = client - .request() - .create_pool_category(&create_dog_cat) - .await - .expect("Could not create pool category"); - - info!("Updating pool category"); - let update_cat = CreateUpdatePoolCategoryBuilder::default() - .version(pool_cat.version.unwrap()) - .color("white".to_string()) - .build() - .expect("Could not build pool category update"); - let pool_cat = client - .request() - .update_pool_category(pool_cat.name.unwrap(), &update_cat) - .await - .expect("Could not update pool category"); - - info!("Getting pool category"); - let pool_cat = client - .request() - .get_pool_category(pool_cat.name.unwrap()) - .await - .expect("Could not get pool category"); - - info!("Deleting pool category"); - client - .request() - .delete_pool_category(dog_pool_cat.name.unwrap(), dog_pool_cat.version.unwrap()) - .await - .expect("Could not delete pool category"); - - info!("Setting default pool category"); - let _pool_cat = client - .request() - .set_default_pool_category(pool_cat.name.unwrap()) - .await - .expect("Could not set default pool category"); -} - -#[instrument(skip(client))] -async fn test_pools(client: &SzurubooruClient) { - info!("Testing post pools"); - let pools = client - .request() - .list_pools(None) - .await - .expect("Could not list pools"); - assert_eq!(pools.total, 0); - - info!("Creating pools"); - let create_pool = CreateUpdatePoolBuilder::default() - .names(vec!["cats_pool".to_string()]) - .category("cat_pool_category".to_string()) - .build() - .expect("Could not build pool creation object"); - let cat_pool = client - .request() - .create_pool(&create_pool) - .await - .expect("Could not create pool"); - let create_pool2 = CreateUpdatePoolBuilder::default() - .names(vec!["catz_pool".to_string()]) - .category("cat_pool_category".to_string()) - .build() - .expect("Could not build pool creation object"); - let catz_pool = client - .request() - .create_pool(&create_pool2) - .await - .expect("Could not create pool"); - let create_pool3 = CreateUpdatePoolBuilder::default() - .names(vec!["dogs_pool".to_string()]) - .category("cat_pool_category".to_string()) - .build() - .expect("Could not build pool creation object"); - let dogs_pool = client - .request() - .create_pool(&create_pool3) - .await - .expect("Could not create pool"); - - info!("Getting pool"); - let cat_pool = client - .request() - .get_pool(cat_pool.id.unwrap()) - .await - .expect("Could not fetch pool"); - - info!("Deleting pool"); - client - .request() - .delete_pool(dogs_pool.id.unwrap(), dogs_pool.version.unwrap()) - .await - .expect("Could not delete pool"); - - info!("Updating pool"); - let f4_results = client - .request() - .list_posts(Some(&vec![QueryToken::anonymous("cat")])) - .await - .expect("Could not list posts by tag cat"); - let post_ids = f4_results - .results - .into_iter() - .map(|p| p.id.unwrap()) - .collect::>(); - let update_pool = CreateUpdatePoolBuilder::default() - .version(cat_pool.version.unwrap()) - .posts(post_ids) - .description("All cat pictures all the time".to_string()) - .build() - .expect("Could not build update object"); - let cat_pool = client - .request() - .update_pool(cat_pool.id.unwrap(), &update_pool) - .await - .expect("Unable to update pool"); - - info!("Merging pools"); - let merge_pool_obj = MergePoolBuilder::default() - .remove_version(catz_pool.version.unwrap()) - .remove(catz_pool.id.unwrap()) - .merge_to_version(cat_pool.version.unwrap()) - .merge_to(cat_pool.id.unwrap()) - .build() - .expect("Unable to build merge object"); - let _cat_pool = client - .request() - .merge_pools(&merge_pool_obj) - .await - .expect("Unable to merge pools"); -} - -#[instrument(skip(client))] -async fn test_comments(client: &SzurubooruClient) { - info!("Testing comments"); - - info!("Listing comments"); - let _comment_list = client - .request() - .list_comments(None) - .await - .expect("Unable to list comments"); - - let f4_results = client - .request() - .list_posts(Some(&vec![QueryToken::anonymous("cat")])) - .await - .expect("Could not list posts by tag cat"); - let post_ids = f4_results - .results - .into_iter() - .map(|p| p.id.unwrap()) - .collect::>(); - let post_id = *post_ids.first().unwrap(); - - info!("Creating comment"); - let create_comment = CreateUpdateCommentBuilder::default() - .text("Excellent cat!".to_string()) - .post_id(post_id) - .build() - .expect("Unable to create comment object"); - let comment = client - .request() - .create_comment(&create_comment) - .await - .expect("Unable to create comment"); - - info!("Updating comment"); - let update_comment = CreateUpdateCommentBuilder::default() - .text("Beautiful cat!".to_string()) - .version(comment.version.unwrap()) - .build() - .expect("Unable to create comment update object"); - let comment = client - .request() - .update_comment(comment.id.unwrap(), &update_comment) - .await - .expect("Unable to update comment"); - - info!("Getting comment"); - let comment = client - .request() - .get_comment(comment.id.unwrap()) - .await - .expect("Unable to fetch comment"); - - info!("Getting all comments for post"); - let comment_list = client - .request() - //.list_comments(None) - .list_comments(Some(&vec![QueryToken::token( - CommentNamedToken::Post, - post_id.to_string(), - )])) - .await - .expect("Unable to fetch comments for post"); - assert_ne!(comment_list.total, 0); - - info!("Rating comment"); - let comment = client - .request() - .rate_comment(comment.id.unwrap(), -1) - .await - .expect("Could not rate comment"); - assert_eq!(comment.own_score, Some(-1)); - - info!("Deleting comment"); - client - .request() - .delete_comment(comment.id.unwrap(), comment.version.unwrap()) - .await - .expect("Could not delete comment"); -} - -#[instrument(skip(client))] -async fn test_users(client: &SzurubooruClient) { - info!("Testing users"); - - info!("Listing users"); - let user_list = client - .request() - .list_users(None) - .await - .expect("Could not list users"); - assert_eq!(user_list.total, 1); - - // Create user is already tested above - info!("Creating user with avatar"); - let avatar_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("avatar.jpg"); - let create_user = CreateUpdateUserBuilder::default() - .name("iu2".to_string()) - .password("ipass2".to_string()) - .rank(UserRank::Regular) - .avatar_style(UserAvatarStyle::Manual) - .build() - .expect("Could not create user creation object"); - let user_obj = client - .request() - .create_user_with_avatar_path(avatar_path, &create_user) - .await - .expect("Could not create user"); - - info!("Updating user"); - let update_user = CreateUpdateUserBuilder::default() - .version(user_obj.version.unwrap()) - .rank(UserRank::Restricted) - .build() - .expect("Could not create user update object"); - let user_obj = client - .request() - .update_user(user_obj.name.unwrap(), &update_user) - .await - .expect("Could not update user"); - - info!("Getting user"); - let user_obj = client - .request() - .get_user(user_obj.name.unwrap()) - .await - .expect("Could not get user"); - - info!("Deleting user"); - client - .request() - .delete_user(user_obj.name.unwrap(), user_obj.version.unwrap()) - .await - .expect("Could not delete user"); - - let username = "integration_user".to_string(); - info!("Listing user tokens"); - let tokens = client - .request() - .list_user_tokens(&username) - .await - .expect("Could not list user tokens"); - assert!(tokens.results.is_empty()); - - info!("Creating user token"); - let create_token = CreateUpdateUserAuthTokenBuilder::default() - .note("My token") - .enabled(true) - .build() - .expect("Could not create token creation object"); - let token = client - .request() - .create_user_token(&username, &create_token) - .await - .expect("Could not create auth token"); - - info!("Updating user token"); - let new_expiration = chrono::offset::Utc::now() - .checked_add_months(Months::new(1)) - .unwrap(); - let update_token = CreateUpdateUserAuthTokenBuilder::default() - .version(token.version.unwrap()) - .expiration_time(new_expiration) - .build() - .expect("Could not create token update object"); - - let token = client - .request() - .update_user_token(&username, &token.token.unwrap(), &update_token) - .await - .expect("Could not update token"); - - info!("Deleting user token"); - client - .request() - .delete_user_token(username, token.token.unwrap(), token.version.unwrap()) - .await - .expect("Could not delete token"); -} - -#[instrument(skip(client))] -async fn test_snapshots(client: &SzurubooruClient) { - info!("Testing snapshots"); - - info!("Listing snapshots"); - let snap_list = client - .request() - .list_snapshots(None) - .await - .expect("Could not list snapshots"); - assert!(snap_list.total > 0); -} - -#[instrument(skip(client))] -async fn test_downloads(client: &SzurubooruClient) { - info!("Testing image download"); - - let folly3_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("folly3.jpg"); - - let mut f3_hasher = Sha1::new(); - - let mut f3_file = File::open(&folly3_path).expect("Unable to open folly3.jpg"); - - std::io::copy(&mut f3_file, &mut f3_hasher).expect("Unable to hash folly3.jpg"); - - let f3_hash = f3_hasher.finalize(); - - let f3post = client - .request() - .reverse_search_file_path(folly3_path) - .await - .expect("Unable to reverse search for file") - .exact_post - .expect("Unable to find exact post for folly3.jpg"); - - let mut dl_file = tempfile().expect("Could not create temporary file"); - //let mut dl_thumb_file = tempfile().expect("Could not create temporary thumbnail file"); - - //let dlfolly3_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("dlfolly3.jpg"); - /*let mut dl_file = File::options() - .create(true) - .truncate(true) - .read(true) - .write(true) - .open(dlfolly3_path) - .expect("unable to open download file");*/ - - client - .request() - .download_image_to_file(f3post.id.unwrap(), &mut dl_file) - .await - .expect("Could not download to temporary file"); - dl_file - .seek(SeekFrom::Start(0)) - .expect("Could not rewind file"); - - let mut dl_f3_hasher = Sha1::new(); - - std::io::copy(&mut dl_file, &mut dl_f3_hasher).expect("Unable to hash folly3.jpg"); - - let dl_f3_hash = dl_f3_hasher.finalize(); - - assert_eq!(f3_hash, dl_f3_hash); -} diff --git a/szurubooru-integration-test/start_szurubooru.sh b/szurubooru-integration-test/start_szurubooru.sh deleted file mode 100755 index 43284ad..0000000 --- a/szurubooru-integration-test/start_szurubooru.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -#export MOUNT_DATA=szurubooru/data -export SERVER_MOUNT=./szurubooru/server -#export MOUNT_SQL=szurubooru/pgsql -export BASE_URL=http://localhost:9801 -export PORT=9801 - -docker compose down || true - -docker compose up -d diff --git a/szurubooru-integration-test/stop_szurubooru.sh b/szurubooru-integration-test/stop_szurubooru.sh deleted file mode 100755 index 5e50d10..0000000 --- a/szurubooru-integration-test/stop_szurubooru.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker compose down diff --git a/szurubooru-integration-test/szurubooru/data/.gitkeep b/szurubooru-integration-test/szurubooru/data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/szurubooru-integration-test/szurubooru/pgsql/.gitkeep b/szurubooru-integration-test/szurubooru/pgsql/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/szurubooru-integration-test/szurubooru/server/.gitkeep b/szurubooru-integration-test/szurubooru/server/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/szurubooru-integration-test/szurubooru/server/config.yaml b/szurubooru-integration-test/szurubooru/server/config.yaml deleted file mode 100644 index aab75cf..0000000 --- a/szurubooru-integration-test/szurubooru/server/config.yaml +++ /dev/null @@ -1,179 +0,0 @@ -# rather than editing this file, it is strongly suggested to create config.yaml -# and override only what you need. - -# shown in the website title and on the front page -name: integrationland -# full url to the homepage of this szurubooru site, with no trailing slash -domain: https://localhost:9801 -# used to salt the users' password hashes and generate filenames for static content -secret: awdopk1mdqsapdoawd21!!!#asw - -# Delete thumbnails and source files on post delete -# Original functionality is no, to mitigate the impacts of admins going -# on unchecked post purges. -delete_source_files: no - -thumbnails: - avatar_width: 300 - avatar_height: 300 - post_width: 300 - post_height: 300 - -# settings used to download files from the web on behalf of the api users -user_agent: -max_dl_filesize: 25.0E+6 # maximum filesize limit in bytes - -# automatically convert animated GIF uploads to video formats -convert: - gif: - to_webm: false - to_mp4: false - -# allow posts to be uploaded even if some image processing errors occur -allow_broken_uploads: false - -# used to send password reset e-mails -smtp: - host: # example: localhost - port: # example: 25 - user: # example: bot - pass: # example: groovy123 - from: # example: noreply@example.com - # if host is left empty the password reset feature will be disabled, - # in which case it is recommended to fill contactEmail so that users - # know who to contact when they want to reset their password - -contact_email: # example: bob@example.com. Meant for manual password reset procedures - -enable_safety: yes - -tag_name_regex: ^\S+$ -tag_category_name_regex: ^[^\s%+#/]+$ - -pool_name_regex: ^\S+$ -pool_category_name_regex: ^[^\s%+#/]+$ - -# don't make these more restrictive unless you want to annoy people; if you do -# customize them, make sure to update the instructions in the registration form -# template as well. -password_regex: '^.{5,}$' -user_name_regex: '^[a-zA-Z0-9_-]{1,32}$' - -# webhooks to call when events occur (such as post/tag/user/etc. changes) -# the listed urls will be called with a HTTP POST request with a payload -# containing a snapshot resource as JSON. See doc/API.md for details -webhooks: -# - https://api.example.com/webhooks/ - -default_rank: regular - -privileges: - 'users:create:self': anonymous # Registration permission - 'users:create:any': administrator - 'users:list': regular - 'users:view': regular - 'users:edit:any:name': moderator - 'users:edit:any:pass': moderator - 'users:edit:any:email': moderator - 'users:edit:any:avatar': moderator - 'users:edit:any:rank': moderator - 'users:edit:self:name': regular - 'users:edit:self:pass': regular - 'users:edit:self:email': regular - 'users:edit:self:avatar': regular - 'users:edit:self:rank': moderator # one can't promote themselves or anyone to upper rank than their own. - 'users:delete:any': administrator - 'users:delete:self': regular - - 'user_tokens:list:any': administrator - 'user_tokens:list:self': regular - 'user_tokens:create:any': administrator - 'user_tokens:create:self': regular - 'user_tokens:edit:any': administrator - 'user_tokens:edit:self': regular - 'user_tokens:delete:any': administrator - 'user_tokens:delete:self': regular - - 'posts:create:anonymous': regular - 'posts:create:identified': regular - 'posts:list': anonymous - 'posts:reverse_search': regular - 'posts:view': anonymous - 'posts:view:featured': anonymous - 'posts:edit:content': power - 'posts:edit:flags': regular - 'posts:edit:notes': regular - 'posts:edit:relations': regular - 'posts:edit:safety': power - 'posts:edit:source': regular - 'posts:edit:tags': regular - 'posts:edit:thumbnail': power - 'posts:feature': moderator - 'posts:delete': moderator - 'posts:score': regular - 'posts:merge': moderator - 'posts:favorite': regular - 'posts:bulk-edit:tags': power - 'posts:bulk-edit:safety': power - 'posts:bulk-edit:delete': power - - 'tags:create': regular - 'tags:edit:names': power - 'tags:edit:category': power - 'tags:edit:description': power - 'tags:edit:implications': power - 'tags:edit:suggestions': power - 'tags:list': regular - 'tags:view': anonymous - 'tags:merge': moderator - 'tags:delete': moderator - - 'tag_categories:create': moderator - 'tag_categories:edit:name': moderator - 'tag_categories:edit:color': moderator - 'tag_categories:edit:order': moderator - 'tag_categories:list': anonymous - 'tag_categories:view': anonymous - 'tag_categories:delete': moderator - 'tag_categories:set_default': moderator - - 'pools:create': regular - 'pools:edit:names': power - 'pools:edit:category': power - 'pools:edit:description': power - 'pools:edit:posts': power - 'pools:list': regular - 'pools:view': anonymous - 'pools:merge': moderator - 'pools:delete': moderator - - 'pool_categories:create': moderator - 'pool_categories:edit:name': moderator - 'pool_categories:edit:color': moderator - 'pool_categories:list': anonymous - 'pool_categories:view': anonymous - 'pool_categories:delete': moderator - 'pool_categories:set_default': moderator - - 'comments:create': regular - 'comments:delete:any': moderator - 'comments:delete:own': regular - 'comments:edit:any': moderator - 'comments:edit:own': regular - 'comments:list': regular - 'comments:view': regular - 'comments:score': regular - - 'snapshots:list': power - - 'uploads:create': regular - 'uploads:use_downloader': power - -## ONLY SET THESE IF DEPLOYING OUTSIDE OF DOCKER -#debug: 0 # generate server logs? -#show_sql: 0 # show sql in server logs? -#data_url: /data/ -#data_dir: /var/www/data -## usage: schema://user:password@host:port/database_name -## example: postgres://szuru:dog@localhost:5432/szuru_test -#database: