From c7ff87bc03d98c7fa8b2354223ae33f0fab8b5bd Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Tue, 13 Nov 2018 15:38:19 -0800 Subject: start using client in some tests --- rust/TODO | 4 + rust/tests/test_api_server.rs | 1026 --------------------------------- rust/tests/test_api_server_client.rs | 57 ++ rust/tests/test_api_server_http.rs | 1034 ++++++++++++++++++++++++++++++++++ 4 files changed, 1095 insertions(+), 1026 deletions(-) delete mode 100644 rust/tests/test_api_server.rs create mode 100644 rust/tests/test_api_server_client.rs create mode 100644 rust/tests/test_api_server_http.rs (limited to 'rust') diff --git a/rust/TODO b/rust/TODO index c8a1a1bd..59722cd8 100644 --- a/rust/TODO +++ b/rust/TODO @@ -19,6 +19,10 @@ account helper tool - test/validate tokens later: +- tried using sync::Once to wrap test database initilization (so it would only + run migrations once), but it didn't seem to work, maybe I had a bug or it + didn't compile? + => could also do a global mutex: https://github.com/SergioBenitez/Rocket/issues/697 - could some of the EntityCrud trait macro stuff be re-implemented as an enum type? - pure-rust "benchmark" scripts that hit, eg, lookups and batch endpoints => criterion.rs benchmarking diff --git a/rust/tests/test_api_server.rs b/rust/tests/test_api_server.rs deleted file mode 100644 index ebc74b67..00000000 --- a/rust/tests/test_api_server.rs +++ /dev/null @@ -1,1026 +0,0 @@ -extern crate diesel; -extern crate fatcat; -extern crate fatcat_api_spec; -extern crate iron; -extern crate iron_test; -extern crate uuid; - -use diesel::prelude::*; -use fatcat::api_helpers::*; -use fatcat::database_schema::*; -use iron::headers::ContentType; -use iron::mime::Mime; -use iron::{status, Headers}; -use iron_test::{request, response}; -use uuid::Uuid; - -fn setup() -> ( - Headers, - fatcat_api_spec::router::Router, - diesel::r2d2::PooledConnection>, -) { - let server = fatcat::test_server().unwrap(); - let conn = server.db_pool.get().expect("db_pool error"); - let router = fatcat_api_spec::router(server); - let mut headers = Headers::new(); - let mime: Mime = "application/json".parse().unwrap(); - headers.set(ContentType(mime)); - (headers, router, conn) -} - -fn check_response( - resp: iron::IronResult, - want_status: status::Status, - in_body: Option<&str>, -) { - let resp = resp.unwrap(); - let status = resp.status; - let body = response::extract_body_to_string(resp); - println!("{}", body); - assert_eq!(status, Some(want_status)); - if let Some(thing) = in_body { - assert!(body.contains(thing)); - } -} - -#[test] -fn test_entity_gets() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - Some("Trivial Results"), - ); - - // Check revision encoding - check_response( - request::get( - "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - Some("00000000-0000-0000-1111-fff000000002"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaae", - headers.clone(), - &router, - ), - status::Ok, - Some("Grace Hopper"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/file/aaaaaaaaaaaaamztaaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - Some("archive.org"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - Some("bigger example"), - ); - - // expand keyword - check_response( - request::get( - "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai?expand=all", - headers.clone(), - &router, - ), - status::Ok, - Some("MySpace Blog"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - None, - ); -} - -#[test] -fn test_entity_404() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/creator/aaaaaaaaaaaaairceeeeeeeeee", - headers.clone(), - &router, - ), - status::NotFound, - None, - ); -} - -#[test] -fn test_entity_history() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai/history", - headers.clone(), - &router, - ), - status::Ok, - Some("changelog"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaae/history", - headers.clone(), - &router, - ), - status::Ok, - Some("changelog"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/file/aaaaaaaaaaaaamztaaaaaaaaai/history", - headers.clone(), - &router, - ), - status::Ok, - Some("changelog"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai/history", - headers.clone(), - &router, - ), - status::Ok, - Some("changelog"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai/history", - headers.clone(), - &router, - ), - status::Ok, - Some("changelog"), - ); -} - -#[test] -fn test_lookups() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/container/lookup?issnl=1234-5678", - headers.clone(), - &router, - ), - status::Ok, - Some("Journal of Trivial Results"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/creator/lookup?orcid=0000-0003-2088-7465", - headers.clone(), - &router, - ), - status::Ok, - Some("Christine Moran"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/file/lookup?sha1=7d97e98f8af710c7e7fe703abc8f639e0ee507c4", - headers.clone(), - &router, - ), - status::Ok, - Some("robots.txt"), - ); -} - -#[test] -fn test_reverse_lookups() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaai/releases", - headers.clone(), - &router, - ), - status::Ok, - Some("bigger example"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai/files", - headers.clone(), - &router, - ), - status::Ok, - Some("7d97e98f8af710c7e7fe703abc8f639e0ee507c4"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai/releases", - headers.clone(), - &router, - ), - status::Ok, - Some("bigger example"), - ); -} - -#[test] -fn test_post_container() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/container", - headers, - r#"{"name": "test journal"}"#, - &router, - ), - status::Created, - None, - ); // TODO: "test journal" -} - -#[test] -fn test_post_batch_container() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/container/batch", - headers, - r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, - &router, - ), - status::Created, - None, - ); // TODO: "test journal" -} - -#[test] -fn test_post_creator() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/creator", - headers, - r#"{"display_name": "some person"}"#, - &router, - ), - status::Created, - None, - ); -} - -#[test] -fn test_post_file() { - let (headers, router, conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/file", - headers.clone(), - r#"{ }"#, - &router, - ), - status::Created, - None, - ); - - check_response( - request::post( - "http://localhost:9411/v0/file", - headers.clone(), - r#"{"size": 76543, - "sha1": "f0000000000000008b7eb2a93e6d0440c1f3e7f8", - "md5": "0b6d347b01d437a092be84c2edfce72c", - "sha256": "a77e4c11a57f1d757fca5754a8f83b5d4ece49a2d28596889127c1a2f3f28832", - "urls": [ - {"url": "http://archive.org/asdf.txt", "rel": "web" }, - {"url": "http://web.archive.org/2/http://archive.org/asdf.txt", "rel": "webarchive" } - ], - "mimetype": "application/pdf", - "releases": [ - "aaaaaaaaaaaaarceaaaaaaaaae", - "aaaaaaaaaaaaarceaaaaaaaaai" - ], - "extra": { "source": "speculation" } - }"#, - &router, - ), - status::Created, - None, - ); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); - - check_response( - request::get( - "http://localhost:9411/v0/file/lookup?sha1=f0000000000000008b7eb2a93e6d0440c1f3e7f8", - headers.clone(), - &router, - ), - status::Ok, - Some("web.archive.org/2/http"), - ); -} - -#[test] -fn test_post_release() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - // TODO: target_release_id - r#"{"title": "secret minimal paper", - "release_type": "journal-article", - "work_id": "aaaaaaaaaaaaavkvaaaaaaaaae" - }"#, - &router, - ), - status::Created, - None, - ); // TODO: "secret paper" - - // No work_id supplied (auto-created) - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - // TODO: target_release_id - r#"{"title": "secret minimal paper the second", - "release_type": "journal-article" - }"#, - &router, - ), - status::Created, - None, - ); - - check_response( - request::post( - "http://localhost:9411/v0/release", - headers, - // TODO: target_release_id - r#"{"title": "secret paper", - "release_type": "journal-article", - "doi": "10.1234/abcde.781231231239", - "pmid": "54321", - "pmcid": "PMC12345", - "wikidata_qid": "Q12345", - "core_id": "7890", - "volume": "439", - "issue": "IV", - "pages": "1-399", - "work_id": "aaaaaaaaaaaaavkvaaaaaaaaai", - "container_id": "aaaaaaaaaaaaaeiraaaaaaaaae", - "refs": [{ - "index": 3, - "raw": "just a string" - },{ - "raw": "just a string" - }], - "contribs": [{ - "index": 1, - "raw_name": "textual description of contributor (aka, name)", - "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", - "contrib_type": "author" - },{ - "raw_name": "shorter" - }], - "extra": { "source": "speculation" } - }"#, - &router, - ), - status::Created, - None, - ); // TODO: "secret paper" -} - -#[test] -fn test_post_work() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/work", - headers.clone(), - // TODO: target_work_id - r#"{ - "extra": { "source": "speculation" } - }"#, - &router, - ), - status::Created, - None, - ); -} - -#[test] -fn test_update_work() { - let (headers, router, conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/work", - headers.clone(), - r#"{ - "extra": { "source": "other speculation" } - }"#, - &router, - ), - status::Created, - None, - ); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); -} - -#[test] -fn test_delete_work() { - let (headers, router, conn) = setup(); - - check_response( - request::delete( - "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai", - headers.clone(), - &router, - ), - status::Ok, - None, - ); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); -} - -#[test] -fn test_accept_editgroup() { - let (headers, router, conn) = setup(); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - - let c: i64 = container_ident::table - .filter(container_ident::is_live.eq(false)) - .count() - .get_result(&conn) - .unwrap(); - assert_eq!(c, 0); - let c: i64 = changelog::table - .filter(changelog::editgroup_id.eq(editgroup_id)) - .count() - .get_result(&conn) - .unwrap(); - assert_eq!(c, 0); - - check_response( - request::post( - "http://localhost:9411/v0/container", - headers.clone(), - &format!( - "{{\"name\": \"test journal 1\", \"editgroup_id\": \"{}\"}}", - uuid2fcid(&editgroup_id) - ), - &router, - ), - status::Created, - None, - ); - check_response( - request::post( - "http://localhost:9411/v0/container", - headers.clone(), - &format!( - "{{\"name\": \"test journal 2\", \"editgroup_id\": \"{}\"}}", - uuid2fcid(&editgroup_id) - ), - &router, - ), - status::Created, - None, - ); - - let c: i64 = container_ident::table - .filter(container_ident::is_live.eq(false)) - .count() - .get_result(&conn) - .unwrap(); - assert_eq!(c, 2); - - check_response( - request::get( - &format!( - "http://localhost:9411/v0/editgroup/{}", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - &router, - ), - status::Ok, - None, - ); - - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); - - let c: i64 = container_ident::table - .filter(container_ident::is_live.eq(false)) - .count() - .get_result(&conn) - .unwrap(); - assert_eq!(c, 0); - let c: i64 = changelog::table - .filter(changelog::editgroup_id.eq(editgroup_id)) - .count() - .get_result(&conn) - .unwrap(); - assert_eq!(c, 1); -} - -#[test] -fn test_changelog() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/changelog", - headers.clone(), - &router, - ), - status::Ok, - Some("editgroup_id"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/changelog/1", - headers.clone(), - &router, - ), - status::Ok, - Some("files"), - ); -} - -#[test] -fn test_stats() { - let (headers, router, _conn) = setup(); - - check_response( - request::get("http://localhost:9411/v0/stats", headers.clone(), &router), - status::Ok, - Some("merged_editgroups"), - ); - check_response( - request::get( - "http://localhost:9411/v0/stats?more=yes", - headers.clone(), - &router, - ), - status::Ok, - Some("merged_editgroups"), - ); -} - -#[test] -fn test_400() { - let (headers, router, _conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/release", - headers, - r#"{"title": "secret paper", - "release_type": "journal-article", - "doi": "10.1234/abcde.781231231239", - "volume": "439", - "issue": "IV", - "pages": "1-399", - "work_id": "aaaaaaaaaaaaavkvaaaaaaaaae", - "container_id": "aaaaaaaaaaaaaeiraaaaaae", - "refs": [{ - "index": 3, - "raw": "just a string" - },{ - "raw": "just a string" - }], - "contribs": [{ - "index": 1, - "raw_name": "textual description of contributor (aka, name)", - "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", - "contrib_type": "author" - },{ - "raw_name": "shorter" - }], - "extra": { "source": "speculation" } - }"#, - &router, - ), - status::BadRequest, - None, - ); -} - -#[test] -fn test_edit_gets() { - let (headers, router, _conn) = setup(); - - check_response( - request::get( - "http://localhost:9411/v0/editor/aaaaaaaaaaaabkvkaaaaaaaaae", - headers.clone(), - &router, - ), - status::Ok, - Some("admin"), - ); - - check_response( - request::get( - "http://localhost:9411/v0/editor/aaaaaaaaaaaabkvkaaaaaaaaae/changelog", - headers.clone(), - &router, - ), - status::Ok, - None, - ); - - check_response( - request::get( - "http://localhost:9411/v0/editgroup/aaaaaaaaaaaabo53aaaaaaaaae", - headers.clone(), - &router, - ), - status::Ok, - None, - ); -} - -#[test] -fn test_bad_external_idents() { - let (headers, router, _conn) = setup(); - - // Bad wikidata QID - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "secret paper", - "wikidata_qid": "P12345" - }"#, - &router, - ), - status::BadRequest, - Some("Wikidata QID"), - ); - check_response( - request::post( - "http://localhost:9411/v0/container", - headers.clone(), - r#"{"name": "my journal", - "wikidata_qid": "P12345" - }"#, - &router, - ), - status::BadRequest, - Some("Wikidata QID"), - ); - check_response( - request::post( - "http://localhost:9411/v0/creator", - headers.clone(), - r#"{"display_name": "some body", - "wikidata_qid": "P12345" - }"#, - &router, - ), - status::BadRequest, - Some("Wikidata QID"), - ); - - // Bad PMCID - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "secret paper", - "pmcid": "12345" - }"#, - &router, - ), - status::BadRequest, - Some("PMCID"), - ); - - // Bad PMID - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "secret paper", - "pmid": "not-a-number" - }"#, - &router, - ), - status::BadRequest, - Some("PMID"), - ); - - // Bad DOI - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "secret paper", - "doi": "asdf" - }"#, - &router, - ), - status::BadRequest, - Some("DOI"), - ); - - // Good identifiers - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "secret paper", - "doi": "10.1234/abcde.781231231239", - "pmid": "54321", - "pmcid": "PMC12345", - "wikidata_qid": "Q12345" - }"#, - &router, - ), - status::Created, - None, - ); -} - -#[test] -fn test_abstracts() { - let (headers, router, conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "some paper", - "doi": "10.1234/iiiiiii", - "abstracts": [ - {"lang": "zh", - "mimetype": "text/plain", - "content": "some rando abstract 24iu3i25u2" }, - {"lang": "en", - "mimetype": "application/xml+jats", - "content": "some other abstract 99139405" } - ] - }"#, - &router, - ), - status::Created, - None, - ); - - // Same abstracts; checking that re-inserting works - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "some paper again", - "abstracts": [ - {"lang": "zh", - "mimetype": "text/plain", - "content": "some rando abstract 24iu3i25u2" }, - {"lang": "en", - "mimetype": "application/xml+jats", - "content": "some other abstract 99139405" } - ] - }"#, - &router, - ), - status::Created, - None, - ); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); - - check_response( - request::get( - "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", - headers.clone(), - &router, - ), - status::Ok, - // SHA-1 of first abstract string (with no trailing newline) - Some("65c171bd8c968e12ede25ad95f02cd4b2ce9db52"), - ); - check_response( - request::get( - "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", - headers.clone(), - &router, - ), - status::Ok, - Some("99139405"), - ); - check_response( - request::get( - "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", - headers.clone(), - &router, - ), - status::Ok, - Some("24iu3i25u2"), - ); -} - -#[test] -fn test_contribs() { - let (headers, router, conn) = setup(); - - check_response( - request::post( - "http://localhost:9411/v0/release", - headers.clone(), - r#"{"title": "some paper", - "doi": "10.1234/iiiiiii", - "contribs": [{ - "index": 1, - "raw_name": "textual description of contributor (aka, name)", - "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", - "contrib_type": "author", - "extra": {"key": "value 28328424942"} - },{ - "raw_name": "shorter" - }] - }"#, - &router, - ), - status::Created, - None, - ); - - let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); - let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); - check_response( - request::post( - &format!( - "http://localhost:9411/v0/editgroup/{}/accept", - uuid2fcid(&editgroup_id) - ), - headers.clone(), - "", - &router, - ), - status::Ok, - None, - ); -} - -#[test] -fn test_post_batch_autoaccept() { - let (headers, router, _conn) = setup(); - - // "true" - check_response( - request::post( - "http://localhost:9411/v0/container/batch?autoaccept=true", - headers.clone(), - r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, - &router, - ), - status::Created, - None, - ); - - // "n" - check_response( - request::post( - "http://localhost:9411/v0/container/batch?autoaccept=n", - headers.clone(), - r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, - &router, - ), - status::Created, - None, - ); - - // editgroup - check_response( - request::post( - "http://localhost:9411/v0/container/batch?autoaccept=yes&editgroup=asdf", - headers.clone(), - r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, - &router, - ), - status::BadRequest, - None, - ); -} diff --git a/rust/tests/test_api_server_client.rs b/rust/tests/test_api_server_client.rs new file mode 100644 index 00000000..381dc6ab --- /dev/null +++ b/rust/tests/test_api_server_client.rs @@ -0,0 +1,57 @@ +/* + * This file contains API server tests that hit the API through the Rust API client library. + * + * These tests are relatively complex and mutate database state. Tests should take care not to be + * racey or overwrite each other; for example, they should randomize external identifiers and + * minimize reliance on hard-coded example entities. + * + * Note that these tests currently do *not* include tests the authentication system, or any other + * middleware. + */ + +extern crate fatcat; +extern crate fatcat_api_spec; +extern crate uuid; +extern crate iron; + +use iron::{Iron, Listening}; +use fatcat_api_spec::{Context, Api, ApiNoContext, Future, ContextWrapperExt}; +use fatcat_api_spec::client::Client; +//use uuid::Uuid; + + +fn setup() -> ( + Context, + Client, + Listening, +) { + let server = fatcat::test_server().unwrap(); + let router = fatcat_api_spec::router(server); + let iron_server = Iron::new(router) + .http("localhost:9144") + .expect("Failed to start HTTP server"); + + let context = Context::new(); + let client = Client::try_new_http("http://localhost:9144").unwrap(); + (context, client, iron_server) +} + +#[test] +fn test_basic() { + + let (context, client, mut server) = setup(); + let client = client.with_context(context); + + client.get_changelog_entry(1).wait().unwrap(); + server.close().unwrap() +} + +#[test] +fn test_basic2() { + + let (context, client, mut server) = setup(); + let client = client.with_context(context); + + client.get_changelog_entry(1).wait().unwrap(); + server.close().unwrap() +} diff --git a/rust/tests/test_api_server_http.rs b/rust/tests/test_api_server_http.rs new file mode 100644 index 00000000..26535bea --- /dev/null +++ b/rust/tests/test_api_server_http.rs @@ -0,0 +1,1034 @@ +/* + * This file contains API server tests that hit the API by connecting via the Iron client, + * essentially doing raw HTTP/JSON requests. + * + * These tests are relatively simple and don't mutate much database state; they are primarily to + * test basic serialization/deserialization, and take advantage of hard-coded example entities. + */ + +extern crate diesel; +extern crate fatcat; +extern crate fatcat_api_spec; +extern crate iron; +extern crate iron_test; +extern crate uuid; + +use diesel::prelude::*; +use fatcat::api_helpers::*; +use fatcat::database_schema::*; +use iron::headers::ContentType; +use iron::mime::Mime; +use iron::{status, Headers}; +use iron_test::{request, response}; +use uuid::Uuid; + +fn setup() -> ( + Headers, + fatcat_api_spec::router::Router, + diesel::r2d2::PooledConnection>, +) { + let server = fatcat::test_server().unwrap(); + let conn = server.db_pool.get().expect("db_pool error"); + let router = fatcat_api_spec::router(server); + let mut headers = Headers::new(); + let mime: Mime = "application/json".parse().unwrap(); + headers.set(ContentType(mime)); + (headers, router, conn) +} + +fn check_response( + resp: iron::IronResult, + want_status: status::Status, + in_body: Option<&str>, +) { + let resp = resp.unwrap(); + let status = resp.status; + let body = response::extract_body_to_string(resp); + println!("{}", body); + assert_eq!(status, Some(want_status)); + if let Some(thing) = in_body { + assert!(body.contains(thing)); + } +} + +#[test] +fn test_entity_gets() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + Some("Trivial Results"), + ); + + // Check revision encoding + check_response( + request::get( + "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + Some("00000000-0000-0000-1111-fff000000002"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaae", + headers.clone(), + &router, + ), + status::Ok, + Some("Grace Hopper"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/file/aaaaaaaaaaaaamztaaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + Some("archive.org"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + // expand keyword + check_response( + request::get( + "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai?expand=all", + headers.clone(), + &router, + ), + status::Ok, + Some("MySpace Blog"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_entity_404() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/creator/aaaaaaaaaaaaairceeeeeeeeee", + headers.clone(), + &router, + ), + status::NotFound, + None, + ); +} + +#[test] +fn test_entity_history() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/container/aaaaaaaaaaaaaeiraaaaaaaaai/history", + headers.clone(), + &router, + ), + status::Ok, + Some("changelog"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaae/history", + headers.clone(), + &router, + ), + status::Ok, + Some("changelog"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/file/aaaaaaaaaaaaamztaaaaaaaaai/history", + headers.clone(), + &router, + ), + status::Ok, + Some("changelog"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai/history", + headers.clone(), + &router, + ), + status::Ok, + Some("changelog"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai/history", + headers.clone(), + &router, + ), + status::Ok, + Some("changelog"), + ); +} + +#[test] +fn test_lookups() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/container/lookup?issnl=1234-5678", + headers.clone(), + &router, + ), + status::Ok, + Some("Journal of Trivial Results"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/creator/lookup?orcid=0000-0003-2088-7465", + headers.clone(), + &router, + ), + status::Ok, + Some("Christine Moran"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/file/lookup?sha1=7d97e98f8af710c7e7fe703abc8f639e0ee507c4", + headers.clone(), + &router, + ), + status::Ok, + Some("robots.txt"), + ); +} + +#[test] +fn test_reverse_lookups() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/creator/aaaaaaaaaaaaaircaaaaaaaaai/releases", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/release/aaaaaaaaaaaaarceaaaaaaaaai/files", + headers.clone(), + &router, + ), + status::Ok, + Some("7d97e98f8af710c7e7fe703abc8f639e0ee507c4"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai/releases", + headers.clone(), + &router, + ), + status::Ok, + Some("bigger example"), + ); +} + +#[test] +fn test_post_container() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/container", + headers, + r#"{"name": "test journal"}"#, + &router, + ), + status::Created, + None, + ); // TODO: "test journal" +} + +#[test] +fn test_post_batch_container() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/container/batch", + headers, + r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, + &router, + ), + status::Created, + None, + ); // TODO: "test journal" +} + +#[test] +fn test_post_creator() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/creator", + headers, + r#"{"display_name": "some person"}"#, + &router, + ), + status::Created, + None, + ); +} + +#[test] +fn test_post_file() { + let (headers, router, conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/file", + headers.clone(), + r#"{ }"#, + &router, + ), + status::Created, + None, + ); + + check_response( + request::post( + "http://localhost:9411/v0/file", + headers.clone(), + r#"{"size": 76543, + "sha1": "f0000000000000008b7eb2a93e6d0440c1f3e7f8", + "md5": "0b6d347b01d437a092be84c2edfce72c", + "sha256": "a77e4c11a57f1d757fca5754a8f83b5d4ece49a2d28596889127c1a2f3f28832", + "urls": [ + {"url": "http://archive.org/asdf.txt", "rel": "web" }, + {"url": "http://web.archive.org/2/http://archive.org/asdf.txt", "rel": "webarchive" } + ], + "mimetype": "application/pdf", + "releases": [ + "aaaaaaaaaaaaarceaaaaaaaaae", + "aaaaaaaaaaaaarceaaaaaaaaai" + ], + "extra": { "source": "speculation" } + }"#, + &router, + ), + status::Created, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); + + check_response( + request::get( + "http://localhost:9411/v0/file/lookup?sha1=f0000000000000008b7eb2a93e6d0440c1f3e7f8", + headers.clone(), + &router, + ), + status::Ok, + Some("web.archive.org/2/http"), + ); +} + +#[test] +fn test_post_release() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + // TODO: target_release_id + r#"{"title": "secret minimal paper", + "release_type": "journal-article", + "work_id": "aaaaaaaaaaaaavkvaaaaaaaaae" + }"#, + &router, + ), + status::Created, + None, + ); // TODO: "secret paper" + + // No work_id supplied (auto-created) + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + // TODO: target_release_id + r#"{"title": "secret minimal paper the second", + "release_type": "journal-article" + }"#, + &router, + ), + status::Created, + None, + ); + + check_response( + request::post( + "http://localhost:9411/v0/release", + headers, + // TODO: target_release_id + r#"{"title": "secret paper", + "release_type": "journal-article", + "doi": "10.1234/abcde.781231231239", + "pmid": "54321", + "pmcid": "PMC12345", + "wikidata_qid": "Q12345", + "core_id": "7890", + "volume": "439", + "issue": "IV", + "pages": "1-399", + "work_id": "aaaaaaaaaaaaavkvaaaaaaaaai", + "container_id": "aaaaaaaaaaaaaeiraaaaaaaaae", + "refs": [{ + "index": 3, + "raw": "just a string" + },{ + "raw": "just a string" + }], + "contribs": [{ + "index": 1, + "raw_name": "textual description of contributor (aka, name)", + "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", + "contrib_type": "author" + },{ + "raw_name": "shorter" + }], + "extra": { "source": "speculation" } + }"#, + &router, + ), + status::Created, + None, + ); // TODO: "secret paper" +} + +#[test] +fn test_post_work() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/work", + headers.clone(), + // TODO: target_work_id + r#"{ + "extra": { "source": "speculation" } + }"#, + &router, + ), + status::Created, + None, + ); +} + +#[test] +fn test_update_work() { + let (headers, router, conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/work", + headers.clone(), + r#"{ + "extra": { "source": "other speculation" } + }"#, + &router, + ), + status::Created, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_delete_work() { + let (headers, router, conn) = setup(); + + check_response( + request::delete( + "http://localhost:9411/v0/work/aaaaaaaaaaaaavkvaaaaaaaaai", + headers.clone(), + &router, + ), + status::Ok, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_accept_editgroup() { + let (headers, router, conn) = setup(); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + + let c: i64 = container_ident::table + .filter(container_ident::is_live.eq(false)) + .count() + .get_result(&conn) + .unwrap(); + assert_eq!(c, 0); + let c: i64 = changelog::table + .filter(changelog::editgroup_id.eq(editgroup_id)) + .count() + .get_result(&conn) + .unwrap(); + assert_eq!(c, 0); + + check_response( + request::post( + "http://localhost:9411/v0/container", + headers.clone(), + &format!( + "{{\"name\": \"test journal 1\", \"editgroup_id\": \"{}\"}}", + uuid2fcid(&editgroup_id) + ), + &router, + ), + status::Created, + None, + ); + check_response( + request::post( + "http://localhost:9411/v0/container", + headers.clone(), + &format!( + "{{\"name\": \"test journal 2\", \"editgroup_id\": \"{}\"}}", + uuid2fcid(&editgroup_id) + ), + &router, + ), + status::Created, + None, + ); + + let c: i64 = container_ident::table + .filter(container_ident::is_live.eq(false)) + .count() + .get_result(&conn) + .unwrap(); + assert_eq!(c, 2); + + check_response( + request::get( + &format!( + "http://localhost:9411/v0/editgroup/{}", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + &router, + ), + status::Ok, + None, + ); + + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); + + let c: i64 = container_ident::table + .filter(container_ident::is_live.eq(false)) + .count() + .get_result(&conn) + .unwrap(); + assert_eq!(c, 0); + let c: i64 = changelog::table + .filter(changelog::editgroup_id.eq(editgroup_id)) + .count() + .get_result(&conn) + .unwrap(); + assert_eq!(c, 1); +} + +#[test] +fn test_changelog() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/changelog", + headers.clone(), + &router, + ), + status::Ok, + Some("editgroup_id"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/changelog/1", + headers.clone(), + &router, + ), + status::Ok, + Some("files"), + ); +} + +#[test] +fn test_stats() { + let (headers, router, _conn) = setup(); + + check_response( + request::get("http://localhost:9411/v0/stats", headers.clone(), &router), + status::Ok, + Some("merged_editgroups"), + ); + check_response( + request::get( + "http://localhost:9411/v0/stats?more=yes", + headers.clone(), + &router, + ), + status::Ok, + Some("merged_editgroups"), + ); +} + +#[test] +fn test_400() { + let (headers, router, _conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/release", + headers, + r#"{"title": "secret paper", + "release_type": "journal-article", + "doi": "10.1234/abcde.781231231239", + "volume": "439", + "issue": "IV", + "pages": "1-399", + "work_id": "aaaaaaaaaaaaavkvaaaaaaaaae", + "container_id": "aaaaaaaaaaaaaeiraaaaaae", + "refs": [{ + "index": 3, + "raw": "just a string" + },{ + "raw": "just a string" + }], + "contribs": [{ + "index": 1, + "raw_name": "textual description of contributor (aka, name)", + "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", + "contrib_type": "author" + },{ + "raw_name": "shorter" + }], + "extra": { "source": "speculation" } + }"#, + &router, + ), + status::BadRequest, + None, + ); +} + +#[test] +fn test_edit_gets() { + let (headers, router, _conn) = setup(); + + check_response( + request::get( + "http://localhost:9411/v0/editor/aaaaaaaaaaaabkvkaaaaaaaaae", + headers.clone(), + &router, + ), + status::Ok, + Some("admin"), + ); + + check_response( + request::get( + "http://localhost:9411/v0/editor/aaaaaaaaaaaabkvkaaaaaaaaae/changelog", + headers.clone(), + &router, + ), + status::Ok, + None, + ); + + check_response( + request::get( + "http://localhost:9411/v0/editgroup/aaaaaaaaaaaabo53aaaaaaaaae", + headers.clone(), + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_bad_external_idents() { + let (headers, router, _conn) = setup(); + + // Bad wikidata QID + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "secret paper", + "wikidata_qid": "P12345" + }"#, + &router, + ), + status::BadRequest, + Some("Wikidata QID"), + ); + check_response( + request::post( + "http://localhost:9411/v0/container", + headers.clone(), + r#"{"name": "my journal", + "wikidata_qid": "P12345" + }"#, + &router, + ), + status::BadRequest, + Some("Wikidata QID"), + ); + check_response( + request::post( + "http://localhost:9411/v0/creator", + headers.clone(), + r#"{"display_name": "some body", + "wikidata_qid": "P12345" + }"#, + &router, + ), + status::BadRequest, + Some("Wikidata QID"), + ); + + // Bad PMCID + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "secret paper", + "pmcid": "12345" + }"#, + &router, + ), + status::BadRequest, + Some("PMCID"), + ); + + // Bad PMID + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "secret paper", + "pmid": "not-a-number" + }"#, + &router, + ), + status::BadRequest, + Some("PMID"), + ); + + // Bad DOI + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "secret paper", + "doi": "asdf" + }"#, + &router, + ), + status::BadRequest, + Some("DOI"), + ); + + // Good identifiers + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "secret paper", + "doi": "10.1234/abcde.781231231239", + "pmid": "54321", + "pmcid": "PMC12345", + "wikidata_qid": "Q12345" + }"#, + &router, + ), + status::Created, + None, + ); +} + +#[test] +fn test_abstracts() { + let (headers, router, conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "some paper", + "doi": "10.1234/iiiiiii", + "abstracts": [ + {"lang": "zh", + "mimetype": "text/plain", + "content": "some rando abstract 24iu3i25u2" }, + {"lang": "en", + "mimetype": "application/xml+jats", + "content": "some other abstract 99139405" } + ] + }"#, + &router, + ), + status::Created, + None, + ); + + // Same abstracts; checking that re-inserting works + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "some paper again", + "abstracts": [ + {"lang": "zh", + "mimetype": "text/plain", + "content": "some rando abstract 24iu3i25u2" }, + {"lang": "en", + "mimetype": "application/xml+jats", + "content": "some other abstract 99139405" } + ] + }"#, + &router, + ), + status::Created, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); + + check_response( + request::get( + "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", + headers.clone(), + &router, + ), + status::Ok, + // SHA-1 of first abstract string (with no trailing newline) + Some("65c171bd8c968e12ede25ad95f02cd4b2ce9db52"), + ); + check_response( + request::get( + "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", + headers.clone(), + &router, + ), + status::Ok, + Some("99139405"), + ); + check_response( + request::get( + "http://localhost:9411/v0/release/lookup?doi=10.1234/iiiiiii", + headers.clone(), + &router, + ), + status::Ok, + Some("24iu3i25u2"), + ); +} + +#[test] +fn test_contribs() { + let (headers, router, conn) = setup(); + + check_response( + request::post( + "http://localhost:9411/v0/release", + headers.clone(), + r#"{"title": "some paper", + "doi": "10.1234/iiiiiii", + "contribs": [{ + "index": 1, + "raw_name": "textual description of contributor (aka, name)", + "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae", + "contrib_type": "author", + "extra": {"key": "value 28328424942"} + },{ + "raw_name": "shorter" + }] + }"#, + &router, + ), + status::Created, + None, + ); + + let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap(); + let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap(); + check_response( + request::post( + &format!( + "http://localhost:9411/v0/editgroup/{}/accept", + uuid2fcid(&editgroup_id) + ), + headers.clone(), + "", + &router, + ), + status::Ok, + None, + ); +} + +#[test] +fn test_post_batch_autoaccept() { + let (headers, router, _conn) = setup(); + + // "true" + check_response( + request::post( + "http://localhost:9411/v0/container/batch?autoaccept=true", + headers.clone(), + r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, + &router, + ), + status::Created, + None, + ); + + // "n" + check_response( + request::post( + "http://localhost:9411/v0/container/batch?autoaccept=n", + headers.clone(), + r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, + &router, + ), + status::Created, + None, + ); + + // editgroup + check_response( + request::post( + "http://localhost:9411/v0/container/batch?autoaccept=yes&editgroup=asdf", + headers.clone(), + r#"[{"name": "test journal"}, {"name": "another test journal"}]"#, + &router, + ), + status::BadRequest, + None, + ); +} -- cgit v1.2.3