diff --git a/tests/dav_compliance/rfc4918_proppatch.rs b/tests/dav_compliance/rfc4918_proppatch.rs deleted file mode 100644 index 5f62b7e2..00000000 --- a/tests/dav_compliance/rfc4918_proppatch.rs +++ /dev/null @@ -1,343 +0,0 @@ -//! RFC 4918 §9.2 PROPPATCH compliance — dead property storage and retrieval. - -use reqwest::Method; - -use super::harness::{get_server, unique_name}; - -fn propfind() -> Method { - Method::from_bytes(b"PROPFIND").unwrap() -} - -fn proppatch() -> Method { - Method::from_bytes(b"PROPPATCH").unwrap() -} - -/// PROPPATCH set a custom property → 207 with 200 propstat. -#[tokio::test] -async fn proppatch_set_returns_207() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_set")); - let (k, v) = srv.auth(); - - srv.client() - .put(srv.url(&path)) - .header(k, v.clone()) - .body("x") - .send() - .await - .unwrap(); - - let xml = r#" - - - - Alice - - -"#; - - let res = srv - .client() - .request(proppatch(), srv.url(&path)) - .header(k, v) - .header("Content-Type", "application/xml") - .body(xml) - .send() - .await - .unwrap(); - assert_eq!(res.status(), 207, "PROPPATCH must return 207"); - let body = res.text().await.unwrap(); - assert!( - body.contains("200") || body.contains("HTTP/1.1 200"), - "PROPPATCH 207 must contain 200 propstat; body: {body}" - ); -} - -/// PROPPATCH set → PROPFIND retrieves the stored value. -#[tokio::test] -async fn proppatch_set_property_visible_in_propfind() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_roundtrip")); - let (k, v) = srv.auth(); - - srv.client() - .put(srv.url(&path)) - .header(k, v.clone()) - .body("data") - .send() - .await - .unwrap(); - - // Set dead property - let set_xml = r#" - - - - blue - - -"#; - - let pp_res = srv - .client() - .request(proppatch(), srv.url(&path)) - .header(k, v.clone()) - .header("Content-Type", "application/xml") - .body(set_xml) - .send() - .await - .unwrap(); - assert_eq!(pp_res.status(), 207, "PROPPATCH set must return 207"); - - // Retrieve via PROPFIND allprop - let pf_res = srv - .client() - .request(propfind(), srv.url(&path)) - .header(k, v) - .header("Depth", "0") - .send() - .await - .unwrap(); - assert_eq!(pf_res.status(), 207); - let body = pf_res.text().await.unwrap(); - assert!( - body.contains("color") || body.contains("blue"), - "PROPFIND allprop must include dead property set by PROPPATCH; body: {body}" - ); -} - -/// PROPPATCH remove → property absent from subsequent PROPFIND. -#[tokio::test] -async fn proppatch_remove_property_not_in_propfind() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_remove")); - let (k, v) = srv.auth(); - - srv.client() - .put(srv.url(&path)) - .header(k, v.clone()) - .body("data") - .send() - .await - .unwrap(); - - // First set - let set_xml = r#" - - removeme -"#; - srv.client() - .request(proppatch(), srv.url(&path)) - .header(k, v.clone()) - .header("Content-Type", "application/xml") - .body(set_xml) - .send() - .await - .unwrap(); - - // Then remove - let remove_xml = r#" - - -"#; - let rem_res = srv - .client() - .request(proppatch(), srv.url(&path)) - .header(k, v.clone()) - .header("Content-Type", "application/xml") - .body(remove_xml) - .send() - .await - .unwrap(); - assert_eq!(rem_res.status(), 207, "PROPPATCH remove must return 207"); - - // Verify gone — request the specific prop, expect 404 propstat - let pf_xml = r#" - - -"#; - let pf_res = srv - .client() - .request(propfind(), srv.url(&path)) - .header(k, v) - .header("Depth", "0") - .header("Content-Type", "application/xml") - .body(pf_xml) - .send() - .await - .unwrap(); - assert_eq!(pf_res.status(), 207); - let body = pf_res.text().await.unwrap(); - assert!( - body.contains("404"), - "Removed dead property must appear in 404 propstat; body: {body}" - ); -} - -/// PROPPATCH set + remove in same request → both applied atomically. -#[tokio::test] -async fn proppatch_set_and_remove_in_same_request() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_setrem")); - let (k, v) = srv.auth(); - - srv.client() - .put(srv.url(&path)) - .header(k, v.clone()) - .body("x") - .send() - .await - .unwrap(); - - // Pre-seed a property to remove - let seed_xml = r#" - - gone -"#; - srv.client() - .request(proppatch(), srv.url(&path)) - .header(k, v.clone()) - .header("Content-Type", "application/xml") - .body(seed_xml) - .send() - .await - .unwrap(); - - // Set new + remove old in one request - let xml = r#" - - here - -"#; - let res = srv - .client() - .request(proppatch(), srv.url(&path)) - .header(k, v) - .header("Content-Type", "application/xml") - .body(xml) - .send() - .await - .unwrap(); - assert_eq!(res.status(), 207, "combined set+remove must return 207"); - let body = res.text().await.unwrap(); - // Both ops should succeed - assert!( - !body.contains("409") && !body.contains("403"), - "combined PROPPATCH must not fail; body: {body}" - ); -} - -/// PROPPATCH on non-existent resource → 404. -#[tokio::test] -async fn proppatch_nonexistent_resource_returns_404() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_ghost")); - let (k, v) = srv.auth(); - - let xml = r#" - - y -"#; - - let res = srv - .client() - .request(proppatch(), srv.url(&path)) - .header(k, v) - .header("Content-Type", "application/xml") - .body(xml) - .send() - .await - .unwrap(); - assert_eq!( - res.status(), - 404, - "PROPPATCH on non-existent resource must return 404" - ); -} - -/// PROPPATCH on collection (folder) → 207. -#[tokio::test] -async fn proppatch_on_collection_returns_207() { - let srv = get_server(); - let col = format!("/webdav/{}", unique_name("pp_col")); - let (k, v) = srv.auth(); - - srv.client() - .request(Method::from_bytes(b"MKCOL").unwrap(), srv.url(&col)) - .header(k, v.clone()) - .send() - .await - .unwrap(); - - let xml = r#" - - my folder -"#; - - let res = srv - .client() - .request(proppatch(), srv.url(&col)) - .header(k, v) - .header("Content-Type", "application/xml") - .body(xml) - .send() - .await - .unwrap(); - assert_eq!(res.status(), 207, "PROPPATCH on collection must return 207"); -} - -/// PROPFIND specific dead property returns value in 200 propstat (not 404). -#[tokio::test] -async fn propfind_specific_dead_property_returns_200_propstat() { - let srv = get_server(); - let path = format!("/webdav/{}", unique_name("pp_specific")); - let (k, v) = srv.auth(); - - srv.client() - .put(srv.url(&path)) - .header(k, v.clone()) - .body("x") - .send() - .await - .unwrap(); - - // Set - let set_xml = r#" - - 5 -"#; - srv.client() - .request(proppatch(), srv.url(&path)) - .header(k, v.clone()) - .header("Content-Type", "application/xml") - .body(set_xml) - .send() - .await - .unwrap(); - - // PROPFIND for that exact property - let pf_xml = r#" - - -"#; - let pf_res = srv - .client() - .request(propfind(), srv.url(&path)) - .header(k, v) - .header("Depth", "0") - .header("Content-Type", "application/xml") - .body(pf_xml) - .send() - .await - .unwrap(); - assert_eq!(pf_res.status(), 207); - let body = pf_res.text().await.unwrap(); - assert!( - !body.contains("404"), - "Known dead property must not be in 404 propstat; body: {body}" - ); - assert!( - body.contains("rating") || body.contains("5"), - "Response must include the dead property value; body: {body}" - ); -}