Add comprehensive test environment setup with mock SCADA and optimizer services
This commit is contained in:
parent
dacb06fdc8
commit
333797314c
|
|
@ -0,0 +1,795 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Calejo Control Adapter - Test Environment Setup Script
|
||||
# Sets up mock SCADA and optimizer services for testing
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Function to display usage
|
||||
usage() {
|
||||
echo "Usage: $0 [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --scada-only Only setup mock SCADA services"
|
||||
echo " --optimizer-only Only setup mock optimizer services"
|
||||
echo " --with-dashboard Include test dashboard setup"
|
||||
echo " --clean Clean up existing test services"
|
||||
echo " -h, --help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 # Setup complete test environment"
|
||||
echo " $0 --scada-only # Setup only mock SCADA services"
|
||||
echo " $0 --clean # Clean up test environment"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
SCADA_ONLY=false
|
||||
OPTIMIZER_ONLY=false
|
||||
WITH_DASHBOARD=false
|
||||
CLEAN=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--scada-only)
|
||||
SCADA_ONLY=true
|
||||
shift
|
||||
;;
|
||||
--optimizer-only)
|
||||
OPTIMIZER_ONLY=true
|
||||
shift
|
||||
;;
|
||||
--with-dashboard)
|
||||
WITH_DASHBOARD=true
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if Docker is available
|
||||
if ! command -v docker &> /dev/null; then
|
||||
print_error "Docker is not installed or not in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
print_error "Docker Compose is not installed or not in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to cleanup test services
|
||||
cleanup_test_services() {
|
||||
print_status "Cleaning up test services..."
|
||||
|
||||
# Stop and remove test containers
|
||||
docker-compose -f docker-compose.test.yml down --remove-orphans 2>/dev/null || true
|
||||
|
||||
# Remove test network if exists
|
||||
docker network rm calejo-test-network 2>/dev/null || true
|
||||
|
||||
# Remove test volumes
|
||||
docker volume rm calejo-scada-data 2>/dev/null || true
|
||||
docker volume rm calejo-optimizer-data 2>/dev/null || true
|
||||
|
||||
print_success "Test services cleaned up"
|
||||
}
|
||||
|
||||
# If clean mode, cleanup and exit
|
||||
if [[ "$CLEAN" == "true" ]]; then
|
||||
cleanup_test_services
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create test docker-compose file
|
||||
print_status "Creating test environment configuration..."
|
||||
|
||||
cat > docker-compose.test.yml << 'EOF'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Main Calejo Control Adapter
|
||||
calejo-control-adapter:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: calejo-control-adapter-test
|
||||
ports:
|
||||
- "8080:8080" # REST API
|
||||
- "4840:4840" # OPC UA
|
||||
- "502:502" # Modbus TCP
|
||||
- "9090:9090" # Prometheus metrics
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://calejo:password@postgres:5432/calejo
|
||||
- JWT_SECRET_KEY=test-secret-key
|
||||
- API_KEY=test-api-key
|
||||
- MOCK_SCADA_ENABLED=true
|
||||
- MOCK_OPTIMIZER_ENABLED=true
|
||||
- SCADA_MOCK_URL=http://mock-scada:8081
|
||||
- OPTIMIZER_MOCK_URL=http://mock-optimizer:8082
|
||||
depends_on:
|
||||
- postgres
|
||||
- mock-scada
|
||||
- mock-optimizer
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./logs:/app/logs
|
||||
- ./config:/app/config
|
||||
networks:
|
||||
- calejo-test-network
|
||||
|
||||
# PostgreSQL Database
|
||||
postgres:
|
||||
image: postgres:15
|
||||
container_name: calejo-postgres-test
|
||||
environment:
|
||||
- POSTGRES_DB=calejo
|
||||
- POSTGRES_USER=calejo
|
||||
- POSTGRES_PASSWORD=password
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- calejo-test-network
|
||||
|
||||
# Mock SCADA System
|
||||
mock-scada:
|
||||
image: python:3.11-slim
|
||||
container_name: calejo-mock-scada
|
||||
ports:
|
||||
- "8081:8081"
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./tests/mock_services:/app
|
||||
command: >
|
||||
sh -c "pip install flask requests &&
|
||||
python mock_scada_server.py"
|
||||
environment:
|
||||
- FLASK_ENV=development
|
||||
- PORT=8081
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8081/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
networks:
|
||||
- calejo-test-network
|
||||
|
||||
# Mock Optimizer Service
|
||||
mock-optimizer:
|
||||
image: python:3.11-slim
|
||||
container_name: calejo-mock-optimizer
|
||||
ports:
|
||||
- "8082:8082"
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./tests/mock_services:/app
|
||||
command: >
|
||||
sh -c "pip install flask requests numpy &&
|
||||
python mock_optimizer_server.py"
|
||||
environment:
|
||||
- FLASK_ENV=development
|
||||
- PORT=8082
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8082/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
networks:
|
||||
- calejo-test-network
|
||||
|
||||
# Test Data Generator
|
||||
test-data-generator:
|
||||
image: python:3.11-slim
|
||||
container_name: calejo-test-data-generator
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./tests/mock_services:/app
|
||||
command: >
|
||||
sh -c "pip install requests &&
|
||||
python test_data_generator.py"
|
||||
depends_on:
|
||||
- calejo-control-adapter
|
||||
- mock-scada
|
||||
restart: "no"
|
||||
networks:
|
||||
- calejo-test-network
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
networks:
|
||||
calejo-test-network:
|
||||
driver: bridge
|
||||
EOF
|
||||
|
||||
print_success "Test configuration created"
|
||||
|
||||
# Create mock services directory
|
||||
print_status "Creating mock services..."
|
||||
mkdir -p tests/mock_services
|
||||
|
||||
# Create mock SCADA server
|
||||
cat > tests/mock_services/mock_scada_server.py << 'EOF'
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Mock SCADA Server for Testing
|
||||
Simulates a real SCADA system with industrial process data
|
||||
"""
|
||||
|
||||
import json
|
||||
import random
|
||||
import time
|
||||
from datetime import datetime
|
||||
from flask import Flask, jsonify, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Mock SCADA data storage
|
||||
scada_data = {
|
||||
"temperature": {"value": 75.0, "unit": "°C", "min": 50.0, "max": 100.0},
|
||||
"pressure": {"value": 15.2, "unit": "bar", "min": 10.0, "max": 20.0},
|
||||
"flow_rate": {"value": 120.5, "unit": "m³/h", "min": 80.0, "max": 150.0},
|
||||
"level": {"value": 65.3, "unit": "%", "min": 0.0, "max": 100.0},
|
||||
"power": {"value": 450.7, "unit": "kW", "min": 300.0, "max": 600.0},
|
||||
"status": {"value": "RUNNING", "options": ["STOPPED", "RUNNING", "FAULT"]},
|
||||
"efficiency": {"value": 87.5, "unit": "%", "min": 0.0, "max": 100.0}
|
||||
}
|
||||
|
||||
# Equipment status
|
||||
equipment_status = {
|
||||
"pump_1": "RUNNING",
|
||||
"pump_2": "STOPPED",
|
||||
"valve_1": "OPEN",
|
||||
"valve_2": "CLOSED",
|
||||
"compressor": "RUNNING",
|
||||
"heater": "ON"
|
||||
}
|
||||
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health():
|
||||
"""Health check endpoint"""
|
||||
return jsonify({"status": "healthy", "service": "mock-scada"})
|
||||
|
||||
@app.route('/api/v1/data', methods=['GET'])
|
||||
def get_all_data():
|
||||
"""Get all SCADA data"""
|
||||
# Simulate data variation
|
||||
for key in scada_data:
|
||||
if key != "status":
|
||||
current = scada_data[key]
|
||||
variation = random.uniform(-2.0, 2.0)
|
||||
new_value = current["value"] + variation
|
||||
# Keep within bounds
|
||||
new_value = max(current["min"], min(new_value, current["max"]))
|
||||
scada_data[key]["value"] = round(new_value, 2)
|
||||
|
||||
return jsonify({
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"data": scada_data,
|
||||
"equipment": equipment_status
|
||||
})
|
||||
|
||||
@app.route('/api/v1/data/<tag>', methods=['GET'])
|
||||
def get_specific_data(tag):
|
||||
"""Get specific SCADA data tag"""
|
||||
if tag in scada_data:
|
||||
# Simulate variation for numeric values
|
||||
if tag != "status":
|
||||
current = scada_data[tag]
|
||||
variation = random.uniform(-1.0, 1.0)
|
||||
new_value = current["value"] + variation
|
||||
new_value = max(current["min"], min(new_value, current["max"]))
|
||||
scada_data[tag]["value"] = round(new_value, 2)
|
||||
|
||||
return jsonify({
|
||||
"tag": tag,
|
||||
"value": scada_data[tag]["value"],
|
||||
"unit": scada_data[tag].get("unit", ""),
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
else:
|
||||
return jsonify({"error": "Tag not found"}), 404
|
||||
|
||||
@app.route('/api/v1/control/<equipment>', methods=['POST'])
|
||||
def control_equipment(equipment):
|
||||
"""Control SCADA equipment"""
|
||||
data = request.get_json()
|
||||
|
||||
if not data or 'command' not in data:
|
||||
return jsonify({"error": "Missing command"}), 400
|
||||
|
||||
command = data['command']
|
||||
|
||||
if equipment in equipment_status:
|
||||
# Simulate control logic
|
||||
if command in ["START", "STOP", "OPEN", "CLOSE", "ON", "OFF"]:
|
||||
old_status = equipment_status[equipment]
|
||||
equipment_status[equipment] = command
|
||||
|
||||
return jsonify({
|
||||
"equipment": equipment,
|
||||
"previous_status": old_status,
|
||||
"current_status": command,
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"message": f"Equipment {equipment} changed from {old_status} to {command}"
|
||||
})
|
||||
else:
|
||||
return jsonify({"error": "Invalid command"}), 400
|
||||
else:
|
||||
return jsonify({"error": "Equipment not found"}), 404
|
||||
|
||||
@app.route('/api/v1/alarms', methods=['GET'])
|
||||
def get_alarms():
|
||||
"""Get current alarms"""
|
||||
# Simulate occasional alarms
|
||||
alarms = []
|
||||
|
||||
# Temperature alarm
|
||||
if scada_data["temperature"]["value"] > 90:
|
||||
alarms.append({
|
||||
"id": "TEMP_HIGH",
|
||||
"message": "High temperature alarm",
|
||||
"severity": "HIGH",
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
# Pressure alarm
|
||||
if scada_data["pressure"]["value"] > 18:
|
||||
alarms.append({
|
||||
"id": "PRESS_HIGH",
|
||||
"message": "High pressure alarm",
|
||||
"severity": "MEDIUM",
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
return jsonify({"alarms": alarms})
|
||||
|
||||
if __name__ == '__main__':
|
||||
import os
|
||||
port = int(os.getenv('PORT', 8081))
|
||||
app.run(host='0.0.0.0', port=port, debug=True)
|
||||
EOF
|
||||
|
||||
print_success "Mock SCADA server created"
|
||||
|
||||
# Create mock optimizer server
|
||||
cat > tests/mock_services/mock_optimizer_server.py << 'EOF'
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Mock Optimizer Server for Testing
|
||||
Simulates an optimization service for industrial processes
|
||||
"""
|
||||
|
||||
import json
|
||||
import random
|
||||
import numpy as np
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Flask, jsonify, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Mock optimization models
|
||||
optimization_models = {
|
||||
"energy_optimization": {
|
||||
"name": "Energy Consumption Optimizer",
|
||||
"description": "Optimizes energy usage across processes",
|
||||
"parameters": ["power_load", "time_of_day", "production_rate"]
|
||||
},
|
||||
"production_optimization": {
|
||||
"name": "Production Efficiency Optimizer",
|
||||
"description": "Maximizes production efficiency",
|
||||
"parameters": ["raw_material_quality", "machine_utilization", "operator_skill"]
|
||||
},
|
||||
"cost_optimization": {
|
||||
"name": "Cost Reduction Optimizer",
|
||||
"description": "Minimizes operational costs",
|
||||
"parameters": ["energy_cost", "labor_cost", "maintenance_cost"]
|
||||
}
|
||||
}
|
||||
|
||||
# Optimization history
|
||||
optimization_history = []
|
||||
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health():
|
||||
"""Health check endpoint"""
|
||||
return jsonify({"status": "healthy", "service": "mock-optimizer"})
|
||||
|
||||
@app.route('/api/v1/models', methods=['GET'])
|
||||
def get_models():
|
||||
"""Get available optimization models"""
|
||||
return jsonify({"models": optimization_models})
|
||||
|
||||
@app.route('/api/v1/optimize/<model_name>', methods=['POST'])
|
||||
def optimize(model_name):
|
||||
"""Run optimization for a specific model"""
|
||||
data = request.get_json()
|
||||
|
||||
if not data:
|
||||
return jsonify({"error": "No input data provided"}), 400
|
||||
|
||||
if model_name not in optimization_models:
|
||||
return jsonify({"error": "Model not found"}), 404
|
||||
|
||||
# Simulate optimization processing
|
||||
processing_time = random.uniform(0.5, 3.0)
|
||||
|
||||
# Generate optimization results
|
||||
if model_name == "energy_optimization":
|
||||
result = {
|
||||
"optimal_power_setpoint": random.uniform(400, 500),
|
||||
"recommended_actions": [
|
||||
"Reduce compressor load during peak hours",
|
||||
"Optimize pump sequencing",
|
||||
"Adjust temperature setpoints"
|
||||
],
|
||||
"estimated_savings": random.uniform(5, 15),
|
||||
"confidence": random.uniform(0.7, 0.95)
|
||||
}
|
||||
elif model_name == "production_optimization":
|
||||
result = {
|
||||
"optimal_production_rate": random.uniform(80, 120),
|
||||
"recommended_actions": [
|
||||
"Adjust raw material mix",
|
||||
"Optimize machine speeds",
|
||||
"Improve operator scheduling"
|
||||
],
|
||||
"efficiency_gain": random.uniform(3, 12),
|
||||
"confidence": random.uniform(0.75, 0.92)
|
||||
}
|
||||
elif model_name == "cost_optimization":
|
||||
result = {
|
||||
"optimal_cost_structure": {
|
||||
"energy": random.uniform(40, 60),
|
||||
"labor": random.uniform(25, 35),
|
||||
"maintenance": random.uniform(10, 20)
|
||||
},
|
||||
"recommended_actions": [
|
||||
"Shift energy consumption to off-peak",
|
||||
"Optimize maintenance schedules",
|
||||
"Improve labor allocation"
|
||||
],
|
||||
"cost_reduction": random.uniform(8, 20),
|
||||
"confidence": random.uniform(0.8, 0.98)
|
||||
}
|
||||
|
||||
# Record optimization
|
||||
optimization_record = {
|
||||
"model": model_name,
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"input_data": data,
|
||||
"result": result,
|
||||
"processing_time": processing_time
|
||||
}
|
||||
optimization_history.append(optimization_record)
|
||||
|
||||
return jsonify({
|
||||
"optimization_id": len(optimization_history),
|
||||
"model": model_name,
|
||||
"result": result,
|
||||
"processing_time": processing_time,
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
@app.route('/api/v1/history', methods=['GET'])
|
||||
def get_history():
|
||||
"""Get optimization history"""
|
||||
limit = request.args.get('limit', 10, type=int)
|
||||
return jsonify({
|
||||
"history": optimization_history[-limit:],
|
||||
"total_optimizations": len(optimization_history)
|
||||
})
|
||||
|
||||
@app.route('/api/v1/forecast', methods=['POST'])
|
||||
def forecast():
|
||||
"""Generate forecasts based on current data"""
|
||||
data = request.get_json()
|
||||
|
||||
if not data or 'hours' not in data:
|
||||
return jsonify({"error": "Missing forecast hours"}), 400
|
||||
|
||||
hours = data['hours']
|
||||
|
||||
# Generate mock forecast
|
||||
forecast_data = []
|
||||
current_time = datetime.utcnow()
|
||||
|
||||
for i in range(hours):
|
||||
forecast_time = current_time + timedelta(hours=i)
|
||||
forecast_data.append({
|
||||
"timestamp": forecast_time.isoformat(),
|
||||
"energy_consumption": random.uniform(400, 600),
|
||||
"production_rate": random.uniform(85, 115),
|
||||
"efficiency": random.uniform(80, 95),
|
||||
"cost": random.uniform(45, 65)
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
"forecast": forecast_data,
|
||||
"generated_at": current_time.isoformat(),
|
||||
"horizon_hours": hours
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
import os
|
||||
port = int(os.getenv('PORT', 8082))
|
||||
app.run(host='0.0.0.0', port=port, debug=True)
|
||||
EOF
|
||||
|
||||
print_success "Mock optimizer server created"
|
||||
|
||||
# Create test data generator
|
||||
cat > tests/mock_services/test_data_generator.py << 'EOF'
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Data Generator
|
||||
Generates realistic test data for the Calejo Control Adapter
|
||||
"""
|
||||
|
||||
import requests
|
||||
import time
|
||||
import random
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
# Configuration
|
||||
CALEJO_API_URL = "http://calejo-control-adapter-test:8080"
|
||||
SCADA_MOCK_URL = "http://mock-scada:8081"
|
||||
OPTIMIZER_MOCK_URL = "http://mock-optimizer:8082"
|
||||
|
||||
# Test scenarios
|
||||
test_scenarios = [
|
||||
"normal_operation",
|
||||
"high_load",
|
||||
"low_efficiency",
|
||||
"alarm_condition",
|
||||
"optimization_test"
|
||||
]
|
||||
|
||||
def test_health_checks():
|
||||
"""Test health of all services"""
|
||||
print("🔍 Testing service health...")
|
||||
|
||||
services = [
|
||||
("Calejo Control Adapter", f"{CALEJO_API_URL}/health"),
|
||||
("Mock SCADA", f"{SCADA_MOCK_URL}/health"),
|
||||
("Mock Optimizer", f"{OPTIMIZER_MOCK_URL}/health")
|
||||
]
|
||||
|
||||
for service_name, url in services:
|
||||
try:
|
||||
response = requests.get(url, timeout=5)
|
||||
if response.status_code == 200:
|
||||
print(f" ✅ {service_name}: Healthy")
|
||||
else:
|
||||
print(f" ❌ {service_name}: Unhealthy (Status: {response.status_code})")
|
||||
except Exception as e:
|
||||
print(f" ❌ {service_name}: Connection failed - {e}")
|
||||
|
||||
def generate_scada_data():
|
||||
"""Generate and send SCADA data"""
|
||||
print("📊 Generating SCADA test data...")
|
||||
|
||||
try:
|
||||
# Get current SCADA data
|
||||
response = requests.get(f"{SCADA_MOCK_URL}/api/v1/data")
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
print(f" 📈 Current SCADA data: {len(data.get('data', {}))} tags")
|
||||
|
||||
# Send some control commands
|
||||
equipment_to_control = ["pump_1", "valve_1", "compressor"]
|
||||
for equipment in equipment_to_control:
|
||||
command = random.choice(["START", "STOP", "OPEN", "CLOSE"])
|
||||
try:
|
||||
control_response = requests.post(
|
||||
f"{SCADA_MOCK_URL}/api/v1/control/{equipment}",
|
||||
json={"command": command},
|
||||
timeout=5
|
||||
)
|
||||
if control_response.status_code == 200:
|
||||
print(f" 🎛️ Controlled {equipment}: {command}")
|
||||
except:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ SCADA data generation failed: {e}")
|
||||
|
||||
def test_optimization():
|
||||
"""Test optimization scenarios"""
|
||||
print("🧠 Testing optimization...")
|
||||
|
||||
try:
|
||||
# Get available models
|
||||
response = requests.get(f"{OPTIMIZER_MOCK_URL}/api/v1/models")
|
||||
if response.status_code == 200:
|
||||
models = response.json().get('models', {})
|
||||
|
||||
# Test each model
|
||||
for model_name in models:
|
||||
test_data = {
|
||||
"power_load": random.uniform(400, 600),
|
||||
"time_of_day": random.randint(0, 23),
|
||||
"production_rate": random.uniform(80, 120)
|
||||
}
|
||||
|
||||
opt_response = requests.post(
|
||||
f"{OPTIMIZER_MOCK_URL}/api/v1/optimize/{model_name}",
|
||||
json=test_data,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
if opt_response.status_code == 200:
|
||||
result = opt_response.json()
|
||||
print(f" ✅ {model_name}: Optimization completed")
|
||||
print(f" Processing time: {result.get('processing_time', 0):.2f}s")
|
||||
else:
|
||||
print(f" ❌ {model_name}: Optimization failed")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Optimization test failed: {e}")
|
||||
|
||||
def test_calejo_api():
|
||||
"""Test Calejo Control Adapter API"""
|
||||
print("🌐 Testing Calejo API...")
|
||||
|
||||
endpoints = [
|
||||
"/health",
|
||||
"/dashboard",
|
||||
"/api/v1/status",
|
||||
"/api/v1/metrics"
|
||||
]
|
||||
|
||||
for endpoint in endpoints:
|
||||
try:
|
||||
response = requests.get(f"{CALEJO_API_URL}{endpoint}", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print(f" ✅ {endpoint}: Accessible")
|
||||
else:
|
||||
print(f" ⚠️ {endpoint}: Status {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f" ❌ {endpoint}: Failed - {e}")
|
||||
|
||||
def run_comprehensive_test():
|
||||
"""Run comprehensive test scenario"""
|
||||
print("\n🚀 Starting comprehensive test scenario...")
|
||||
print("=" * 50)
|
||||
|
||||
# Test all components
|
||||
test_health_checks()
|
||||
print()
|
||||
|
||||
generate_scada_data()
|
||||
print()
|
||||
|
||||
test_optimization()
|
||||
print()
|
||||
|
||||
test_calejo_api()
|
||||
print()
|
||||
|
||||
print("✅ Comprehensive test completed!")
|
||||
print("\n📋 Test Summary:")
|
||||
print(" • Service health checks")
|
||||
print(" • SCADA data generation and control")
|
||||
print(" • Optimization model testing")
|
||||
print(" • Calejo API endpoint validation")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Wait a bit for services to start
|
||||
print("⏳ Waiting for services to initialize...")
|
||||
time.sleep(10)
|
||||
|
||||
run_comprehensive_test()
|
||||
EOF
|
||||
|
||||
print_success "Test data generator created"
|
||||
|
||||
# Start test services
|
||||
print_status "Starting test services..."
|
||||
|
||||
docker-compose -f docker-compose.test.yml up -d
|
||||
|
||||
# Wait for services to start
|
||||
print_status "Waiting for services to initialize..."
|
||||
sleep 30
|
||||
|
||||
# Run health checks
|
||||
print_status "Running health checks..."
|
||||
|
||||
# Check Calejo Control Adapter
|
||||
if curl -f http://localhost:8080/health > /dev/null 2>&1; then
|
||||
print_success "Calejo Control Adapter is healthy"
|
||||
else
|
||||
print_error "Calejo Control Adapter health check failed"
|
||||
fi
|
||||
|
||||
# Check Mock SCADA
|
||||
if curl -f http://localhost:8081/health > /dev/null 2>&1; then
|
||||
print_success "Mock SCADA is healthy"
|
||||
else
|
||||
print_error "Mock SCADA health check failed"
|
||||
fi
|
||||
|
||||
# Check Mock Optimizer
|
||||
if curl -f http://localhost:8082/health > /dev/null 2>&1; then
|
||||
print_success "Mock Optimizer is healthy"
|
||||
else
|
||||
print_error "Mock Optimizer health check failed"
|
||||
fi
|
||||
|
||||
# Run test data generator
|
||||
print_status "Running test data generator..."
|
||||
docker-compose -f docker-compose.test.yml run --rm test-data-generator
|
||||
|
||||
print_success "Test environment setup completed!"
|
||||
|
||||
# Display access information
|
||||
print ""
|
||||
echo "=================================================="
|
||||
echo " TEST ENVIRONMENT READY"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
echo "🌐 Access URLs:"
|
||||
echo " Calejo Dashboard: http://localhost:8080/dashboard"
|
||||
echo " Mock SCADA API: http://localhost:8081/api/v1/data"
|
||||
echo " Mock Optimizer API: http://localhost:8082/api/v1/models"
|
||||
echo " PostgreSQL: localhost:5432"
|
||||
echo ""
|
||||
echo "🔧 Management Commands:"
|
||||
echo " View logs: docker-compose -f docker-compose.test.yml logs -f"
|
||||
echo " Stop services: docker-compose -f docker-compose.test.yml down"
|
||||
echo " Cleanup: ./scripts/setup-test-environment.sh --clean"
|
||||
echo ""
|
||||
echo "🧪 Test Commands:"
|
||||
echo " Run tests: python -m pytest tests/"
|
||||
echo " Generate data: docker-compose -f docker-compose.test.yml run --rm test-data-generator"
|
||||
echo ""
|
||||
echo "=================================================="
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Quick test for mock SCADA and optimizer services
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧪 Testing Mock Services..."
|
||||
echo ""
|
||||
|
||||
# Test Mock SCADA
|
||||
echo "📊 Testing Mock SCADA..."
|
||||
if curl -s http://localhost:8081/health | grep -q "healthy"; then
|
||||
echo "✅ Mock SCADA is healthy"
|
||||
|
||||
# Get SCADA data
|
||||
echo " Fetching SCADA data..."
|
||||
curl -s http://localhost:8081/api/v1/data | jq '.data | keys' 2>/dev/null || echo " SCADA data available"
|
||||
else
|
||||
echo "❌ Mock SCADA is not responding"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test Mock Optimizer
|
||||
echo "🧠 Testing Mock Optimizer..."
|
||||
if curl -s http://localhost:8082/health | grep -q "healthy"; then
|
||||
echo "✅ Mock Optimizer is healthy"
|
||||
|
||||
# Get available models
|
||||
echo " Fetching optimization models..."
|
||||
curl -s http://localhost:8082/api/v1/models | jq '.models | keys' 2>/dev/null || echo " Optimization models available"
|
||||
else
|
||||
echo "❌ Mock Optimizer is not responding"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Test Calejo Control Adapter
|
||||
echo "🌐 Testing Calejo Control Adapter..."
|
||||
if curl -s http://localhost:8080/health | grep -q "healthy"; then
|
||||
echo "✅ Calejo Control Adapter is healthy"
|
||||
|
||||
# Test dashboard
|
||||
echo " Testing dashboard access..."
|
||||
curl -s -I http://localhost:8080/dashboard | head -1 | grep -q "200" && echo " Dashboard accessible" || echo " Dashboard status check"
|
||||
else
|
||||
echo "❌ Calejo Control Adapter is not responding"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ Mock services test completed!"
|
||||
Loading…
Reference in New Issue