I have a repository implementation as below:
#[async_trait]
impl FileIDRepository for SqliteFileIDRepository {
// ... other method implementations ...
async fn upsert(&self, file_id: FileID) -> Result<(), OperationError> {
debug!("Upserting the file id into the file id cache database...");
trace!("file id: {:?}", file_id);
let conn = self.conn.lock().await;
debug!("Creating the hash...");
let hash_pk: usize = match conn.execute(
"INSERT INTO hashes (hash) VALUES (?1)",
params![file_id.hash],
) {
Ok(_) => {
match conn.prepare("SELECT pk, hash FROM hashes WHERE hash=:hash") {
Ok(mut stmt) => {
match stmt.query(&[(":hash", &file_id.hash)]) {
Ok(mut rows) => {
debug!("Reading the row in hashes table...");
match rows.next() {
Ok(row_o) => match row_o {
Some(row) => match row.get(0) {
Ok(v) => v,
Err(e) => return handle_fidc_error!(Some(e)),
},
None => return handle_fidc_error!(Some("Expected newly inserted hash to exist but it does not.")),
},
Err(e) => return handle_fidc_error!(Some(e)),
}
}
Err(e) => return handle_fidc_error!(Some(e)),
}
}
Err(e) => return handle_fidc_error!(Some(e)),
}
}
Err(e) => return handle_fidc_error!(Some(e)),
};
debug!("Creating the file id...");
match conn.execute(
"INSERT INTO fids (fid, hash_pk) VALUES (?1, ?2)",
params![file_id.file_id, hash_pk],
) {
Ok(_) => Ok(()),
Err(e) => return handle_fidc_error!(Some(e)),
}
}
// ... other method implementations ...
}
And I have a test like below:
#[rstest]
#[tokio::test]
#[serial]
async fn upsert_present(#[future] repo_future: SqliteFileIDRepository) {
// set up
let repo = repo_future.await;
let conn = repo.conn.lock().await;
{
conn.execute("INSERT INTO hashes (hash) VALUES ('foo')", params![])
.expect("Could not insert into hashes.");
conn.execute(
"INSERT INTO fids (fid, hash_pk) VALUES ('bar', 1)",
params![],
)
.expect("Could not insert into fids.");
}
let file_id = FileID::new("foo", "bar");
// test
repo.upsert(file_id)
.await
.expect("Could not upsert file id.");
let hash_exists = conn
.prepare("SELECT hash FROM hashes WHERE hash = 'foo'")
.expect("Could not prepare the connection for db.")
.exists(params![])
.expect("Could not check if hash exists.");
let fid_exists = conn
.prepare("SELECT fid FROM fids WHERE fid = 'bar'")
.expect("Could not prepare the connection for db.")
.exists(params![])
.expect("Could not check if file id exists.");
assert!(hash_exists, "Expected hash to exist.");
assert!(fid_exists, "Expected file id to exist.");
}
I want to test out if the related method upserts the given value if exists. The weird thing is I have upsert_absent
test which runs just okay, but this one fails.
I'd like to also give the Drop
implementation in the test module so that it clears the database after the test.
impl Drop for SqliteFileIDRepository {
fn drop(&mut self) {
use std::fs;
let db_path = get_db_path().expect("Could not get db path.");
fs::remove_file(db_path).expect("Could not remove the db.");
}
}
And also the fixture I use with rstest
, which deletes the SQLite database if exists before providing an instance of SqliteFileIDRepository
:
#[fixture]
async fn repo_future() -> SqliteFileIDRepository {
let _ = fs::remove_file(get_db_path().expect("Could not get db path.")).await;
SqliteFileIDRepository::default()
.await
.expect("Could not initialize SqliteFileIDRepository.")
}
The test just hangs when it comes upsert_present
test. I can confirm this by doing RUST_TEST_THREADS=1 cargo test upsert_present --lib
.
I'd like to get more information as to why it hangs. Debugging in VSCode does not work for me for some reason. If you also have no clue why this happens, do you know how I can debug this further?
Thanks in advance.
Further Troubleshooting
I have set up debugging in VSCode so I can see where it gets stuck.
The test upsert_present
gets stuck at this line:
repo.upsert(file_id)
.await
.expect("Could not upsert file id.");
The debugger led me an assembly (?) line where it got stuck:
; id = {0x000007e7}, range = [0x0000000000111f50-0x0000000000111f87), name="syscall"
; Source location: unknown
7FFFF79C5F50: F3 0F 1E FA endbr64
7FFFF79C5F54: 48 89 F8 movq %rdi, %rax
7FFFF79C5F57: 48 89 F7 movq %rsi, %rdi
7FFFF79C5F5A: 48 89 D6 movq %rdx, %rsi
7FFFF79C5F5D: 48 89 CA movq %rcx, %rdx
7FFFF79C5F60: 4D 89 C2 movq %r8, %r10
7FFFF79C5F63: 4D 89 C8 movq %r9, %r8
7FFFF79C5F66: 4C 8B 4C 24 08 movq 0x8(%rsp), %r9
7FFFF79C5F6B: 0F 05 syscall
7FFFF79C5F6D: 48 3D 01 F0 FF FF cmpq $-0xfff, %rax ; imm = 0xF001 ; this is where it gets stuck
7FFFF79C5F73: 73 01 jae 0x7ffff79c5f76 ; <+38>
7FFFF79C5F75: C3 retq
7FFFF79C5F76: 48 8B 0D CB DE 0C 00 movq 0xcdecb(%rip), %rcx
7FFFF79C5F7D: F7 D8 negl %eax
7FFFF79C5F7F: 64 89 01 movl %eax, %fs:(%rcx)
7FFFF79C5F82: 48 83 C8 FF orq $-0x1, %rax
7FFFF79C5F86: C3 retq
I don't know any assembly so I am not sure what this is.
Environment
- Rust 1.57.0 (2021)
- Kubuntu 21.04 (if relevant)