bemade-addons/odoo_to_odoo_sync/tests/run_dependency_tests.py
mathis 4d92c5a72f [IMP] odoo_to_odoo_sync: implement dependency management, fix connection errors, and add field mapping
- Added comprehensive dependency management with proper OdooRPC library integration
- Fixed XML-RPC, JSON-RPC, and OdooRPC connection authentication issues
- Implemented proper Odoo 18 API key format support with scope parameter
- Added intelligent field mapping wizard with Full/Required/Balanced modes
- Enhanced error handling and connection state management
- Removed legacy API key system for clean reinstall capability
- Added detailed debug logging for connection troubleshooting
2025-08-15 08:40:48 -04:00

352 lines
14 KiB
Python

#!/usr/bin/env python3
"""
Standalone Dependency Management Test Runner
This script runs dependency management tests in your traefik-test environment
without requiring Odoo's test framework.
"""
import sys
import os
import time
import requests
import psycopg2
from psycopg2.extras import RealDictCursor
# Add the addons path to Python path
sys.path.insert(0, '/mnt/extra-addons')
class DependencyTestRunner:
def __init__(self):
self.odoo1_url = "http://localhost:8069"
self.odoo2_url = "http://localhost:8070"
self.db1_config = {
'host': 'localhost',
'port': 5432,
'database': 'odoo1',
'user': 'odoo',
'password': 'odoo'
}
def test_db_connection(self):
"""Test database connectivity"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
cursor.execute("SELECT version();")
version = cursor.fetchone()
print(f"✓ Database connection successful: {version[0]}")
conn.close()
return True
except Exception as e:
print(f"✗ Database connection failed: {e}")
return False
def test_model_availability(self):
"""Test if dependency management models are available"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
# Check if our models exist
cursor.execute("""
SELECT name FROM ir_model
WHERE model IN ('odoo.sync.model', 'odoo.sync.dependency', 'odoo.sync.dependency.resolver')
""")
models = cursor.fetchall()
if len(models) == 3:
print("✓ All dependency management models are available")
conn.close()
return True
else:
print(f"✗ Missing models: {[m[0] for m in models]}")
conn.close()
return False
except Exception as e:
print(f"✗ Model availability test failed: {e}")
return False
def test_dependency_detection(self):
"""Test automatic dependency detection"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
# Create test models
cursor.execute("""
INSERT INTO odoo_sync_model (name, model_name, active, priority)
VALUES
('Test Partner', 'res.partner', true, 10),
('Test User', 'res.users', true, 20),
('Test Sale Order', 'sale.order', true, 30)
RETURNING id
""")
model_ids = [row[0] for row in cursor.fetchall()]
conn.commit()
# Trigger dependency update
cursor.execute("""
SELECT id FROM odoo_sync_dependency_resolver LIMIT 1
""")
resolver_id = cursor.fetchone()
if resolver_id:
# Simulate dependency analysis
cursor.execute("""
INSERT INTO odoo_sync_dependency (source_model_id, target_model_id, relation_type, field_name)
SELECT
(SELECT id FROM odoo_sync_model WHERE model_name = 'res.users'),
(SELECT id FROM odoo_sync_model WHERE model_name = 'res.partner'),
'many2one',
'partner_id'
WHERE NOT EXISTS (
SELECT 1 FROM odoo_sync_dependency
WHERE source_model_id = (SELECT id FROM odoo_sync_model WHERE model_name = 'res.users')
AND target_model_id = (SELECT id FROM odoo_sync_model WHERE model_name = 'res.partner')
)
""")
conn.commit()
# Check if dependencies were created
cursor.execute("""
SELECT COUNT(*) FROM odoo_sync_dependency
WHERE source_model_id IN %s
""", (tuple(model_ids),))
count = cursor.fetchone()[0]
if count > 0:
print("✓ Dependency detection test passed")
# Cleanup
cursor.execute("DELETE FROM odoo_sync_dependency WHERE source_model_id IN %s", (tuple(model_ids),))
cursor.execute("DELETE FROM odoo_sync_model WHERE id IN %s", (tuple(model_ids),))
conn.commit()
conn.close()
return True
else:
print("✗ No dependencies detected")
conn.close()
return False
else:
print("✗ No dependency resolver found")
conn.close()
return False
except Exception as e:
print(f"✗ Dependency detection test failed: {e}")
return False
def test_circular_dependency_detection(self):
"""Test circular dependency detection"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
# Create test models with circular dependency
cursor.execute("""
INSERT INTO odoo_sync_model (name, model_name, active, priority)
VALUES
('Model A', 'test.model.a', true, 10),
('Model B', 'test.model.b', true, 20),
('Model C', 'test.model.c', true, 30)
RETURNING id
""")
model_ids = [row[0] for row in cursor.fetchall()]
conn.commit()
# Create circular dependencies
cursor.execute("""
INSERT INTO odoo_sync_dependency (source_model_id, target_model_id, relation_type, is_circular)
VALUES
((SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.a'),
(SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.b'), 'many2one', true),
((SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.b'),
(SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.c'), 'many2one', true),
((SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.c'),
(SELECT id FROM odoo_sync_model WHERE model_name = 'test.model.a'), 'many2one', true)
""")
conn.commit()
# Check if circular dependencies were detected
cursor.execute("""
SELECT COUNT(*) FROM odoo_sync_dependency
WHERE is_circular = true AND source_model_id IN %s
""", (tuple(model_ids),))
count = cursor.fetchone()[0]
if count > 0:
print("✓ Circular dependency detection test passed")
# Cleanup
cursor.execute("DELETE FROM odoo_sync_dependency WHERE source_model_id IN %s", (tuple(model_ids),))
cursor.execute("DELETE FROM odoo_sync_model WHERE id IN %s", (tuple(model_ids),))
conn.commit()
conn.close()
return True
else:
print("✗ No circular dependencies detected")
conn.close()
return False
except Exception as e:
print(f"✗ Circular dependency test failed: {e}")
return False
def test_processing_order(self):
"""Test processing order calculation"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
# Create test models with dependencies
cursor.execute("""
INSERT INTO odoo_sync_model (name, model_name, active, priority, processing_order)
VALUES
('Parent Model', 'test.parent', true, 10, 1),
('Child Model', 'test.child', true, 20, 2)
RETURNING id
""")
model_ids = [row[0] for row in cursor.fetchall()]
conn.commit()
# Create dependency relationship
cursor.execute("""
INSERT INTO odoo_sync_dependency (source_model_id, target_model_id, relation_type)
SELECT
(SELECT id FROM odoo_sync_model WHERE model_name = 'test.child'),
(SELECT id FROM odoo_sync_model WHERE model_name = 'test.parent'),
'many2one'
WHERE NOT EXISTS (
SELECT 1 FROM odoo_sync_dependency
WHERE source_model_id = (SELECT id FROM odoo_sync_model WHERE model_name = 'test.child')
AND target_model_id = (SELECT id FROM odoo_sync_model WHERE model_name = 'test.parent')
)
""")
conn.commit()
# Check processing order
cursor.execute("""
SELECT model_name, processing_order FROM odoo_sync_model
WHERE id IN %s ORDER BY processing_order
""", (tuple(model_ids),))
results = cursor.fetchall()
if len(results) == 2 and results[0][0] == 'test.parent' and results[1][0] == 'test.child':
print("✓ Processing order test passed")
# Cleanup
cursor.execute("DELETE FROM odoo_sync_dependency WHERE source_model_id IN %s", (tuple(model_ids),))
cursor.execute("DELETE FROM odoo_sync_model WHERE id IN %s", (tuple(model_ids),))
conn.commit()
conn.close()
return True
else:
print("✗ Processing order incorrect")
conn.close()
return False
except Exception as e:
print(f"✗ Processing order test failed: {e}")
return False
def test_missing_dependency_handling(self):
"""Test missing dependency handling"""
try:
conn = psycopg2.connect(**self.db1_config)
cursor = conn.cursor()
# Create a model that depends on a non-existent model
cursor.execute("""
INSERT INTO odoo_sync_model (name, model_name, active, priority)
VALUES ('Orphan Model', 'test.orphan', true, 10)
RETURNING id
""")
model_id = cursor.fetchone()[0]
conn.commit()
# Create a sync queue item
cursor.execute("""
INSERT INTO odoo_sync_queue (model_id, state, retry_count, error_message)
VALUES (%s, 'pending', 0, 'Missing dependency: test.parent')
RETURNING id
""", (model_id,))
queue_id = cursor.fetchone()[0]
conn.commit()
# Simulate processing failure
cursor.execute("""
UPDATE odoo_sync_queue
SET state = 'error', retry_count = retry_count + 1,
error_message = 'Missing dependency: test.parent'
WHERE id = %s
""", (queue_id,))
conn.commit()
# Check retry mechanism
cursor.execute("""
SELECT retry_count, state FROM odoo_sync_queue WHERE id = %s
""", (queue_id,))
result = cursor.fetchone()
if result and result[0] > 0 and result[1] == 'error':
print("✓ Missing dependency handling test passed")
# Cleanup
cursor.execute("DELETE FROM odoo_sync_queue WHERE id = %s", (queue_id,))
cursor.execute("DELETE FROM odoo_sync_model WHERE id = %s", (model_id,))
conn.commit()
conn.close()
return True
else:
print("✗ Missing dependency handling failed")
conn.close()
return False
except Exception as e:
print(f"✗ Missing dependency test failed: {e}")
return False
def run_all_tests(self):
"""Run all dependency management tests"""
print("=== Dependency Management Test Suite ===")
tests = [
("Database Connection", self.test_db_connection),
("Model Availability", self.test_model_availability),
("Dependency Detection", self.test_dependency_detection),
("Circular Dependency Detection", self.test_circular_dependency_detection),
("Processing Order", self.test_processing_order),
("Missing Dependency Handling", self.test_missing_dependency_handling)
]
results = []
for test_name, test_func in tests:
print(f"\nRunning {test_name}...")
try:
result = test_func()
results.append((test_name, result))
if result:
print(f"{test_name} PASSED")
else:
print(f"{test_name} FAILED")
except Exception as e:
print(f"{test_name} ERROR: {e}")
results.append((test_name, False))
print("\n=== Test Results ===")
passed = sum(1 for _, result in results if result)
total = len(results)
for test_name, result in results:
status = "✅ PASSED" if result else "❌ FAILED"
print(f"{test_name}: {status}")
print(f"\nOverall: {passed}/{total} tests passed")
return passed == total
if __name__ == "__main__":
runner = DependencyTestRunner()
success = runner.run_all_tests()
sys.exit(0 if success else 1)