mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 09:09:19 +08:00
Merge pull request #420 from gwenn/interrupt
Try to fix test_interrupt #415
This commit is contained in:
commit
e894b7c3b2
72
src/lib.rs
72
src/lib.rs
@ -1523,65 +1523,31 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "functions")]
|
||||||
fn test_interrupt() {
|
fn test_interrupt() {
|
||||||
use std::thread;
|
let db = checked_memory_handle();
|
||||||
use std::time::Duration;
|
|
||||||
let tries = 15;
|
|
||||||
// Sadly, this is inherently finnicky. Even if sqlite gets the
|
|
||||||
// interrupt, it isn't guaranteed to stop. In practice, 15 tends to be
|
|
||||||
// more than enough so long as we move everything we can outside of
|
|
||||||
// the thread body, but it still is unfortunate.
|
|
||||||
for i in 0..tries {
|
|
||||||
let db = checked_memory_handle();
|
|
||||||
db.execute_batch("CREATE TABLE dummy(id)").unwrap();
|
|
||||||
let interrupt_handle = db.get_interrupt_handle();
|
|
||||||
// generate an arbitrary query which will be very slow to execute.
|
|
||||||
let sql = format!(
|
|
||||||
"{};",
|
|
||||||
(0..100_000)
|
|
||||||
.into_iter()
|
|
||||||
.map(|i| format!("INSERT INTO dummy(id) VALUES({})", i))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(";\n")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Do this on the main thread to minimize the amount of time spent
|
let interrupt_handle = db.get_interrupt_handle();
|
||||||
// when interrupt won't do anything (because we haven't started
|
|
||||||
// executing the query).
|
|
||||||
let c_sql = str_to_cstring(&sql).unwrap();
|
|
||||||
|
|
||||||
let joiner = thread::spawn(move || unsafe {
|
db.create_scalar_function("interrupt", 0, false, move |_| {
|
||||||
let raw_db = db.db.borrow().db;
|
|
||||||
let r = ffi::sqlite3_exec(
|
|
||||||
raw_db,
|
|
||||||
c_sql.as_ptr(),
|
|
||||||
None,
|
|
||||||
ptr::null_mut(),
|
|
||||||
ptr::null_mut(),
|
|
||||||
);
|
|
||||||
db.decode_result(r)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Try a few times to make sure we don't catch it too early.
|
|
||||||
interrupt_handle.interrupt();
|
interrupt_handle.interrupt();
|
||||||
for &delay in &[10, 100, 1000] {
|
Ok(0)
|
||||||
thread::sleep(Duration::from_millis(delay));
|
})
|
||||||
interrupt_handle.interrupt();
|
.unwrap();
|
||||||
}
|
|
||||||
let result = joiner.join().unwrap();
|
|
||||||
|
|
||||||
if i != tries - 1 && !result.is_err() {
|
let mut stmt = db
|
||||||
continue;
|
.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")
|
||||||
}
|
.unwrap();
|
||||||
|
|
||||||
match result.unwrap_err() {
|
let result: Result<Vec<i32>> = stmt.query_map(NO_PARAMS, |r| r.get(0)).unwrap().collect();
|
||||||
Error::SqliteFailure(err, _) => {
|
|
||||||
assert_eq!(err.code, ErrorCode::OperationInterrupted);
|
match result.unwrap_err() {
|
||||||
return;
|
Error::SqliteFailure(err, _) => {
|
||||||
}
|
assert_eq!(err.code, ErrorCode::OperationInterrupted);
|
||||||
err => {
|
return;
|
||||||
panic!("Unexpected error {}", err);
|
}
|
||||||
}
|
err => {
|
||||||
|
panic!("Unexpected error {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user