diff --git a/siro_driver/android/app/src/main/AndroidManifest.xml b/siro_driver/android/app/src/main/AndroidManifest.xml
index 90907b90..417c3005 100644
--- a/siro_driver/android/app/src/main/AndroidManifest.xml
+++ b/siro_driver/android/app/src/main/AndroidManifest.xml
@@ -68,10 +68,7 @@
-
-
+
-
-
-
-
-
-
+
diff --git a/siro_driver/pubspec.yaml b/siro_driver/pubspec.yaml
index ba95cd32..5a6c3fd6 100644
--- a/siro_driver/pubspec.yaml
+++ b/siro_driver/pubspec.yaml
@@ -2,7 +2,7 @@ name: siro_driver
description: "A new Flutter project."
publish_to: "none" # Remove this line if you wish to publish to pub.dev
-version: 1.0.0+4
+version: 1.0.0+5
environment:
sdk: ">=3.0.5 <4.0.0"
diff --git a/stress_test/generate_mock_data.php b/stress_test/generate_mock_data.php
new file mode 100644
index 00000000..d9677e57
--- /dev/null
+++ b/stress_test/generate_mock_data.php
@@ -0,0 +1,37 @@
+ (string)$driverId,
+ 'role' => 'driver',
+ 'iat' => time(),
+ 'exp' => time() + 86400
+];
+
+$jwt = JWT::encode($payload, $secret, 'HS256');
+
+echo json_encode([
+ 'driver_id' => $driverId,
+ 'jwt' => $jwt
+]);
diff --git a/stress_test/load_test.js b/stress_test/load_test.js
new file mode 100644
index 00000000..bd02d862
--- /dev/null
+++ b/stress_test/load_test.js
@@ -0,0 +1,179 @@
+const { io } = require('socket.io-client');
+const axios = require('axios');
+const { execSync } = require('child_process');
+const yargs = require('yargs/yargs');
+const { hideBin } = require('yargs/helpers');
+
+const argv = yargs(hideBin(process.argv))
+ .option('trips', {
+ alias: 't',
+ type: 'number',
+ description: 'Number of concurrent trips to simulate',
+ default: 1
+ })
+ .option('base-url', {
+ alias: 'b',
+ type: 'string',
+ description: 'Base URL for backend APIs',
+ default: 'http://localhost/backend'
+ })
+ .option('socket-url', {
+ alias: 's',
+ type: 'string',
+ description: 'Location server socket URL',
+ default: 'ws://localhost:2020'
+ })
+ .argv;
+
+// Helper to get JWT for mock driver
+function getMockDriverJwt(driverId) {
+ try {
+ const output = execSync(`php generate_mock_data.php ${driverId}`).toString();
+ return JSON.parse(output).jwt;
+ } catch (err) {
+ console.error(`Failed to generate JWT for driver ${driverId}`, err.message);
+ return 'mock_jwt';
+ }
+}
+
+async function simulateTrip(tripIndex) {
+ const driverId = 900000 + tripIndex;
+ const passengerId = 800000 + tripIndex;
+ const driverJwt = getMockDriverJwt(driverId);
+
+ console.log(`[Trip ${tripIndex}] Starting simulation... Driver: ${driverId}, Passenger: ${passengerId}`);
+
+ // 1. Connect Driver to Socket
+ const socket = io(argv.socketUrl, {
+ query: {
+ driver_id: driverId,
+ platform: 'android',
+ jwt: driverJwt
+ },
+ transports: ['websocket']
+ });
+
+ return new Promise((resolve, reject) => {
+ let rideId = null;
+
+ socket.on('connect', async () => {
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} connected to socket.`);
+
+ // 2. Passenger Requests Ride
+ try {
+ const addRideFormData = new URLSearchParams({
+ passenger_id: passengerId,
+ start_location: '31.95,35.91', // Amman
+ end_location: '31.96,35.92',
+ price: '5',
+ price_token: 'dummy',
+ distance: '2',
+ carType: 'Economy',
+ passenger_name: 'Test Passenger',
+ passenger_phone: '0790000000',
+ start_name: 'Start',
+ end_name: 'End'
+ });
+
+ const reqStart = Date.now();
+ const res = await axios.post(`${argv.baseUrl}/ride/rides/add_ride.php`, addRideFormData.toString(), {
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+ });
+
+ // Note: the backend add_ride.php might return the newly created ride ID
+ console.log(`[Trip ${tripIndex}] Passenger requested ride. Response time: ${Date.now() - reqStart}ms`);
+ } catch (err) {
+ console.error(`[Trip ${tripIndex}] Error requesting ride:`, err.message);
+ socket.disconnect();
+ return reject(err);
+ }
+ });
+
+ socket.on('market_new_ride', async (payload) => {
+ rideId = payload.id;
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} received ride offer #${rideId}. Accepting...`);
+
+ // 3. Driver Accepts Ride
+ try {
+ const acceptFormData = new URLSearchParams({
+ id: rideId,
+ driver_id: driverId,
+ status: 'accepted'
+ });
+
+ const acceptStart = Date.now();
+ await axios.post(`${argv.baseUrl}/ride/rides/acceptRide.php`, acceptFormData.toString(), {
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+ });
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} accepted ride #${rideId}. Response time: ${Date.now() - acceptStart}ms`);
+
+ // 4. Simulate Driving (Updates Location)
+ let steps = 0;
+ const driveInterval = setInterval(async () => {
+ steps++;
+ socket.emit('update_location', {
+ lat: 31.95 + (steps * 0.001),
+ lng: 35.91 + (steps * 0.001),
+ heading: 90,
+ speed: 40,
+ status: 'on'
+ });
+
+ if (steps === 3) {
+ // Driver Arrived / Starts Ride
+ const startFormData = new URLSearchParams({
+ id: rideId,
+ driver_id: driverId,
+ status: 'start'
+ });
+ await axios.post(`${argv.baseUrl}/ride/rides/start_ride.php`, startFormData.toString());
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} started ride #${rideId}`);
+ }
+
+ if (steps === 6) {
+ clearInterval(driveInterval);
+ // 5. Finish Ride
+ const finishFormData = new URLSearchParams({
+ id: rideId,
+ driver_id: driverId,
+ status: 'finish'
+ });
+ await axios.post(`${argv.baseUrl}/ride/rides/finish_ride_updates.php`, finishFormData.toString());
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} finished ride #${rideId}.`);
+
+ socket.disconnect();
+ resolve(`Trip ${tripIndex} completed successfully.`);
+ }
+ }, 1000);
+
+ } catch (err) {
+ console.error(`[Trip ${tripIndex}] Error during ride execution:`, err.message);
+ socket.disconnect();
+ reject(err);
+ }
+ });
+
+ socket.on('disconnect', () => {
+ console.log(`[Trip ${tripIndex}] Driver ${driverId} disconnected.`);
+ });
+ });
+}
+
+async function runTest() {
+ console.log(`🚀 Starting Load Test with ${argv.trips} concurrent trips`);
+ const promises = [];
+ for (let i = 1; i <= argv.trips; i++) {
+ promises.push(simulateTrip(i));
+ // Add a slight stagger so we don't overwhelm immediately
+ await new Promise(r => setTimeout(r, 100));
+ }
+
+ try {
+ await Promise.all(promises);
+ console.log("✅ All simulated trips finished successfully.");
+ } catch (e) {
+ console.error("❌ Some trips failed.", e);
+ }
+}
+
+runTest();
diff --git a/stress_test/package.json b/stress_test/package.json
new file mode 100644
index 00000000..39a6842e
--- /dev/null
+++ b/stress_test/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "siro-stress-test",
+ "version": "1.0.0",
+ "description": "Stress testing suite for Siro ride-hailing services",
+ "main": "load_test.js",
+ "scripts": {
+ "test": "node load_test.js",
+ "test:multi": "node load_test.js --trips=100"
+ },
+ "dependencies": {
+ "axios": "^1.6.8",
+ "socket.io-client": "^4.7.5",
+ "uuid": "^9.0.1",
+ "yargs": "^17.7.2",
+ "dotenv": "^16.4.5"
+ }
+}