Implement native inventory manager workflows (#62)
This commit is contained in:
152
tools/check_milestone_09_issue_62.py
Normal file
152
tools/check_milestone_09_issue_62.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Audit issue 62's native UDP inventory-manager boundary."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import generate_api_shims
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SOURCE = ROOT / "crates" / "libremetaverse" / "src" / "inventory_manager.rs"
|
||||
DOC = ROOT / "docs" / "inventory.md"
|
||||
MANAGER_TESTS = ROOT / "tests" / "compat" / "tests" / "inventory_manager_semantics.rs"
|
||||
TASK_TESTS = ROOT / "tests" / "compat" / "tests" / "task_inventory_semantics.rs"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
REQUIRED_TYPES = {
|
||||
"T:LibreMetaverse.FindObjectByPathReplyEventArgs",
|
||||
"T:LibreMetaverse.FolderUpdatedEventArgs",
|
||||
"T:LibreMetaverse.InventoryManager",
|
||||
"T:LibreMetaverse.InventoryManager.CopyItemsResult",
|
||||
"T:LibreMetaverse.InventoryManager.FolderUpdateResult",
|
||||
"T:LibreMetaverse.InventoryObjectOfferedEventArgs",
|
||||
"T:LibreMetaverse.ItemReceivedEventArgs",
|
||||
"T:LibreMetaverse.SaveAssetToInventoryEventArgs",
|
||||
"T:LibreMetaverse.ScriptRunningReplyEventArgs",
|
||||
"T:LibreMetaverse.TaskInventoryReplyEventArgs",
|
||||
"T:LibreMetaverse.TaskItemReceivedEventArgs",
|
||||
}
|
||||
|
||||
REQUIRED_MEMBERS = {
|
||||
"E:LibreMetaverse.InventoryManager.FindObjectByPathReply",
|
||||
"E:LibreMetaverse.InventoryManager.FolderUpdated",
|
||||
"E:LibreMetaverse.InventoryManager.InventoryObjectOffered",
|
||||
"E:LibreMetaverse.InventoryManager.ItemReceived",
|
||||
"E:LibreMetaverse.InventoryManager.ScriptRunningReply",
|
||||
"E:LibreMetaverse.InventoryManager.TaskInventoryReply",
|
||||
"E:LibreMetaverse.InventoryManager.TaskItemReceived",
|
||||
"M:LibreMetaverse.InventoryManager.#ctor(LibreMetaverse.GridClient)",
|
||||
"M:LibreMetaverse.InventoryManager.CreateFolder(LibreMetaverse.UUID,System.String,LibreMetaverse.FolderType)",
|
||||
"M:LibreMetaverse.InventoryManager.CreateItemAsync(LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,LibreMetaverse.InventoryType,LibreMetaverse.WearableType,LibreMetaverse.PermissionMask,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.CreateLinkAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.InventoryType,LibreMetaverse.UUID,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.FetchItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.FindObjectByPathAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.FolderContentsAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken,System.Boolean)",
|
||||
"M:LibreMetaverse.InventoryManager.GetTaskInventoryAsync(LibreMetaverse.UUID,System.UInt32,LibreMetaverse.Simulator,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.GiveFolderAsync(LibreMetaverse.UUID,System.String,LibreMetaverse.UUID,System.Boolean,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.GiveItem(LibreMetaverse.UUID,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,System.Boolean)",
|
||||
"M:LibreMetaverse.InventoryManager.MoveFolders(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.MoveItemsAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.RemoveItemsAsync(System.Collections.Generic.IEnumerable{LibreMetaverse.UUID},System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestCopyItemsWithResultAsync(System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{System.String},LibreMetaverse.UUID,System.Threading.CancellationToken)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestDeRezToInventory(System.UInt32,LibreMetaverse.DeRezDestination,LibreMetaverse.UUID,LibreMetaverse.UUID)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestFetchInventoryAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken,System.Action{System.Collections.Generic.List{LibreMetaverse.InventoryItem}})",
|
||||
"M:LibreMetaverse.InventoryManager.RequestRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.UUID,LibreMetaverse.Quaternion,LibreMetaverse.Vector3,LibreMetaverse.InventoryItem,LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestTaskInventory(System.UInt32,LibreMetaverse.Simulator)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem},LibreMetaverse.UUID)",
|
||||
"M:LibreMetaverse.InventoryManager.UpdateTaskInventory(System.UInt32,LibreMetaverse.InventoryItem,LibreMetaverse.Simulator,System.Boolean)",
|
||||
"M:LibreMetaverse.InventoryManager.WaitForNextInventoryOfferAsync(System.Threading.CancellationToken)",
|
||||
}
|
||||
|
||||
|
||||
def require_markers(path: Path, markers: tuple[str, ...]) -> None:
|
||||
source = path.read_text()
|
||||
missing = [marker for marker in markers if marker not in source]
|
||||
if missing:
|
||||
raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
native_types = (
|
||||
generate_api_shims.NATIVE_TYPES.keys()
|
||||
| generate_api_shims.NATIVE_DECLARATIONS.keys()
|
||||
)
|
||||
missing_types = sorted(REQUIRED_TYPES - native_types)
|
||||
if missing_types:
|
||||
raise SystemExit("issue 62 native types missing: " + ", ".join(missing_types))
|
||||
missing_members = sorted(
|
||||
REQUIRED_MEMBERS - generate_api_shims.NATIVE_MEMBER_BODIES.keys()
|
||||
)
|
||||
if missing_members:
|
||||
raise SystemExit("issue 62 native members missing: " + ", ".join(missing_members))
|
||||
update_task = (
|
||||
"M:LibreMetaverse.InventoryManager.UpdateTaskInventory(System.UInt32,"
|
||||
"LibreMetaverse.InventoryItem,LibreMetaverse.Simulator,System.Boolean)"
|
||||
)
|
||||
if "only_mod_meta.unwrap_or(true)" not in generate_api_shims.NATIVE_MEMBER_BODIES[update_task]:
|
||||
raise SystemExit("UpdateTaskInventory must retain the C# metadata-only default")
|
||||
for update_member in (
|
||||
"M:LibreMetaverse.InventoryManager.RequestUpdateItem(LibreMetaverse.InventoryItem)",
|
||||
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem})",
|
||||
):
|
||||
if "UUID::random()?" not in generate_api_shims.NATIVE_MEMBER_BODIES[update_member]:
|
||||
raise SystemExit(f"{update_member} must generate a transaction ID")
|
||||
if STUB_RE.search(SOURCE.read_text()):
|
||||
raise SystemExit("issue 62 owned Rust stubs remain in inventory_manager.rs")
|
||||
|
||||
require_markers(
|
||||
SOURCE,
|
||||
(
|
||||
"MAX_TASK_INVENTORY_BYTES",
|
||||
"MAX_PENDING_REQUESTS",
|
||||
"encode_multiple",
|
||||
"pending_created",
|
||||
"pending_fetches",
|
||||
"pending_task_replies",
|
||||
"callbacks are not invoked while an inventory lock is held",
|
||||
"cancelling_one_fetch_waiter_preserves_concurrent_correlation",
|
||||
"fake_bulk_copy_reply_waits_for_every_block",
|
||||
"asset_type_without_folder_type_falls_back_to_inventory_root",
|
||||
"stale_descendents_packet_cannot_mutate_store",
|
||||
"task_xfer_rejects_announced_data_above_bound",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
DOC,
|
||||
(
|
||||
"UDP inventory manager",
|
||||
"4,096 pending operations",
|
||||
"16 MiB",
|
||||
"RequestXfer",
|
||||
"No store lock is held across an await",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
MANAGER_TESTS,
|
||||
(
|
||||
"inventory_manager_null_throws",
|
||||
"encrypt_decrypt_round_trip",
|
||||
"item_crc_is_deterministic_and_changes_when_fields_change",
|
||||
"create_inventory_item_returns_correct_subclass",
|
||||
),
|
||||
)
|
||||
require_markers(
|
||||
TASK_TESTS,
|
||||
(
|
||||
"cap_available_returns_contents_folder_and_decrypts_shadow_id",
|
||||
"plain_asset_id_parses_without_decryption",
|
||||
"non_success_status_returns_contents_folder_only",
|
||||
"no_capability_does_not_make_http_request",
|
||||
),
|
||||
)
|
||||
print(
|
||||
"issue 62 audit: native inventory packet mappings, bounded correlation and Xfer, "
|
||||
"lock-free callback evidence, documentation, and translated compatibility cases are present"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user