Fix martin integration tests (#952)

Turns out some integration tests were not running after `martin` was
moved to subdir
This commit is contained in:
Yuri Astrakhan 2023-10-19 23:40:08 -04:00 committed by GitHub
parent 3ef969bc1a
commit 502413aecb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 455 additions and 233 deletions

1
Cargo.lock generated
View File

@ -1710,6 +1710,7 @@ dependencies = [
"flate2",
"futures",
"indoc",
"insta",
"itertools 0.11.0",
"json-patch",
"log",

View File

@ -28,7 +28,7 @@ env_logger = "0.10"
flate2 = "1"
futures = "0.3"
indoc = "2"
insta = { version = "1", features = ["toml"] }
insta = "1"
itertools = "0.11"
json-patch = "1.2"
log = "0.4"

View File

@ -2,6 +2,7 @@
set shell := ["bash", "-c"]
#export DATABASE_URL="postgres://postgres:postgres@localhost:5411/db"
export PGPORT := "5411"
export DATABASE_URL := "postgres://postgres:postgres@localhost:" + PGPORT + "/db"
export CARGO_TERM_COLOR := "always"
@ -138,7 +139,7 @@ test-int: clean-test install-sqlx
fi
# Run integration tests and save its output as the new expected output
bless: restart clean-test bless-insta
bless: restart clean-test bless-insta-martin bless-insta-mbtiles
rm -rf tests/temp
cargo test -p martin --features bless-tests
tests/test.sh
@ -146,10 +147,14 @@ bless: restart clean-test bless-insta
mv tests/output tests/expected
# Run integration tests and save its output as the new expected output
bless-insta *ARGS: (cargo-install "insta" "cargo-insta")
bless-insta-mbtiles *ARGS: (cargo-install "insta" "cargo-insta")
#rm -rf martin-mbtiles/tests/snapshots
cargo insta test --accept --unreferenced=auto -p martin-mbtiles {{ ARGS }}
# Run integration tests and save its output as the new expected output
bless-insta-martin *ARGS: (cargo-install "insta" "cargo-insta")
cargo insta test --accept --unreferenced=auto -p martin {{ ARGS }}
# Build and open mdbook documentation
book: (cargo-install "mdbook")
mdbook serve docs --open --port 8321

View File

@ -37,7 +37,7 @@ tokio = { workspace = true, features = ["rt-multi-thread"], optional = true }
actix-rt.workspace = true
ctor.workspace = true
env_logger.workspace = true
insta.workspace = true
insta = { workspace = true, features = ["toml"] }
pretty_assertions.workspace = true
rstest.workspace = true

View File

@ -92,6 +92,7 @@ cargo-husky.workspace = true
criterion.workspace = true
ctor.workspace = true
indoc.workspace = true
insta = { workspace = true, features = ["yaml"] }
#test-log = "0.2"
[[bench]]

View File

@ -2,6 +2,6 @@ mod config;
mod server;
pub use config::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT};
pub use server::{new_server, router, RESERVED_KEYWORDS};
pub use server::{new_server, router, Catalog, RESERVED_KEYWORDS};
pub use crate::source::CatalogSourceEntry;

View File

@ -29,7 +29,7 @@ use crate::sprites::{SpriteCatalog, SpriteError, SpriteSources};
use crate::srv::config::{SrvConfig, KEEP_ALIVE_DEFAULT, LISTEN_ADDRESSES_DEFAULT};
use crate::utils::{decode_brotli, decode_gzip, encode_brotli, encode_gzip};
use crate::Error::BindingError;
use crate::Xyz;
use crate::{Error, Xyz};
/// List of keywords that cannot be used as source IDs. Some of these are reserved for future use.
/// Reserved keywords must never end in a "dot number" (e.g. ".1").
@ -51,6 +51,15 @@ pub struct Catalog {
pub sprites: SpriteCatalog,
}
impl Catalog {
pub fn new(state: &ServerState) -> Result<Self, Error> {
Ok(Self {
tiles: state.tiles.get_catalog(),
sprites: state.sprites.get_catalog()?,
})
}
}
#[derive(Deserialize)]
struct TileJsonRequest {
source_ids: String,
@ -421,26 +430,22 @@ pub fn router(cfg: &mut web::ServiceConfig) {
}
/// Create a new initialized Actix `App` instance together with the listening address.
pub fn new_server(config: SrvConfig, all_sources: ServerState) -> crate::Result<(Server, String)> {
pub fn new_server(config: SrvConfig, state: ServerState) -> crate::Result<(Server, String)> {
let catalog = Catalog::new(&state)?;
let keep_alive = Duration::from_secs(config.keep_alive.unwrap_or(KEEP_ALIVE_DEFAULT));
let worker_processes = config.worker_processes.unwrap_or_else(num_cpus::get);
let listen_addresses = config
.listen_addresses
.unwrap_or_else(|| LISTEN_ADDRESSES_DEFAULT.to_owned());
let catalog = Catalog {
tiles: all_sources.tiles.get_catalog(),
sprites: all_sources.sprites.get_catalog()?,
};
let server = HttpServer::new(move || {
let cors_middleware = Cors::default()
.allow_any_origin()
.allowed_methods(vec!["GET"]);
App::new()
.app_data(Data::new(all_sources.tiles.clone()))
.app_data(Data::new(all_sources.sprites.clone()))
.app_data(Data::new(state.tiles.clone()))
.app_data(Data::new(state.sprites.clone()))
.app_data(Data::new(catalog.clone()))
.wrap(cors_middleware)
.wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly))

View File

@ -2,8 +2,8 @@ use actix_web::http::header::{ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_TYPE};
use actix_web::test::{call_service, read_body, read_body_json, TestRequest};
use ctor::ctor;
use indoc::indoc;
use insta::assert_yaml_snapshot;
use martin::decode_gzip;
use martin::srv::IndexEntry;
use tilejson::TileJSON;
pub mod utils;
@ -16,11 +16,13 @@ fn init() {
macro_rules! create_app {
($sources:expr) => {{
let sources = mock_sources(mock_cfg($sources)).await.0;
let state = crate::utils::mock_app_data(sources).await;
let state = mock_sources(mock_cfg($sources)).await.0;
::actix_web::test::init_service(
::actix_web::App::new()
.app_data(state)
.app_data(actix_web::web::Data::new(
::martin::srv::Catalog::new(&state).unwrap(),
))
.app_data(actix_web::web::Data::new(state.tiles))
.configure(::martin::srv::router),
)
.await
@ -34,10 +36,10 @@ fn test_get(path: &str) -> TestRequest {
const CONFIG: &str = indoc! {"
mbtiles:
sources:
m_json: tests/fixtures/mbtiles/json.mbtiles
m_mvt: tests/fixtures/mbtiles/world_cities.mbtiles
m_raw_mvt: tests/fixtures/mbtiles/uncompressed_mvt.mbtiles
m_webp: tests/fixtures/mbtiles/webp.mbtiles
m_json: ../tests/fixtures/mbtiles/json.mbtiles
m_mvt: ../tests/fixtures/mbtiles/world_cities.mbtiles
m_raw_mvt: ../tests/fixtures/mbtiles/uncompressed_mvt.mbtiles
m_webp: ../tests/fixtures/mbtiles/webp.mbtiles
"};
#[actix_rt::test]
@ -47,11 +49,27 @@ async fn mbt_get_catalog() {
let req = test_get("/catalog").to_request();
let response = call_service(&app, req).await;
assert!(response.status().is_success());
let body = read_body(response).await;
let sources: Vec<IndexEntry> = serde_json::from_slice(&body).unwrap();
assert_eq!(sources.iter().filter(|v| v.id == "m_mvt").count(), 1);
assert_eq!(sources.iter().filter(|v| v.id == "m_webp").count(), 1);
assert_eq!(sources.iter().filter(|v| v.id == "m_raw_mvt").count(), 1);
let body: serde_json::Value = read_body_json(response).await;
assert_yaml_snapshot!(body, @r###"
---
tiles:
m_json:
content_type: application/json
name: Dummy json data
m_mvt:
content_type: application/x-protobuf
content_encoding: gzip
name: Major cities from Natural Earth data
description: Major cities from Natural Earth data
m_raw_mvt:
content_type: application/x-protobuf
name: Major cities from Natural Earth data
description: Major cities from Natural Earth data
m_webp:
content_type: image/webp
name: ne2sr
sprites: {}
"###);
}
#[actix_rt::test]
@ -62,10 +80,27 @@ async fn mbt_get_catalog_gzip() {
let response = call_service(&app, req).await;
assert!(response.status().is_success());
let body = decode_gzip(&read_body(response).await).unwrap();
let sources: Vec<IndexEntry> = serde_json::from_slice(&body).unwrap();
assert_eq!(sources.iter().filter(|v| v.id == "m_mvt").count(), 1);
assert_eq!(sources.iter().filter(|v| v.id == "m_webp").count(), 1);
assert_eq!(sources.iter().filter(|v| v.id == "m_raw_mvt").count(), 1);
let body: serde_json::Value = serde_json::from_slice(&body).unwrap();
assert_yaml_snapshot!(body, @r###"
---
tiles:
m_json:
content_type: application/json
name: Dummy json data
m_mvt:
content_type: application/x-protobuf
content_encoding: gzip
name: Major cities from Natural Earth data
description: Major cities from Natural Earth data
m_raw_mvt:
content_type: application/x-protobuf
name: Major cities from Natural Earth data
description: Major cities from Natural Earth data
m_webp:
content_type: image/webp
name: ne2sr
sprites: {}
"###);
}
#[actix_rt::test]

View File

@ -1,6 +1,6 @@
use ctor::ctor;
use indoc::indoc;
use itertools::Itertools;
use insta::assert_yaml_snapshot;
use martin::Xyz;
pub mod utils;
@ -14,18 +14,15 @@ fn init() {
#[actix_rt::test]
async fn function_source_tilejson() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
assert_eq!(
source(&mock, "function_zxy_query").get_tilejson(),
serde_json::from_str(indoc! {r#"
{
"name": "function_zxy_query",
"description": "public.function_zxy_query",
"tilejson": "3.0.0",
"tiles": []
}
"#})
.unwrap()
);
let tj = source(&mock, "function_zxy_query").get_tilejson();
assert_yaml_snapshot!(tj, @r###"
---
tilejson: 3.0.0
tiles: []
name: function_zxy_query
foo:
bar: foo
"###);
}
#[actix_rt::test]
@ -55,9 +52,11 @@ async fn function_source_schemas() {
functions:
from_schemas: MixedCase
"});
let sources = mock_sources(cfg).await.0;
assert_eq!(
sources.keys().sorted().collect::<Vec<_>>(),
vec!["function_Mixed_Name"],
);
let sources = mock_sources(cfg).await.0.tiles;
assert_yaml_snapshot!(sources.get_catalog(), @r###"
---
function_Mixed_Name:
content_type: application/x-protobuf
description: a function source with MixedCase name
"###);
}

View File

@ -3,7 +3,7 @@ use actix_web::http::StatusCode;
use actix_web::test::{call_and_read_body_json, call_service, read_body, TestRequest};
use ctor::ctor;
use indoc::indoc;
use martin::srv::IndexEntry;
use insta::assert_yaml_snapshot;
use martin::OneOrMany;
use tilejson::TileJSON;
@ -18,11 +18,13 @@ fn init() {
macro_rules! create_app {
($sources:expr) => {{
let cfg = mock_cfg(indoc::indoc!($sources));
let sources = mock_sources(cfg).await.0;
let state = crate::utils::mock_app_data(sources).await;
let state = mock_sources(cfg).await.0;
::actix_web::test::init_service(
::actix_web::App::new()
.app_data(state)
.app_data(actix_web::web::Data::new(
::martin::srv::Catalog::new(&state).unwrap(),
))
.app_data(actix_web::web::Data::new(state.tiles))
.configure(::martin::srv::router),
)
.await
@ -44,16 +46,76 @@ postgres:
let response = call_service(&app, req).await;
assert!(response.status().is_success());
let body = read_body(response).await;
let sources: Vec<IndexEntry> = serde_json::from_slice(&body).unwrap();
let expected = "table_source";
assert_eq!(sources.iter().filter(|v| v.id == expected).count(), 1);
let expected = "function_zxy_query";
assert_eq!(sources.iter().filter(|v| v.id == expected).count(), 1);
let expected = "function_zxy_query_jsonb";
assert_eq!(sources.iter().filter(|v| v.id == expected).count(), 1);
let body: serde_json::Value = serde_json::from_slice(&body).unwrap();
assert_yaml_snapshot!(body, @r###"
---
tiles:
MixPoints:
content_type: application/x-protobuf
description: a description from comment on table
auto_table:
content_type: application/x-protobuf
description: autodetect.auto_table.geom
bigint_table:
content_type: application/x-protobuf
description: autodetect.bigint_table.geom
function_Mixed_Name:
content_type: application/x-protobuf
description: a function source with MixedCase name
function_null:
content_type: application/x-protobuf
description: public.function_null
function_null_row:
content_type: application/x-protobuf
description: public.function_null_row
function_null_row2:
content_type: application/x-protobuf
description: public.function_null_row2
function_zoom_xy:
content_type: application/x-protobuf
description: public.function_zoom_xy
function_zxy:
content_type: application/x-protobuf
description: public.function_zxy
function_zxy2:
content_type: application/x-protobuf
description: public.function_zxy2
function_zxy_query:
content_type: application/x-protobuf
function_zxy_query_jsonb:
content_type: application/x-protobuf
description: public.function_zxy_query_jsonb
function_zxy_query_test:
content_type: application/x-protobuf
description: public.function_zxy_query_test
function_zxy_row:
content_type: application/x-protobuf
description: public.function_zxy_row
function_zxy_row_key:
content_type: application/x-protobuf
description: public.function_zxy_row_key
points1:
content_type: application/x-protobuf
description: public.points1.geom
points1_vw:
content_type: application/x-protobuf
description: public.points1_vw.geom
points2:
content_type: application/x-protobuf
description: public.points2.geom
points3857:
content_type: application/x-protobuf
description: public.points3857.geom
table_source:
content_type: application/x-protobuf
table_source_multiple_geom:
content_type: application/x-protobuf
description: public.table_source_multiple_geom.geom1
table_source_multiple_geom.1:
content_type: application/x-protobuf
description: public.table_source_multiple_geom.geom2
sprites: {}
"###);
}
#[actix_rt::test]
@ -947,44 +1009,85 @@ tables:
let src = table(&mock, "no_id");
assert_eq!(src.id_column, None);
assert!(matches!(&src.properties, Some(v) if v.len() == 1));
assert_eq!(
source(&mock, "no_id").get_tilejson(),
serde_json::from_str(indoc! {r#"
{
"name": "no_id",
"description": "MixedCase.MixPoints.Geom",
"tilejson": "3.0.0",
"tiles": [],
"vector_layers": [
{
"id": "no_id",
"fields": {"TABLE": "text"}
}
],
"bounds": [-180.0, -90.0, 180.0, 90.0]
}
"#})
.unwrap()
);
let tj = source(&mock, "no_id").get_tilejson();
assert_yaml_snapshot!(tj, @r###"
---
tilejson: 3.0.0
tiles: []
vector_layers:
- id: no_id
fields:
TABLE: text
bounds:
- -180
- -90
- 180
- 90
description: MixedCase.MixPoints.Geom
name: no_id
"###);
let src = table(&mock, "id_only");
assert_eq!(src.id_column, some("giD"));
assert!(matches!(&src.properties, Some(v) if v.len() == 1));
assert_yaml_snapshot!(table(&mock, "id_only"), @r###"
---
schema: MixedCase
table: MixPoints
srid: 4326
geometry_column: Geom
id_column: giD
bounds:
- -180
- -90
- 180
- 90
geometry_type: POINT
properties:
TABLE: text
"###);
let src = table(&mock, "id_and_prop");
assert_eq!(src.id_column, some("giD"));
assert!(matches!(&src.properties, Some(v) if v.len() == 2));
assert_yaml_snapshot!(table(&mock, "id_and_prop"), @r###"
---
schema: MixedCase
table: MixPoints
srid: 4326
geometry_column: Geom
id_column: giD
bounds:
- -180
- -90
- 180
- 90
geometry_type: POINT
properties:
TABLE: text
giD: int4
"###);
let src = table(&mock, "prop_only");
assert_eq!(src.id_column, None);
assert!(matches!(&src.properties, Some(v) if v.len() == 2));
assert_yaml_snapshot!(table(&mock, "prop_only"), @r###"
---
schema: MixedCase
table: MixPoints
srid: 4326
geometry_column: Geom
bounds:
- -180
- -90
- 180
- 90
geometry_type: POINT
properties:
TABLE: text
giD: int4
"###);
// --------------------------------------------
let state = mock_app_data(mock.0).await;
let state = mock_sources(cfg.clone()).await.0;
let app = ::actix_web::test::init_service(
::actix_web::App::new()
.app_data(state)
.app_data(actix_web::web::Data::new(
::martin::srv::Catalog::new(&state).unwrap(),
))
.app_data(actix_web::web::Data::new(state.tiles))
.configure(::martin::srv::router),
)
.await;

View File

@ -0,0 +1,185 @@
use ctor::ctor;
use indoc::indoc;
use insta::assert_yaml_snapshot;
use martin::Xyz;
pub mod utils;
pub use utils::*;
#[ctor]
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[actix_rt::test]
async fn table_source() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
assert_yaml_snapshot!(mock.0.tiles.get_catalog(), @r###"
---
MixPoints:
content_type: application/x-protobuf
description: a description from comment on table
auto_table:
content_type: application/x-protobuf
description: autodetect.auto_table.geom
bigint_table:
content_type: application/x-protobuf
description: autodetect.bigint_table.geom
function_Mixed_Name:
content_type: application/x-protobuf
description: a function source with MixedCase name
function_null:
content_type: application/x-protobuf
description: public.function_null
function_null_row:
content_type: application/x-protobuf
description: public.function_null_row
function_null_row2:
content_type: application/x-protobuf
description: public.function_null_row2
function_zoom_xy:
content_type: application/x-protobuf
description: public.function_zoom_xy
function_zxy:
content_type: application/x-protobuf
description: public.function_zxy
function_zxy2:
content_type: application/x-protobuf
description: public.function_zxy2
function_zxy_query:
content_type: application/x-protobuf
function_zxy_query_jsonb:
content_type: application/x-protobuf
description: public.function_zxy_query_jsonb
function_zxy_query_test:
content_type: application/x-protobuf
description: public.function_zxy_query_test
function_zxy_row:
content_type: application/x-protobuf
description: public.function_zxy_row
function_zxy_row_key:
content_type: application/x-protobuf
description: public.function_zxy_row_key
points1:
content_type: application/x-protobuf
description: public.points1.geom
points1_vw:
content_type: application/x-protobuf
description: public.points1_vw.geom
points2:
content_type: application/x-protobuf
description: public.points2.geom
points3857:
content_type: application/x-protobuf
description: public.points3857.geom
table_source:
content_type: application/x-protobuf
table_source_multiple_geom:
content_type: application/x-protobuf
description: public.table_source_multiple_geom.geom1
table_source_multiple_geom.1:
content_type: application/x-protobuf
description: public.table_source_multiple_geom.geom2
"###);
let source = table(&mock, "table_source");
assert_yaml_snapshot!(source, @r###"
---
schema: public
table: table_source
srid: 4326
geometry_column: geom
bounds:
- -2
- -1
- 142.84131509869133
- 45
geometry_type: GEOMETRY
properties:
gid: int4
"###);
}
#[actix_rt::test]
async fn tables_tilejson() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
let tj = source(&mock, "table_source").get_tilejson();
assert_yaml_snapshot!(tj, @r###"
---
tilejson: 3.0.0
tiles: []
vector_layers:
- id: table_source
fields:
gid: int4
bounds:
- -2
- -1
- 142.84131509869133
- 45
name: table_source
foo:
bar: foo
"###);
}
#[actix_rt::test]
async fn tables_tile_ok() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
let tile = source(&mock, "table_source")
.get_tile(&Xyz { z: 0, x: 0, y: 0 }, &None)
.await
.unwrap();
assert!(!tile.is_empty());
}
#[actix_rt::test]
async fn tables_srid_ok() {
let mock = mock_sources(mock_pgcfg(indoc! {"
connection_string: $DATABASE_URL
default_srid: 900913
"}))
.await;
let source = table(&mock, "points1");
assert_eq!(source.srid, 4326);
let source = table(&mock, "points2");
assert_eq!(source.srid, 4326);
let source = table(&mock, "points3857");
assert_eq!(source.srid, 3857);
let source = table(&mock, "points_empty_srid");
assert_eq!(source.srid, 900_913);
}
#[actix_rt::test]
async fn tables_multiple_geom_ok() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
let source = table(&mock, "table_source_multiple_geom");
assert_eq!(source.geometry_column, "geom1");
let source = table(&mock, "table_source_multiple_geom.1");
assert_eq!(source.geometry_column, "geom2");
}
#[actix_rt::test]
async fn table_source_schemas() {
let cfg = mock_pgcfg(indoc! {"
connection_string: $DATABASE_URL
auto_publish:
tables:
from_schemas: MixedCase
functions: false
"});
let sources = mock_sources(cfg).await.0;
assert_yaml_snapshot!(sources.tiles.get_catalog(), @r###"
---
MixPoints:
content_type: application/x-protobuf
description: a description from comment on table
"###);
}

View File

@ -2,8 +2,8 @@ use actix_web::http::header::{ACCEPT_ENCODING, CONTENT_ENCODING, CONTENT_TYPE};
use actix_web::test::{call_service, read_body, read_body_json, TestRequest};
use ctor::ctor;
use indoc::indoc;
use insta::assert_yaml_snapshot;
use martin::decode_gzip;
use martin::srv::IndexEntry;
use tilejson::TileJSON;
pub mod utils;
@ -16,11 +16,13 @@ fn init() {
macro_rules! create_app {
($sources:expr) => {{
let sources = mock_sources(mock_cfg($sources)).await.0;
let state = crate::utils::mock_app_data(sources).await;
let state = mock_sources(mock_cfg($sources)).await.0;
::actix_web::test::init_service(
::actix_web::App::new()
.app_data(state)
.app_data(actix_web::web::Data::new(
::martin::srv::Catalog::new(&state).unwrap(),
))
.app_data(actix_web::web::Data::new(state.tiles))
.configure(::martin::srv::router),
)
.await
@ -34,22 +36,25 @@ fn test_get(path: &str) -> TestRequest {
const CONFIG: &str = indoc! {"
pmtiles:
sources:
p_png: tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles
p_png: ../tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles
"};
#[actix_rt::test]
async fn pmt_get_catalog() {
let path = "pmtiles: tests/fixtures/pmtiles/stamen_toner__raster_CC-BY+ODbL_z3.pmtiles";
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;
assert!(response.status().is_success());
let body = read_body(response).await;
let sources: Vec<IndexEntry> = serde_json::from_slice(&body).unwrap();
let expected = "stamen_toner__raster_CC-BY-ODbL_z3";
assert_eq!(sources.iter().filter(|v| v.id == expected).count(), 1);
let body: serde_json::Value = read_body_json(response).await;
assert_yaml_snapshot!(body, @r###"
---
tiles:
stamen_toner__raster_CC-BY-ODbL_z3:
content_type: image/png
sprites: {}
"###);
}
#[actix_rt::test]
@ -60,8 +65,14 @@ async fn pmt_get_catalog_gzip() {
let response = call_service(&app, req).await;
assert!(response.status().is_success());
let body = decode_gzip(&read_body(response).await).unwrap();
let sources: Vec<IndexEntry> = serde_json::from_slice(&body).unwrap();
assert_eq!(sources.iter().filter(|v| v.id == "p_png").count(), 1);
let body: serde_json::Value = serde_json::from_slice(&body).unwrap();
assert_yaml_snapshot!(body, @r###"
---
tiles:
p_png:
content_type: image/png
sprites: {}
"###);
}
#[actix_rt::test]

View File

@ -4,10 +4,8 @@
mod pg_utils;
use actix_web::web::Data;
use log::warn;
use martin::srv::AppState;
use martin::{Config, Sources};
use martin::Config;
pub use pg_utils::*;
#[path = "../../src/utils/test_utils.rs"]
@ -15,10 +13,6 @@ mod test_utils;
#[allow(clippy::wildcard_imports)]
pub use test_utils::*;
pub async fn mock_app_data(sources: Sources) -> Data<Sources> {
Data::new(sources)
}
#[must_use]
pub fn mock_cfg(yaml: &str) -> Config {
let env = if let Ok(db_url) = std::env::var("DATABASE_URL") {

View File

@ -1,7 +1,7 @@
use indoc::formatdoc;
pub use martin::args::Env;
use martin::pg::TableInfo;
use martin::{Config, IdResolver, Source, Sources};
use martin::{Config, IdResolver, ServerState, Source};
use crate::mock_cfg;
@ -10,7 +10,7 @@ use crate::mock_cfg;
// Each function should allow dead_code as they might not be used by a specific test file.
//
pub type MockSource = (Sources, Config);
pub type MockSource = (ServerState, Config);
#[allow(dead_code)]
#[must_use]
@ -48,5 +48,5 @@ pub fn table<'a>(mock: &'a MockSource, name: &str) -> &'a TableInfo {
#[must_use]
pub fn source<'a>(mock: &'a MockSource, name: &str) -> &'a dyn Source {
let (sources, _) = mock;
sources.get(name).unwrap().as_ref()
sources.tiles.get_source(name).unwrap()
}

View File

@ -1,117 +0,0 @@
use std::collections::HashMap;
use ctor::ctor;
use indoc::indoc;
use martin::Xyz;
pub mod utils;
pub use utils::*;
#[ctor]
fn init() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[actix_rt::test]
async fn table_source() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
assert!(!mock.0.is_empty());
let source = table(&mock, "table_source");
assert_eq!(source.schema, "public");
assert_eq!(source.table, "table_source");
assert_eq!(source.srid, 4326);
assert_eq!(source.geometry_column, "geom");
assert_eq!(source.id_column, None);
assert_eq!(source.minzoom, None);
assert_eq!(source.maxzoom, None);
assert!(source.bounds.is_some());
assert_eq!(source.extent, Some(4096));
assert_eq!(source.buffer, Some(64));
assert_eq!(source.clip_geom, Some(true));
assert_eq!(source.geometry_type, some("GEOMETRY"));
let mut properties = HashMap::new();
properties.insert("gid".to_owned(), "int4".to_owned());
assert_eq!(source.properties, Some(properties));
}
#[actix_rt::test]
async fn tables_tilejson() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
assert_eq!(
source(&mock, "table_source").get_tilejson(),
serde_json::from_str(indoc! {r#"
{
"name": "table_source",
"description": "public.table_source.geom",
"tilejson": "3.0.0",
"tiles": [],
"vector_layers": [
{
"id": "table_source",
"fields": {"gid": "int4"}
}
],
"bounds": [-2.0, -1.0, 142.84131509869133, 45.0]
}
"#})
.unwrap()
);
}
#[actix_rt::test]
async fn tables_tile_ok() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
let tile = source(&mock, "table_source")
.get_tile(&Xyz { z: 0, x: 0, y: 0 }, &None)
.await
.unwrap();
assert!(!tile.is_empty());
}
#[actix_rt::test]
async fn tables_srid_ok() {
let mock = mock_sources(mock_pgcfg(indoc! {"
connection_string: $DATABASE_URL
default_srid: 900913
"}))
.await;
let source = table(&mock, "points1");
assert_eq!(source.srid, 4326);
let source = table(&mock, "points2");
assert_eq!(source.srid, 4326);
let source = table(&mock, "points3857");
assert_eq!(source.srid, 3857);
let source = table(&mock, "points_empty_srid");
assert_eq!(source.srid, 900_913);
}
#[actix_rt::test]
async fn tables_multiple_geom_ok() {
let mock = mock_sources(mock_pgcfg("connection_string: $DATABASE_URL")).await;
let source = table(&mock, "table_source_multiple_geom");
assert_eq!(source.geometry_column, "geom1");
let source = table(&mock, "table_source_multiple_geom.1");
assert_eq!(source.geometry_column, "geom2");
}
#[actix_rt::test]
async fn table_source_schemas() {
let cfg = mock_pgcfg(indoc! {"
connection_string: $DATABASE_URL
auto_publish:
tables:
from_schemas: MixedCase
functions: false
"});
let sources = mock_sources(cfg).await.0;
assert_eq!(sources.keys().collect::<Vec<_>>(), vec!["MixPoints"]);
}