From 62a13fd132d257c0997f4cca27d4bf89f11b118f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 28 Sep 2023 21:29:43 -0400 Subject: [PATCH] Fix mbtiles validation, CI, and logging --- Cargo.lock | 1 + justfile | 1 + martin-mbtiles/Cargo.toml | 3 ++- martin-mbtiles/src/bin/main.rs | 33 ++++++++++++++--------- martin-mbtiles/src/mbtiles.rs | 33 +++++++++++------------ tests/expected/auto/catalog_auto.json | 6 +++++ tests/expected/generated_config.yaml | 1 + tests/expected/mbtiles/copy_diff.txt | 1 + tests/expected/mbtiles/validate-bad.txt | 3 +++ tests/expected/mbtiles/validate-fix.txt | 3 +++ tests/expected/mbtiles/validate-fix2.txt | 3 +++ tests/expected/mbtiles/validate-ok.txt | 3 +++ tests/fixtures/files/bad_hash.mbtiles | Bin 0 -> 14848 bytes tests/pg_table_source_test.rs | 2 +- tests/test.sh | 13 +++++++++ 15 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 tests/expected/mbtiles/validate-bad.txt create mode 100644 tests/expected/mbtiles/validate-fix.txt create mode 100644 tests/expected/mbtiles/validate-fix2.txt create mode 100644 tests/expected/mbtiles/validate-ok.txt create mode 100644 tests/fixtures/files/bad_hash.mbtiles diff --git a/Cargo.lock b/Cargo.lock index a09f224f3..0fadd1617 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,6 +1799,7 @@ dependencies = [ "actix-rt", "anyhow", "clap", + "env_logger", "futures", "log", "martin-tile-utils", diff --git a/justfile b/justfile index 503a4df79..ba9bfdd6a 100644 --- a/justfile +++ b/justfile @@ -110,6 +110,7 @@ test-int: clean-test install-sqlx # Run integration tests and save its output as the new expected output bless: start clean-test + rm -rf tests/temp cargo test --features bless-tests tests/test.sh rm -rf tests/expected diff --git a/martin-mbtiles/Cargo.toml b/martin-mbtiles/Cargo.toml index 3392c25a9..fd746f043 100644 --- a/martin-mbtiles/Cargo.toml +++ b/martin-mbtiles/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true [features] # TODO: Disable "cli" feature in default builds default = ["cli", "native-tls"] -cli = ["dep:anyhow", "dep:clap", "dep:tokio"] +cli = ["dep:anyhow", "dep:clap", "dep:env_logger", "dep:tokio"] # One of the following two must be used native-tls = ["sqlx/runtime-tokio-native-tls"] rustls = ["sqlx/runtime-tokio-rustls"] @@ -30,6 +30,7 @@ tilejson.workspace = true # Bin dependencies anyhow = { workspace = true, optional = true } clap = { workspace = true, optional = true } +env_logger = { workspace = true, optional = true } serde_yaml.workspace = true sqlite-hashes.workspace = true tokio = { workspace = true, features = ["rt-multi-thread"], optional = true } diff --git a/martin-mbtiles/src/bin/main.rs b/martin-mbtiles/src/bin/main.rs index 5a7b0f542..4df966ce1 100644 --- a/martin-mbtiles/src/bin/main.rs +++ b/martin-mbtiles/src/bin/main.rs @@ -1,11 +1,10 @@ use std::path::{Path, PathBuf}; use clap::{Parser, Subcommand}; +use log::{error, LevelFilter}; use martin_mbtiles::{ apply_mbtiles_diff, IntegrityCheckType, MbtResult, Mbtiles, TileCopierOptions, }; -use sqlx::sqlite::SqliteConnectOptions; -use sqlx::{Connection, SqliteConnection}; #[derive(Parser, PartialEq, Eq, Debug)] #[command( @@ -73,9 +72,23 @@ enum Commands { } #[tokio::main] -async fn main() -> anyhow::Result<()> { - let args = Args::parse(); +async fn main() { + env_logger::builder() + .filter_level(LevelFilter::Info) + .format_indent(None) + .format_module_path(false) + .format_target(false) + .format_timestamp(None) + .init(); + if let Err(err) = main_int().await { + error!("{err}"); + std::process::exit(1); + } +} + +async fn main_int() -> anyhow::Result<()> { + let args = Args::parse(); match args.command { Commands::MetaAll { file } => { meta_print_all(file.as_path()).await?; @@ -109,8 +122,7 @@ async fn main() -> anyhow::Result<()> { async fn meta_print_all(file: &Path) -> anyhow::Result<()> { let mbt = Mbtiles::new(file)?; - let opt = SqliteConnectOptions::new().filename(file).read_only(true); - let mut conn = SqliteConnection::connect_with(&opt).await?; + let mut conn = mbt.open_with_hashes(true).await?; let metadata = mbt.get_metadata(&mut conn).await?; println!("{}", serde_yaml::to_string(&metadata)?); Ok(()) @@ -118,8 +130,7 @@ async fn meta_print_all(file: &Path) -> anyhow::Result<()> { async fn meta_get_value(file: &Path, key: &str) -> MbtResult<()> { let mbt = Mbtiles::new(file)?; - let opt = SqliteConnectOptions::new().filename(file).read_only(true); - let mut conn = SqliteConnection::connect_with(&opt).await?; + let mut conn = mbt.open_with_hashes(true).await?; if let Some(s) = mbt.get_metadata_value(&mut conn, key).await? { println!("{s}"); } @@ -128,8 +139,7 @@ async fn meta_get_value(file: &Path, key: &str) -> MbtResult<()> { async fn meta_set_value(file: &Path, key: &str, value: Option) -> MbtResult<()> { let mbt = Mbtiles::new(file)?; - let opt = SqliteConnectOptions::new().filename(file); - let mut conn = SqliteConnection::connect_with(&opt).await?; + let mut conn = mbt.open_with_hashes(false).await?; mbt.set_metadata_value(&mut conn, key, value).await } @@ -139,8 +149,7 @@ async fn validate_mbtiles( update_agg_tiles_hash: bool, ) -> MbtResult<()> { let mbt = Mbtiles::new(file)?; - let opt = SqliteConnectOptions::new().filename(file).read_only(true); - let mut conn = SqliteConnection::connect_with(&opt).await?; + let mut conn = mbt.open_with_hashes(!update_agg_tiles_hash).await?; mbt.check_integrity(&mut conn, check_type).await?; mbt.check_each_tile_hash(&mut conn).await?; if update_agg_tiles_hash { diff --git a/martin-mbtiles/src/mbtiles.rs b/martin-mbtiles/src/mbtiles.rs index 6a1c37242..574cf0035 100644 --- a/martin-mbtiles/src/mbtiles.rs +++ b/martin-mbtiles/src/mbtiles.rs @@ -435,7 +435,9 @@ impl Mbtiles { where for<'e> &'e mut T: SqliteExecutor<'e>, { + let filepath = self.filepath(); if integrity_check == IntegrityCheckType::Off { + info!("Skipping integrity check for {filepath}"); return Ok(()); } @@ -452,13 +454,14 @@ impl Mbtiles { if result.len() > 1 || result.get(0).ok_or(FailedIntegrityCheck( - self.filepath().to_string(), + filepath.to_string(), vec!["SQLite could not perform integrity check".to_string()], ))? != "ok" { return Err(FailedIntegrityCheck(self.filepath().to_string(), result)); } + info!("{integrity_check:?} integrity check passed for {filepath}"); Ok(()) } @@ -466,16 +469,17 @@ impl Mbtiles { where for<'e> &'e mut T: SqliteExecutor<'e>, { + let filepath = self.filepath(); let Some(stored) = self.get_agg_tiles_hash(&mut *conn).await? else { - return Err(AggHashValueNotFound(self.filepath().to_string())); + return Err(AggHashValueNotFound(filepath.to_string())); }; - let computed = calc_agg_tiles_hash(&mut *conn).await?; if stored != computed { - let file = self.filepath().to_string(); + let file = filepath.to_string(); return Err(AggHashMismatch(computed, stored, file)); } + info!("The agg_tiles_hashes={computed} has been verified for {filepath}"); Ok(()) } @@ -486,23 +490,15 @@ impl Mbtiles { { let old_hash = self.get_agg_tiles_hash(&mut *conn).await?; let hash = calc_agg_tiles_hash(&mut *conn).await?; + let path = self.filepath(); if old_hash.as_ref() == Some(&hash) { - info!( - "agg_tiles_hash is already set to the correct value `{hash}` in {}", - self.filepath() - ); + info!("agg_tiles_hash is already set to the correct value `{hash}` in {path}"); Ok(()) } else { if let Some(old_hash) = old_hash { - info!( - "Updating agg_tiles_hash from {old_hash} to {hash} in {}", - self.filepath() - ); + info!("Updating agg_tiles_hash from {old_hash} to {hash} in {path}"); } else { - info!( - "Initializing agg_tiles_hash to {hash} in {}", - self.filepath() - ); + info!("Creating new metadata value agg_tiles_hash = {hash} in {path}"); } self.set_metadata_value(&mut *conn, "agg_tiles_hash", Some(hash)) .await @@ -550,7 +546,10 @@ impl Mbtiles { v.get(0), v.get(1), )) - }) + })?; + + info!("All tile hashes are valid for {}", self.filepath()); + Ok(()) } } diff --git a/tests/expected/auto/catalog_auto.json b/tests/expected/auto/catalog_auto.json index 1de39eb3b..54051c79d 100644 --- a/tests/expected/auto/catalog_auto.json +++ b/tests/expected/auto/catalog_auto.json @@ -8,6 +8,12 @@ "content_type": "application/x-protobuf", "description": "autodetect.auto_table.geom" }, + "bad_hash": { + "content_type": "application/x-protobuf", + "content_encoding": "gzip", + "name": "Major cities from Natural Earth data", + "description": "Major cities from Natural Earth data" + }, "bigint_table": { "content_type": "application/x-protobuf", "description": "autodetect.bigint_table.geom" diff --git a/tests/expected/generated_config.yaml b/tests/expected/generated_config.yaml index c51f1f02f..930b6b036 100644 --- a/tests/expected/generated_config.yaml +++ b/tests/expected/generated_config.yaml @@ -141,6 +141,7 @@ pmtiles: mbtiles: paths: tests/fixtures/files sources: + bad_hash: tests/fixtures/files/bad_hash.mbtiles geography-class-jpg: tests/fixtures/files/geography-class-jpg.mbtiles geography-class-jpg-diff: tests/fixtures/files/geography-class-jpg-diff.mbtiles geography-class-jpg-modified: tests/fixtures/files/geography-class-jpg-modified.mbtiles diff --git a/tests/expected/mbtiles/copy_diff.txt b/tests/expected/mbtiles/copy_diff.txt index e69de29bb..4fc7c848d 100644 --- a/tests/expected/mbtiles/copy_diff.txt +++ b/tests/expected/mbtiles/copy_diff.txt @@ -0,0 +1 @@ +[INFO ] Creating new metadata value agg_tiles_hash = C7E2E5A9BA04693994DB1F57D1DF5646 in tests/temp/world_cities_diff.mbtiles diff --git a/tests/expected/mbtiles/validate-bad.txt b/tests/expected/mbtiles/validate-bad.txt new file mode 100644 index 000000000..242a6aaaa --- /dev/null +++ b/tests/expected/mbtiles/validate-bad.txt @@ -0,0 +1,3 @@ +[INFO ] Quick integrity check passed for ./tests/fixtures/files/bad_hash.mbtiles +[INFO ] All tile hashes are valid for ./tests/fixtures/files/bad_hash.mbtiles +[ERROR] Computed aggregate tiles hash D4E1030D57751A0B45A28A71267E46B8 does not match tile data in metadata CAFEC0DEDEADBEEFDEADBEEFDEADBEEF for MBTile file ./tests/fixtures/files/bad_hash.mbtiles diff --git a/tests/expected/mbtiles/validate-fix.txt b/tests/expected/mbtiles/validate-fix.txt new file mode 100644 index 000000000..ded275f11 --- /dev/null +++ b/tests/expected/mbtiles/validate-fix.txt @@ -0,0 +1,3 @@ +[INFO ] Quick integrity check passed for tests/temp/fix_bad_hash.mbtiles +[INFO ] All tile hashes are valid for tests/temp/fix_bad_hash.mbtiles +[INFO ] Updating agg_tiles_hash from CAFEC0DEDEADBEEFDEADBEEFDEADBEEF to D4E1030D57751A0B45A28A71267E46B8 in tests/temp/fix_bad_hash.mbtiles diff --git a/tests/expected/mbtiles/validate-fix2.txt b/tests/expected/mbtiles/validate-fix2.txt new file mode 100644 index 000000000..250ba58e6 --- /dev/null +++ b/tests/expected/mbtiles/validate-fix2.txt @@ -0,0 +1,3 @@ +[INFO ] Quick integrity check passed for tests/temp/fix_bad_hash.mbtiles +[INFO ] All tile hashes are valid for tests/temp/fix_bad_hash.mbtiles +[INFO ] The agg_tiles_hashes=D4E1030D57751A0B45A28A71267E46B8 has been verified for tests/temp/fix_bad_hash.mbtiles diff --git a/tests/expected/mbtiles/validate-ok.txt b/tests/expected/mbtiles/validate-ok.txt new file mode 100644 index 000000000..2220bb36d --- /dev/null +++ b/tests/expected/mbtiles/validate-ok.txt @@ -0,0 +1,3 @@ +[INFO ] Quick integrity check passed for ./tests/fixtures/files/zoomed_world_cities.mbtiles +[INFO ] All tile hashes are valid for ./tests/fixtures/files/zoomed_world_cities.mbtiles +[INFO ] The agg_tiles_hashes=D4E1030D57751A0B45A28A71267E46B8 has been verified for ./tests/fixtures/files/zoomed_world_cities.mbtiles diff --git a/tests/fixtures/files/bad_hash.mbtiles b/tests/fixtures/files/bad_hash.mbtiles new file mode 100644 index 0000000000000000000000000000000000000000..33943e69916a1187237dfd4b0dd39d6309b054ab GIT binary patch literal 14848 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 wt@^^r!e9OHOOH%ZDDmQnXH4J^!Hu0jkz>Z~y=R literal 0 HcmV?d00001 diff --git a/tests/pg_table_source_test.rs b/tests/pg_table_source_test.rs index 4207138d4..5bba0b85b 100644 --- a/tests/pg_table_source_test.rs +++ b/tests/pg_table_source_test.rs @@ -113,5 +113,5 @@ async fn table_source_schemas() { functions: false "}); let sources = mock_sources(cfg).await.0; - assert_eq!(sources.keys().collect::>(), vec!["MixPoints"],); + assert_eq!(sources.keys().collect::>(), vec!["MixPoints"]); } diff --git a/tests/test.sh b/tests/test.sh index 846e1a3de..6d9fdde17 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -293,6 +293,19 @@ if [[ "$MBTILES_BIN" != "-" ]]; then $MBTILES_BIN meta-get --help 2>&1 | tee "$TEST_OUT_DIR/meta-get_help.txt" $MBTILES_BIN meta-get ./tests/fixtures/files/world_cities.mbtiles name 2>&1 | tee "$TEST_OUT_DIR/meta-get_name.txt" $MBTILES_BIN meta-get ./tests/fixtures/files/world_cities.mbtiles missing_value 2>&1 | tee "$TEST_OUT_DIR/meta-get_missing_value.txt" + $MBTILES_BIN validate ./tests/fixtures/files/zoomed_world_cities.mbtiles 2>&1 | tee "$TEST_OUT_DIR/validate-ok.txt" + + set +e + $MBTILES_BIN validate ./tests/fixtures/files/bad_hash.mbtiles 2>&1 | tee "$TEST_OUT_DIR/validate-bad.txt" + if [[ $? -eq 0 ]]; then + echo "ERROR: validate with bad_hash should have failed" + exit 1 + fi + set -e + + cp ./tests/fixtures/files/bad_hash.mbtiles "$TEST_TEMP_DIR/fix_bad_hash.mbtiles" + $MBTILES_BIN validate --update-agg-tiles-hash "$TEST_TEMP_DIR/fix_bad_hash.mbtiles" 2>&1 | tee "$TEST_OUT_DIR/validate-fix.txt" + $MBTILES_BIN validate "$TEST_TEMP_DIR/fix_bad_hash.mbtiles" 2>&1 | tee "$TEST_OUT_DIR/validate-fix2.txt" # Create diff file $MBTILES_BIN copy \