toasty_driver_integration_suite/tests/
infra_connection_per_clone.rs

1use crate::prelude::*;
2
3#[driver_test(id(ID))]
4pub async fn db_does_not_hold_connection(t: &mut Test) -> Result<()> {
5    if !t.capability().test_connection_pool {
6        return Ok(());
7    }
8
9    #[derive(Debug, toasty::Model)]
10    struct Item {
11        #[key]
12        #[auto]
13        id: ID,
14    }
15
16    let mut db = t.setup_db(models!(Item)).await;
17
18    // Db is stateless — after setup_db, the connection used for push_schema has
19    // been returned to the pool, so it should be available.
20    let status = db.pool().status();
21    assert_eq!(
22        status.size, 1,
23        "setup_db should have created one connection"
24    );
25    assert_eq!(
26        status.available, 1,
27        "connection should be back in the pool (Db is stateless)"
28    );
29
30    // Execute an operation — it acquires a connection, runs, and returns it.
31    Item::create().exec(&mut db).await?;
32
33    let status = db.pool().status();
34    assert_eq!(
35        status.available, 1,
36        "connection should be returned after operation"
37    );
38
39    // Clone the handle — both share the same pool.
40    let mut db2 = db.clone();
41    Item::create().exec(&mut db2).await?;
42
43    let status = db.pool().status();
44    assert_eq!(
45        status.available, status.size,
46        "all connections should be available after operations"
47    );
48
49    // The original handle still works fine.
50    let item = Item::create().exec(&mut db).await?;
51    let found = Item::filter_by_id(item.id).exec(&mut db).await?;
52    assert_eq!(found.len(), 1);
53
54    Ok(())
55}
56
57#[driver_test(id(ID))]
58pub async fn dedicated_connection_holds_pool_slot(t: &mut Test) -> Result<()> {
59    if !t.capability().test_connection_pool {
60        return Ok(());
61    }
62
63    #[derive(Debug, toasty::Model)]
64    struct Item {
65        #[key]
66        #[auto]
67        id: ID,
68    }
69
70    let db = t.setup_db(models!(Item)).await;
71
72    // All connections available since Db is stateless.
73    let status = db.pool().status();
74    assert_eq!(status.available, status.size);
75
76    // Acquire a dedicated connection — it should be held from the pool.
77    let mut conn = db.connection().await?;
78
79    let status = db.pool().status();
80    assert_eq!(
81        status.available,
82        status.size - 1,
83        "dedicated connection should be held from the pool"
84    );
85
86    // Use the connection.
87    Item::create().exec(&mut conn).await?;
88
89    // Connection is still held.
90    let status = db.pool().status();
91    assert_eq!(
92        status.available,
93        status.size - 1,
94        "connection should still be held after operation"
95    );
96
97    // Drop the connection — it should return to the pool.
98    drop(conn);
99
100    // The background task needs a moment to notice the channel closed and exit.
101    tokio::task::yield_now().await;
102
103    let status = db.pool().status();
104    assert_eq!(
105        status.available, status.size,
106        "connection should be returned after drop"
107    );
108
109    Ok(())
110}
111
112#[driver_test(id(ID))]
113pub async fn write_visible_on_same_handle(t: &mut Test) -> Result<()> {
114    #[derive(Debug, toasty::Model)]
115    struct Note {
116        #[key]
117        #[auto]
118        id: ID,
119
120        body: String,
121    }
122
123    let mut db = t.setup_db(models!(Note)).await;
124
125    // Write and immediately read on the same handle — must see the write.
126    let created = Note::create().body("hello").exec(&mut db).await?;
127    let found = Note::filter_by_id(created.id).get(&mut db).await?;
128    assert_eq!(found.body, "hello");
129
130    Ok(())
131}