Skip to content

Commit d13d964

Browse files
author
test
committed
Better tests
1 parent 67a7779 commit d13d964

3 files changed

Lines changed: 129 additions & 26 deletions

File tree

src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use storage::engine::{
1515
AppState, ClusterData, delete_value, get_value, get_table_store, join_cluster, put_value,
1616
};
1717
use storage::persistance::{cold_save, load_all_tables};
18+
use crate::storage::engine::{get_all_keys, get_multiple_keys};
1819

1920
/// Declare APP_STATE globally so that it’s available throughout the module.
2021
static APP_STATE: OnceCell<web::Data<AppState>> = OnceCell::new();
@@ -214,6 +215,11 @@ async fn main() -> std::io::Result<()> {
214215
.route("/store", web::get().to(|state: web::Data<AppState>| async move {
215216
web::Json(state.store.lock().unwrap().clone())
216217
}))
218+
// Endpoint to get all key names in a table.
219+
.route("/{table}/keys", web::get().to(get_all_keys))
220+
// Endpoint to retrieve multiple keys from a table (using a JSON body).
221+
.route("/{table}/keys", web::post().to(get_multiple_keys))
222+
217223
})
218224
.bind(bind_addr.as_str())?
219225
.run()

src/storage/engine.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,47 @@ pub async fn delete_value(
267267
let _results = join_all(tasks).await;
268268
HttpResponse::Ok().body("Key deleted from all replicas")
269269
}
270+
271+
/// GET /{table}/keys
272+
/// Returns a JSON array with all key names in the given table.
273+
pub async fn get_all_keys(table: web::Path<String>, state: web::Data<AppState>) -> impl Responder {
274+
let table_name = table.into_inner();
275+
let store = state.store.lock().unwrap();
276+
if let Some(table_data) = store.get(&table_name) {
277+
let keys: Vec<String> = table_data.keys().cloned().collect();
278+
HttpResponse::Ok().json(keys)
279+
} else {
280+
HttpResponse::NotFound().body("Table not found")
281+
}
282+
}
283+
284+
/// Input for retrieving multiple keys.
285+
#[derive(Deserialize)]
286+
pub struct KeysRequest {
287+
/// List of keys requested.
288+
pub keys: Vec<String>,
289+
}
290+
291+
/// POST /{table}/keys
292+
/// With a JSON body { "keys": ["key1", "key2", ...] },
293+
/// returns a JSON object mapping each found key to its stored value.
294+
pub async fn get_multiple_keys(
295+
table: web::Path<String>,
296+
keys_request: web::Json<KeysRequest>,
297+
state: web::Data<AppState>,
298+
) -> impl Responder {
299+
let table_name = table.into_inner();
300+
let requested_keys = keys_request.into_inner().keys;
301+
let store = state.store.lock().unwrap();
302+
if let Some(table_data) = store.get(&table_name) {
303+
let mut result = HashMap::new();
304+
for key in requested_keys {
305+
if let Some(value) = table_data.get(&key) {
306+
result.insert(key, value.clone());
307+
}
308+
}
309+
HttpResponse::Ok().json(result)
310+
} else {
311+
HttpResponse::NotFound().body("Table not found")
312+
}
313+
}

test.sh

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,114 @@
11
#!/bin/bash
2-
# This script launches 100 nodes (one seed + 99 joiners),
3-
# writes a key to the seed node, waits for propagation,
4-
# and then performs 10 random reads to verify data consistency.
2+
# This script:
3+
# - Clones the DynaRust binary into a unique folder for each node so that each node uses its own file system.
4+
# - Launches 100 nodes (one seed and 99 joiners) from their own working directories.
5+
# - Writes a key/value pair to the "default" table on the seed node.
6+
# - Waits for propagation and performs random reads.
7+
# - Also tests endpoints for listing keys and retrieving multiple keys.
8+
# - Finally, it cleans up (kills node processes and removes the temporary directories).
59

610
set -e
711

8-
# Trap exit signals to kill background nodes when the script exits.
9-
trap "kill $(jobs -p) 2>/dev/null" EXIT
12+
# Create a temporary directory where we'll create subdirectories for each node.
13+
TMP_DIR=$(mktemp -d -t dynatest.XXXXXX)
14+
echo "Using temporary directory: ${TMP_DIR}"
15+
16+
# Trap exit signals to kill background nodes and cleanup TMP_DIR when the script exits.
17+
cleanup() {
18+
echo "Cleaning up..."
19+
kill $(jobs -p) 2>/dev/null || true
20+
rm -rf "${TMP_DIR}"
21+
}
22+
trap cleanup EXIT
1023

1124
# Total number of cluster nodes to start.
12-
NODES=100
25+
NODES=30
1326
# Base port for the first (seed) node.
1427
BASE_PORT=6660
1528

1629
echo "Starting DynaRust nodes for cluster test..."
1730

