Files
tranquil-pds/tests/backup.rs
2026-01-03 00:58:28 +02:00

326 lines
9.6 KiB
Rust

mod common;
mod helpers;
use common::*;
use reqwest::{StatusCode, header};
use serde_json::{Value, json};
#[tokio::test]
async fn test_list_backups_empty() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let res = client
.get(format!("{}/xrpc/_backup.listBackups", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("listBackups request failed");
assert_eq!(res.status(), StatusCode::OK);
let body: Value = res.json().await.expect("Invalid JSON");
assert!(body["backups"].is_array());
assert_eq!(body["backups"].as_array().unwrap().len(), 0);
assert!(body["backupEnabled"].as_bool().unwrap_or(false));
}
#[tokio::test]
async fn test_create_and_list_backup() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let create_res = client
.post(format!("{}/xrpc/_backup.createBackup", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("createBackup request failed");
assert_eq!(create_res.status(), StatusCode::OK, "createBackup failed");
let create_body: Value = create_res.json().await.expect("Invalid JSON");
assert!(create_body["id"].is_string());
assert!(create_body["repoRev"].is_string());
assert!(create_body["sizeBytes"].is_i64());
assert!(create_body["blockCount"].is_i64());
let list_res = client
.get(format!("{}/xrpc/_backup.listBackups", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("listBackups request failed");
assert_eq!(list_res.status(), StatusCode::OK);
let list_body: Value = list_res.json().await.expect("Invalid JSON");
let backups = list_body["backups"].as_array().unwrap();
assert!(!backups.is_empty());
}
#[tokio::test]
async fn test_download_backup() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let create_res = client
.post(format!("{}/xrpc/_backup.createBackup", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("createBackup request failed");
assert_eq!(create_res.status(), StatusCode::OK);
let create_body: Value = create_res.json().await.expect("Invalid JSON");
let backup_id = create_body["id"].as_str().unwrap();
let get_res = client
.get(format!(
"{}/xrpc/_backup.getBackup?id={}",
base_url().await,
backup_id
))
.bearer_auth(&token)
.send()
.await
.expect("getBackup request failed");
assert_eq!(get_res.status(), StatusCode::OK);
let content_type = get_res.headers().get(header::CONTENT_TYPE).unwrap();
assert_eq!(content_type, "application/vnd.ipld.car");
let bytes = get_res.bytes().await.expect("Failed to read body");
assert!(bytes.len() > 100, "CAR file should have content");
assert_eq!(
bytes[1], 0xa2,
"CAR file should have valid header structure"
);
}
#[tokio::test]
async fn test_delete_backup() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let create_res = client
.post(format!("{}/xrpc/_backup.createBackup", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("createBackup request failed");
assert_eq!(create_res.status(), StatusCode::OK);
let create_body: Value = create_res.json().await.expect("Invalid JSON");
let backup_id = create_body["id"].as_str().unwrap();
let delete_res = client
.post(format!(
"{}/xrpc/_backup.deleteBackup?id={}",
base_url().await,
backup_id
))
.bearer_auth(&token)
.send()
.await
.expect("deleteBackup request failed");
assert_eq!(delete_res.status(), StatusCode::OK);
let get_res = client
.get(format!(
"{}/xrpc/_backup.getBackup?id={}",
base_url().await,
backup_id
))
.bearer_auth(&token)
.send()
.await
.expect("getBackup request failed");
assert_eq!(get_res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_toggle_backup_enabled() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let list_res = client
.get(format!("{}/xrpc/_backup.listBackups", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("listBackups request failed");
assert_eq!(list_res.status(), StatusCode::OK);
let list_body: Value = list_res.json().await.expect("Invalid JSON");
assert!(list_body["backupEnabled"].as_bool().unwrap());
let disable_res = client
.post(format!("{}/xrpc/_backup.setEnabled", base_url().await))
.bearer_auth(&token)
.json(&json!({"enabled": false}))
.send()
.await
.expect("setEnabled request failed");
assert_eq!(disable_res.status(), StatusCode::OK);
let disable_body: Value = disable_res.json().await.expect("Invalid JSON");
assert!(!disable_body["enabled"].as_bool().unwrap());
let list_res2 = client
.get(format!("{}/xrpc/_backup.listBackups", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("listBackups request failed");
let list_body2: Value = list_res2.json().await.expect("Invalid JSON");
assert!(!list_body2["backupEnabled"].as_bool().unwrap());
let enable_res = client
.post(format!("{}/xrpc/_backup.setEnabled", base_url().await))
.bearer_auth(&token)
.json(&json!({"enabled": true}))
.send()
.await
.expect("setEnabled request failed");
assert_eq!(enable_res.status(), StatusCode::OK);
}
#[tokio::test]
async fn test_backup_includes_blobs() {
let client = client();
let (token, did) = create_account_and_login(&client).await;
let blob_data = b"Hello, this is test blob data for backup testing!";
let upload_res = client
.post(format!(
"{}/xrpc/com.atproto.repo.uploadBlob",
base_url().await
))
.header(header::CONTENT_TYPE, "text/plain")
.bearer_auth(&token)
.body(blob_data.to_vec())
.send()
.await
.expect("uploadBlob request failed");
assert_eq!(upload_res.status(), StatusCode::OK);
let upload_body: Value = upload_res.json().await.expect("Invalid JSON");
let blob = &upload_body["blob"];
let record = json!({
"$type": "app.bsky.feed.post",
"text": "Test post with blob",
"createdAt": chrono::Utc::now().to_rfc3339(),
"embed": {
"$type": "app.bsky.embed.images",
"images": [{
"alt": "test image",
"image": blob
}]
}
});
let create_record_res = client
.post(format!(
"{}/xrpc/com.atproto.repo.createRecord",
base_url().await
))
.bearer_auth(&token)
.json(&json!({
"repo": did,
"collection": "app.bsky.feed.post",
"record": record
}))
.send()
.await
.expect("createRecord request failed");
assert_eq!(create_record_res.status(), StatusCode::OK);
let create_backup_res = client
.post(format!("{}/xrpc/_backup.createBackup", base_url().await))
.bearer_auth(&token)
.send()
.await
.expect("createBackup request failed");
assert_eq!(create_backup_res.status(), StatusCode::OK);
let backup_body: Value = create_backup_res.json().await.expect("Invalid JSON");
let backup_id = backup_body["id"].as_str().unwrap();
let get_backup_res = client
.get(format!(
"{}/xrpc/_backup.getBackup?id={}",
base_url().await,
backup_id
))
.bearer_auth(&token)
.send()
.await
.expect("getBackup request failed");
assert_eq!(get_backup_res.status(), StatusCode::OK);
let car_bytes = get_backup_res.bytes().await.expect("Failed to read body");
let blob_cid = blob["ref"]["$link"].as_str().unwrap();
let blob_found = String::from_utf8_lossy(&car_bytes).contains("Hello, this is test blob data");
assert!(
blob_found || car_bytes.len() > 500,
"Backup should contain blob data (cid: {})",
blob_cid
);
}
#[tokio::test]
async fn test_backup_unauthorized() {
let client = client();
let res = client
.get(format!("{}/xrpc/_backup.listBackups", base_url().await))
.send()
.await
.expect("listBackups request failed");
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
}
#[tokio::test]
async fn test_get_nonexistent_backup() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let fake_id = uuid::Uuid::new_v4();
let res = client
.get(format!(
"{}/xrpc/_backup.getBackup?id={}",
base_url().await,
fake_id
))
.bearer_auth(&token)
.send()
.await
.expect("getBackup request failed");
assert_eq!(res.status(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_backup_invalid_id() {
let client = client();
let (token, _did) = create_account_and_login(&client).await;
let res = client
.get(format!(
"{}/xrpc/_backup.getBackup?id=not-a-uuid",
base_url().await
))
.bearer_auth(&token)
.send()
.await
.expect("getBackup request failed");
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
}