martin 1.11.0

Blazing fast and lightweight tile server with PostGIS, MBTiles, and PMTiles support
Documentation
#![cfg(feature = "pmtiles")]

use actix_web::http::header::{ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_TYPE};
use actix_web::test::{TestRequest, call_service, read_body, read_body_json};
use indoc::indoc;
#[cfg(all(feature = "rendering", target_os = "linux"))]
use insta::assert_yaml_snapshot;
use martin::config::file::srv::SrvConfig;
use martin_tile_utils::decode_gzip;
use tilejson::TileJSON;

pub mod utils;
pub use utils::*;

macro_rules! create_app {
    ($sources:expr) => {{
        let state = mock_sources(mock_cfg($sources)).await.0;
        ::actix_web::test::init_service(
            ::actix_web::App::new()
                .app_data(actix_web::web::Data::new(
                    ::martin::srv::Catalog::new(
                        #[cfg(any(feature = "sprites", feature = "fonts", feature = "styles"))]
                        &state,
                    )
                    .unwrap(),
                ))
                .app_data(actix_web::web::Data::new(state.tile_manager))
                .app_data(actix_web::web::Data::new(SrvConfig::default()))
                .configure(|c| ::martin::srv::router(c, &SrvConfig::default())),
        )
        .await
    }};
}

fn test_get(path: &str) -> TestRequest {
    TestRequest::get().uri(path)
}

const CONFIG: &str = indoc! {"
        pmtiles:
            aws_region: eu-central-1
            skip_signature: true
            sources:
                p_png: ../tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles
                s3: s3://pmtilestest/cb_2018_us_zcta510_500k.pmtiles
    "};

#[cfg(all(feature = "rendering", target_os = "linux"))]
#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_catalog_with_rendering_feature() {
    let path = "pmtiles: ../tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles";
    let app = create_app! { path };

    let req = test_get("/catalog").to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let body: serde_json::Value = read_body_json(response).await;
    assert_yaml_snapshot!(body, @"
    fonts: {}
    settings:
      rendering: false
    sprites: {}
    styles: {}
    tiles:
      stamen_toner__raster_CC-BY-ODbL_z3:
        content_type: image/png
    ");
}

#[cfg(all(feature = "rendering", target_os = "linux"))]
#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_catalog_gzip_with_rendering_feature() {
    let app = create_app! { CONFIG };
    let accept = (ACCEPT_ENCODING, "gzip");
    let req = test_get("/catalog").insert_header(accept).to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let body = decode_gzip(&read_body(response).await).unwrap();
    let body: serde_json::Value = serde_json::from_slice(&body).unwrap();
    assert_yaml_snapshot!(body, @"
    fonts: {}
    settings:
      rendering: false
    sprites: {}
    styles: {}
    tiles:
      p_png:
        content_type: image/png
      s3:
        content_encoding: gzip
        content_type: application/x-protobuf
        description: cb_2018_us_zcta510_500k.mbtiles
        name: cb_2018_us_zcta510_500k.mbtiles
    ");
}

#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_tilejson() {
    let app = create_app! { CONFIG };
    let req = test_get("/p_png").to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let headers = response.headers();
    assert_eq!(headers.get(CONTENT_TYPE).unwrap(), "application/json");
    assert!(headers.get(CONTENT_ENCODING).is_none());
    let body: TileJSON = read_body_json(response).await;
    assert_eq!(body.maxzoom, Some(3));
}

#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_tilejson_gzip() {
    let app = create_app! { CONFIG };
    let accept = (ACCEPT_ENCODING, "gzip");
    let req = test_get("/p_png").insert_header(accept).to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let headers = response.headers();
    assert_eq!(headers.get(CONTENT_TYPE).unwrap(), "application/json");
    assert_eq!(headers.get(CONTENT_ENCODING).unwrap(), "gzip");
    let body = decode_gzip(&read_body(response).await).unwrap();
    let body: TileJSON = serde_json::from_slice(body.as_slice()).unwrap();
    assert_eq!(body.maxzoom, Some(3));
}

#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_raster() {
    let app = create_app! { CONFIG };
    let req = test_get("/p_png/0/0/0").to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    assert_eq!(response.headers().get(CONTENT_TYPE).unwrap(), "image/png");
    assert!(response.headers().get(CONTENT_ENCODING).is_none());
    let body = read_body(response).await;
    assert_eq!(body.len(), 18404);
}

/// get a raster tile with accepted gzip enc, but should still be non-gzipped
#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_raster_gzip() {
    let app = create_app! { CONFIG };
    let accept = (ACCEPT_ENCODING, "gzip");
    let req = test_get("/p_png/0/0/0").insert_header(accept).to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    assert_eq!(response.headers().get(CONTENT_TYPE).unwrap(), "image/png");
    assert!(response.headers().get(CONTENT_ENCODING).is_none());
    let body = read_body(response).await;
    assert_eq!(body.len(), 18404);
}

#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_tilejson_s3() {
    let app = create_app! { CONFIG };
    let req = test_get("/s3").to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let headers = response.headers();
    assert_eq!(headers.get(CONTENT_TYPE).unwrap(), "application/json");
    assert!(headers.get(CONTENT_ENCODING).is_none());
    let body: TileJSON = read_body_json(response).await;
    assert_eq!(body.name, Some("cb_2018_us_zcta510_500k.mbtiles".into()));
    assert_eq!(body.maxzoom, Some(7));
}

#[actix_rt::test]
#[tracing_test::traced_test]
async fn pmt_get_tile_s3() {
    let app = create_app! { CONFIG };
    let req = test_get("/s3/0/0/0").to_request();
    let response = call_service(&app, req).await;
    let response = assert_response(response).await;
    let headers = response.headers();
    assert_eq!(headers.get(CONTENT_TYPE).unwrap(), "application/x-protobuf");
}