--init
This commit is contained in:
parent
6c71045b3a
commit
de3abc691b
136
README_TESTS.md
136
README_TESTS.md
@ -1,136 +0,0 @@
|
||||
# RabbitMQ Test Suite
|
||||
|
||||
This directory contains comprehensive tests for different RabbitMQ exchange types and patterns.
|
||||
|
||||
## Test Files
|
||||
|
||||
### Individual Test Files
|
||||
|
||||
1. **`run_fanout_test.py`** - Tests Fanout Exchange
|
||||
- Broadcasts messages to all bound queues
|
||||
- Demonstrates one-to-many messaging pattern
|
||||
- Run: `python run_fanout_test.py`
|
||||
|
||||
2. **`run_direct_test.py`** - Tests Direct Exchange
|
||||
- Routes messages based on exact routing key matches
|
||||
- Demonstrates selective message routing
|
||||
- Run: `python run_direct_test.py`
|
||||
|
||||
3. **`run_topic_test.py`** - Tests Topic Exchange
|
||||
- Routes messages using wildcard patterns (* and #)
|
||||
- Demonstrates hierarchical message routing
|
||||
- Run: `python run_topic_test.py`
|
||||
|
||||
4. **`run_multi_queue_test.py`** - Tests Multi-Queue Load Balancing
|
||||
- Distributes messages across multiple queues
|
||||
- Demonstrates load balancing and parallel processing
|
||||
- Run: `python run_multi_queue_test.py`
|
||||
|
||||
### Combined Test File
|
||||
|
||||
5. **`test.py`** - Runs all tests sequentially
|
||||
- Executes all exchange type tests in order
|
||||
- Run: `python test.py`
|
||||
|
||||
## Test Features
|
||||
|
||||
### Producer and Consumer Coordination
|
||||
- Each test starts consumers in the background
|
||||
- Producers send messages after consumers are ready
|
||||
- Tests demonstrate real-time message processing
|
||||
- Automatic cleanup and task cancellation
|
||||
|
||||
### Message Patterns Tested
|
||||
|
||||
#### Fanout Exchange
|
||||
- **Pattern**: One-to-many broadcasting
|
||||
- **Queues**: 3 queues (demo.fanout.queue-0, demo.fanout.queue-1, demo.fanout.queue-2)
|
||||
- **Behavior**: All queues receive every message
|
||||
- **Use Case**: Notifications, announcements, logging
|
||||
|
||||
#### Direct Exchange
|
||||
- **Pattern**: Exact routing key matching
|
||||
- **Queues**: error, warning, info (with debug routing to info)
|
||||
- **Behavior**: Messages routed based on exact routing key
|
||||
- **Use Case**: Log level routing, priority-based processing
|
||||
|
||||
#### Topic Exchange
|
||||
- **Pattern**: Wildcard pattern matching
|
||||
- **Queues**: Critical, Success, Failed
|
||||
- **Behavior**: Messages routed using * and # wildcards
|
||||
- **Use Case**: Hierarchical event routing, microservice communication
|
||||
|
||||
#### Multi-Queue Load Balancing
|
||||
- **Pattern**: Round-robin distribution
|
||||
- **Queues**: 3 balanced queues
|
||||
- **Behavior**: Messages distributed evenly across queues
|
||||
- **Use Case**: Horizontal scaling, parallel processing
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Prerequisites
|
||||
- RabbitMQ server running on localhost:5673
|
||||
- Python 3.7+ with asyncio support
|
||||
- Required packages: aio-pika
|
||||
|
||||
### Individual Test Execution
|
||||
```bash
|
||||
# Test Fanout Exchange
|
||||
python run_fanout_test.py
|
||||
|
||||
# Test Direct Exchange
|
||||
python run_direct_test.py
|
||||
|
||||
# Test Topic Exchange
|
||||
python run_topic_test.py
|
||||
|
||||
# Test Multi-Queue Load Balancing
|
||||
python run_multi_queue_test.py
|
||||
```
|
||||
|
||||
### Run All Tests
|
||||
```bash
|
||||
python test.py
|
||||
```
|
||||
|
||||
## Test Output
|
||||
|
||||
Each test provides detailed output showing:
|
||||
- Consumer startup messages
|
||||
- Message reception and processing
|
||||
- Queue routing behavior
|
||||
- Message persistence status
|
||||
- Test completion status
|
||||
|
||||
## Configuration
|
||||
|
||||
Tests use the configuration from `config.py`:
|
||||
- RabbitMQ URI: `amqp://guest:guest@localhost:5673/`
|
||||
- Exchange and queue naming conventions
|
||||
- Message persistence settings
|
||||
|
||||
## Architecture
|
||||
|
||||
### Producer Side
|
||||
- Sets up exchanges and queues
|
||||
- Publishes test messages with appropriate routing keys
|
||||
- Handles connection management
|
||||
|
||||
### Consumer Side
|
||||
- Starts multiple consumers for different queues
|
||||
- Processes messages with simulated business logic
|
||||
- Demonstrates concurrent message handling
|
||||
|
||||
### Test Coordination
|
||||
- Uses asyncio tasks for concurrent execution
|
||||
- Implements proper startup/shutdown sequences
|
||||
- Ensures clean resource cleanup
|
||||
|
||||
## Extending Tests
|
||||
|
||||
To add new test scenarios:
|
||||
1. Create a new test file following the naming pattern `run_xxx_test.py`
|
||||
2. Import appropriate producer and consumer functions
|
||||
3. Implement the test logic with proper async/await patterns
|
||||
4. Add consumer startup, message publishing, and cleanup phases
|
||||
5. Update this README with the new test description
|
||||
BIN
assert/img.png
Normal file
BIN
assert/img.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
assert/img_1.png
Normal file
BIN
assert/img_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
assert/img_2.png
Normal file
BIN
assert/img_2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
assert/img_3.png
Normal file
BIN
assert/img_3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
BIN
assert/img_4.png
Normal file
BIN
assert/img_4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
BIN
assert/img_5.png
Normal file
BIN
assert/img_5.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
75
help.py
75
help.py
@ -1,75 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
RabbitMQ Test Help
|
||||
Shows available test commands and usage information.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def show_help():
|
||||
"""Display help information for RabbitMQ tests"""
|
||||
print("🐰 RabbitMQ Test Suite Help")
|
||||
print("=" * 50)
|
||||
|
||||
print("\n📋 Available Test Files:")
|
||||
print("-" * 30)
|
||||
|
||||
test_files = [
|
||||
("run_fanout_test.py", "Test Fanout Exchange (broadcast messaging)"),
|
||||
("run_direct_test.py", "Test Direct Exchange (routing by key)"),
|
||||
("run_topic_test.py", "Test Topic Exchange (wildcard routing)"),
|
||||
("run_multi_queue_test.py", "Test Multi-Queue Load Balancing"),
|
||||
("test.py", "Run all tests sequentially"),
|
||||
("run_all_tests.py", "Run all individual test files with summary")
|
||||
]
|
||||
|
||||
for filename, description in test_files:
|
||||
exists = "✅" if os.path.exists(filename) else "❌"
|
||||
print(f"{exists} {filename:<25} - {description}")
|
||||
|
||||
print("\n🚀 Usage Examples:")
|
||||
print("-" * 20)
|
||||
print("python run_fanout_test.py # Test fanout exchange")
|
||||
print("python run_direct_test.py # Test direct exchange")
|
||||
print("python run_topic_test.py # Test topic exchange")
|
||||
print("python run_multi_queue_test.py # Test load balancing")
|
||||
print("python test.py # Run all tests")
|
||||
print("python run_all_tests.py # Run with detailed summary")
|
||||
|
||||
print("\n📖 Test Patterns:")
|
||||
print("-" * 20)
|
||||
print("• Fanout: One-to-many broadcasting")
|
||||
print("• Direct: Exact routing key matching")
|
||||
print("• Topic: Wildcard pattern matching (* and #)")
|
||||
print("• Multi: Round-robin load balancing")
|
||||
|
||||
print("\n⚙️ Prerequisites:")
|
||||
print("-" * 20)
|
||||
print("• RabbitMQ server running on localhost:5673")
|
||||
print("• Python 3.7+ with asyncio support")
|
||||
print("• aio-pika package installed")
|
||||
|
||||
print("\n📁 File Structure:")
|
||||
print("-" * 20)
|
||||
print("product/ - Message producers")
|
||||
print("comsumer/ - Message consumers")
|
||||
print("config.py - RabbitMQ configuration")
|
||||
print("run_*.py - Individual test files")
|
||||
print("test.py - Combined test runner")
|
||||
|
||||
print("\n🔧 Configuration:")
|
||||
print("-" * 20)
|
||||
print("Edit config.py to change:")
|
||||
print("• RabbitMQ connection URI")
|
||||
print("• Exchange and queue names")
|
||||
print("• Message persistence settings")
|
||||
|
||||
print("\n📚 Documentation:")
|
||||
print("-" * 20)
|
||||
print("See README_TESTS.md for detailed information")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
show_help()
|
||||
113
run_all_tests.py
113
run_all_tests.py
@ -1,113 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run All RabbitMQ Tests
|
||||
This script runs all individual test files in sequence.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Add current directory to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
def run_test_file(test_file):
|
||||
"""Run a test file and return success status"""
|
||||
try:
|
||||
print(f"\n{'='*60}")
|
||||
print(f"Running {test_file}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
result = subprocess.run([sys.executable, test_file],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30)
|
||||
|
||||
if result.returncode == 0:
|
||||
print(f"✅ {test_file} completed successfully")
|
||||
if result.stdout:
|
||||
print("Output:")
|
||||
print(result.stdout)
|
||||
return True
|
||||
else:
|
||||
print(f"❌ {test_file} failed with return code {result.returncode}")
|
||||
if result.stderr:
|
||||
print("Error:")
|
||||
print(result.stderr)
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"⏰ {test_file} timed out after 30 seconds")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"💥 {test_file} failed with exception: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to run all tests"""
|
||||
print("🚀 Starting RabbitMQ Test Suite")
|
||||
print("This will run all individual test files in sequence.")
|
||||
|
||||
# List of test files to run
|
||||
test_files = [
|
||||
"run_fanout_test.py",
|
||||
"run_direct_test.py",
|
||||
"run_topic_test.py",
|
||||
"run_multi_queue_test.py"
|
||||
]
|
||||
|
||||
# Check if test files exist
|
||||
missing_files = []
|
||||
for test_file in test_files:
|
||||
if not os.path.exists(test_file):
|
||||
missing_files.append(test_file)
|
||||
|
||||
if missing_files:
|
||||
print(f"❌ Missing test files: {missing_files}")
|
||||
sys.exit(1)
|
||||
|
||||
# Run all tests
|
||||
results = []
|
||||
for test_file in test_files:
|
||||
success = run_test_file(test_file)
|
||||
results.append((test_file, success))
|
||||
|
||||
# Wait between tests
|
||||
if test_file != test_files[-1]: # Don't wait after last test
|
||||
print("\n⏳ Waiting 2 seconds before next test...")
|
||||
import time
|
||||
time.sleep(2)
|
||||
|
||||
# Print summary
|
||||
print(f"\n{'='*60}")
|
||||
print("TEST SUMMARY")
|
||||
print(f"{'='*60}")
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for test_file, success in results:
|
||||
status = "✅ PASSED" if success else "❌ FAILED"
|
||||
print(f"{test_file:<25} {status}")
|
||||
if success:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\nTotal: {len(results)} tests")
|
||||
print(f"Passed: {passed}")
|
||||
print(f"Failed: {failed}")
|
||||
|
||||
if failed == 0:
|
||||
print("\n🎉 All tests passed!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"\n💥 {failed} test(s) failed!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
165
test.py
165
test.py
@ -1,165 +0,0 @@
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add current directory to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from product.direct_multi_publish import setup_multi_queue_balance, BalancedProducer
|
||||
from product.direct_publish import setup_direct_exchange, direct_publish
|
||||
from product.fanout_publish import fanout_publish, setup_fanout_exchange
|
||||
from product.topic_publish import setup_topic_exchange, topic_publish
|
||||
from comsumer.direct_consumer import start_all_direct_consumers
|
||||
from comsumer.fanout_consumer import start_all_fanout_consumers
|
||||
from comsumer.topic_consumer import start_all_topic_consumers
|
||||
from comsumer.direct_multi_consumer import start_balanced_consumers
|
||||
|
||||
|
||||
async def run_fanout_test():
|
||||
"""Run fanout exchange test with producer and consumer"""
|
||||
print("=== Running Fanout Exchange Test ===")
|
||||
|
||||
# Start consumer in background
|
||||
consumer_task = asyncio.create_task(start_all_fanout_consumers())
|
||||
|
||||
# Wait for consumer to start
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Setup and publish messages
|
||||
await setup_fanout_exchange("demo.fanout", "demo.fanout.queue-")
|
||||
await fanout_publish(message="hello world", exchange_name="demo.fanout")
|
||||
await fanout_publish(message="test message 2", exchange_name="demo.fanout")
|
||||
await fanout_publish(message="test message 3", exchange_name="demo.fanout")
|
||||
|
||||
# Wait for messages to be processed
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# Cancel consumer
|
||||
consumer_task.cancel()
|
||||
print("✅ Fanout test completed successfully!")
|
||||
|
||||
|
||||
async def run_direct_exchange_test():
|
||||
"""Run direct exchange test with producer and consumer"""
|
||||
print("=== Running Direct Exchange Test ===")
|
||||
|
||||
# Start consumer in background
|
||||
consumer_task = asyncio.create_task(start_all_direct_consumers())
|
||||
|
||||
# Wait for consumer to start
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Setup exchange and publish messages
|
||||
await setup_direct_exchange()
|
||||
|
||||
test_messages = [
|
||||
("System crash, unable to start", "error"), # Route to error queue
|
||||
("Disk space insufficient", "warning"), # Route to warning queue
|
||||
("User login successful", "info"), # Route to info queue
|
||||
("Debug info: Database connection successful", "debug") # Route to info queue
|
||||
]
|
||||
|
||||
for msg, routing_key in test_messages:
|
||||
await direct_publish(msg, routing_key)
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
# Wait for messages to be processed
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# Cancel consumer
|
||||
consumer_task.cancel()
|
||||
print("✅ Direct exchange test completed successfully!")
|
||||
|
||||
|
||||
async def run_topic_exchange_test():
|
||||
"""Run topic exchange test with producer and consumer"""
|
||||
print("=== Running Topic Exchange Test ===")
|
||||
|
||||
# Start consumer in background
|
||||
consumer_task = asyncio.create_task(start_all_topic_consumers())
|
||||
|
||||
# Wait for consumer to start
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Setup exchange and publish messages
|
||||
await setup_topic_exchange()
|
||||
|
||||
test_messages = [
|
||||
("Order creation failed (critical error)", "order.create.critical"),
|
||||
("User login successful", "user.login.success"),
|
||||
("Order payment completed", "order.pay.success"),
|
||||
("System crash (critical error)", "system.crash.critical"),
|
||||
("User login failed", "user.login.failed"),
|
||||
("Normal system log", "system.log.info") # Won't match any binding key, will be discarded
|
||||
]
|
||||
|
||||
for msg, routing_key in test_messages:
|
||||
await topic_publish(msg, routing_key)
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
# Wait for messages to be processed
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# Cancel consumer
|
||||
consumer_task.cancel()
|
||||
print("✅ Topic exchange test completed successfully!")
|
||||
|
||||
|
||||
async def run_multi_queue_balance_test():
|
||||
"""Run multi-queue load balancing test with producer and consumer"""
|
||||
print("=== Running Multi-Queue Load Balancing Test ===")
|
||||
|
||||
queue_count = 3
|
||||
|
||||
# Start consumer in background
|
||||
consumer_task = asyncio.create_task(start_balanced_consumers(queue_count=queue_count))
|
||||
|
||||
# Wait for consumer to start
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Setup and publish messages
|
||||
await setup_multi_queue_balance(queue_count=queue_count)
|
||||
|
||||
producer = BalancedProducer(queue_count=queue_count)
|
||||
await producer.connect()
|
||||
|
||||
for i in range(10):
|
||||
await producer.publish(f"Task {i + 1}: Multi-queue load balancing test")
|
||||
await asyncio.sleep(0.3)
|
||||
|
||||
await producer.close()
|
||||
|
||||
# Wait for messages to be processed
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# Cancel consumer
|
||||
consumer_task.cancel()
|
||||
print("✅ Multi-queue load balancing test completed successfully!")
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main function to run all tests"""
|
||||
print("🚀 Starting RabbitMQ Tests...")
|
||||
|
||||
try:
|
||||
# Run all tests
|
||||
await run_fanout_test()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await run_direct_exchange_test()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await run_topic_exchange_test()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
await run_multi_queue_balance_test()
|
||||
|
||||
print("\n🎉 All tests completed successfully!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Test failed: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Loading…
Reference in New Issue
Block a user