test_pack_missing_source_returns_nonzero (test_cli.CliFailureTest.test_pack_missing_source_returns_nonzero) ... ok test_pack_to_missing_output_directory_reports_clean_error (test_cli.CliFailureTest.test_pack_to_missing_output_directory_reports_clean_error) ... ok test_unpack_missing_db_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_db_returns_nonzero) ... ok test_unpack_missing_path_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_path_returns_nonzero) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:420: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes cursor.execute( ok test_unpack_non_database_file_reports_clean_error (test_cli.CliFailureTest.test_unpack_non_database_file_reports_clean_error) ... ok test_migrates_in_place_with_backup (test_cli.CliMigrateTest.test_migrates_in_place_with_backup) ... ok test_non_vfs_file_is_rejected (test_cli.CliMigrateTest.test_non_vfs_file_is_rejected) ... ok test_output_mode_leaves_the_original_alone (test_cli.CliMigrateTest.test_output_mode_leaves_the_original_alone) ... ok test_reports_when_nothing_to_do (test_cli.CliMigrateTest.test_reports_when_nothing_to_do) ... ok test_compress_algo_huffman_is_still_selectable (test_cli.CliPackTest.test_compress_algo_huffman_is_still_selectable) 早期算法仍然可选,且打出来的包能被正常读回。 ... ok test_default_compression_algorithm_is_zlib (test_cli.CliPackTest.test_default_compression_algorithm_is_zlib) ... ok test_exclude_prunes_directory_subtree (test_cli.CliPackTest.test_exclude_prunes_directory_subtree) ... ok test_exclude_supports_glob_patterns (test_cli.CliPackTest.test_exclude_supports_glob_patterns) P1-9: README 承诺 glob 语义,`*.log` 必须真的排除 .log 文件, ... ok test_pack_reports_file_count_matching_database (test_cli.CliPackTest.test_pack_reports_file_count_matching_database) ... ok test_pack_stores_every_file (test_cli.CliPackTest.test_pack_stores_every_file) ... ok test_list_snapshots_option (test_cli.CliUnpackSnapshotTest.test_list_snapshots_option) ... ok test_unknown_snapshot_is_rejected_cleanly (test_cli.CliUnpackSnapshotTest.test_unknown_snapshot_is_rejected_cleanly) ... ok test_full_roundtrip_via_cli (test_cli.CliUnpackTest.test_full_roundtrip_via_cli) ... ok test_ignore_timestamps_full_export_does_not_recurse (test_cli.CliUnpackTest.test_ignore_timestamps_full_export_does_not_recurse) P0-3: --ignore-timestamps 曾把 export_filesystem 赋成引用自身的 lambda。 ... ok test_ignore_timestamps_with_path_subdirectory (test_cli.CliUnpackTest.test_ignore_timestamps_with_path_subdirectory) ... ok test_list_root_only_shows_top_level (test_cli.CliUnpackTest.test_list_root_only_shows_top_level) P0-2: 根目录列表不能把整张表铺平。 ... ok test_path_exports_single_file (test_cli.CliUnpackTest.test_path_exports_single_file) ... ok test_path_exports_subdirectory_with_contents (test_cli.CliUnpackTest.test_path_exports_subdirectory_with_contents) ... ok test_rejects_old_schema_database_cleanly (test_cli.CliUnpackTest.test_rejects_old_schema_database_cleanly) P1-7: 旧格式库要给出明确提示,退出码非 0,且不能是 traceback。 ... ok test_content_tampering_needs_check_content (test_cli.CliVerifyTest.test_content_tampering_needs_check_content) ... ok test_json_output (test_cli.CliVerifyTest.test_json_output) ... ok test_list_snapshots (test_cli.CliVerifyTest.test_list_snapshots) ... ok test_missing_db_exits_nonzero (test_cli.CliVerifyTest.test_missing_db_exits_nonzero) ... ok test_sign_then_verify (test_cli.CliVerifyTest.test_sign_then_verify) ... ok test_snapshot_selection (test_cli.CliVerifyTest.test_snapshot_selection) ... ok test_verify_does_not_modify_the_pack (test_cli.CliVerifyTest.test_verify_does_not_modify_the_pack) ... ok test_verify_exits_nonzero_on_metadata_tampering (test_cli.CliVerifyTest.test_verify_exits_nonzero_on_metadata_tampering) ... ok test_verify_reports_ok (test_cli.CliVerifyTest.test_verify_reports_ok) ... ok test_verify_with_content_check (test_cli.CliVerifyTest.test_verify_with_content_check) ... ok test_importing_core_never_pulls_in_third_party (test_contrib_optional.OptionalDependencyTest.test_importing_core_never_pulls_in_third_party) import sqlite_vfs 不能顺带把 fastapi/starlette 拖进来。 ... ok test_missing_database_path_hint (test_contrib_optional.OptionalDependencyTest.test_missing_database_path_hint) 未生成资源包时的报错要给出下一步命令。 ... skipped '当前环境没有 FastAPI' test_missing_fastapi_gives_actionable_error (test_contrib_optional.OptionalDependencyTest.test_missing_fastapi_gives_actionable_error) 缺少可选依赖时,报错信息必须能直接照着做。 ... ok test_plugin_module_is_not_imported_by_the_package (test_contrib_optional.OptionalDependencyTest.test_plugin_module_is_not_imported_by_the_package) contrib 子包不能自动导入插件模块(否则缺依赖时整包不可用)。 ... ok test_third_party_is_installed_or_not (test_contrib_optional.OptionalDependencyTest.test_third_party_is_installed_or_not) 只用于在输出里说明当前环境状态,不断言。 ... ok test_duplicate_add_file_is_reported_and_keeps_first_content (test_core.AddFileConflictTest.test_duplicate_add_file_is_reported_and_keeps_first_content) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:740: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes cursor.execute( ok test_compression_disabled_stores_raw (test_core.CompressionAlgorithmTest.test_compression_disabled_stores_raw) ... ok test_default_algorithm_is_zlib (test_core.CompressionAlgorithmTest.test_default_algorithm_is_zlib) ... ok test_each_algorithm_roundtrips (test_core.CompressionAlgorithmTest.test_each_algorithm_roundtrips) ... ok test_early_huffman_packs_are_still_readable (test_core.CompressionAlgorithmTest.test_early_huffman_packs_are_still_readable) 早期版本用 huffman 打的包必须还能读——这是保留该算法唯一的理由。 ... ok test_unknown_algorithm_in_database_raises_on_read (test_core.CompressionAlgorithmTest.test_unknown_algorithm_in_database_raises_on_read) 库里的算法名本版本不认识时要明确报错,而不是返回坏数据。 ... ok test_unknown_algorithm_rejected_at_construction (test_core.CompressionAlgorithmTest.test_unknown_algorithm_rejected_at_construction) ... ok test_zlib_compresses_better_than_huffman (test_core.CompressionAlgorithmTest.test_zlib_compresses_better_than_huffman) 同一份文本,zlib 的结果必须明显小于 huffman(LZ77 能吃重复)。 ... ok test_directories_come_before_files (test_core.DirectoryListingTest.test_directories_come_before_files) ... ok test_leaf_directory_is_empty (test_core.DirectoryListingTest.test_leaf_directory_is_empty) ... ok test_nested_directory_lists_its_children (test_core.DirectoryListingTest.test_nested_directory_lists_its_children) ... ok test_paths_are_returned_as_dicts_with_datetime (test_core.DirectoryListingTest.test_paths_are_returned_as_dicts_with_datetime) ... ok test_root_lists_top_level_only (test_core.DirectoryListingTest.test_root_lists_top_level_only) ... ok test_subdirectory_lists_its_children (test_core.DirectoryListingTest.test_subdirectory_lists_its_children) ... ok test_export_directory_full_tree (test_core.ExportTest.test_export_directory_full_tree) ... ok test_export_file_accepts_bare_filename (test_core.ExportTest.test_export_file_accepts_bare_filename) P1-6: local_path 没有目录部分时 dirname 为 '',不能抛 FileNotFoundError。 ... ok test_export_file_writes_exact_bytes (test_core.ExportTest.test_export_file_writes_exact_bytes) ... ok test_export_filesystem_matches_tree (test_core.ExportTest.test_export_filesystem_matches_tree) ... ok test_export_subdirectory_does_not_recurse_forever (test_core.ExportTest.test_export_subdirectory_does_not_recurse_forever) P0-2: list_directory 按 path 过滤时,导出 doc 会无限自我递归。 ... ok test_compressible_file_uses_zlib (test_core.FileContentTest.test_compressible_file_uses_zlib) ... ok test_compression_applies_below_the_old_1kb_bar (test_core.FileContentTest.test_compression_applies_below_the_old_1kb_bar) zlib 包头只有几字节,小文件也值得压(旧的哈夫曼阈值是 1KB)。 ... ok test_empty_file_roundtrip (test_core.FileContentTest.test_empty_file_roundtrip) ... ok test_file_size_recorded_matches_content (test_core.FileContentTest.test_file_size_recorded_matches_content) ... ok test_incompressible_file_falls_back_to_none (test_core.FileContentTest.test_incompressible_file_falls_back_to_none) ... ok test_read_file_offset_and_size (test_core.FileContentTest.test_read_file_offset_and_size) ... ok test_read_file_rejects_directory_and_missing_path (test_core.FileContentTest.test_read_file_rejects_directory_and_missing_path) ... ok test_small_file_roundtrip (test_core.FileContentTest.test_small_file_roundtrip) ... ok test_tiny_file_is_not_compressed (test_core.FileContentTest.test_tiny_file_is_not_compressed) ... ok test_mk_dir_creates_directory (test_core.MkDirTest.test_mk_dir_creates_directory) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:1262: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes cursor.execute( ok test_mk_dir_existing_raises_cleanly (test_core.MkDirTest.test_mk_dir_existing_raises_cleanly) ... ok test_mv_dir_does_not_touch_prefix_sibling (test_core.MoveAndRemoveTest.test_mv_dir_does_not_touch_prefix_sibling) ... ok test_mv_dir_into_existing_parent_directory (test_core.MoveAndRemoveTest.test_mv_dir_into_existing_parent_directory) ... ok test_mv_dir_into_itself_raises (test_core.MoveAndRemoveTest.test_mv_dir_into_itself_raises) ... ok test_mv_dir_rename_is_not_applied_twice (test_core.MoveAndRemoveTest.test_mv_dir_rename_is_not_applied_twice) P1-2: mv_dir("doc","doc_new") 的第二条 UPDATE 会再次命中已改名的目录自身。 ... ok test_mv_dir_root_creates_destination_and_fixes_parent_paths (test_core.MoveAndRemoveTest.test_mv_dir_root_creates_destination_and_fixes_parent_paths) P1-3: 把根目录整体移进 archive 时,archive 目录行必须存在, ... ok test_mv_dir_to_existing_destination_raises_and_keeps_source (test_core.MoveAndRemoveTest.test_mv_dir_to_existing_destination_raises_and_keeps_source) ... ok test_mv_dir_to_missing_parent_raises (test_core.MoveAndRemoveTest.test_mv_dir_to_missing_parent_raises) 目标的父目录不存在时要明确报错,而不是造出一个不可达的目录。 ... ok test_mv_dir_updates_children_parent_paths (test_core.MoveAndRemoveTest.test_mv_dir_updates_children_parent_paths) ... ok test_mv_file_updates_name_and_parent (test_core.MoveAndRemoveTest.test_mv_file_updates_name_and_parent) ... ok test_remove_directory_does_not_touch_prefix_sibling (test_core.MoveAndRemoveTest.test_remove_directory_does_not_touch_prefix_sibling) 删除 doc 不能连带删掉 docs(LIKE 'doc%' 会把 docs 一起匹配上)。 ... ok test_remove_file_with_percent_is_not_a_wildcard (test_core.MoveAndRemoveTest.test_remove_file_with_percent_is_not_a_wildcard) ... ok test_remove_file_with_underscore_is_not_a_wildcard (test_core.MoveAndRemoveTest.test_remove_file_with_underscore_is_not_a_wildcard) 文件名里的 _ 不能被当成 LIKE 的单字符通配符。 ... ok test_remove_missing_path_reports_error (test_core.MoveAndRemoveTest.test_remove_missing_path_reports_error) ... ok test_add_file_survives_close_without_further_commit (test_core.PersistenceTest.test_add_file_survives_close_without_further_commit) ... ok test_fresh_database_is_accepted (test_core.SchemaCompatibilityTest.test_fresh_database_is_accepted) ... ok test_legacy_pack_is_readable_after_migration (test_core.SchemaCompatibilityTest.test_legacy_pack_is_readable_after_migration) 迁移工具必须真的能读懂最早那版格式(compressed 布尔 + zlib)。 ... ok test_non_sqlite_file_is_rejected (test_core.SchemaCompatibilityTest.test_non_sqlite_file_is_rejected) ... ok test_repository_sample_db_is_rejected (test_core.SchemaCompatibilityTest.test_repository_sample_db_is_rejected) ... ok test_synthesized_old_schema_db_is_rejected (test_core.SchemaCompatibilityTest.test_synthesized_old_schema_db_is_rejected) ... ok test_v2_schema_db_is_rejected_with_migration_hint (test_core.SchemaCompatibilityTest.test_v2_schema_db_is_rejected_with_migration_hint) ... ok test_add_file_actually_stores_a_row (test_core.SchemaContractTest.test_add_file_actually_stores_a_row) add_file 之后库里必须真的有这条记录。 ... ok test_expected_columns_exist (test_core.SchemaContractTest.test_expected_columns_exist) v3:目录项与内容分家,files 只留元数据 + content_hash。 ... ok test_clear_snapshot_keeps_other_snapshot_content (test_dedup.BlobGarbageCollectionTest.test_clear_snapshot_keeps_other_snapshot_content) ... ok test_deleting_snapshot_allows_gc (test_dedup.BlobGarbageCollectionTest.test_deleting_snapshot_allows_gc) 只被某个快照引用的内容,在删掉那个快照后应当被回收。 ... ok test_gc_keeps_blobs_referenced_by_another_snapshot (test_dedup.BlobGarbageCollectionTest.test_gc_keeps_blobs_referenced_by_another_snapshot) 多快照共用内容时,删掉一个版本不能影响另一个版本。 ... ok test_gc_returns_deleted_count (test_dedup.BlobGarbageCollectionTest.test_gc_returns_deleted_count) ... ok test_remove_directory_collects_blobs (test_dedup.BlobGarbageCollectionTest.test_remove_directory_collects_blobs) ... ok test_remove_file_collects_unreferenced_blob (test_dedup.BlobGarbageCollectionTest.test_remove_file_collects_unreferenced_blob) ... ok test_shared_blob_survives_partial_removal (test_dedup.BlobGarbageCollectionTest.test_shared_blob_survives_partial_removal) ... ok test_blob_records_original_and_stored_size (test_dedup.DedupTest.test_blob_records_original_and_stored_size) ... ok test_dedup_skips_recompression (test_dedup.DedupTest.test_dedup_skips_recompression) 第二次写入相同内容时不该再压一遍——这是增量打包能变快的原因。 ... ok test_distinct_content_gets_distinct_blobs (test_dedup.DedupTest.test_distinct_content_gets_distinct_blobs) ... ok test_empty_files_share_one_blob (test_dedup.DedupTest.test_empty_files_share_one_blob) ... ok test_identical_content_in_different_directories_shares_blob (test_dedup.DedupTest.test_identical_content_in_different_directories_shares_blob) ... ok test_identical_files_share_one_blob (test_dedup.DedupTest.test_identical_files_share_one_blob) ... ok test_repacking_identical_tree_does_not_grow_storage (test_dedup.DedupTest.test_repacking_identical_tree_does_not_grow_storage) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:650: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes cursor.execute( ok test_replacing_with_identical_content_does_not_add_blob (test_dedup.DedupTest.test_replacing_with_identical_content_does_not_add_blob) ... ok test_rewrite_different_content_keeps_only_new_blob (test_dedup.DedupTest.test_rewrite_different_content_keeps_only_new_blob) ... ok test_content_length_matches_body (test_fastapi_static.BasicServingTest.test_content_length_matches_body) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_compressed_file_correctly (test_fastapi_static.BasicServingTest.test_serves_compressed_file_correctly) 大文件在库里是哈夫曼压缩存储的,取出来必须还原成原始字节。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_empty_file (test_fastapi_static.BasicServingTest.test_serves_empty_file) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_nested_file (test_fastapi_static.BasicServingTest.test_serves_nested_file) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_top_level_file (test_fastapi_static.BasicServingTest.test_serves_top_level_file) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_large_asset_survives_compressed_roundtrip (test_fastapi_static.CompressionAlgorithmServingTest.test_large_asset_survives_compressed_roundtrip) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_pack_uses_zlib_by_default (test_fastapi_static.CompressionAlgorithmServingTest.test_pack_uses_zlib_by_default) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_etag_and_last_modified_present (test_fastapi_static.ConditionalRequestTest.test_etag_and_last_modified_present) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_etag_is_stable_across_instances (test_fastapi_static.ConditionalRequestTest.test_etag_is_stable_across_instances) 同一个资源包重新打开,ETag 不能变,否则缓存永远失效。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_if_modified_since_returns_304 (test_fastapi_static.ConditionalRequestTest.test_if_modified_since_returns_304) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_if_none_match_returns_304 (test_fastapi_static.ConditionalRequestTest.test_if_none_match_returns_304) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_if_none_match_with_weak_prefix (test_fastapi_static.ConditionalRequestTest.test_if_none_match_with_weak_prefix) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_max_age_sets_cache_control (test_fastapi_static.ConditionalRequestTest.test_max_age_sets_cache_control) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_stale_if_none_match_returns_full_body (test_fastapi_static.ConditionalRequestTest.test_stale_if_none_match_returns_full_body) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_missing_pack_raises_runtime_error_with_hint (test_fastapi_static.ConstructionTest.test_missing_pack_raises_runtime_error_with_hint) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_non_database_file_is_rejected (test_fastapi_static.ConstructionTest.test_non_database_file_is_rejected) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_old_format_pack_is_rejected_clearly (test_fastapi_static.ConstructionTest.test_old_format_pack_is_rejected_clearly) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_repr_and_close (test_fastapi_static.ConstructionTest.test_repr_and_close) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_unknown_extension_falls_back_to_octet_stream (test_fastapi_static.ContentTypeTest.test_unknown_extension_falls_back_to_octet_stream) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_web_types_are_not_platform_dependent (test_fastapi_static.ContentTypeTest.test_web_types_are_not_platform_dependent) Windows 注册表会把 .mjs 判成 text/plain(浏览器会拒绝执行模块), ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_head_has_no_body_but_real_length (test_fastapi_static.HeadAndRangeTest.test_head_has_no_body_but_real_length) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_head_with_range (test_fastapi_static.HeadAndRangeTest.test_head_with_range) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_if_range_match_uses_range (test_fastapi_static.HeadAndRangeTest.test_if_range_match_uses_range) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_if_range_mismatch_ignores_range (test_fastapi_static.HeadAndRangeTest.test_if_range_mismatch_ignores_range) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_malformed_range_is_ignored (test_fastapi_static.HeadAndRangeTest.test_malformed_range_is_ignored) 语法错误的 Range 按 RFC 应当被忽略,返回整份内容。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_multi_range_falls_back_to_full_body (test_fastapi_static.HeadAndRangeTest.test_multi_range_falls_back_to_full_body) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_range_on_compressed_content_is_correct (test_fastapi_static.HeadAndRangeTest.test_range_on_compressed_content_is_correct) 库里存的是压缩数据,Range 必须作用在解压后的内容上。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_range_returns_206_with_slice (test_fastapi_static.HeadAndRangeTest.test_range_returns_206_with_slice) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_range_with_open_end (test_fastapi_static.HeadAndRangeTest.test_range_with_open_end) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_suffix_range (test_fastapi_static.HeadAndRangeTest.test_suffix_range) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_unsatisfiable_range_returns_416 (test_fastapi_static.HeadAndRangeTest.test_unsatisfiable_range_returns_416) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_conditional_request_works_on_huffman_pack (test_fastapi_static.HuffmanPackServingTest.test_conditional_request_works_on_huffman_pack) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_range_works_on_huffman_pack (test_fastapi_static.HuffmanPackServingTest.test_range_works_on_huffman_pack) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_huffman_compressed_asset (test_fastapi_static.HuffmanPackServingTest.test_serves_huffman_compressed_asset) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_directory_redirects_to_trailing_slash (test_fastapi_static.IndexAndSpaTest.test_directory_redirects_to_trailing_slash) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_directory_with_slash_serves_its_index (test_fastapi_static.IndexAndSpaTest.test_directory_with_slash_serves_its_index) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_missing_file_returns_404 (test_fastapi_static.IndexAndSpaTest.test_missing_file_returns_404) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_no_fallback_for_json_request (test_fastapi_static.IndexAndSpaTest.test_no_fallback_for_json_request) XHR/接口请求(Accept 不含 text/html)不该被回退成 index.html。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_no_fallback_for_missing_asset (test_fastapi_static.IndexAndSpaTest.test_no_fallback_for_missing_asset) 缺静态资源必须是 404,否则前端拿到一份 HTML 会报诡异的解析错误。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_path_traversal_cannot_escape_the_pack (test_fastapi_static.IndexAndSpaTest.test_path_traversal_cannot_escape_the_pack) 资源包不是磁盘目录,.. 之类无法越出数据库。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_post_is_rejected (test_fastapi_static.IndexAndSpaTest.test_post_is_rejected) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_repeated_requests_do_not_modify_pack (test_fastapi_static.IndexAndSpaTest.test_repeated_requests_do_not_modify_pack) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_root_serves_index_html (test_fastapi_static.IndexAndSpaTest.test_root_serves_index_html) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_spa_fallback_for_deep_route (test_fastapi_static.IndexAndSpaTest.test_spa_fallback_for_deep_route) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_spa_fallback_for_frontend_route (test_fastapi_static.IndexAndSpaTest.test_spa_fallback_for_frontend_route) 浏览器导航到前端路由 /settings 时应当拿到 index.html。 ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_304_does_not_read_content (test_fastapi_static.InterruptedReadTest.test_304_does_not_read_content) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_outside_prefix_is_404 (test_fastapi_static.MountPrefixTest.test_outside_prefix_is_404) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_serves_under_prefix (test_fastapi_static.MountPrefixTest.test_serves_under_prefix) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_plain_file_still_served (test_fastapi_static.StrictModeTest.test_plain_file_still_served) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_root_is_404 (test_fastapi_static.StrictModeTest.test_root_is_404) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_route_is_404 (test_fastapi_static.StrictModeTest.test_route_is_404) ... skipped "需要 fastapi/starlette/httpx: No module named 'fastapi'" test_bad_magic_rejected (test_huffman.HeaderValidationTest.test_bad_magic_rejected) ... ok test_single_symbol_payload_is_not_validated (test_huffman.HeaderValidationTest.test_single_symbol_payload_is_not_validated) 记录既有行为(非缺陷):单符号数据解压时直接按原长度展开,完全不读 payload, ... ok test_too_short_blob_rejected (test_huffman.HeaderValidationTest.test_too_short_blob_rejected) ... ok test_truncated_payload_rejected (test_huffman.HeaderValidationTest.test_truncated_payload_rejected) ... ok test_wrong_freq_blob_size_rejected (test_huffman.HeaderValidationTest.test_wrong_freq_blob_size_rejected) ... ok test_all_256_byte_values (test_huffman.RoundTripTest.test_all_256_byte_values) ... ok test_binary_with_nulls_and_high_bytes (test_huffman.RoundTripTest.test_binary_with_nulls_and_high_bytes) ... ok test_empty (test_huffman.RoundTripTest.test_empty) ... ok test_incompressible_random (test_huffman.RoundTripTest.test_incompressible_random) ... ok test_just_above_core_threshold (test_huffman.RoundTripTest.test_just_above_core_threshold) ... ok test_repetitive_text_compresses (test_huffman.RoundTripTest.test_repetitive_text_compresses) ... ok test_single_byte (test_huffman.RoundTripTest.test_single_byte) ... ok test_single_symbol_repeated (test_huffman.RoundTripTest.test_single_symbol_repeated) ... ok test_two_symbols (test_huffman.RoundTripTest.test_two_symbols) ... ok test_utf8_chinese (test_huffman.RoundTripTest.test_utf8_chinese) ... ok test_deleted_directory_is_removed (test_incremental.ChangeDetectionTest.test_deleted_directory_is_removed) ... ok test_deleted_file_is_removed (test_incremental.ChangeDetectionTest.test_deleted_file_is_removed) ... ok test_file_replaced_by_directory (test_incremental.ChangeDetectionTest.test_file_replaced_by_directory) 同一路径从文件变成目录时必须换掉类型,而不是留着旧条目。 ... ok test_mixed_changes_in_one_run (test_incremental.ChangeDetectionTest.test_mixed_changes_in_one_run) ... ok test_modified_file_is_updated (test_incremental.ChangeDetectionTest.test_modified_file_is_updated) ... ok test_new_directory_is_created (test_incremental.ChangeDetectionTest.test_new_directory_is_created) ... ok test_new_file_is_added (test_incremental.ChangeDetectionTest.test_new_file_is_added) ... ok test_result_still_verifies (test_incremental.ChangeDetectionTest.test_result_still_verifies) ... ok test_unchanged_tree_writes_nothing (test_incremental.ChangeDetectionTest.test_unchanged_tree_writes_nothing) ... ok test_cli_incremental (test_incremental.IncrementalCliTest.test_cli_incremental) ... ok test_cli_snapshot_creates_a_new_version (test_incremental.IncrementalCliTest.test_cli_snapshot_creates_a_new_version) ... ok test_first_incremental_on_an_empty_database (test_incremental.IncrementalSnapshotTest.test_first_incremental_on_an_empty_database) ... ok test_incremental_does_not_touch_other_snapshots (test_incremental.IncrementalSnapshotTest.test_incremental_does_not_touch_other_snapshots) ... ok test_incremental_into_a_new_snapshot_keeps_history (test_incremental.IncrementalSnapshotTest.test_incremental_into_a_new_snapshot_keeps_history) 派生新快照后再增量:旧版本原样保留,新版本只有变化的部分被重写。 ... ok test_dedup_reuses_blob_for_identical_new_file (test_incremental.NoRewriteTest.test_dedup_reuses_blob_for_identical_new_file) 新路径但内容与已有文件相同 → 直接复用,不新增 blob。 ... ok test_rehash_skips_files_whose_content_is_identical (test_incremental.NoRewriteTest.test_rehash_skips_files_whose_content_is_identical) mtime 变了但内容没变:rehash 模式应当判为未变,不做任何写入。 ... ok test_replacing_content_frees_the_old_blob (test_incremental.NoRewriteTest.test_replacing_content_frees_the_old_blob) ... ok test_unchanged_file_keeps_its_blob_hash (test_incremental.NoRewriteTest.test_unchanged_file_keeps_its_blob_hash) ... ok test_unchanged_files_do_not_add_blobs (test_incremental.NoRewriteTest.test_unchanged_files_do_not_add_blobs) ... ok test_mtime_only_change_is_detected_without_rehash (test_incremental.RehashDetectionTest.test_mtime_only_change_is_detected_without_rehash) 同大小 + 同秒修改:默认模式可能漏掉,这正是 rehash 存在的理由。 ... ok test_rehash_catches_same_size_same_mtime_edit (test_incremental.RehashDetectionTest.test_rehash_catches_same_size_same_mtime_edit) ... ok test_digest_changes_when_a_file_is_added (test_integrity.DigestTest.test_digest_changes_when_a_file_is_added) ... ok test_digest_changes_when_content_changes (test_integrity.DigestTest.test_digest_changes_when_content_changes) ... ok test_digest_changes_when_metadata_changes (test_integrity.DigestTest.test_digest_changes_when_metadata_changes) 路径/大小/时间戳/权限也参与摘要,不只是内容。 ... ok test_digest_ignores_insertion_order (test_integrity.DigestTest.test_digest_ignores_insertion_order) 摘要必须只取决于内容与元数据,与插入顺序无关。 ... ok test_digest_is_recorded_and_stable_across_reopen (test_integrity.DigestTest.test_digest_is_recorded_and_stable_across_reopen) ... ok test_digest_matches_manual_recomputation (test_integrity.DigestTest.test_digest_matches_manual_recomputation) ... ok test_digest_can_be_exported_for_external_signing (test_integrity.SignatureTest.test_digest_can_be_exported_for_external_signing) 非对称签名要交给外部工具,所以摘要必须能干净地取出来。 ... ok test_sign_and_verify (test_integrity.SignatureTest.test_sign_and_verify) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:1164: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes self.conn.execute( ok test_sign_requires_write_access (test_integrity.SignatureTest.test_sign_requires_write_access) ... ok test_signature_verifies_on_a_readonly_connection (test_integrity.SignatureTest.test_signature_verifies_on_a_readonly_connection) 只读方必须能在不改动库的前提下完成验证。 ... ok test_tampering_after_signing_fails (test_integrity.SignatureTest.test_tampering_after_signing_fails) ... ok test_verify_signature_by_key_id (test_integrity.SignatureTest.test_verify_signature_by_key_id) ... ok test_verify_without_a_signature_is_reported (test_integrity.SignatureTest.test_verify_without_a_signature_is_reported) ... ok test_wrong_key_fails (test_integrity.SignatureTest.test_wrong_key_fails) ... ok test_content_tamper_is_caught_by_check_content (test_integrity.VerifyTest.test_content_tamper_is_caught_by_check_content) 同大小改掉内容:元数据级校验看不出来,权威校验必须抓到。 ... ok test_metadata_tamper_is_caught_by_digest (test_integrity.VerifyTest.test_metadata_tamper_is_caught_by_digest) ... ok test_missing_blob_is_caught (test_integrity.VerifyTest.test_missing_blob_is_caught) ... ok test_path_tamper_is_caught_by_digest (test_integrity.VerifyTest.test_path_tamper_is_caught_by_digest) ... ok test_read_file_with_verify_hash_raises_on_tamper (test_integrity.VerifyTest.test_read_file_with_verify_hash_raises_on_tamper) ... ok test_size_mismatch_is_caught (test_integrity.VerifyTest.test_size_mismatch_is_caught) ... ok test_verify_can_target_an_older_snapshot (test_integrity.VerifyTest.test_verify_can_target_an_older_snapshot) 摘要防的是"绕过 API 的改动";走 API 的写入会刷新摘要,不算篡改。 ... ok test_verify_passes_on_a_fresh_pack (test_integrity.VerifyTest.test_verify_passes_on_a_fresh_pack) ... ok test_verify_reports_empty_database (test_integrity.VerifyTest.test_verify_reports_empty_database) ... ok test_verify_with_content_check_passes (test_integrity.VerifyTest.test_verify_with_content_check_passes) ... ok test_detects_each_format (test_migration.DetectVersionTest.test_detects_each_format) ... ok test_detects_non_vfs_database (test_migration.DetectVersionTest.test_detects_non_vfs_database) ... ok test_missing_file_raises (test_migration.DetectVersionTest.test_missing_file_raises) ... ok test_migrated_database_unpacks_via_cli (test_migration.MigrateCliTest.test_migrated_database_unpacks_via_cli) ... ok test_v1_bool_flag_is_mapped_to_zlib (test_migration.MigrateFromV1Test.test_v1_bool_flag_is_mapped_to_zlib) ... ok test_backup_can_be_disabled (test_migration.MigrateFromV2Test.test_backup_can_be_disabled) ... ok test_backup_can_be_forced_with_output (test_migration.MigrateFromV2Test.test_backup_can_be_forced_with_output) ... ok test_backup_is_created_and_original_untouched (test_migration.MigrateFromV2Test.test_backup_is_created_and_original_untouched) ... ok test_content_survives_byte_for_byte (test_migration.MigrateFromV2Test.test_content_survives_byte_for_byte) ... ok test_custom_snapshot_name (test_migration.MigrateFromV2Test.test_custom_snapshot_name) ... ok test_identical_content_is_deduplicated_during_migration (test_migration.MigrateFromV2Test.test_identical_content_is_deduplicated_during_migration) ... ok test_metadata_is_carried_over (test_migration.MigrateFromV2Test.test_metadata_is_carried_over) ... ok test_migrate_to_a_new_file_leaves_the_original_alone (test_migration.MigrateFromV2Test.test_migrate_to_a_new_file_leaves_the_original_alone) 原库在只读介质上时不能原地替换,所以支持输出到新路径。 ... ok test_migrated_pack_verifies_and_signs (test_migration.MigrateFromV2Test.test_migrated_pack_verifies_and_signs) ... ok test_migration_of_a_readonly_file_into_a_new_file (test_migration.MigrateFromV2Test.test_migration_of_a_readonly_file_into_a_new_file) ... ok test_refuses_to_overwrite_an_existing_output (test_migration.MigrateFromV2Test.test_refuses_to_overwrite_an_existing_output) ... ok test_second_migration_is_a_no_op (test_migration.MigrateFromV2Test.test_second_migration_is_a_no_op) ... ok test_snapshot_name_defaults_to_the_pack_name (test_migration.MigrateFromV2Test.test_snapshot_name_defaults_to_the_pack_name) ... ok test_structure_is_preserved (test_migration.MigrateFromV2Test.test_structure_is_preserved) ... ok test_missing_file_raises (test_migration.MigrateInvalidInputTest.test_missing_file_raises) ... ok test_non_vfs_database_is_rejected (test_migration.MigrateInvalidInputTest.test_non_vfs_database_is_rejected) ... ok test_original_survives_a_failure (test_migration.MigrateInvalidInputTest.test_original_survives_a_failure) 迁移失败时原库必须原样保留(中间态写在临时文件里)。 ... ok test_compression_reduces_database_size (test_roundtrip.RoundTripTest.test_compression_reduces_database_size) 用一个足够大的重复文本,让压缩效果超过 SQLite 页粒度(4KB)的噪声。 ... ok test_every_source_file_is_stored (test_roundtrip.RoundTripTest.test_every_source_file_is_stored) P0-1:打包后库里必须有和源目录一一对应的文件记录。 ... ok test_metadata_counts_match_database (test_roundtrip.RoundTripTest.test_metadata_counts_match_database) P1-5:上报的统计数字必须来自真实入库的数据,而不是遍历计数。 ... ok test_packed_database_contains_no_duplicate_paths (test_roundtrip.RoundTripTest.test_packed_database_contains_no_duplicate_paths) 唯一性现在是"每个快照内"的:UNIQUE(snapshot_id, path)。 ... ok test_roundtrip_with_compression (test_roundtrip.RoundTripTest.test_roundtrip_with_compression) ... ok test_roundtrip_with_ignore_timestamps (test_roundtrip.RoundTripTest.test_roundtrip_with_ignore_timestamps) ... ok test_roundtrip_without_compression (test_roundtrip.RoundTripTest.test_roundtrip_without_compression) ... ok test_stored_blob_of_compressible_file_is_smaller (test_roundtrip.RoundTripTest.test_stored_blob_of_compressible_file_is_smaller) 压缩不只是"标记了一下":库里真正存的字节必须变少。 ... ok test_add_vfs_metadata_names_the_default_snapshot (test_snapshots.SnapshotLifecycleTest.test_add_vfs_metadata_names_the_default_snapshot) ... ok test_create_snapshot_becomes_active_and_is_listed (test_snapshots.SnapshotLifecycleTest.test_create_snapshot_becomes_active_and_is_listed) ... ok test_delete_snapshot_removes_entries_and_signature_rows (test_snapshots.SnapshotLifecycleTest.test_delete_snapshot_removes_entries_and_signature_rows) ... ok test_first_write_creates_a_default_snapshot (test_snapshots.SnapshotLifecycleTest.test_first_write_creates_a_default_snapshot) ... ok test_readonly_never_creates_a_snapshot (test_snapshots.SnapshotLifecycleTest.test_readonly_never_creates_a_snapshot) 只读打开不能因为"读一下"就写库——否则只读挂载会失败。 ... ok test_reopen_defaults_to_the_latest_snapshot (test_snapshots.SnapshotLifecycleTest.test_reopen_defaults_to_the_latest_snapshot) ... ok test_use_missing_snapshot_raises (test_snapshots.SnapshotLifecycleTest.test_use_missing_snapshot_raises) ... ok test_use_snapshot_switches_the_view (test_snapshots.SnapshotLifecycleTest.test_use_snapshot_switches_the_view) ... ok test_blobs_are_shared_between_snapshots (test_snapshots.TimeTravelTest.test_blobs_are_shared_between_snapshots) ... ok test_copy_entries_forks_from_the_parent (test_snapshots.TimeTravelTest.test_copy_entries_forks_from_the_parent) ... ok test_counts_are_per_snapshot (test_snapshots.TimeTravelTest.test_counts_are_per_snapshot) ... ok test_each_snapshot_has_its_own_digest (test_snapshots.TimeTravelTest.test_each_snapshot_has_its_own_digest) ... ok test_export_respects_the_active_snapshot (test_snapshots.TimeTravelTest.test_export_respects_the_active_snapshot) ... ok test_list_directory_is_snapshot_scoped (test_snapshots.TimeTravelTest.test_list_directory_is_snapshot_scoped) ... ok test_mkdir_in_one_snapshot_does_not_leak (test_snapshots.TimeTravelTest.test_mkdir_in_one_snapshot_does_not_leak) ... ok test_new_files_are_invisible_in_the_older_snapshot (test_snapshots.TimeTravelTest.test_new_files_are_invisible_in_the_older_snapshot) ... ok test_remove_in_one_snapshot_does_not_affect_the_other (test_snapshots.TimeTravelTest.test_remove_in_one_snapshot_does_not_affect_the_other) ... ok test_same_path_has_different_content_per_snapshot (test_snapshots.TimeTravelTest.test_same_path_has_different_content_per_snapshot) ... ok test_snapshot_id_can_be_chosen_at_construction (test_snapshots.TimeTravelTest.test_snapshot_id_can_be_chosen_at_construction) ... ok test_unpacker_check_database_counts_only_the_active_snapshot (test_snapshots.UnpackerSnapshotTest.test_unpacker_check_database_counts_only_the_active_snapshot) ... ok test_unpacker_export_follows_the_snapshot (test_snapshots.UnpackerSnapshotTest.test_unpacker_export_follows_the_snapshot) ... ok test_unpacker_list_root_is_snapshot_scoped (test_snapshots.UnpackerSnapshotTest.test_unpacker_list_root_is_snapshot_scoped) ... ok ---------------------------------------------------------------------- Ran 270 tests in 14.648s OK (skipped=52) EXIT=0