#![expect(
clippy::unwrap_used,
reason = "clippy's allow-*-in-tests covers #[test] fns but not the free helper fns in an integration-test crate; the unwraps in these helpers are the intended failure mechanism"
)]
use geopackage::core::ddl;
use geopackage::core::version::{APPLICATION_ID_GP10, APPLICATION_ID_GP11};
use geopackage::{GeoPackage, GpkgVersion, OpenWarning};
use std::path::Path;
fn legacy_file(path: &Path, application_id: u32) {
let conn = rusqlite::Connection::open(path).unwrap();
conn.pragma_update(None, "application_id", application_id)
.unwrap();
conn.pragma_update(None, "user_version", 0).unwrap();
conn.execute_batch(&format!(
"{};\n{};",
ddl::CREATE_GPKG_SPATIAL_REF_SYS,
ddl::CREATE_GPKG_CONTENTS
))
.unwrap();
for stmt in ddl::SEED_SPATIAL_REF_SYS {
conn.execute(stmt, []).unwrap();
}
}
#[test]
fn legacy_application_id_warns_but_opens() {
for (application_id, expected) in [
(APPLICATION_ID_GP10, GpkgVersion::V1_0),
(APPLICATION_ID_GP11, GpkgVersion::V1_1),
] {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("legacy.gpkg");
legacy_file(&path, application_id);
let gpkg = GeoPackage::open_lenient(&path).unwrap();
assert_eq!(gpkg.version(), expected);
assert!(
gpkg.open_warnings()
.contains(&OpenWarning::LegacyApplicationId {
version: expected,
application_id,
})
);
let strict = GeoPackage::open(&path).unwrap();
assert_eq!(strict.version(), expected);
assert!(strict.open_warnings().is_empty());
}
}
#[test]
fn missing_geometry_columns_warns_for_attribute_only_file() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("attr.gpkg");
drop(GeoPackage::create(&path).unwrap());
let gpkg = GeoPackage::open_lenient(&path).unwrap();
assert!(
gpkg.open_warnings()
.contains(&OpenWarning::MissingGeometryColumns)
);
let strict = GeoPackage::open(&path).unwrap();
assert!(strict.open_warnings().is_empty());
}
#[test]
fn wrong_case_table_name_warns_and_resolves() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("case.gpkg");
{
let gpkg = GeoPackage::create(&path).unwrap();
gpkg.connection()
.execute_batch(
"CREATE TABLE roads (fid INTEGER PRIMARY KEY, geom POINT, name TEXT);\
INSERT INTO gpkg_contents (table_name, data_type, srs_id) \
VALUES ('Roads', 'features', 4326);\
CREATE TABLE gpkg_geometry_columns (\
table_name TEXT NOT NULL, column_name TEXT NOT NULL, \
geometry_type_name TEXT NOT NULL, srs_id INTEGER NOT NULL, \
z TINYINT NOT NULL, m TINYINT NOT NULL);\
INSERT INTO gpkg_geometry_columns VALUES ('roads', 'geom', 'POINT', 4326, 0, 0);",
)
.unwrap();
}
let gpkg = GeoPackage::open_lenient(&path).unwrap();
assert!(
gpkg.open_warnings()
.contains(&OpenWarning::TableNameCaseMismatch {
declared: "Roads".to_string(),
actual: "roads".to_string(),
})
);
let layer = gpkg.layer("Roads").unwrap();
assert_eq!(layer.table_name(), "roads");
assert!(layer.geometry_column().is_some());
let layers = gpkg.layers().unwrap();
assert_eq!(layers.len(), 1);
assert_eq!(layers[0].table_name(), "roads");
}
#[test]
fn strict_open_of_a_normal_file_has_no_warnings() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("ok.gpkg");
drop(GeoPackage::create(&path).unwrap());
let gpkg = GeoPackage::open(&path).unwrap();
assert!(gpkg.open_warnings().is_empty());
}
#[test]
fn open_lenient_still_rejects_a_non_geopackage() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("plain.sqlite");
rusqlite::Connection::open(&path)
.unwrap()
.execute_batch("CREATE TABLE t(x);")
.unwrap();
assert!(matches!(
GeoPackage::open_lenient(&path),
Err(geopackage::Error::NotAGeoPackage { .. })
));
}