--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