python-detector-worker/tests/unit/pipeline/test_field_mapper.py
2025-09-12 18:55:23 +07:00

786 lines
No EOL
29 KiB
Python

"""
Unit tests for field mapping and template resolution.
"""
import pytest
from unittest.mock import Mock, patch
from datetime import datetime
import json
from detector_worker.pipeline.field_mapper import (
FieldMapper,
MappingContext,
TemplateResolver,
FieldMappingError,
NestedFieldAccessor
)
from detector_worker.detection.detection_result import DetectionResult, BoundingBox
class TestNestedFieldAccessor:
"""Test nested field access functionality."""
def test_get_nested_value_simple(self):
"""Test getting simple nested values."""
data = {
"user": {
"name": "John",
"age": 30,
"address": {
"city": "New York",
"zip": "10001"
}
}
}
accessor = NestedFieldAccessor()
assert accessor.get_nested_value(data, "user.name") == "John"
assert accessor.get_nested_value(data, "user.age") == 30
assert accessor.get_nested_value(data, "user.address.city") == "New York"
assert accessor.get_nested_value(data, "user.address.zip") == "10001"
def test_get_nested_value_array_access(self):
"""Test accessing array elements."""
data = {
"results": [
{"score": 0.9, "label": "car"},
{"score": 0.8, "label": "truck"}
],
"bbox": [100, 200, 300, 400]
}
accessor = NestedFieldAccessor()
assert accessor.get_nested_value(data, "results[0].score") == 0.9
assert accessor.get_nested_value(data, "results[0].label") == "car"
assert accessor.get_nested_value(data, "results[1].score") == 0.8
assert accessor.get_nested_value(data, "bbox[0]") == 100
assert accessor.get_nested_value(data, "bbox[3]") == 400
def test_get_nested_value_nonexistent_path(self):
"""Test accessing non-existent paths."""
data = {"user": {"name": "John"}}
accessor = NestedFieldAccessor()
assert accessor.get_nested_value(data, "user.nonexistent") is None
assert accessor.get_nested_value(data, "nonexistent.field") is None
assert accessor.get_nested_value(data, "user.address.city") is None
def test_get_nested_value_with_default(self):
"""Test getting nested values with default fallback."""
data = {"user": {"name": "John"}}
accessor = NestedFieldAccessor()
assert accessor.get_nested_value(data, "user.age", default=25) == 25
assert accessor.get_nested_value(data, "user.name", default="Unknown") == "John"
def test_set_nested_value(self):
"""Test setting nested values."""
data = {}
accessor = NestedFieldAccessor()
accessor.set_nested_value(data, "user.name", "John")
assert data["user"]["name"] == "John"
accessor.set_nested_value(data, "user.address.city", "New York")
assert data["user"]["address"]["city"] == "New York"
accessor.set_nested_value(data, "scores[0]", 0.95)
assert data["scores"][0] == 0.95
def test_set_nested_value_overwrite(self):
"""Test overwriting existing nested values."""
data = {"user": {"name": "John", "age": 30}}
accessor = NestedFieldAccessor()
accessor.set_nested_value(data, "user.name", "Jane")
assert data["user"]["name"] == "Jane"
assert data["user"]["age"] == 30 # Should not affect other fields
class TestTemplateResolver:
"""Test template string resolution."""
def test_resolve_simple_template(self):
"""Test resolving simple template variables."""
resolver = TemplateResolver()
template = "Hello {name}, you are {age} years old"
context = {"name": "John", "age": 30}
result = resolver.resolve(template, context)
assert result == "Hello John, you are 30 years old"
def test_resolve_nested_template(self):
"""Test resolving nested field templates."""
resolver = TemplateResolver()
template = "User: {user.name} from {user.address.city}"
context = {
"user": {
"name": "John",
"address": {"city": "New York", "zip": "10001"}
}
}
result = resolver.resolve(template, context)
assert result == "User: John from New York"
def test_resolve_array_template(self):
"""Test resolving array element templates."""
resolver = TemplateResolver()
template = "First result: {results[0].label} ({results[0].score})"
context = {
"results": [
{"label": "car", "score": 0.95},
{"label": "truck", "score": 0.87}
]
}
result = resolver.resolve(template, context)
assert result == "First result: car (0.95)"
def test_resolve_missing_variables(self):
"""Test resolving templates with missing variables."""
resolver = TemplateResolver()
template = "Hello {name}, you are {age} years old"
context = {"name": "John"} # Missing age
with pytest.raises(FieldMappingError) as exc_info:
resolver.resolve(template, context)
assert "Variable 'age' not found" in str(exc_info.value)
def test_resolve_with_defaults(self):
"""Test resolving templates with default values."""
resolver = TemplateResolver(allow_missing=True)
template = "Hello {name}, you are {age|25} years old"
context = {"name": "John"} # Missing age, should use default
result = resolver.resolve(template, context)
assert result == "Hello John, you are 25 years old"
def test_resolve_complex_template(self):
"""Test resolving complex templates with multiple variable types."""
resolver = TemplateResolver()
template = "{camera_id}:{timestamp}:{session_id}:{results[0].class}_{bbox[0]}_{bbox[1]}"
context = {
"camera_id": "cam001",
"timestamp": 1640995200000,
"session_id": "sess123",
"results": [{"class": "car", "confidence": 0.95}],
"bbox": [100, 200, 300, 400]
}
result = resolver.resolve(template, context)
assert result == "cam001:1640995200000:sess123:car_100_200"
def test_resolve_conditional_template(self):
"""Test resolving conditional templates."""
resolver = TemplateResolver()
# Simple conditional
template = "{name} is {age > 18 ? 'adult' : 'minor'}"
context_adult = {"name": "John", "age": 25}
result_adult = resolver.resolve(template, context_adult)
assert result_adult == "John is adult"
context_minor = {"name": "Jane", "age": 16}
result_minor = resolver.resolve(template, context_minor)
assert result_minor == "Jane is minor"
def test_escape_braces(self):
"""Test escaping braces in templates."""
resolver = TemplateResolver()
template = "Literal {{braces}} and variable {name}"
context = {"name": "John"}
result = resolver.resolve(template, context)
assert result == "Literal {braces} and variable John"
class TestMappingContext:
"""Test mapping context data structure."""
def test_creation(self):
"""Test mapping context creation."""
detection = DetectionResult("car", 0.9, BoundingBox(100, 200, 300, 400), 1001, 1640995200000)
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123",
detection=detection,
timestamp=1640995200000
)
assert context.camera_id == "camera_001"
assert context.display_id == "display_001"
assert context.session_id == "session_123"
assert context.detection == detection
assert context.timestamp == 1640995200000
assert context.branch_results == {}
assert context.metadata == {}
def test_add_branch_result(self):
"""Test adding branch results to context."""
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123"
)
context.add_branch_result("car_brand_cls", {"brand": "Toyota", "confidence": 0.87})
context.add_branch_result("car_bodytype_cls", {"body_type": "Sedan", "confidence": 0.82})
assert len(context.branch_results) == 2
assert context.branch_results["car_brand_cls"]["brand"] == "Toyota"
assert context.branch_results["car_bodytype_cls"]["body_type"] == "Sedan"
def test_to_dict(self):
"""Test converting context to dictionary."""
detection = DetectionResult("car", 0.9, BoundingBox(100, 200, 300, 400), 1001, 1640995200000)
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123",
detection=detection,
timestamp=1640995200000
)
context.add_branch_result("car_brand_cls", {"brand": "Toyota"})
context.add_metadata("model_id", "yolo_v8")
context_dict = context.to_dict()
assert context_dict["camera_id"] == "camera_001"
assert context_dict["display_id"] == "display_001"
assert context_dict["session_id"] == "session_123"
assert context_dict["timestamp"] == 1640995200000
assert context_dict["class"] == "car"
assert context_dict["confidence"] == 0.9
assert context_dict["track_id"] == 1001
assert context_dict["bbox"]["x1"] == 100
assert context_dict["car_brand_cls"]["brand"] == "Toyota"
assert context_dict["model_id"] == "yolo_v8"
def test_add_metadata(self):
"""Test adding metadata to context."""
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123"
)
context.add_metadata("model_version", "v2.1")
context.add_metadata("inference_time", 0.15)
assert context.metadata["model_version"] == "v2.1"
assert context.metadata["inference_time"] == 0.15
class TestFieldMapper:
"""Test field mapping functionality."""
def test_initialization(self):
"""Test field mapper initialization."""
mapper = FieldMapper()
assert isinstance(mapper.template_resolver, TemplateResolver)
assert isinstance(mapper.field_accessor, NestedFieldAccessor)
def test_map_fields_simple(self):
"""Test simple field mapping."""
mapper = FieldMapper()
field_mappings = {
"camera_id": "{camera_id}",
"detection_class": "{class}",
"confidence_score": "{confidence}",
"track_identifier": "{track_id}"
}
detection = DetectionResult("car", 0.92, BoundingBox(100, 200, 300, 400), 1001, 1640995200000)
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123",
detection=detection,
timestamp=1640995200000
)
mapped_fields = mapper.map_fields(field_mappings, context)
assert mapped_fields["camera_id"] == "camera_001"
assert mapped_fields["detection_class"] == "car"
assert mapped_fields["confidence_score"] == 0.92
assert mapped_fields["track_identifier"] == 1001
def test_map_fields_with_branch_results(self):
"""Test field mapping with branch results."""
mapper = FieldMapper()
field_mappings = {
"car_brand": "{car_brand_cls.brand}",
"car_model": "{car_brand_cls.model}",
"body_type": "{car_bodytype_cls.body_type}",
"brand_confidence": "{car_brand_cls.confidence}",
"combined_info": "{car_brand_cls.brand} {car_bodytype_cls.body_type}"
}
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123"
)
context.add_branch_result("car_brand_cls", {
"brand": "Toyota",
"model": "Camry",
"confidence": 0.87
})
context.add_branch_result("car_bodytype_cls", {
"body_type": "Sedan",
"confidence": 0.82
})
mapped_fields = mapper.map_fields(field_mappings, context)
assert mapped_fields["car_brand"] == "Toyota"
assert mapped_fields["car_model"] == "Camry"
assert mapped_fields["body_type"] == "Sedan"
assert mapped_fields["brand_confidence"] == 0.87
assert mapped_fields["combined_info"] == "Toyota Sedan"
def test_map_fields_bbox_access(self):
"""Test field mapping with bounding box access."""
mapper = FieldMapper()
field_mappings = {
"bbox_x1": "{bbox.x1}",
"bbox_y1": "{bbox.y1}",
"bbox_x2": "{bbox.x2}",
"bbox_y2": "{bbox.y2}",
"bbox_width": "{bbox.width}",
"bbox_height": "{bbox.height}",
"bbox_area": "{bbox.area}",
"bbox_center_x": "{bbox.center_x}",
"bbox_center_y": "{bbox.center_y}"
}
detection = DetectionResult("car", 0.9, BoundingBox(100, 200, 300, 400), 1001)
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123",
detection=detection
)
mapped_fields = mapper.map_fields(field_mappings, context)
assert mapped_fields["bbox_x1"] == 100
assert mapped_fields["bbox_y1"] == 200
assert mapped_fields["bbox_x2"] == 300
assert mapped_fields["bbox_y2"] == 400
assert mapped_fields["bbox_width"] == 200 # 300 - 100
assert mapped_fields["bbox_height"] == 200 # 400 - 200
assert mapped_fields["bbox_area"] == 40000 # 200 * 200
assert mapped_fields["bbox_center_x"] == 200 # (100 + 300) / 2
assert mapped_fields["bbox_center_y"] == 300 # (200 + 400) / 2
def test_map_fields_with_sql_functions(self):
"""Test field mapping with SQL function templates."""
mapper = FieldMapper()
field_mappings = {
"created_at": "NOW()",
"updated_at": "CURRENT_TIMESTAMP",
"uuid_field": "UUID()",
"json_data": "JSON_OBJECT('class', '{class}', 'confidence', {confidence})"
}
detection = DetectionResult("car", 0.9, BoundingBox(100, 200, 300, 400), 1001)
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123",
detection=detection
)
mapped_fields = mapper.map_fields(field_mappings, context)
# SQL functions should pass through unchanged
assert mapped_fields["created_at"] == "NOW()"
assert mapped_fields["updated_at"] == "CURRENT_TIMESTAMP"
assert mapped_fields["uuid_field"] == "UUID()"
assert mapped_fields["json_data"] == "JSON_OBJECT('class', 'car', 'confidence', 0.9)"
def test_map_fields_missing_branch_data(self):
"""Test field mapping with missing branch data."""
mapper = FieldMapper()
field_mappings = {
"car_brand": "{car_brand_cls.brand}",
"car_model": "{nonexistent_branch.model}"
}
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123"
)
# Only add one branch result
context.add_branch_result("car_brand_cls", {"brand": "Toyota"})
with pytest.raises(FieldMappingError) as exc_info:
mapper.map_fields(field_mappings, context)
assert "nonexistent_branch.model" in str(exc_info.value)
def test_map_fields_with_defaults(self):
"""Test field mapping with default values."""
mapper = FieldMapper(allow_missing=True)
field_mappings = {
"car_brand": "{car_brand_cls.brand|Unknown}",
"car_model": "{car_brand_cls.model|N/A}",
"confidence": "{confidence|0.0}"
}
context = MappingContext(
camera_id="camera_001",
display_id="display_001",
session_id="session_123"
)
# Don't add any branch results
mapped_fields = mapper.map_fields(field_mappings, context)
assert mapped_fields["car_brand"] == "Unknown"
assert mapped_fields["car_model"] == "N/A"
assert mapped_fields["confidence"] == "0.0"
def test_map_database_fields(self):
"""Test mapping fields for database operations."""
mapper = FieldMapper()
# Database field mapping
db_field_mappings = {
"camera_id": "{camera_id}",
"session_id": "{session_id}",
"detection_timestamp": "{timestamp}",
"object_class": "{class}",
"detection_confidence": "{confidence}",
"track_id": "{track_id}",
"bbox_json": "JSON_OBJECT('x1', {bbox.x1}, 'y1', {bbox.y1}, 'x2', {bbox.x2}, 'y2', {bbox.y2})",
"car_brand": "{car_brand_cls.brand}",
"car_body_type": "{car_bodytype_cls.body_type}",
"license_plate": "{license_ocr.text}",
"created_at": "NOW()",
"updated_at": "NOW()"
}
detection = DetectionResult("car", 0.93, BoundingBox(150, 250, 350, 450), 2001, 1640995300000)
context = MappingContext(
camera_id="camera_002",
display_id="display_002",
session_id="session_456",
detection=detection,
timestamp=1640995300000
)
# Add branch results
context.add_branch_result("car_brand_cls", {"brand": "Honda", "confidence": 0.89})
context.add_branch_result("car_bodytype_cls", {"body_type": "SUV", "confidence": 0.85})
context.add_branch_result("license_ocr", {"text": "ABC-123", "confidence": 0.76})
mapped_fields = mapper.map_fields(db_field_mappings, context)
assert mapped_fields["camera_id"] == "camera_002"
assert mapped_fields["session_id"] == "session_456"
assert mapped_fields["detection_timestamp"] == 1640995300000
assert mapped_fields["object_class"] == "car"
assert mapped_fields["detection_confidence"] == 0.93
assert mapped_fields["track_id"] == 2001
assert mapped_fields["bbox_json"] == "JSON_OBJECT('x1', 150, 'y1', 250, 'x2', 350, 'y2', 450)"
assert mapped_fields["car_brand"] == "Honda"
assert mapped_fields["car_body_type"] == "SUV"
assert mapped_fields["license_plate"] == "ABC-123"
assert mapped_fields["created_at"] == "NOW()"
assert mapped_fields["updated_at"] == "NOW()"
def test_map_redis_keys(self):
"""Test mapping Redis key templates."""
mapper = FieldMapper()
key_templates = [
"inference:{camera_id}:{timestamp}:{session_id}:car",
"detection:{display_id}:{track_id}",
"cropped_image:{camera_id}:{session_id}:{class}",
"metadata:{session_id}:brands:{car_brand_cls.brand}",
"tracking:{camera_id}:active_tracks"
]
detection = DetectionResult("car", 0.88, BoundingBox(200, 300, 400, 500), 3001, 1640995400000)
context = MappingContext(
camera_id="camera_003",
display_id="display_003",
session_id="session_789",
detection=detection,
timestamp=1640995400000
)
context.add_branch_result("car_brand_cls", {"brand": "Ford"})
mapped_keys = [mapper.map_template(template, context) for template in key_templates]
expected_keys = [
"inference:camera_003:1640995400000:session_789:car",
"detection:display_003:3001",
"cropped_image:camera_003:session_789:car",
"metadata:session_789:brands:Ford",
"tracking:camera_003:active_tracks"
]
assert mapped_keys == expected_keys
def test_map_template(self):
"""Test single template mapping."""
mapper = FieldMapper()
template = "Camera {camera_id} detected {class} with {confidence:.2f} confidence at {timestamp}"
detection = DetectionResult("truck", 0.876, BoundingBox(100, 150, 300, 350), 4001, 1640995500000)
context = MappingContext(
camera_id="camera_004",
display_id="display_004",
session_id="session_101",
detection=detection,
timestamp=1640995500000
)
result = mapper.map_template(template, context)
expected = "Camera camera_004 detected truck with 0.88 confidence at 1640995500000"
assert result == expected
def test_validate_field_mappings(self):
"""Test field mapping validation."""
mapper = FieldMapper()
# Valid mappings
valid_mappings = {
"camera_id": "{camera_id}",
"class": "{class}",
"confidence": "{confidence}",
"created_at": "NOW()"
}
assert mapper.validate_field_mappings(valid_mappings) is True
# Invalid mappings (malformed templates)
invalid_mappings = {
"camera_id": "{camera_id", # Missing closing brace
"class": "class}", # Missing opening brace
"confidence": "{nonexistent_field}" # This might be valid depending on context
}
with pytest.raises(FieldMappingError):
mapper.validate_field_mappings(invalid_mappings)
def test_create_context_from_detection(self):
"""Test creating mapping context from detection result."""
mapper = FieldMapper()
detection = DetectionResult("car", 0.95, BoundingBox(50, 100, 250, 300), 5001, 1640995600000)
context = mapper.create_context_from_detection(
detection,
camera_id="camera_005",
display_id="display_005",
session_id="session_202"
)
assert context.camera_id == "camera_005"
assert context.display_id == "display_005"
assert context.session_id == "session_202"
assert context.detection == detection
assert context.timestamp == 1640995600000
def test_format_sql_value(self):
"""Test SQL value formatting."""
mapper = FieldMapper()
# String values should be quoted
assert mapper.format_sql_value("test_string") == "'test_string'"
assert mapper.format_sql_value("John's car") == "'John''s car'" # Escape quotes
# Numeric values should not be quoted
assert mapper.format_sql_value(42) == "42"
assert mapper.format_sql_value(3.14) == "3.14"
assert mapper.format_sql_value(0.95) == "0.95"
# Boolean values
assert mapper.format_sql_value(True) == "TRUE"
assert mapper.format_sql_value(False) == "FALSE"
# None/NULL values
assert mapper.format_sql_value(None) == "NULL"
# SQL functions should pass through
assert mapper.format_sql_value("NOW()") == "NOW()"
assert mapper.format_sql_value("CURRENT_TIMESTAMP") == "CURRENT_TIMESTAMP"
class TestFieldMapperIntegration:
"""Integration tests for field mapping."""
def test_complete_mapping_workflow(self):
"""Test complete field mapping workflow."""
mapper = FieldMapper()
# Simulate complete detection workflow
detection = DetectionResult("car", 0.91, BoundingBox(120, 180, 320, 380), 6001, 1640995700000)
context = MappingContext(
camera_id="camera_006",
display_id="display_006",
session_id="session_303",
detection=detection,
timestamp=1640995700000
)
# Add comprehensive branch results
context.add_branch_result("car_brand_cls", {
"brand": "BMW",
"model": "X5",
"confidence": 0.84,
"top3_brands": ["BMW", "Audi", "Mercedes"]
})
context.add_branch_result("car_bodytype_cls", {
"body_type": "SUV",
"confidence": 0.79,
"features": ["tall", "4_doors", "roof_rails"]
})
context.add_branch_result("car_color_cls", {
"color": "Black",
"confidence": 0.73,
"rgb_values": [20, 25, 30]
})
context.add_branch_result("license_ocr", {
"text": "XYZ-789",
"confidence": 0.68,
"region_bbox": [150, 320, 290, 360]
})
# Database field mapping
db_mappings = {
"camera_id": "{camera_id}",
"display_id": "{display_id}",
"session_id": "{session_id}",
"detection_timestamp": "{timestamp}",
"object_class": "{class}",
"detection_confidence": "{confidence}",
"track_id": "{track_id}",
"bbox_x1": "{bbox.x1}",
"bbox_y1": "{bbox.y1}",
"bbox_x2": "{bbox.x2}",
"bbox_y2": "{bbox.y2}",
"bbox_area": "{bbox.area}",
"car_brand": "{car_brand_cls.brand}",
"car_model": "{car_brand_cls.model}",
"car_body_type": "{car_bodytype_cls.body_type}",
"car_color": "{car_color_cls.color}",
"license_plate": "{license_ocr.text}",
"brand_confidence": "{car_brand_cls.confidence}",
"bodytype_confidence": "{car_bodytype_cls.confidence}",
"color_confidence": "{car_color_cls.confidence}",
"license_confidence": "{license_ocr.confidence}",
"detection_summary": "{car_brand_cls.brand} {car_bodytype_cls.body_type} ({car_color_cls.color})",
"created_at": "NOW()",
"updated_at": "NOW()"
}
mapped_db_fields = mapper.map_fields(db_mappings, context)
# Verify all mappings
assert mapped_db_fields["camera_id"] == "camera_006"
assert mapped_db_fields["session_id"] == "session_303"
assert mapped_db_fields["object_class"] == "car"
assert mapped_db_fields["detection_confidence"] == 0.91
assert mapped_db_fields["track_id"] == 6001
assert mapped_db_fields["bbox_area"] == 40000 # 200 * 200
assert mapped_db_fields["car_brand"] == "BMW"
assert mapped_db_fields["car_model"] == "X5"
assert mapped_db_fields["car_body_type"] == "SUV"
assert mapped_db_fields["car_color"] == "Black"
assert mapped_db_fields["license_plate"] == "XYZ-789"
assert mapped_db_fields["detection_summary"] == "BMW SUV (Black)"
# Redis key mapping
redis_key_templates = [
"detection:{camera_id}:{session_id}:main",
"cropped:{camera_id}:{session_id}:car_image",
"metadata:{session_id}:brand:{car_brand_cls.brand}",
"tracking:{camera_id}:track_{track_id}",
"classification:{session_id}:results"
]
mapped_redis_keys = [
mapper.map_template(template, context)
for template in redis_key_templates
]
expected_redis_keys = [
"detection:camera_006:session_303:main",
"cropped:camera_006:session_303:car_image",
"metadata:session_303:brand:BMW",
"tracking:camera_006:track_6001",
"classification:session_303:results"
]
assert mapped_redis_keys == expected_redis_keys
def test_error_handling_and_recovery(self):
"""Test error handling and recovery in field mapping."""
mapper = FieldMapper(allow_missing=True)
# Context with missing detection
context = MappingContext(
camera_id="camera_007",
display_id="display_007",
session_id="session_404"
)
# Partial branch results
context.add_branch_result("car_brand_cls", {"brand": "Unknown"})
# Missing car_bodytype_cls branch
# Field mappings with some missing data
mappings = {
"camera_id": "{camera_id}",
"detection_class": "{class|Unknown}",
"confidence": "{confidence|0.0}",
"car_brand": "{car_brand_cls.brand|N/A}",
"car_body_type": "{car_bodytype_cls.body_type|Unknown}",
"car_model": "{car_brand_cls.model|N/A}"
}
mapped_fields = mapper.map_fields(mappings, context)
assert mapped_fields["camera_id"] == "camera_007"
assert mapped_fields["detection_class"] == "Unknown"
assert mapped_fields["confidence"] == "0.0"
assert mapped_fields["car_brand"] == "Unknown"
assert mapped_fields["car_body_type"] == "Unknown"
assert mapped_fields["car_model"] == "N/A"