mirror of
https://github.com/maplibre/martin.git
synced 2024-12-19 12:51:37 +03:00
Fix martin integration tests (#952)
Turns out some integration tests were not running after `martin` was moved to subdir
This commit is contained in:
parent
3ef969bc1a
commit
502413aecb
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1710,6 +1710,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"futures",
|
||||
"indoc",
|
||||
"insta",
|
||||
"itertools 0.11.0",
|
||||
"json-patch",
|
||||
"log",
|
||||
|
@ -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"
|
||||
|
9
justfile
9
justfile
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]]
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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]
|
@ -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
|
||||
"###);
|
||||
}
|
@ -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;
|
185
martin/tests/pg_table_source_test.rs
Normal file
185
martin/tests/pg_table_source_test.rs
Normal 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
|
||||
"###);
|
||||
}
|
@ -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]
|
@ -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") {
|
@ -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()
|
||||
}
|
@ -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"]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user