Files
microdao-daarion/tools/contract_tool/tests/test_contract_tool.py
Apple 129e4ea1fc feat(platform): add new services, tools, tests and crews modules
New router intelligence modules (26 files): alert_ingest/store, audit_store,
architecture_pressure, backlog_generator/store, cost_analyzer, data_governance,
dependency_scanner, drift_analyzer, incident_* (5 files), llm_enrichment,
platform_priority_digest, provider_budget, release_check_runner, risk_* (6 files),
signature_state_store, sofiia_auto_router, tool_governance

New services:
- sofiia-console: Dockerfile, adapters/, monitor/nodes/ops/voice modules, launchd, react static
- memory-service: integration_endpoints, integrations, voice_endpoints, static UI
- aurora-service: full app suite (analysis, job_store, orchestrator, reporting, schemas, subagents)
- sofiia-supervisor: new supervisor service
- aistalk-bridge-lite: Telegram bridge lite
- calendar-service: CalDAV calendar service with reminders
- mlx-stt-service / mlx-tts-service: Apple Silicon speech services
- binance-bot-monitor: market monitor service
- node-worker: STT/TTS memory providers

New tools (9): agent_email, browser_tool, contract_tool, observability_tool,
oncall_tool, pr_reviewer_tool, repo_tool, safe_code_executor, secure_vault

New crews: agromatrix_crew (10 modules: depth_classifier, doc_facts, doc_focus,
farm_state, light_reply, llm_factory, memory_manager, proactivity, reflection_engine,
session_context, style_adapter, telemetry)

Tests: 85+ test files for all new modules
Made-with: Cursor
2026-03-03 07:14:14 -08:00

439 lines
10 KiB
Python

"""
Tests for Contract Tool (OpenAPI/JSON Schema)
"""
import pytest
import os
import sys
import yaml
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from services.router.tool_manager import ToolManager, ToolResult
class TestContractToolLinting:
"""Test OpenAPI linting functionality"""
@pytest.mark.asyncio
async def test_lint_missing_operation_id(self):
"""Test detection of missing operationId"""
tool_mgr = ToolManager({})
spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths:
/users:
get:
responses:
"200":
description: Success
"""
result = await tool_mgr._contract_tool({
"action": "lint_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": spec}
},
"options": {}
})
assert result.success is True
assert len(result.result["lint"]) > 0
assert any("operationId" in i["message"] for i in result.result["lint"])
@pytest.mark.asyncio
async def test_lint_good_spec(self):
"""Test that valid spec passes lint"""
tool_mgr = ToolManager({})
spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths:
/users:
get:
operationId: getUsers
responses:
"200":
description: Success
content:
application/json:
schema:
type: array
"""
result = await tool_mgr._contract_tool({
"action": "lint_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": spec}
},
"options": {}
})
assert result.success is True
errors = [i for i in result.result["lint"] if i["severity"] == "error"]
assert len(errors) == 0
@pytest.mark.asyncio
async def test_lint_no_spec(self):
"""Test error when no spec provided"""
tool_mgr = ToolManager({})
result = await tool_mgr._contract_tool({
"action": "lint_openapi",
"inputs": {},
"options": {}
})
assert result.success is False
class TestContractToolDiff:
"""Test OpenAPI diff/breaking changes detection"""
@pytest.mark.asyncio
async def test_endpoint_removed_breaking(self):
"""Test detection of removed endpoint"""
tool_mgr = ToolManager({})
base_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths:
/users:
get:
operationId: getUsers
responses:
"200":
description: Success
"""
head_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": base_spec},
"head": {"source": "text", "value": head_spec}
},
"options": {}
})
assert result.success is True
assert len(result.result["breaking"]) > 0
assert any("endpoint_removed" in i["type"] for i in result.result["breaking"])
@pytest.mark.asyncio
async def test_required_field_added_breaking(self):
"""Test detection of required field added"""
tool_mgr = ToolManager({})
base_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
User:
type: object
properties:
name:
type: string
"""
head_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
User:
type: object
required:
- email
properties:
name:
type: string
email:
type: string
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": base_spec},
"head": {"source": "text", "value": head_spec}
},
"options": {}
})
assert result.success is True
assert len(result.result["breaking"]) > 0
assert any("required_added" in i["type"] for i in result.result["breaking"])
@pytest.mark.asyncio
async def test_optional_field_added_nonbreaking(self):
"""Test that optional field addition is non-breaking"""
tool_mgr = ToolManager({})
base_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
User:
type: object
properties:
name:
type: string
"""
head_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
User:
type: object
properties:
name:
type: string
email:
type: string
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": base_spec},
"head": {"source": "text", "value": head_spec}
},
"options": {}
})
assert result.success is True
# Should have non-breaking, no breaking
breaking = result.result.get("breaking", [])
assert len(breaking) == 0
@pytest.mark.asyncio
async def test_enum_narrowed_breaking(self):
"""Test detection of enum narrowing"""
tool_mgr = ToolManager({})
base_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
Status:
type: string
enum:
- pending
- active
- completed
"""
head_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
components:
schemas:
Status:
type: string
enum:
- pending
- active
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": base_spec},
"head": {"source": "text", "value": head_spec}
},
"options": {}
})
assert result.success is True
assert len(result.result["breaking"]) > 0
@pytest.mark.asyncio
async def test_fail_on_breaking(self):
"""Test fail_on_breaking option"""
tool_mgr = ToolManager({})
base_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths:
/users:
get:
operationId: getUsers
responses:
"200":
description: Success
"""
head_spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": base_spec},
"head": {"source": "text", "value": head_spec}
},
"options": {
"fail_on_breaking": True
}
})
assert result.success is False
assert result.error is not None
class TestContractToolLimits:
"""Test limit enforcement"""
@pytest.mark.asyncio
async def test_max_chars_limit(self):
"""Test that max_chars limit is enforced"""
tool_mgr = ToolManager({})
large_spec = "x" * 900000 # 900KB
result = await tool_mgr._contract_tool({
"action": "lint_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": large_spec}
},
"options": {
"max_chars": 800000
}
})
assert result.success is False
assert "too large" in result.error.lower()
@pytest.mark.asyncio
async def test_missing_base_or_head(self):
"""Test error when base or head missing for diff"""
tool_mgr = ToolManager({})
spec = """
openapi: "3.0.0"
info:
title: Test API
version: "1.0.0"
paths: {}
"""
result = await tool_mgr._contract_tool({
"action": "diff_openapi",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": spec}
},
"options": {}
})
assert result.success is False
class TestContractToolStub:
"""Test client stub generation"""
@pytest.mark.asyncio
async def test_generate_python_stub(self):
"""Test Python client stub generation"""
tool_mgr = ToolManager({})
spec = """
openapi: "3.0.0"
info:
title: User API
version: "1.0.0"
paths:
/users:
get:
operationId: getUsers
summary: Get all users
responses:
"200":
description: Success
post:
operationId: createUser
summary: Create user
parameters:
- name: data
in: body
required: true
responses:
"201":
description: Created
"""
result = await tool_mgr._contract_tool({
"action": "generate_client_stub",
"inputs": {
"format": "openapi_yaml",
"base": {"source": "text", "value": spec}
},
"options": {}
})
assert result.success is True
assert "client_stub" in result.result
assert "def getUsers" in result.result["client_stub"]
assert "def createUser" in result.result["client_stub"]
if __name__ == "__main__":
pytest.main([__file__, "-v"])