This is an automated email from the ASF dual-hosted git repository.

CritasWang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iotdb-client-rust.git

commit 7377de3d21b9ed6c1d3c41c3e33e0b3826a3aebf
Author: CritasWang <[email protected]>
AuthorDate: Fri Jul 10 18:17:03 2026 +0800

    Address audit findings: value-asserting live insert/readback test (16 rows, 
nulls, unsorted input); run examples in CI integration job
---
 .github/workflows/ci.yml |   7 ++++
 src/client/session.rs    | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fbcfa5a..d7b001c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -84,3 +84,10 @@ jobs:
       # Includes the live-server tests now that IoTDB is reachable.
       - name: Integration tests
         run: cargo test
+
+      # Examples double as end-to-end smoke tests against the live server.
+      - name: Run examples
+        run: |
+          cargo run --example tree_session
+          cargo run --example table_session
+          cargo run --example session_pool
diff --git a/src/client/session.rs b/src/client/session.rs
index 5909ea9..775391b 100644
--- a/src/client/session.rs
+++ b/src/client/session.rs
@@ -541,4 +541,105 @@ mod tests {
         session.close().expect("close session");
         assert!(!session.is_open());
     }
+
+    /// Value-asserting live roundtrip: unsorted input, nulls, and a row count
+    /// that is a multiple of 8 (stresses the rows/8+1 bitmap padding byte).
+    /// Skipped when no IoTDB instance is reachable on localhost:6667.
+    #[test]
+    fn live_insert_tablet_readback() {
+        use crate::data::{tablet::Tablet, TSDataType, Value};
+        use std::net::TcpStream;
+        if TcpStream::connect_timeout(
+            &"127.0.0.1:6667".parse().unwrap(),
+            Duration::from_millis(300),
+        )
+        .is_err()
+        {
+            eprintln!("skipping live_insert_tablet_readback: no IoTDB server 
on 127.0.0.1:6667");
+            return;
+        }
+
+        const DB: &str = "root.rusttest_readback";
+        const ROWS: i64 = 16;
+
+        let mut session = Session::new(SessionConfig::default());
+        session.open().expect("open session");
+        // Fresh database (ignore error if it doesn't exist yet).
+        let _ = session.execute_non_query(&format!("DELETE DATABASE {DB}"));
+        session
+            .execute_non_query(&format!("CREATE DATABASE {DB}"))
+            .expect("create database");
+
+        let mut tablet = Tablet::new(
+            format!("{DB}.d1"),
+            vec!["ival".into(), "dval".into(), "sval".into()],
+            vec![TSDataType::Int32, TSDataType::Double, TSDataType::Text],
+        )
+        .expect("tablet");
+        // Insert in reverse timestamp order; serialization must sort.
+        for ts in (0..ROWS).rev() {
+            let ival = if ts % 3 == 0 {
+                None
+            } else {
+                Some(Value::Int32(ts as i32 * 10))
+            };
+            let dval = if ts % 5 == 0 {
+                None
+            } else {
+                Some(Value::Double(ts as f64 + 0.5))
+            };
+            let sval = Some(Value::Text(format!("row-{ts}")));
+            tablet.add_row(ts, vec![ival, dval, sval]).expect("add_row");
+        }
+        session.insert_tablet(&tablet).expect("insert_tablet");
+
+        // Read back all rows and assert every cell.
+        let mut seen = 0i64;
+        {
+            let mut dataset = session
+                .execute_query(&format!("SELECT ival, dval, sval FROM 
{DB}.d1"))
+                .expect("query");
+            while let Some(row) = dataset.next_row().expect("next_row") {
+                let ts = row.timestamp.expect("timestamp");
+                assert_eq!(ts, seen, "rows must come back in ascending time 
order");
+                let expect_ival = if ts % 3 == 0 {
+                    Value::Null
+                } else {
+                    Value::Int32(ts as i32 * 10)
+                };
+                let expect_dval = if ts % 5 == 0 {
+                    Value::Null
+                } else {
+                    Value::Double(ts as f64 + 0.5)
+                };
+                assert_eq!(row.values[0], expect_ival, "ival at ts={ts}");
+                assert_eq!(row.values[1], expect_dval, "dval at ts={ts}");
+                assert_eq!(
+                    row.values[2],
+                    Value::Text(format!("row-{ts}")),
+                    "sval at ts={ts}"
+                );
+                seen += 1;
+            }
+        }
+        assert_eq!(seen, ROWS, "row count");
+
+        // Filtered query must honor the predicate.
+        let mut filtered = 0i64;
+        {
+            let mut dataset = session
+                .execute_query(&format!("SELECT sval FROM {DB}.d1 WHERE time 
>= 10"))
+                .expect("filtered query");
+            while let Some(row) = dataset.next_row().expect("next_row") {
+                assert!(row.timestamp.expect("timestamp") >= 10);
+                filtered += 1;
+            }
+        }
+        assert_eq!(filtered, ROWS - 10, "filtered row count");
+
+        session
+            .execute_non_query(&format!("DELETE DATABASE {DB}"))
+            .expect("cleanup");
+        session.close().expect("close session");
+    }
 }

Reply via email to