18-
# Start the seed node.
19-
echo "Starting seed node at 127.0.0.1:${BASE_PORT}"
20-
./target/release/DynaRust 127.0.0.1:${BASE_PORT} &
21-
# Save the PID if needed.
22-
PIDS=($!)
23-
24-
# Start additional nodes joining the seed.
25-
for (( i=1; i<NODES; i++ )); do
26-
PORT=$((BASE_PORT + i))
27-
echo "Starting node at 127.0.0.1:${PORT} joining 127.0.0.1:${BASE_PORT}"
28-
./target/release/DynaRust 127.0.0.1:${PORT} 127.0.0.1:${BASE_PORT} &
29-
PIDS+=($!)
31+
# Array to hold the PIDs of launched processes.
32+
PIDS=()
33+
34+
# Start nodes. Each node will be run from its own directory under TMP_DIR.
35+
for (( i=0; i<NODES; i++ )); do
36+
NODE_DIR="${TMP_DIR}/node${i}"
37+
mkdir -p "${NODE_DIR}"
38+
# Copy the binary to the node directory.
39+
cp ./target/release/DynaRust "${NODE_DIR}/DynaRust"
40+
41+
PORT=$((BASE_PORT + i))
42+
43+
if [ $i -eq 0 ]; then
44+
# Seed node - no join argument.
45+
echo "Starting seed node at 127.0.0.1:${PORT} in ${NODE_DIR}"
46+
( cd "${NODE_DIR}" && ./DynaRust 127.0.0.1:${PORT} ) &
47+
PIDS+=($!)
48+
else
49+
# Other nodes join the seed node.
50+
echo "Starting node at 127.0.0.1:${PORT} in ${NODE_DIR}, joining 127.0.0.1:${BASE_PORT}"
51+
( cd "${NODE_DIR}" && ./DynaRust 127.0.0.1:${PORT} 127.0.0.1:${BASE_PORT} ) &
52+
PIDS+=($!)
53+
fi
3054
done
3155

32-
# Wait for the cluster nodes to start and join.
3356
echo "Waiting 5 seconds for cluster stabilization..."
3457
sleep 5
3558

36-
# Write a test value to the seed node.
59+
# Define test parameters.
60+
TABLE="default"
3761
KEY="testkey"
3862
VALUE="testvalue"
39-
echo "Writing key '$KEY' with value '$VALUE' to the seed node..."
40-
curl -s -X PUT "http://127.0.0.1:${BASE_PORT}/key/${KEY}" \
63+
64+
# Write a test value to the seed node in the "default" table.
65+
echo "Writing key '$KEY' with value '$VALUE' to table '$TABLE' on the seed node..."
66+
curl -s -X PUT "http://127.0.0.1:${BASE_PORT}/${TABLE}/key/${KEY}" \
4167
-H "Content-Type: application/json" \
42-
-d "{\"value\": \"${VALUE}\"}"
68+
-d "{\"attribute\": \"${VALUE}\"}"
4369
echo ""
4470

45-
# Wait 3 seconds to allow the update to propagate to all nodes.
4671
echo "Waiting 3 seconds for data propagation..."
4772
sleep 3
4873

4974
# Perform 10 random read operations from nodes in the cluster.
5075
NUM_READS=10
5176
echo "Performing ${NUM_READS} random reads from cluster nodes..."
5277
for (( i=1; i<=NUM_READS; i++ )); do
53-
# Using the built-in $RANDOM to generate a random index.
5478
NODE_INDEX=$(($RANDOM % $NODES))
5579
READ_PORT=$((BASE_PORT + NODE_INDEX))
5680
echo "Read attempt ${i} from node at 127.0.0.1:${READ_PORT}:"
57-
curl -s "http://127.0.0.1:${READ_PORT}/key/${KEY}"
81+
curl -s "http://127.0.0.1:${READ_PORT}/${TABLE}/key/${KEY}"
82+
echo -e "\n-------------------------"
83+
done
84+
85+
# Test the new endpoint to list all keys in the table from the seed node.
86+
echo "Listing all keys in table '$TABLE' from the seed node:"
87+
curl -s "http://127.0.0.1:${BASE_PORT}/${TABLE}/keys"
88+
echo -e "\n-------------------------"
89+
90+
# Test the new endpoint to retrieve multiple keys from the table from the seed node.
91+
echo "Retrieving multiple keys from table '$TABLE' from the seed node (requesting 'testkey' and 'nonexistent'):"
92+
curl -s -X POST "http://127.0.0.1:${BASE_PORT}/${TABLE}/keys" \
93+
-H "Content-Type: application/json" \
94+
-d '{"keys": ["testkey", "nonexistent"]}'
95+
echo -e "\n-------------------------"
96+
97+
# Select 3 random nodes and for each:
98+
# - Retrieve the test key value using GET /default/key/{key}
99+
# - List all keys using GET /default/keys
100+
echo "Selecting 3 random nodes to verify key access and key listing:"
101+
for (( i=1; i<=3; i++ )); do
102+
NODE_INDEX=$(($RANDOM % $NODES))
103+
READ_PORT=$((BASE_PORT + NODE_INDEX))
104+
echo "From node at 127.0.0.1:${READ_PORT}:"
105+
echo "Retrieving key '$KEY':"
106+
curl -s "http://127.0.0.1:${READ_PORT}/${TABLE}/key/${KEY}"
107+
echo ""
108+
echo "Listing keys in table '$TABLE':"
109+
curl -s "http://127.0.0.1:${READ_PORT}/${TABLE}/keys"
58110
echo -e "\n-------------------------"
59111
done
60112
pkill DynaRust
113+
61114
echo "Test completed successfully."

0 commit comments

Comments
 (0)