mirror of
https://github.com/azaion/detections.git
synced 2026-04-22 08:56:32 +00:00
[AZ-175] Media table integration with XxHash64 content hashing and status lifecycle
Made-with: Cursor
This commit is contained in:
@@ -74,7 +74,7 @@ def test_merged_annotation_nested_sections():
|
||||
assert out["altitude"] == 100
|
||||
|
||||
|
||||
def test_build_media_detect_config_uses_api_path_and_defaults_when_api_empty():
|
||||
def test_resolve_media_for_detect_uses_api_path_and_defaults_when_api_empty():
|
||||
# Arrange
|
||||
import main
|
||||
|
||||
@@ -84,13 +84,14 @@ def test_build_media_detect_config_uses_api_path_and_defaults_when_api_empty():
|
||||
mock_ann.fetch_media_path.return_value = "/m/file.jpg"
|
||||
with patch("main.annotations_client", mock_ann):
|
||||
# Act
|
||||
cfg = main._build_media_detect_config_dict("mid-1", tm, None)
|
||||
cfg, path = main._resolve_media_for_detect("mid-1", tm, None)
|
||||
# Assert
|
||||
assert cfg["paths"] == ["/m/file.jpg"]
|
||||
assert path == "/m/file.jpg"
|
||||
assert "paths" not in cfg
|
||||
assert "probability_threshold" not in cfg
|
||||
|
||||
|
||||
def test_build_media_detect_config_override_wins():
|
||||
def test_resolve_media_for_detect_override_wins():
|
||||
# Arrange
|
||||
import main
|
||||
|
||||
@@ -104,14 +105,15 @@ def test_build_media_detect_config_override_wins():
|
||||
mock_ann.fetch_media_path.return_value = "/m/v.mp4"
|
||||
with patch("main.annotations_client", mock_ann):
|
||||
# Act
|
||||
cfg = main._build_media_detect_config_dict("vid-1", tm, override)
|
||||
cfg, path = main._resolve_media_for_detect("vid-1", tm, override)
|
||||
# Assert
|
||||
assert cfg["probability_threshold"] == 0.99
|
||||
assert cfg["altitude"] == 500
|
||||
assert cfg["paths"] == ["/m/v.mp4"]
|
||||
assert path == "/m/v.mp4"
|
||||
assert "paths" not in cfg
|
||||
|
||||
|
||||
def test_build_media_detect_config_raises_when_no_media_path():
|
||||
def test_resolve_media_for_detect_raises_when_no_media_path():
|
||||
# Arrange
|
||||
import main
|
||||
|
||||
@@ -122,5 +124,5 @@ def test_build_media_detect_config_raises_when_no_media_path():
|
||||
with patch("main.annotations_client", mock_ann):
|
||||
# Act / Assert
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
main._build_media_detect_config_dict("missing", tm, None)
|
||||
main._resolve_media_for_detect("missing", tm, None)
|
||||
assert exc.value.status_code == 503
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
def test_post_media_record_json_and_auth():
|
||||
# Arrange
|
||||
import main
|
||||
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.status_code = 201
|
||||
payload = {
|
||||
"id": "h1",
|
||||
"name": "a.jpg",
|
||||
"path": "/x/a.jpg",
|
||||
"mediaType": "Image",
|
||||
"mediaStatus": 1,
|
||||
"userId": "u1",
|
||||
}
|
||||
with patch.object(main.http_requests, "post", return_value=mock_resp) as post:
|
||||
# Act
|
||||
ok = main._post_media_record(payload, "tok")
|
||||
# Assert
|
||||
assert ok is True
|
||||
post.assert_called_once()
|
||||
args, kwargs = post.call_args
|
||||
assert kwargs["json"] == payload
|
||||
assert kwargs["headers"]["Authorization"] == "Bearer tok"
|
||||
|
||||
|
||||
def test_put_media_status_json():
|
||||
# Arrange
|
||||
import main
|
||||
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.status_code = 204
|
||||
with patch.object(main.http_requests, "put", return_value=mock_resp) as put:
|
||||
# Act
|
||||
ok = main._put_media_status("mid", 2, "t")
|
||||
# Assert
|
||||
assert ok is True
|
||||
put.assert_called_once()
|
||||
_args, kwargs = put.call_args
|
||||
assert kwargs["json"] == {"mediaStatus": 2}
|
||||
assert "/api/media/mid/status" in put.call_args[0][0]
|
||||
@@ -0,0 +1,46 @@
|
||||
import xxhash
|
||||
|
||||
|
||||
def test_compute_media_content_hash_small_file():
|
||||
# Arrange
|
||||
from media_hash import compute_media_content_hash
|
||||
|
||||
data = b"x" * 100
|
||||
expected = xxhash.xxh64(len(data).to_bytes(8, "little") + data).hexdigest()
|
||||
# Act
|
||||
out = compute_media_content_hash(data)
|
||||
# Assert
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_compute_media_content_hash_large_file():
|
||||
# Arrange
|
||||
from media_hash import compute_media_content_hash
|
||||
|
||||
data = (bytes(range(256)) * 20)[:5000]
|
||||
n = len(data)
|
||||
mid = (n - 1024) // 2
|
||||
blob = (
|
||||
n.to_bytes(8, "little")
|
||||
+ data[0:1024]
|
||||
+ data[mid : mid + 1024]
|
||||
+ data[-1024:]
|
||||
)
|
||||
expected = xxhash.xxh64(blob).hexdigest()
|
||||
# Act
|
||||
out = compute_media_content_hash(data)
|
||||
# Assert
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_compute_media_content_hash_virtual_prefix():
|
||||
# Arrange
|
||||
from media_hash import compute_media_content_hash
|
||||
|
||||
# Act
|
||||
v = compute_media_content_hash(b"abc", virtual=True)
|
||||
n = compute_media_content_hash(b"abc", virtual=False)
|
||||
# Assert
|
||||
assert v.startswith("V")
|
||||
assert not n.startswith("V")
|
||||
assert v == "V" + n
|
||||
Reference in New Issue
Block a user