bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use bucketwarden_server::{
    s3_service_specific_error_catalog, BucketWarden, RuntimeConfig, S3ServiceSpecificError,
};
use serde_json::Value;
use std::collections::BTreeSet;

const S3ERR_RUNTIME_EVIDENCE_JSON: &str =
    include_str!("../../../.ssot/evidence/s3-service-specific-errors-runtime-foundation-t0.json");

fn expected_feature_ids() -> Vec<String> {
    let payload: Value =
        serde_json::from_str(S3ERR_RUNTIME_EVIDENCE_JSON).expect("valid ssot evidence JSON");
    payload["feature_ids"]
        .as_array()
        .expect("runtime evidence has feature_ids array")
        .iter()
        .map(|value| {
            value
                .as_str()
                .expect("feature id must be a string")
                .to_owned()
        })
        .collect()
}

#[test]
fn service_specific_s3_error_catalog_emits_all_tracked_leaf_codes() {
    let catalog = s3_service_specific_error_catalog();
    let expected_features = expected_feature_ids();
    assert_eq!(catalog.len(), expected_features.len());
    assert_eq!(
        catalog
            .iter()
            .map(|error| error.feature_id)
            .map(str::to_owned)
            .collect::<Vec<_>>(),
        expected_features
    );
    assert_eq!(
        catalog
            .iter()
            .map(|error| error.feature_id)
            .collect::<BTreeSet<_>>()
            .len(),
        expected_features.len()
    );

    let mut runtime = BucketWarden::new(RuntimeConfig::development()).expect("runtime");
    for error in catalog {
        let response = runtime
            .s3_service_specific_error_response(error.feature_id)
            .expect("service-specific error response");
        assert_eq!(response.status, error.status, "{}", error.feature_id);
        assert_eq!(
            response.headers.get("x-bucketwarden-error-family"),
            Some(&error.family.to_string()),
            "{}",
            error.feature_id
        );
        assert_error_body(&response.body, error);
        if error.status >= 400 {
            assert!(response.headers.contains_key("x-amz-request-id"));
            assert!(response.headers.contains_key("x-amz-id-2"));
            assert_eq!(
                response.headers.get("x-bucketwarden-error-retryable"),
                Some(&(error.status == 500 || error.status == 503).to_string()),
                "{}",
                error.feature_id
            );
        }
    }

    assert!(runtime
        .s3_service_specific_error_response("feat:bucketwarden.s3err.unknown")
        .is_none());
}

fn assert_error_body(body: &[u8], error: &S3ServiceSpecificError) {
    let body = String::from_utf8(body.to_vec()).expect("xml body");
    assert!(
        body.contains(&format!("<Code>{}</Code>", error.code)),
        "{} body: {body}",
        error.feature_id
    );
    assert!(
        body.contains("<Message>"),
        "{} body: {body}",
        error.feature_id
    );
    if error.status >= 400 {
        assert!(
            body.contains("<RequestId>bwreq"),
            "{} body: {body}",
            error.feature_id
        );
        assert!(
            body.contains("<HostId>"),
            "{} body: {body}",
            error.feature_id
        );
    }
}