sqlite3/tests: Run Rust-based test suite also with SQLite

You can now run the tests with SQLite with:

```
cargo test --test compat --features sqlite3
```
This commit is contained in:
Pekka Enberg 2025-05-14 13:38:02 +03:00
parent d086ab29a6
commit 41e9d7f9b8
4 changed files with 233 additions and 185 deletions

View file

@ -7,10 +7,12 @@ authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
build = "build.rs"
[features]
capi = []
lfs = []
sqlite3 = []
[package.metadata.dist]
dist = true
@ -25,6 +27,11 @@ libc = "0.2.169"
limbo_core = { path = "../core" }
log = "0.4.22"
[package.metadata.capi.header]
name = "sqlite3.h"
[[test]]
name = "compat"
path = "tests/compat/mod.rs"
[build-dependencies]

3
sqlite3/build.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
println!("cargo:rustc-link-search=native=target/debug");
}

View file

@ -1083,187 +1083,3 @@ pub unsafe extern "C" fn sqlite3_wal_checkpoint_v2(
}
SQLITE_OK
}
#[cfg(test)]
mod tests {
use super::*;
use std::ptr;
#[test]
fn test_libversion() {
unsafe {
let version = sqlite3_libversion();
assert!(!version.is_null());
}
}
#[test]
fn test_libversion_number() {
unsafe {
let version_num = sqlite3_libversion_number();
assert_eq!(version_num, 3042000);
}
}
#[test]
fn test_open_misuse() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(sqlite3_open(ptr::null(), &mut db), SQLITE_MISUSE);
}
}
#[test]
fn test_open_not_found() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"not-found/local.db\0".as_ptr() as *const i8, &mut db),
SQLITE_CANTOPEN
);
}
}
#[test]
#[ignore]
fn test_open_existing() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
fn test_close() {
unsafe {
assert_eq!(sqlite3_close(ptr::null_mut()), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_prepare_misuse() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
let mut stmt = ptr::null_mut();
assert_eq!(
sqlite3_prepare_v2(
db,
b"SELECT 1\0".as_ptr() as *const i8,
-1,
&mut stmt,
ptr::null_mut()
),
SQLITE_OK
);
assert_eq!(sqlite3_finalize(stmt), SQLITE_OK);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_wal_checkpoint() {
unsafe {
// Test with NULL db handle
assert_eq!(
sqlite3_wal_checkpoint(ptr::null_mut(), ptr::null()),
SQLITE_MISUSE
);
// Test with valid db
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
assert_eq!(sqlite3_wal_checkpoint(db, ptr::null()), SQLITE_OK);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_wal_checkpoint_v2() {
unsafe {
// Test with NULL db handle
assert_eq!(
sqlite3_wal_checkpoint_v2(
ptr::null_mut(),
ptr::null(),
SQLITE_CHECKPOINT_PASSIVE,
ptr::null_mut(),
ptr::null_mut()
),
SQLITE_MISUSE
);
// Test with valid db
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
let mut log_size = 0;
let mut checkpoint_count = 0;
// Test different checkpoint modes
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_PASSIVE,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_FULL,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_RESTART,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_TRUNCATE,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
}

222
sqlite3/tests/compat/mod.rs Normal file
View file

@ -0,0 +1,222 @@
#[allow(non_camel_case_types)]
use std::ptr;
#[repr(C)]
struct sqlite3 {
_private: [u8; 0],
}
#[repr(C)]
struct sqlite3_stmt {
_private: [u8; 0],
}
#[cfg_attr(not(feature = "sqlite3"), link(name = "limbo_sqlite3"))]
#[cfg_attr(feature = "sqlite3", link(name = "sqlite3"))]
extern "C" {
fn sqlite3_libversion() -> *const libc::c_char;
fn sqlite3_libversion_number() -> i32;
fn sqlite3_close(db: *mut sqlite3) -> i32;
fn sqlite3_open(filename: *const libc::c_char, db: *mut *mut sqlite3) -> i32;
fn sqlite3_prepare_v2(
db: *mut sqlite3,
sql: *const libc::c_char,
n_bytes: i32,
stmt: *mut *mut sqlite3_stmt,
tail: *mut *const libc::c_char,
) -> i32;
fn sqlite3_finalize(stmt: *mut sqlite3_stmt) -> i32;
fn sqlite3_wal_checkpoint(db: *mut sqlite3, db_name: *const libc::c_char) -> i32;
fn sqlite3_wal_checkpoint_v2(
db: *mut sqlite3,
db_name: *const libc::c_char,
mode: i32,
log_size: *mut i32,
checkpoint_count: *mut i32,
) -> i32;
}
const SQLITE_OK: i32 = 0;
const SQLITE_MISUSE: i32 = 21;
const SQLITE_CANTOPEN: i32 = 14;
const SQLITE_CHECKPOINT_PASSIVE: i32 = 0;
const SQLITE_CHECKPOINT_FULL: i32 = 1;
const SQLITE_CHECKPOINT_RESTART: i32 = 2;
const SQLITE_CHECKPOINT_TRUNCATE: i32 = 3;
#[test]
fn test_libversion() {
unsafe {
let version = sqlite3_libversion();
assert!(!version.is_null());
}
}
#[test]
fn test_libversion_number() {
unsafe {
let version_num = sqlite3_libversion_number();
assert_eq!(version_num, 3042000);
}
}
#[test]
fn test_open_misuse() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(sqlite3_open(ptr::null(), &mut db), SQLITE_MISUSE);
}
}
#[test]
fn test_open_not_found() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"not-found/local.db\0".as_ptr() as *const i8, &mut db),
SQLITE_CANTOPEN
);
}
}
#[test]
fn test_open_existing() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
fn test_close() {
unsafe {
assert_eq!(sqlite3_close(ptr::null_mut()), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_prepare_misuse() {
unsafe {
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
let mut stmt = ptr::null_mut();
assert_eq!(
sqlite3_prepare_v2(
db,
b"SELECT 1\0".as_ptr() as *const i8,
-1,
&mut stmt,
ptr::null_mut()
),
SQLITE_OK
);
assert_eq!(sqlite3_finalize(stmt), SQLITE_OK);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_wal_checkpoint() {
unsafe {
// Test with NULL db handle
assert_eq!(
sqlite3_wal_checkpoint(ptr::null_mut(), ptr::null()),
SQLITE_MISUSE
);
// Test with valid db
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
assert_eq!(sqlite3_wal_checkpoint(db, ptr::null()), SQLITE_OK);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}
#[test]
#[ignore]
fn test_wal_checkpoint_v2() {
unsafe {
// Test with NULL db handle
assert_eq!(
sqlite3_wal_checkpoint_v2(
ptr::null_mut(),
ptr::null(),
SQLITE_CHECKPOINT_PASSIVE,
ptr::null_mut(),
ptr::null_mut()
),
SQLITE_MISUSE
);
// Test with valid db
let mut db = ptr::null_mut();
assert_eq!(
sqlite3_open(b"../testing/testing.db\0".as_ptr() as *const i8, &mut db),
SQLITE_OK
);
let mut log_size = 0;
let mut checkpoint_count = 0;
// Test different checkpoint modes
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_PASSIVE,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_FULL,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_RESTART,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(
sqlite3_wal_checkpoint_v2(
db,
ptr::null(),
SQLITE_CHECKPOINT_TRUNCATE,
&mut log_size,
&mut checkpoint_count
),
SQLITE_OK
);
assert_eq!(sqlite3_close(db), SQLITE_OK);
}
}