|
| 1 | +//! Basic integration tests using mock data |
| 2 | +//! |
| 3 | +//! This module tests basic distributed query functionality using simple, |
| 4 | +//! controlled test data to verify join operations and basic SQL features. |
| 5 | +
|
| 6 | +use datafusion::arrow::util::pretty::pretty_format_batches; |
| 7 | +use insta::assert_snapshot; |
| 8 | +use std::sync::Once; |
| 9 | +use tokio::sync::OnceCell; |
| 10 | + |
| 11 | +mod cluster_setup; |
| 12 | +mod mock_data; |
| 13 | + |
| 14 | +use cluster_setup::{ClusterConfig, TestCluster}; |
| 15 | +use mock_data::generate_mock_data; |
| 16 | + |
| 17 | +/// Ensure mock data is generated only once across all tests |
| 18 | +static MOCK_DATA_INIT: Once = Once::new(); |
| 19 | + |
| 20 | +/// Global cluster instance shared across basic tests |
| 21 | +static BASIC_CLUSTER: OnceCell<TestCluster> = OnceCell::const_new(); |
| 22 | + |
| 23 | +/// Initialize mock data once for all tests |
| 24 | +fn ensure_mock_data() { |
| 25 | + MOCK_DATA_INIT.call_once(|| { |
| 26 | + generate_mock_data().expect("Failed to generate mock data"); |
| 27 | + println!("✅ Mock data initialized for all basic tests"); |
| 28 | + }); |
| 29 | +} |
| 30 | + |
| 31 | +/// Get or initialize the shared basic test cluster |
| 32 | +async fn get_basic_cluster() -> &'static TestCluster { |
| 33 | + BASIC_CLUSTER |
| 34 | + .get_or_init(|| async { |
| 35 | + println!("🚀 Initializing shared basic test cluster..."); |
| 36 | + |
| 37 | + // Ensure mock data exists |
| 38 | + ensure_mock_data(); |
| 39 | + |
| 40 | + // Configure cluster with mock data tables |
| 41 | + let config = ClusterConfig::new() |
| 42 | + .with_base_port(33000) // Use different port range from TPC-H tests |
| 43 | + .with_csv_table("customers", "testdata/mock/customers.csv") |
| 44 | + .with_csv_table("orders", "testdata/mock/orders.csv"); |
| 45 | + |
| 46 | + let cluster = TestCluster::start_with_config(config) |
| 47 | + .await |
| 48 | + .expect("Failed to start basic test cluster"); |
| 49 | + |
| 50 | + println!("✅ Shared basic test cluster ready!"); |
| 51 | + cluster |
| 52 | + }) |
| 53 | + .await |
| 54 | +} |
| 55 | + |
| 56 | +/// Execute a SQL query and return formatted results (now supports concurrent execution!) |
| 57 | +async fn execute_basic_query(sql: &str) -> String { |
| 58 | + println!("🔍 Executing query concurrently: {}", sql); |
| 59 | + |
| 60 | + // Get the shared cluster instance (no mutex - concurrent access allowed!) |
| 61 | + let cluster = get_basic_cluster().await; |
| 62 | + |
| 63 | + let batches = cluster |
| 64 | + .execute_sql(sql) |
| 65 | + .await |
| 66 | + .expect("Failed to execute query"); |
| 67 | + |
| 68 | + println!("✅ Query completed successfully"); |
| 69 | + |
| 70 | + pretty_format_batches(&batches).unwrap().to_string() |
| 71 | +} |
| 72 | + |
| 73 | +#[tokio::test] |
| 74 | +async fn test_select_customers() { |
| 75 | + let result = execute_basic_query("SELECT * FROM customers ORDER BY customer_id").await; |
| 76 | + assert_snapshot!(result, @r" |
| 77 | + +-------------+---------------+----------+-----------+ |
| 78 | + | customer_id | name | city | country | |
| 79 | + +-------------+---------------+----------+-----------+ |
| 80 | + | 1 | Alice Johnson | New York | USA | |
| 81 | + | 2 | Bob Smith | London | UK | |
| 82 | + | 3 | Carol Davis | Paris | France | |
| 83 | + | 4 | David Wilson | Tokyo | Japan | |
| 84 | + | 5 | Eve Brown | Sydney | Australia | |
| 85 | + +-------------+---------------+----------+-----------+ |
| 86 | + "); |
| 87 | +} |
| 88 | + |
| 89 | +#[tokio::test] |
| 90 | +async fn test_select_orders() { |
| 91 | + let result = execute_basic_query("SELECT * FROM orders ORDER BY order_id").await; |
| 92 | + assert_snapshot!(result, @r" |
| 93 | + +----------+-------------+------------+--------+------------+ |
| 94 | + | order_id | customer_id | product | amount | order_date | |
| 95 | + +----------+-------------+------------+--------+------------+ |
| 96 | + | 101 | 1 | Laptop | 1200.0 | 2024-01-15 | |
| 97 | + | 102 | 1 | Mouse | 25.5 | 2024-01-16 | |
| 98 | + | 103 | 2 | Keyboard | 75.0 | 2024-01-17 | |
| 99 | + | 104 | 3 | Monitor | 350.0 | 2024-01-18 | |
| 100 | + | 105 | 2 | Headphones | 120.0 | 2024-01-19 | |
| 101 | + | 106 | 4 | Tablet | 600.0 | 2024-01-20 | |
| 102 | + | 107 | 5 | Phone | 800.0 | 2024-01-21 | |
| 103 | + | 108 | 1 | Cable | 15.99 | 2024-01-22 | |
| 104 | + | 109 | 3 | Speaker | 200.0 | 2024-01-23 | |
| 105 | + | 110 | 4 | Charger | 45.0 | 2024-01-24 | |
| 106 | + +----------+-------------+------------+--------+------------+ |
| 107 | + "); |
| 108 | +} |
| 109 | + |
| 110 | +#[tokio::test] |
| 111 | +async fn test_customer_order_count() { |
| 112 | + let result = execute_basic_query( |
| 113 | + "SELECT c.name, COUNT(o.order_id) as order_count |
| 114 | + FROM customers c |
| 115 | + LEFT JOIN orders o ON c.customer_id = o.customer_id |
| 116 | + GROUP BY c.customer_id, c.name |
| 117 | + ORDER BY c.name", |
| 118 | + ) |
| 119 | + .await; |
| 120 | + assert_snapshot!(result, @r" |
| 121 | + +---------------+-------------+ |
| 122 | + | name | order_count | |
| 123 | + +---------------+-------------+ |
| 124 | + | Alice Johnson | 3 | |
| 125 | + | Bob Smith | 2 | |
| 126 | + | Carol Davis | 2 | |
| 127 | + | David Wilson | 2 | |
| 128 | + | Eve Brown | 1 | |
| 129 | + +---------------+-------------+ |
| 130 | + "); |
| 131 | +} |
| 132 | + |
| 133 | +#[tokio::test] |
| 134 | +async fn test_customer_total_spending() { |
| 135 | + let result = execute_basic_query( |
| 136 | + "SELECT c.name, c.city, COALESCE(SUM(o.amount), 0) as total_spent |
| 137 | + FROM customers c |
| 138 | + LEFT JOIN orders o ON c.customer_id = o.customer_id |
| 139 | + GROUP BY c.customer_id, c.name, c.city |
| 140 | + ORDER BY total_spent DESC", |
| 141 | + ) |
| 142 | + .await; |
| 143 | + assert_snapshot!(result, @r" |
| 144 | + +---------------+----------+-------------+ |
| 145 | + | name | city | total_spent | |
| 146 | + +---------------+----------+-------------+ |
| 147 | + | Alice Johnson | New York | 1241.49 | |
| 148 | + | Eve Brown | Sydney | 800.0 | |
| 149 | + | David Wilson | Tokyo | 645.0 | |
| 150 | + | Carol Davis | Paris | 550.0 | |
| 151 | + | Bob Smith | London | 195.0 | |
| 152 | + +---------------+----------+-------------+ |
| 153 | + "); |
| 154 | +} |
| 155 | + |
| 156 | +#[tokio::test] |
| 157 | +async fn test_orders_by_country() { |
| 158 | + let result = execute_basic_query( |
| 159 | + "SELECT c.country, COUNT(o.order_id) as order_count, SUM(o.amount) as total_amount |
| 160 | + FROM customers c |
| 161 | + INNER JOIN orders o ON c.customer_id = o.customer_id |
| 162 | + GROUP BY c.country |
| 163 | + ORDER BY total_amount DESC", |
| 164 | + ) |
| 165 | + .await; |
| 166 | + assert_snapshot!(result, @r" |
| 167 | + +-----------+-------------+--------------+ |
| 168 | + | country | order_count | total_amount | |
| 169 | + +-----------+-------------+--------------+ |
| 170 | + | USA | 3 | 1241.49 | |
| 171 | + | Australia | 1 | 800.0 | |
| 172 | + | Japan | 2 | 645.0 | |
| 173 | + | France | 2 | 550.0 | |
| 174 | + | UK | 2 | 195.0 | |
| 175 | + +-----------+-------------+--------------+ |
| 176 | + "); |
| 177 | +} |
| 178 | + |
| 179 | +#[tokio::test] |
| 180 | +async fn test_expensive_orders() { |
| 181 | + let result = execute_basic_query( |
| 182 | + "SELECT o.order_id, c.name, o.product, o.amount |
| 183 | + FROM orders o |
| 184 | + INNER JOIN customers c ON o.customer_id = c.customer_id |
| 185 | + WHERE o.amount > 100 |
| 186 | + ORDER BY o.amount DESC", |
| 187 | + ) |
| 188 | + .await; |
| 189 | + assert_snapshot!(result, @r" |
| 190 | + +----------+---------------+------------+--------+ |
| 191 | + | order_id | name | product | amount | |
| 192 | + +----------+---------------+------------+--------+ |
| 193 | + | 101 | Alice Johnson | Laptop | 1200.0 | |
| 194 | + | 107 | Eve Brown | Phone | 800.0 | |
| 195 | + | 106 | David Wilson | Tablet | 600.0 | |
| 196 | + | 104 | Carol Davis | Monitor | 350.0 | |
| 197 | + | 109 | Carol Davis | Speaker | 200.0 | |
| 198 | + | 105 | Bob Smith | Headphones | 120.0 | |
| 199 | + +----------+---------------+------------+--------+ |
| 200 | + "); |
| 201 | +} |
| 202 | + |
| 203 | +#[tokio::test] |
| 204 | +async fn test_product_sales_summary() { |
| 205 | + let result = execute_basic_query( |
| 206 | + "SELECT o.product, COUNT(*) as quantity_sold, SUM(o.amount) as total_revenue |
| 207 | + FROM orders o |
| 208 | + GROUP BY o.product |
| 209 | + ORDER BY total_revenue DESC", |
| 210 | + ) |
| 211 | + .await; |
| 212 | + assert_snapshot!(result, @r" |
| 213 | + +------------+---------------+---------------+ |
| 214 | + | product | quantity_sold | total_revenue | |
| 215 | + +------------+---------------+---------------+ |
| 216 | + | Laptop | 1 | 1200.0 | |
| 217 | + | Phone | 1 | 800.0 | |
| 218 | + | Tablet | 1 | 600.0 | |
| 219 | + | Monitor | 1 | 350.0 | |
| 220 | + | Speaker | 1 | 200.0 | |
| 221 | + | Headphones | 1 | 120.0 | |
| 222 | + | Keyboard | 1 | 75.0 | |
| 223 | + | Charger | 1 | 45.0 | |
| 224 | + | Mouse | 1 | 25.5 | |
| 225 | + | Cable | 1 | 15.99 | |
| 226 | + +------------+---------------+---------------+ |
| 227 | + "); |
| 228 | +} |
0 commit comments