Skip to content

Commit 18ed7d3

Browse files
committed
Build end-to-end test infrastructure and add some tests
1 parent 07e26de commit 18ed7d3

File tree

4 files changed

+1290
-0
lines changed

4 files changed

+1290
-0
lines changed

tests/basic_tests.rs

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
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

Comments
 (0)