docs: 补 README 能力章节、缺陷报告与两份设计说明
- README:新增「数据能力」四节(内容寻址去重 / 快照与时间旅行 / 完整性校验与签名 / 增量打包)与「发布到对象存储」一节,附实测对比表;重写「要不要用 --compress」 (结论从"别用"反转为"默认就该开")、「迁移旧格式」;修正项目结构与字段表 - BUG_REPORT.md:13 节,含 P0/P1 逐条分析、P2/P3 清单、五批后续追加的记录, 以及过程中被推翻的两处结论(第九节的压缩建议、P3-1 的 uv sync 判断) - docs/encryption-design.md:加密的设计说明——去重与随机 nonce 的冲突、 标准库没有密码学原语、以及现有 freq_blob 可作为每块附加数据的槽位 - docs/evidence-*.txt:各阶段的测试运行证据(修复前 / 修复后 / 双环境)
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# 加密设计说明(写代码之前必须先定的两件事)
|
||||
|
||||
这份说明是给"后面考虑加加密"准备的。它不实现任何东西,只把两个**必须先决定**的
|
||||
约束摆在前面——因为它们都会反过来改数据结构,等到写完再发现就要返工。
|
||||
|
||||
---
|
||||
|
||||
## 一、去重与随机 nonce 是冲突的
|
||||
|
||||
这是最要紧的一条。当前设计里 `blobs.hash` 是 `sha256(原始内容)` 并且是主键,
|
||||
"相同内容只存一份"完全建立在这上面。加密会直接冲击它:
|
||||
|
||||
| 方案 | nonce 怎么来 | 去重 | 代价 |
|
||||
|---|---|---|---|
|
||||
| **A. 确定性(收敛)加密** | nonce 由 `HMAC(key, 明文hash)` 派生 | **保留** | 密文相同 ⇒ 泄露"这两份内容一样"(其实去重本来就泄露);可被确认攻击:拿到明文猜测的人能判断库里有没有这份内容 |
|
||||
| **B. 每块随机 nonce** | `os.urandom` | **包内保留,跨包丢失** | 同一份内容在不同包里密文不同 → 对象名(当前是明文 hash)不再能当 URL;`vfsfetch` 的"名字即 sha256"校验失效;同一个 CDN 路径可能返回不同字节 |
|
||||
| **C. 按文件加密** | 每个文件一份 | **完全丢失** | 相同的两个文件各存一份密文,体积翻倍 |
|
||||
| **D. 只加密容器/对象,不动 blob** | 不适用 | 保留 | 服务方(插件/CDN 之外的那一层)拿不到明文;本地 `.svfs` 仍是明文 |
|
||||
|
||||
### 我的建议
|
||||
|
||||
**先明确你要防谁**,答案不同、方案不同:
|
||||
|
||||
* **防"存储方/传输方看到内容"**(S3、CDN、对象存储被拖库)→ 选 **D**:发布前把对象加密
|
||||
(或直接用带 SSE 的桶 + TLS),本地 `.svfs` 保持明文。代价最低,完全不动现有结构,
|
||||
而且**不影响去重与对象名**。这是我最推荐的起点。
|
||||
* **防"本地库被拿走也读不出"**(笔记本丢了、镜像层被人翻)→ 需要 A 或 B:
|
||||
* 如果你同时要"跨包去重 + 对象名稳定"(也就是现在的发布能力),只能选 **A**,
|
||||
并接受确认攻击这个已知代价。这在"内容多半是公开前端资源"的场景里通常可以接受。
|
||||
* 如果你只要"包内去重",**B** 更安全,但发布能力要跟着改:
|
||||
对象名不能再用明文 hash,`manifest.json` 里得同时记录明文 hash 与密文 hash,
|
||||
`vfsfetch` 改为校验"解密后再算 hash"(那就意味着客户端必须持有密钥)。
|
||||
|
||||
一句话:**A 与现在的发布/去重能力兼容,B 与它不兼容。这个岔路口必须先选。**
|
||||
|
||||
---
|
||||
|
||||
## 二、标准库没有密码学原语,所以"高效"指向一个依赖
|
||||
|
||||
Python 标准库只有 `hashlib` / `hmac` / `secrets` / `os.urandom`——**没有任何分组密码**。
|
||||
所以:
|
||||
|
||||
| 选项 | 性能(量级) | 评价 |
|
||||
|---|---|---|
|
||||
| `cryptography`(pyca)的 AES-256-GCM | **1~5 GB/s**(AES-NI 硬件加速) | 推荐。单一依赖、AEAD 一次过、有认证 |
|
||||
| 同库的 ChaCha20-Poly1305 | 1~3 GB/s(纯软件即很快) | 没有 AES-NI 的机器上更稳 |
|
||||
| 纯 Python 实现 AES | **~1 MB/s** | 不可用(慢三个数量级),且自己写密码学实现本身就是风险 |
|
||||
| 用 HMAC-SHA256 / SHA-256 计数器模式自建流密码 + HMAC 认证 | 约 0.5~1.5 GB/s | 构造上是成立的(PRF 派生 keystream + encrypt-then-MAC),但**必须**自己保证"同一密钥下计数器永不重复",且要正确实现认证——省一个依赖,多一份责任 |
|
||||
|
||||
**"尽可能高效"的实际含义**:用 AEAD(AES-GCM 或 ChaCha20-Poly1305),
|
||||
而不是"自己写一个更快的"。自己写在 Python 里赢不了硬件指令。
|
||||
|
||||
顺带三条实现纪律:
|
||||
|
||||
1. **先压缩再加密**。压缩靠的是内容里的冗余,密文是随机-looking 的,压不动。
|
||||
顺序反了等于白压。
|
||||
2. **认证必须做**(AEAD 或 encrypt-then-MAC)。只加密不认证,攻击者可以翻动密文比特,
|
||||
密文解出来就是"看起来合法但已被改动"的数据——而我们整个完整性体系(sha256 + 摘要
|
||||
+ HMAC 签名)就是为了不让这种事发生。
|
||||
3. **密钥不要进库**。库里的 `signatures` 表存的是 HMAC 签名,那是防篡改用的,
|
||||
不是密钥保管。密钥从环境变量/密钥管理服务来。
|
||||
|
||||
---
|
||||
|
||||
## 三、现有结构对加密友好的地方
|
||||
|
||||
好消息是**几乎不用改 schema**:
|
||||
|
||||
* `blobs.freq_blob`(BLOB)本质是一个**通用的"每块附加数据"槽**。它现在是哈夫曼频率表,
|
||||
加密的 nonce + 认证标签可以放这里,不需要加列。
|
||||
* `blobs.compress_algo`(TEXT)现在存 `'none' / 'zlib' / 'huffman'`。加一档 `'aes-gcm'`
|
||||
就走通了——`compression.py` 是唯一的算法分发点(见该模块 docstring 的契约说明)。
|
||||
* 如果"先压后加"需要同时表达两层,建议**加一列 `encrypt_algo`** 而不是把算法名拼成
|
||||
`'zlib+aes-gcm'` 这种字符串:拼字符串会让 `decompress_with` 的分发逻辑变脆,
|
||||
而且查询"这个包里加密了吗"要靠 LIKE。加列的成本是一次 v4 迁移(迁移机制已经在了,
|
||||
`migration.py` + `vfsmigrate`)。
|
||||
|
||||
---
|
||||
|
||||
## 四、建议的推进顺序
|
||||
|
||||
1. **先只做 D**(发布层的信封加密):不动 blob、不动去重、不动对象名。
|
||||
验证一下"发布到不可信存储"这个需求是不是就满足了——大概率是。
|
||||
2. 如果确实需要"静态加密整个库",再做 A(确定性 nonce),并接受确认攻击;
|
||||
这时要同步改:`manifest.json` 增加密文字段、`vfsfetch` 的校验时机、
|
||||
以及"未授权方拿不到密钥就什么也读不出"的密钥分发方案。
|
||||
3. 无论走哪条,先给 `compression.py` 加一层算法链的**契约测试**
|
||||
(`tests/test_compression.py` 已有骨架),保证加算法不破坏现有往返。
|
||||
@@ -0,0 +1,110 @@
|
||||
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) ... ok
|
||||
test_unpack_non_database_file_reports_clean_error (test_cli.CliFailureTest.test_unpack_non_database_file_reports_clean_error) ... 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_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_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:264: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes
|
||||
cursor.execute(
|
||||
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_below_threshold_is_not_compressed (test_core.FileContentTest.test_below_threshold_is_not_compressed) ... ok
|
||||
test_compressible_file_uses_huffman (test_core.FileContentTest.test_compressible_file_uses_huffman) ... 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_mk_dir_creates_directory (test_core.MkDirTest.test_mk_dir_creates_directory) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:425: 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_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_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) ... ok
|
||||
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_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:打包后库里必须有和源目录一一对应的文件记录。 ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:214: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes
|
||||
cursor.execute(
|
||||
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) ... 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
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 81 tests in 6.741s
|
||||
|
||||
OK
|
||||
EXIT=0
|
||||
@@ -0,0 +1,829 @@
|
||||
test_pack_missing_source_returns_nonzero (test_cli.CliFailureTest.test_pack_missing_source_returns_nonzero) ... FAIL
|
||||
test_pack_to_missing_output_directory_reports_clean_error (test_cli.CliFailureTest.test_pack_to_missing_output_directory_reports_clean_error) ... FAIL
|
||||
test_unpack_missing_db_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_db_returns_nonzero) ... FAIL
|
||||
test_unpack_missing_path_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_path_returns_nonzero) ... FAIL
|
||||
test_unpack_non_database_file_reports_clean_error (test_cli.CliFailureTest.test_unpack_non_database_file_reports_clean_error) ... FAIL
|
||||
test_exclude_prunes_directory_subtree (test_cli.CliPackTest.test_exclude_prunes_directory_subtree) ... FAIL
|
||||
test_exclude_supports_glob_patterns (test_cli.CliPackTest.test_exclude_supports_glob_patterns)
|
||||
P1-9: README 承诺 glob 语义,`*.log` 必须真的排除 .log 文件, ... FAIL
|
||||
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) ... FAIL
|
||||
test_full_roundtrip_via_cli (test_cli.CliUnpackTest.test_full_roundtrip_via_cli) ... FAIL
|
||||
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。 ... FAIL
|
||||
test_ignore_timestamps_with_path_subdirectory (test_cli.CliUnpackTest.test_ignore_timestamps_with_path_subdirectory) ... FAIL
|
||||
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) ... ERROR
|
||||
test_path_exports_subdirectory_with_contents (test_cli.CliUnpackTest.test_path_exports_subdirectory_with_contents) ... FAIL
|
||||
test_rejects_old_schema_database_cleanly (test_cli.CliUnpackTest.test_rejects_old_schema_database_cleanly)
|
||||
P1-7: 旧格式库要给出明确提示,退出码非 0,且不能是 traceback。 ... FAIL
|
||||
test_duplicate_add_file_is_reported_and_keeps_first_content (test_core.AddFileConflictTest.test_duplicate_add_file_is_reported_and_keeps_first_content) ... FAIL
|
||||
test_directories_come_before_files (test_core.DirectoryListingTest.test_directories_come_before_files) ... FAIL
|
||||
test_leaf_directory_is_empty (test_core.DirectoryListingTest.test_leaf_directory_is_empty) ... FAIL
|
||||
test_nested_directory_lists_its_children (test_core.DirectoryListingTest.test_nested_directory_lists_its_children) ... FAIL
|
||||
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) ... FAIL
|
||||
test_subdirectory_lists_its_children (test_core.DirectoryListingTest.test_subdirectory_lists_its_children) ... FAIL
|
||||
test_export_directory_full_tree (test_core.ExportTest.test_export_directory_full_tree) ... Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 483, in export_file
|
||||
content = self.read_file(vfs_path)
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 278, in read_file
|
||||
algo = file_info["compress_algo"] or "none"
|
||||
~~~~~~~~~^^^^^^^^^^^^^^^^^
|
||||
KeyError: 'compress_algo'
|
||||
FAIL
|
||||
test_export_file_accepts_bare_filename (test_core.ExportTest.test_export_file_accepts_bare_filename)
|
||||
P1-6: local_path 没有目录部分时 dirname 为 '',不能抛 FileNotFoundError。 ... Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 480, in export_file
|
||||
os.makedirs(os.path.dirname(local_path), exist_ok=True)
|
||||
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "<frozen os>", line 228, in makedirs
|
||||
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: ''
|
||||
FAIL
|
||||
test_export_file_writes_exact_bytes (test_core.ExportTest.test_export_file_writes_exact_bytes) ... Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 483, in export_file
|
||||
content = self.read_file(vfs_path)
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 278, in read_file
|
||||
algo = file_info["compress_algo"] or "none"
|
||||
~~~~~~~~~^^^^^^^^^^^^^^^^^
|
||||
KeyError: 'compress_algo'
|
||||
FAIL
|
||||
test_export_filesystem_matches_tree (test_core.ExportTest.test_export_filesystem_matches_tree) ... Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 483, in export_file
|
||||
content = self.read_file(vfs_path)
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 278, in read_file
|
||||
algo = file_info["compress_algo"] or "none"
|
||||
~~~~~~~~~^^^^^^^^^^^^^^^^^
|
||||
KeyError: 'compress_algo'
|
||||
FAIL
|
||||
test_export_subdirectory_does_not_recurse_forever (test_core.ExportTest.test_export_subdirectory_does_not_recurse_forever)
|
||||
P0-2: list_directory 按 path 过滤时,导出 doc 会无限自我递归。 ... FAIL
|
||||
test_below_threshold_is_not_compressed (test_core.FileContentTest.test_below_threshold_is_not_compressed) ... ERROR
|
||||
test_compressible_file_uses_huffman (test_core.FileContentTest.test_compressible_file_uses_huffman) ... ERROR
|
||||
test_empty_file_roundtrip (test_core.FileContentTest.test_empty_file_roundtrip) ... ERROR
|
||||
test_file_size_recorded_matches_content (test_core.FileContentTest.test_file_size_recorded_matches_content) ... ERROR
|
||||
test_incompressible_file_falls_back_to_none (test_core.FileContentTest.test_incompressible_file_falls_back_to_none) ... ERROR
|
||||
test_read_file_offset_and_size (test_core.FileContentTest.test_read_file_offset_and_size) ... ERROR
|
||||
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) ... ERROR
|
||||
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:319: 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) ... FAIL
|
||||
test_mv_dir_into_new_parent_directory (test_core.MoveAndRemoveTest.test_mv_dir_into_new_parent_directory) ... 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 会再次命中已改名的目录自身。 ... FAIL
|
||||
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 目录行必须存在, ... FAIL
|
||||
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_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 一起匹配上)。 ... FAIL
|
||||
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) ... FAIL
|
||||
test_add_file_survives_close_without_further_commit (test_core.PersistenceTest.test_add_file_survives_close_without_further_commit) ... FAIL
|
||||
test_fresh_database_is_accepted (test_core.SchemaCompatibilityTest.test_fresh_database_is_accepted) ... 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) ... FAIL
|
||||
test_synthesized_old_schema_db_is_rejected (test_core.SchemaCompatibilityTest.test_synthesized_old_schema_db_is_rejected) ... FAIL
|
||||
test_add_file_actually_stores_a_row (test_core.SchemaContractTest.test_add_file_actually_stores_a_row)
|
||||
add_file 之后库里必须真的有这条记录。 ... FAIL
|
||||
test_expected_columns_exist (test_core.SchemaContractTest.test_expected_columns_exist) ... FAIL
|
||||
test_bad_magic_rejected (test_huffman.HeaderValidationTest.test_bad_magic_rejected) ... 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) ... FAIL
|
||||
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) ... FAIL
|
||||
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) ... ERROR
|
||||
test_compression_reduces_database_size (test_roundtrip.RoundTripTest.test_compression_reduces_database_size) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:124: DeprecationWarning: The default datetime adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes
|
||||
cursor.execute(
|
||||
FAIL
|
||||
test_every_source_file_is_stored (test_roundtrip.RoundTripTest.test_every_source_file_is_stored)
|
||||
P0-1:打包后库里必须有和源目录一一对应的文件记录。 ... FAIL
|
||||
test_metadata_counts_match_database (test_roundtrip.RoundTripTest.test_metadata_counts_match_database)
|
||||
P1-5:上报的统计数字必须来自真实入库的数据,而不是遍历计数。 ... FAIL
|
||||
test_packed_database_contains_no_duplicate_paths (test_roundtrip.RoundTripTest.test_packed_database_contains_no_duplicate_paths) ... ok
|
||||
test_roundtrip_with_compression (test_roundtrip.RoundTripTest.test_roundtrip_with_compression) ... E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py:242: ResourceWarning: unclosed database in <sqlite3.Connection object at 0x000002E9E0ACFC40>
|
||||
parsed_row["created_time"].replace("Z", "+00:00")
|
||||
ResourceWarning: Enable tracemalloc to get the object allocation traceback
|
||||
FAIL
|
||||
test_roundtrip_with_ignore_timestamps (test_roundtrip.RoundTripTest.test_roundtrip_with_ignore_timestamps) ... FAIL
|
||||
test_roundtrip_without_compression (test_roundtrip.RoundTripTest.test_roundtrip_without_compression) ... FAIL
|
||||
|
||||
======================================================================
|
||||
ERROR: test_path_exports_single_file (test_cli.CliUnpackTest.test_path_exports_single_file)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 184, in test_path_exports_single_file
|
||||
with open(os.path.join(out, "top.txt"), "rb") as f:
|
||||
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\chakcy\\AppData\\Local\\Temp\\svfs_test_kelch2hu\\out\\top.txt'
|
||||
|
||||
======================================================================
|
||||
ERROR: test_below_threshold_is_not_compressed (test_core.FileContentTest.test_below_threshold_is_not_compressed)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 116, in test_below_threshold_is_not_compressed
|
||||
vfs, content = self._write_and_read(data, compress=True)
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_compressible_file_uses_huffman (test_core.FileContentTest.test_compressible_file_uses_huffman)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 93, in test_compressible_file_uses_huffman
|
||||
vfs, content = self._write_and_read(data, compress=True)
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_empty_file_roundtrip (test_core.FileContentTest.test_empty_file_roundtrip)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 88, in test_empty_file_roundtrip
|
||||
_, content = self._write_and_read(b"")
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_file_size_recorded_matches_content (test_core.FileContentTest.test_file_size_recorded_matches_content)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 122, in test_file_size_recorded_matches_content
|
||||
vfs, _ = self._write_and_read(data)
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_incompressible_file_falls_back_to_none (test_core.FileContentTest.test_incompressible_file_falls_back_to_none)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 106, in test_incompressible_file_falls_back_to_none
|
||||
vfs, content = self._write_and_read(data, compress=True)
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_read_file_offset_and_size (test_core.FileContentTest.test_read_file_offset_and_size)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 126, in test_read_file_offset_and_size
|
||||
vfs, _ = self._write_and_read(b"0123456789")
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_small_file_roundtrip (test_core.FileContentTest.test_small_file_roundtrip)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 83, in test_small_file_roundtrip
|
||||
vfs, content = self._write_and_read(b"hello sqlite vfs")
|
||||
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 80, in _write_and_read
|
||||
return vfs, vfs.read_file(rel_path)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\core.py", line 273, in read_file
|
||||
raise FileNotFoundError(f"文件不存在: {path}")
|
||||
FileNotFoundError: 文件不存在: data.bin
|
||||
|
||||
======================================================================
|
||||
ERROR: test_utf8_chinese (test_huffman.RoundTripTest.test_utf8_chinese)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_huffman.py", line 78, in test_utf8_chinese
|
||||
self.assert_roundtrip("中文内容,测试哈夫曼编码是否无损。\n" * 200, "中文")
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_huffman.py", line 24, in assert_roundtrip
|
||||
freq_blob, compressed_blob = compress_bytes(data)
|
||||
~~~~~~~~~~~~~~^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\src\sqlite_vfs\huffman.py", line 128, in compress_bytes
|
||||
freq[b] += 1
|
||||
~~~~^^^
|
||||
TypeError: list indices must be integers or slices, not str
|
||||
|
||||
======================================================================
|
||||
FAIL: test_pack_missing_source_returns_nonzero (test_cli.CliFailureTest.test_pack_missing_source_returns_nonzero)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 49, in test_pack_missing_source_returns_nonzero
|
||||
self.assertNotEqual(0, result.returncode, "源目录不存在却返回了成功")
|
||||
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 0 == 0 : 源目录不存在却返回了成功
|
||||
|
||||
======================================================================
|
||||
FAIL: test_pack_to_missing_output_directory_reports_clean_error (test_cli.CliFailureTest.test_pack_to_missing_output_directory_reports_clean_error)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 61, in test_pack_to_missing_output_directory_reports_clean_error
|
||||
self.assertNotIn("Traceback", helpers.cli_output(result))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'Traceback' unexpectedly found in 'Traceback (most recent call last):\n File "<frozen runpy>", line 198, in _run_module_as_main\n File "<frozen runpy>", line 88, in _run_code\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\packer.py", line 40, in <module>\n pack()\n ~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\packer.py", line 28, in pack\n sqlite_vfs=SQLiteVFS(args.output_db, args.compress),\n ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\core.py", line 20, in __init__\n self.connect()\n ~~~~~~~~~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\core.py", line 24, in connect\n self.conn = sqlite3.connect(self.db_path)\n ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^\nsqlite3.OperationalError: unable to open database file\n'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_unpack_missing_db_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_db_returns_nonzero)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 54, in test_unpack_missing_db_returns_nonzero
|
||||
self.assertNotEqual(0, result.returncode, "数据库不存在却返回了成功")
|
||||
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 0 == 0 : 数据库不存在却返回了成功
|
||||
|
||||
======================================================================
|
||||
FAIL: test_unpack_missing_path_returns_nonzero (test_cli.CliFailureTest.test_unpack_missing_path_returns_nonzero)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 73, in test_unpack_missing_path_returns_nonzero
|
||||
self.assertNotEqual(0, result.returncode, "导出不存在的路径却返回了成功")
|
||||
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 0 == 0 : 导出不存在的路径却返回了成功
|
||||
|
||||
======================================================================
|
||||
FAIL: test_unpack_non_database_file_reports_clean_error (test_cli.CliFailureTest.test_unpack_non_database_file_reports_clean_error)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 68, in test_unpack_non_database_file_reports_clean_error
|
||||
self.assertNotIn("Traceback", helpers.cli_output(result))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'Traceback' unexpectedly found in 'Traceback (most recent call last):\n File "<frozen runpy>", line 198, in _run_module_as_main\n File "<frozen runpy>", line 88, in _run_code\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 77, in <module>\n unpack()\n ~~~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 34, in unpack\n unpacker = FolderUnpacker(sqlite_vfs=SQLiteVFS(args.db_file))\n ~~~~~~~~~^^^^^^^^^^^^^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\core.py", line 20, in __init__\n self.connect()\n ~~~~~~~~~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\core.py", line 26, in connect\n self._create_tables()\n ~~~~~~~~~~~~~~~~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\core.py", line 72, in _create_tables\n cursor.execute(\n ~~~~~~~~~~~~~~^\n """\n ^^^\n ...<7 lines>...\n """\n ^^^\n )\n ^\nsqlite3.DatabaseError: file is not a database\n'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_exclude_prunes_directory_subtree (test_cli.CliPackTest.test_exclude_prunes_directory_subtree)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 123, in test_exclude_prunes_directory_subtree
|
||||
self.assertEqual({"keep.txt"}, set(helpers.stored_files(vfs)))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Items in the first set but not the second:
|
||||
'keep.txt'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_exclude_supports_glob_patterns (test_cli.CliPackTest.test_exclude_supports_glob_patterns)
|
||||
P1-9: README 承诺 glob 语义,`*.log` 必须真的排除 .log 文件,
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 106, in test_exclude_supports_glob_patterns
|
||||
self.assertEqual(
|
||||
~~~~~~~~~~~~~~~~^
|
||||
{"keep.txt", "catalog.txt", "sub/keep2.txt"}, set(helpers.stored_files(vfs))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: Items in the first set but not the second:
|
||||
'catalog.txt'
|
||||
'sub/keep2.txt'
|
||||
'keep.txt'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_pack_stores_every_file (test_cli.CliPackTest.test_pack_stores_every_file)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 86, in test_pack_stores_every_file
|
||||
self.assertEqual(expected, set(helpers.stored_files(vfs)))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Items in the first set but not the second:
|
||||
'sub/inner.txt'
|
||||
'top.txt'
|
||||
'sub/deep/leaf.bin'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_full_roundtrip_via_cli (test_cli.CliUnpackTest.test_full_roundtrip_via_cli)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 152, in test_full_roundtrip_via_cli
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 3 项,例如: ['sub/deep/leaf.bin', 'sub/in[1427 chars]ir']"
|
||||
Diff is 1482 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
======================================================================
|
||||
FAIL: 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。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 194, in test_ignore_timestamps_full_export_does_not_recurse
|
||||
self.assertNotIn("RecursionError", output)
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'RecursionError' unexpectedly found in '数据库状态: 数据库正常,共有 6 个文件/目录,根目录下有 3 个项目\nTraceback (most recent call last):\n File "<frozen runpy>", line 198, in _run_module_as_main\n File "<frozen runpy>", line 88, in _run_code\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 77, in <module>\n unpack()\n ~~~~~~^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 70, in unpack\n unpacker.unpack_filesystem(args.export_folder)\n ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\folder_unpacker.py", line 60, in unpack_filesystem\n return self.sqlite_vfs.export_filesystem(export_folder)\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 66, in <lambda>\n lambda export_root: unpacker.sqlite_vfs.export_filesystem(\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n export_root\n ^^^^^^^^^^^\n )\n ^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 66, in <lambda>\n lambda export_root: unpacker.sqlite_vfs.export_filesystem(\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n export_root\n ^^^^^^^^^^^\n )\n ^\n File "E:\\HuaweiMoveData\\Users\\chakcy\\Desktop\\新建文件夹\\sqlite_vfs\\src\\sqlite_vfs\\cli\\unpacker.py", line 66, in <lambda>\n lambda export_root: unpacker.sqlite_vfs.export_filesystem(\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n export_root\n ^^^^^^^^^^^\n )\n ^\n [Previous line repeated 992 more times]\nRecursionError: maximum recursion depth exceeded\n'
|
||||
|
||||
======================================================================
|
||||
FAIL: test_ignore_timestamps_with_path_subdirectory (test_cli.CliUnpackTest.test_ignore_timestamps_with_path_subdirectory)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 215, in test_ignore_timestamps_with_path_subdirectory
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(os.path.join(out, "doc")))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt'][536 chars]oc']"
|
||||
- 无差异
|
||||
+ 缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt']
|
||||
+ 多出 991 项,例如: ['doc', 'doc/doc', 'doc/doc/doc', 'doc/doc/doc/doc', 'doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc']
|
||||
|
||||
|
||||
======================================================================
|
||||
FAIL: test_path_exports_subdirectory_with_contents (test_cli.CliUnpackTest.test_path_exports_subdirectory_with_contents)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 177, in test_path_exports_subdirectory_with_contents
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(os.path.join(out, "doc")))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt'][536 chars]oc']"
|
||||
- 无差异
|
||||
+ 缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt']
|
||||
+ 多出 991 项,例如: ['doc', 'doc/doc', 'doc/doc/doc', 'doc/doc/doc/doc', 'doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc']
|
||||
|
||||
|
||||
======================================================================
|
||||
FAIL: test_rejects_old_schema_database_cleanly (test_cli.CliUnpackTest.test_rejects_old_schema_database_cleanly)
|
||||
P1-7: 旧格式库要给出明确提示,退出码非 0,且不能是 traceback。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_cli.py", line 222, in test_rejects_old_schema_database_cleanly
|
||||
self.assertNotEqual(0, result.returncode)
|
||||
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 0 == 0
|
||||
|
||||
======================================================================
|
||||
FAIL: test_duplicate_add_file_is_reported_and_keeps_first_content (test_core.AddFileConflictTest.test_duplicate_add_file_is_reported_and_keeps_first_content)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 368, in test_duplicate_add_file_is_reported_and_keeps_first_content
|
||||
self.assertTrue(first, "首次写入应当成功")
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: None is not true : 首次写入应当成功
|
||||
|
||||
======================================================================
|
||||
FAIL: test_directories_come_before_files (test_core.DirectoryListingTest.test_directories_come_before_files)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 182, in test_directories_come_before_files
|
||||
self.assertEqual([1, 0], [row["is_directory"] for row in rows])
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Lists differ: [1, 0] != [1]
|
||||
|
||||
First list contains 1 additional elements.
|
||||
First extra element 1:
|
||||
0
|
||||
|
||||
- [1, 0]
|
||||
+ [1]
|
||||
|
||||
======================================================================
|
||||
FAIL: test_leaf_directory_is_empty (test_core.DirectoryListingTest.test_leaf_directory_is_empty)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 186, in test_leaf_directory_is_empty
|
||||
self.assertEqual([], vfs.list_directory("docs"))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Lists differ: [] != [{'id': 2, 'path': 'docs', 'name': 'docs',[177 chars]ne'}]
|
||||
|
||||
Second list contains 1 additional elements.
|
||||
First extra element 0:
|
||||
{'id': 2, 'path': 'docs', 'name': 'docs', 'parent_path': '', 'is_directory': 1, 'file_size': 0, 'created_time': None, 'modified_time': None, 'permissions': 644, 'content': None, 'freq_blob': None, 'compresse_algo': 'none'}
|
||||
|
||||
- []
|
||||
+ [{'compresse_algo': 'none',
|
||||
+ 'content': None,
|
||||
+ 'created_time': None,
|
||||
+ 'file_size': 0,
|
||||
+ 'freq_blob': None,
|
||||
+ 'id': 2,
|
||||
+ 'is_directory': 1,
|
||||
+ 'modified_time': None,
|
||||
+ 'name': 'docs',
|
||||
+ 'parent_path': '',
|
||||
+ 'path': 'docs',
|
||||
+ 'permissions': 644}]
|
||||
|
||||
======================================================================
|
||||
FAIL: test_nested_directory_lists_its_children (test_core.DirectoryListingTest.test_nested_directory_lists_its_children)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 177, in test_nested_directory_lists_its_children
|
||||
self.assertEqual(["doc/sub/b.txt"], paths)
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Lists differ: ['doc/sub/b.txt'] != ['doc/sub']
|
||||
|
||||
First differing element 0:
|
||||
'doc/sub/b.txt'
|
||||
'doc/sub'
|
||||
|
||||
- ['doc/sub/b.txt']
|
||||
? ------
|
||||
|
||||
+ ['doc/sub']
|
||||
|
||||
======================================================================
|
||||
FAIL: test_root_lists_top_level_only (test_core.DirectoryListingTest.test_root_lists_top_level_only)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 167, in test_root_lists_top_level_only
|
||||
self.assertEqual(["doc", "docs", "top.txt"], paths)
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Lists differ: ['doc', 'docs', 'top.txt'] != ['doc', 'doc/a.txt', 'doc/sub', 'doc/sub/b.txt', 'doc[23 chars]txt']
|
||||
|
||||
First differing element 1:
|
||||
'docs'
|
||||
'doc/a.txt'
|
||||
|
||||
Second list contains 4 additional elements.
|
||||
First extra element 3:
|
||||
'doc/sub/b.txt'
|
||||
|
||||
- ['doc', 'docs', 'top.txt']
|
||||
+ ['doc',
|
||||
+ 'doc/a.txt',
|
||||
+ 'doc/sub',
|
||||
+ 'doc/sub/b.txt',
|
||||
+ 'docs',
|
||||
+ 'docs/c.txt',
|
||||
+ 'top.txt']
|
||||
|
||||
======================================================================
|
||||
FAIL: test_subdirectory_lists_its_children (test_core.DirectoryListingTest.test_subdirectory_lists_its_children)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 172, in test_subdirectory_lists_its_children
|
||||
self.assertEqual(["doc/a.txt", "doc/sub"], paths)
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Lists differ: ['doc/a.txt', 'doc/sub'] != ['doc']
|
||||
|
||||
First differing element 0:
|
||||
'doc/a.txt'
|
||||
'doc'
|
||||
|
||||
First list contains 1 additional elements.
|
||||
First extra element 1:
|
||||
'doc/sub'
|
||||
|
||||
- ['doc/a.txt', 'doc/sub']
|
||||
+ ['doc']
|
||||
|
||||
======================================================================
|
||||
FAIL: test_export_directory_full_tree (test_core.ExportTest.test_export_directory_full_tree)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 432, in test_export_directory_full_tree
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 4 项,例如: ['doc/a.txt', 'doc/sub', 'doc[620 chars]oc']"
|
||||
Diff is 675 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
======================================================================
|
||||
FAIL: test_export_file_accepts_bare_filename (test_core.ExportTest.test_export_file_accepts_bare_filename)
|
||||
P1-6: local_path 没有目录部分时 dirname 为 '',不能抛 FileNotFoundError。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 413, in test_export_file_accepts_bare_filename
|
||||
self.assertTrue(ok, "导出到当前目录下的裸文件名应当成功")
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: False is not true : 导出到当前目录下的裸文件名应当成功
|
||||
|
||||
======================================================================
|
||||
FAIL: test_export_file_writes_exact_bytes (test_core.ExportTest.test_export_file_writes_exact_bytes)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 401, in test_export_file_writes_exact_bytes
|
||||
self.assertTrue(vfs.export_file("top.txt", target))
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: False is not true
|
||||
|
||||
======================================================================
|
||||
FAIL: test_export_filesystem_matches_tree (test_core.ExportTest.test_export_filesystem_matches_tree)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 457, in test_export_filesystem_matches_tree
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 4 项,例如: ['doc/a.txt', 'doc/sub', 'doc[620 chars]oc']"
|
||||
Diff is 675 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
======================================================================
|
||||
FAIL: test_export_subdirectory_does_not_recurse_forever (test_core.ExportTest.test_export_subdirectory_does_not_recurse_forever)
|
||||
P0-2: list_directory 按 path 过滤时,导出 doc 会无限自我递归。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 442, in test_export_subdirectory_does_not_recurse_forever
|
||||
helpers.assert_tree_equal(self, expected, helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt'][536 chars]oc']"
|
||||
- 无差异
|
||||
+ 缺失 3 项,例如: ['a.txt', 'sub', 'sub/b.txt']
|
||||
+ 多出 980 项,例如: ['doc', 'doc/doc', 'doc/doc/doc', 'doc/doc/doc/doc', 'doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc', 'doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc/doc']
|
||||
|
||||
|
||||
======================================================================
|
||||
FAIL: test_mv_dir_does_not_touch_prefix_sibling (test_core.MoveAndRemoveTest.test_mv_dir_does_not_touch_prefix_sibling)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 277, in test_mv_dir_does_not_touch_prefix_sibling
|
||||
self.assertIn("docs", helpers.all_paths(vfs))
|
||||
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'docs' not found in {'doc_new/sub/b.txt', 'top.txt', 'doc_new/a.txt', 'doc_new/sub', 'doc_news/c.txt', 'doc_new_new', 'doc_news'}
|
||||
|
||||
======================================================================
|
||||
FAIL: 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 会再次命中已改名的目录自身。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 261, in test_mv_dir_rename_is_not_applied_twice
|
||||
self.assertEqual(
|
||||
~~~~~~~~~~~~~~~~^
|
||||
{
|
||||
^
|
||||
...<8 lines>...
|
||||
helpers.all_paths(vfs),
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: Items in the first set but not the second:
|
||||
'docs/c.txt'
|
||||
'docs'
|
||||
'doc_new'
|
||||
Items in the second set but not the first:
|
||||
'doc_new_new'
|
||||
'doc_news/c.txt'
|
||||
'doc_news'
|
||||
|
||||
======================================================================
|
||||
FAIL: 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 目录行必须存在,
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 303, in test_mv_dir_root_creates_destination_and_fixes_parent_paths
|
||||
self.assertIn("archive", parents, "目标目录 archive 没有对应的目录行")
|
||||
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'archive' not found in {'archive/doc': 'archive/', 'archive/doc/a.txt': 'archive/doc', 'archive/doc/sub': 'archive/doc', 'archive/doc/sub/b.txt': 'archive/doc/sub', 'archive/docs': 'archive/', 'archive/docs/c.txt': 'archive/docs', 'archive/top.txt': 'archive'} : 目标目录 archive 没有对应的目录行
|
||||
|
||||
======================================================================
|
||||
FAIL: test_remove_directory_does_not_touch_prefix_sibling (test_core.MoveAndRemoveTest.test_remove_directory_does_not_touch_prefix_sibling)
|
||||
删除 doc 不能连带删掉 docs(LIKE 'doc%' 会把 docs 一起匹配上)。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 224, in test_remove_directory_does_not_touch_prefix_sibling
|
||||
self.assertEqual(
|
||||
~~~~~~~~~~~~~~~~^
|
||||
{"docs", "docs/c.txt", "top.txt"},
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
paths,
|
||||
^^^^^^
|
||||
"删除 doc 误伤了 docs",
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: Items in the first set but not the second:
|
||||
'docs/c.txt'
|
||||
'docs' : 删除 doc 误伤了 docs
|
||||
|
||||
======================================================================
|
||||
FAIL: test_remove_missing_path_reports_error (test_core.MoveAndRemoveTest.test_remove_missing_path_reports_error)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 253, in test_remove_missing_path_reports_error
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: FileNotFoundError not raised
|
||||
|
||||
======================================================================
|
||||
FAIL: test_add_file_survives_close_without_further_commit (test_core.PersistenceTest.test_add_file_survives_close_without_further_commit)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 65, in test_add_file_survives_close_without_further_commit
|
||||
self.assertTrue(
|
||||
~~~~~~~~~~~~~~~^
|
||||
reopened.exists("x.bin"),
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
"add_file 之后直接 close(),数据丢失——事务没有提交",
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: False is not true : add_file 之后直接 close(),数据丢失——事务没有提交
|
||||
|
||||
======================================================================
|
||||
FAIL: test_repository_sample_db_is_rejected (test_core.SchemaCompatibilityTest.test_repository_sample_db_is_rejected)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 480, in test_repository_sample_db_is_rejected
|
||||
self.fail("core 没有定义 VFSFormatError 一类的异常")
|
||||
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: core 没有定义 VFSFormatError 一类的异常
|
||||
|
||||
======================================================================
|
||||
FAIL: test_synthesized_old_schema_db_is_rejected (test_core.SchemaCompatibilityTest.test_synthesized_old_schema_db_is_rejected)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 466, in test_synthesized_old_schema_db_is_rejected
|
||||
self.fail(
|
||||
~~~~~~~~~^
|
||||
"core 没有定义 VFSFormatError 一类的异常,"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
"调用方无法区分「旧格式库」与「正常库」,只能在导出阶段看到一堆导出失败"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: core 没有定义 VFSFormatError 一类的异常,调用方无法区分「旧格式库」与「正常库」,只能在导出阶段看到一堆导出失败
|
||||
|
||||
======================================================================
|
||||
FAIL: test_add_file_actually_stores_a_row (test_core.SchemaContractTest.test_add_file_actually_stores_a_row)
|
||||
add_file 之后库里必须真的有这条记录。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 47, in test_add_file_actually_stores_a_row
|
||||
self.assertTrue(vfs.exists("input.bin"), "add_file 没有把文件写进数据库")
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: False is not true : add_file 没有把文件写进数据库
|
||||
|
||||
======================================================================
|
||||
FAIL: test_expected_columns_exist (test_core.SchemaContractTest.test_expected_columns_exist)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_core.py", line 32, in test_expected_columns_exist
|
||||
self.assertIn(name, columns, f"files 表缺少列 {name}")
|
||||
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 'compress_algo' not found in {'content', 'permissions', 'id', 'modified_time', 'compresse_algo', 'is_directory', 'file_size', 'freq_blob', 'created_time', 'name', 'parent_path', 'path'} : files 表缺少列 compress_algo
|
||||
|
||||
======================================================================
|
||||
FAIL: test_truncated_payload_rejected (test_huffman.HeaderValidationTest.test_truncated_payload_rejected)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_huffman.py", line 112, in test_truncated_payload_rejected
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
|
||||
AssertionError: ValueError not raised
|
||||
|
||||
======================================================================
|
||||
FAIL: test_repetitive_text_compresses (test_huffman.RoundTripTest.test_repetitive_text_compresses)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_huffman.py", line 71, in test_repetitive_text_compresses
|
||||
self.assertLess(
|
||||
~~~~~~~~~~~~~~~^
|
||||
len(compressed_blob),
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
len(data) // 2,
|
||||
^^^^^^^^^^^^^^^
|
||||
"高度重复的文本应当被显著压缩",
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: 50263 not less than 45000 : 高度重复的文本应当被显著压缩
|
||||
|
||||
======================================================================
|
||||
FAIL: test_compression_reduces_database_size (test_roundtrip.RoundTripTest.test_compression_reduces_database_size)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 112, in test_compression_reduces_database_size
|
||||
self.assertLess(
|
||||
~~~~~~~~~~~~~~~^
|
||||
compressed_size,
|
||||
^^^^^^^^^^^^^^^^
|
||||
plain_size,
|
||||
^^^^^^^^^^^
|
||||
"源目录里有大量重复文本,启用压缩后数据库应当变小",
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: 32768 not less than 32768 : 源目录里有大量重复文本,启用压缩后数据库应当变小
|
||||
|
||||
======================================================================
|
||||
FAIL: test_every_source_file_is_stored (test_roundtrip.RoundTripTest.test_every_source_file_is_stored)
|
||||
P0-1:打包后库里必须有和源目录一一对应的文件记录。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 77, in test_every_source_file_is_stored
|
||||
self.assertEqual(
|
||||
~~~~~~~~~~~~~~~~^
|
||||
"无差异",
|
||||
^^^^^^^^^
|
||||
helpers.diff_trees({p: None for p in expected}, {p: None for p in stored}),
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
AssertionError: '无差异' != "缺失 12 项,例如: ['below_threshold.bin', 'com[184 chars]xt']"
|
||||
- 无差异
|
||||
+ 缺失 12 项,例如: ['below_threshold.bin', 'compressible.txt', 'doc/a.txt', 'docs/b.txt', 'empty.txt', 'one_byte.bin', 'random.bin', 'sub/deep/deeper/nested.txt', 'sub/percent%name_.txt', 'sub/space name.txt', 'sub/中文名.txt', 'top.txt']
|
||||
|
||||
|
||||
======================================================================
|
||||
FAIL: test_metadata_counts_match_database (test_roundtrip.RoundTripTest.test_metadata_counts_match_database)
|
||||
P1-5:上报的统计数字必须来自真实入库的数据,而不是遍历计数。
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 94, in test_metadata_counts_match_database
|
||||
self.assertEqual(source_count, stored_count, "入库文件数 ≠ 源文件数")
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: 12 != 0 : 入库文件数 ≠ 源文件数
|
||||
|
||||
======================================================================
|
||||
FAIL: test_roundtrip_with_compression (test_roundtrip.RoundTripTest.test_roundtrip_with_compression)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 63, in test_roundtrip_with_compression
|
||||
self._assert_lossless(src, db)
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 55, in _assert_lossless
|
||||
helpers.assert_tree_equal(self, expected_tree(build_spec()), helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 12 项,例如: ['below_threshold.bin', 'com[725 chars]oc']"
|
||||
Diff is 780 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
======================================================================
|
||||
FAIL: test_roundtrip_with_ignore_timestamps (test_roundtrip.RoundTripTest.test_roundtrip_with_ignore_timestamps)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 67, in test_roundtrip_with_ignore_timestamps
|
||||
self._assert_lossless(src, db, ignore_timestamps=True)
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 55, in _assert_lossless
|
||||
helpers.assert_tree_equal(self, expected_tree(build_spec()), helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 12 项,例如: ['below_threshold.bin', 'com[725 chars]oc']"
|
||||
Diff is 780 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
======================================================================
|
||||
FAIL: test_roundtrip_without_compression (test_roundtrip.RoundTripTest.test_roundtrip_without_compression)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 59, in test_roundtrip_without_compression
|
||||
self._assert_lossless(src, db)
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\test_roundtrip.py", line 55, in _assert_lossless
|
||||
helpers.assert_tree_equal(self, expected_tree(build_spec()), helpers.read_tree(out))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\HuaweiMoveData\Users\chakcy\Desktop\新建文件夹\sqlite_vfs\tests\helpers.py", line 136, in assert_tree_equal
|
||||
case.assertEqual("无差异", diff_trees(expected, actual))
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: '无差异' != "缺失 12 项,例如: ['below_threshold.bin', 'com[725 chars]oc']"
|
||||
Diff is 780 characters long. Set self.maxDiff to None to see it.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 77 tests in 175.700s
|
||||
|
||||
FAILED (failures=42, errors=9)
|
||||
EXIT=1
|
||||
@@ -0,0 +1,415 @@
|
||||
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) ... 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_demo_runs_and_reports_success (test_cli.DemoScriptTest.test_demo_runs_and_reports_success) ... ok
|
||||
test_default_algorithm_is_zlib (test_compression.AlgorithmRegistryTest.test_default_algorithm_is_zlib) ... ok
|
||||
test_every_registered_algorithm_roundtrips (test_compression.AlgorithmRegistryTest.test_every_registered_algorithm_roundtrips) ... ok
|
||||
test_registry_contains_the_three_builtins (test_compression.AlgorithmRegistryTest.test_registry_contains_the_three_builtins) ... ok
|
||||
test_unknown_algorithm_is_rejected_on_both_sides (test_compression.AlgorithmRegistryTest.test_unknown_algorithm_is_rejected_on_both_sides) ... ok
|
||||
test_huffman_is_not_used_for_small_files (test_compression.AlgorithmTradeoffTest.test_huffman_is_not_used_for_small_files)
|
||||
huffman 每个文件要带 1024 字节频率表,小文件必然负收益。 ... ok
|
||||
test_zlib_beats_huffman_by_a_lot_on_repetitive_text (test_compression.AlgorithmTradeoffTest.test_zlib_beats_huffman_by_a_lot_on_repetitive_text) ... ok
|
||||
test_huffman_carries_a_fixed_size_frequency_table (test_compression.CompressContractTest.test_huffman_carries_a_fixed_size_frequency_table) ... ok
|
||||
test_huffman_without_frequency_table_is_rejected (test_compression.CompressContractTest.test_huffman_without_frequency_table_is_rejected) ... ok
|
||||
test_none_returns_the_input_unchanged (test_compression.CompressContractTest.test_none_returns_the_input_unchanged) ... ok
|
||||
test_stored_size_counts_the_frequency_table (test_compression.CompressContractTest.test_stored_size_counts_the_frequency_table) ... ok
|
||||
test_stored_size_ignores_an_empty_frequency_table (test_compression.CompressContractTest.test_stored_size_ignores_an_empty_frequency_table) ... ok
|
||||
test_zlib_produces_a_real_zlib_stream (test_compression.CompressContractTest.test_zlib_produces_a_real_zlib_stream) ... 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_connection_survives_a_failed_insert (test_core.AddDirectoryContractTest.test_connection_survives_a_failed_insert) ... ok
|
||||
test_duplicate_without_replace_fails_cleanly (test_core.AddDirectoryContractTest.test_duplicate_without_replace_fails_cleanly) ... ok
|
||||
test_replace_updates_in_place (test_core.AddDirectoryContractTest.test_replace_updates_in_place) ... ok
|
||||
test_returns_false_for_a_missing_source_directory (test_core.AddDirectoryContractTest.test_returns_false_for_a_missing_source_directory) ... ok
|
||||
test_returns_true_and_creates_the_row (test_core.AddDirectoryContractTest.test_returns_true_and_creates_the_row) ... ok
|
||||
test_duplicate_add_file_is_reported_and_keeps_first_content (test_core.AddFileConflictTest.test_duplicate_add_file_is_reported_and_keeps_first_content) ... ok
|
||||
test_all_entries_covers_the_whole_tree (test_core.BlobPrimitiveTest.test_all_entries_covers_the_whole_tree) ... ok
|
||||
test_all_entries_is_snapshot_scoped (test_core.BlobPrimitiveTest.test_all_entries_is_snapshot_scoped) ... ok
|
||||
test_get_blob_info_returns_none_for_a_directory (test_core.BlobPrimitiveTest.test_get_blob_info_returns_none_for_a_directory) ... ok
|
||||
test_get_blob_info_returns_none_for_a_missing_path (test_core.BlobPrimitiveTest.test_get_blob_info_returns_none_for_a_missing_path) ... ok
|
||||
test_list_blobs_reports_sizes_without_content (test_core.BlobPrimitiveTest.test_list_blobs_reports_sizes_without_content) ... ok
|
||||
test_list_blobs_returns_one_row_per_unique_content (test_core.BlobPrimitiveTest.test_list_blobs_returns_one_row_per_unique_content) ... ok
|
||||
test_read_blob_detects_a_size_mismatch_without_asking (test_core.BlobPrimitiveTest.test_read_blob_detects_a_size_mismatch_without_asking)
|
||||
大小对不上是便宜的结构性检查,不需要调用方显式要求。 ... ok
|
||||
test_read_blob_detects_tampering_when_asked (test_core.BlobPrimitiveTest.test_read_blob_detects_tampering_when_asked) ... ok
|
||||
test_read_blob_returns_original_bytes (test_core.BlobPrimitiveTest.test_read_blob_returns_original_bytes) ... ok
|
||||
test_read_blob_unknown_hash_raises (test_core.BlobPrimitiveTest.test_read_blob_unknown_hash_raises) ... ok
|
||||
test_clean_wipes_every_table (test_core.CleanTest.test_clean_wipes_every_table) ... ok
|
||||
test_pack_after_clean_starts_fresh (test_core.CleanTest.test_pack_after_clean_starts_fresh) ... 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_all_three_agree_with_the_entry_type (test_core.ExistsHelpersTest.test_all_three_agree_with_the_entry_type) ... 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) ... 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_boundary_semantics_hold_for_compressed_content (test_core.ReadFileBoundaryTest.test_boundary_semantics_hold_for_compressed_content)
|
||||
压缩路径下 offset/size 作用的是**解压后**的字节。 ... ok
|
||||
test_full_read (test_core.ReadFileBoundaryTest.test_full_read) ... ok
|
||||
test_negative_offset_is_rejected (test_core.ReadFileBoundaryTest.test_negative_offset_is_rejected)
|
||||
负数会走 Python 切片语义(从末尾数),对调用方是陷阱,直接拒绝。 ... ok
|
||||
test_negative_size_is_rejected (test_core.ReadFileBoundaryTest.test_negative_size_is_rejected) ... ok
|
||||
test_offset_at_eof_returns_empty (test_core.ReadFileBoundaryTest.test_offset_at_eof_returns_empty) ... ok
|
||||
test_offset_beyond_eof_returns_empty (test_core.ReadFileBoundaryTest.test_offset_beyond_eof_returns_empty) ... ok
|
||||
test_offset_in_the_middle (test_core.ReadFileBoundaryTest.test_offset_in_the_middle) ... ok
|
||||
test_size_larger_than_remaining_clamps (test_core.ReadFileBoundaryTest.test_size_larger_than_remaining_clamps) ... ok
|
||||
test_zero_size (test_core.ReadFileBoundaryTest.test_zero_size) ... 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_no_deprecation_warning_from_any_write_path (test_core.TimestampStorageTest.test_no_deprecation_warning_from_any_write_path) ... ok
|
||||
test_stored_text_keeps_the_historical_format (test_core.TimestampStorageTest.test_stored_text_keeps_the_historical_format) ... ok
|
||||
test_stored_text_parses_back_to_the_file_mtime (test_core.TimestampStorageTest.test_stored_text_parses_back_to_the_file_mtime) ... 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) ... 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) ... 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_manifest_contents (test_publish.ExportTest.test_manifest_contents) ... ok
|
||||
test_manifest_is_deterministic_for_the_same_snapshot (test_publish.ExportTest.test_manifest_is_deterministic_for_the_same_snapshot)
|
||||
清单里不放"生成时间",所以同一快照导出两次得到完全一样的清单(可 diff、可签名)。 ... ok
|
||||
test_manifest_of_a_nonexistent_snapshot_is_rejected (test_publish.ExportTest.test_manifest_of_a_nonexistent_snapshot_is_rejected) ... ok
|
||||
test_object_content_is_the_original_bytes (test_publish.ExportTest.test_object_content_is_the_original_bytes)
|
||||
库里内容是压缩的,导出必须是原始字节——消费方不该需要我们的解压代码。 ... ok
|
||||
test_object_name_is_its_hash (test_publish.ExportTest.test_object_name_is_its_hash) ... ok
|
||||
test_objects_are_deduplicated (test_publish.ExportTest.test_objects_are_deduplicated) ... ok
|
||||
test_publish_a_specific_snapshot (test_publish.ExportTest.test_publish_a_specific_snapshot) ... ok
|
||||
test_publish_is_read_only_on_the_pack (test_publish.ExportTest.test_publish_is_read_only_on_the_pack) ... ok
|
||||
test_refuses_non_empty_output_without_overwrite (test_publish.ExportTest.test_refuses_non_empty_output_without_overwrite) ... ok
|
||||
test_savings_are_reported_in_separate_units (test_publish.ExportTest.test_savings_are_reported_in_separate_units)
|
||||
去重与压缩必须分开报:把"压缩省下的"算进"去重省下的"会误导选型。 ... ok
|
||||
test_shard_zero_puts_objects_flat (test_publish.ExportTest.test_shard_zero_puts_objects_flat) ... ok
|
||||
test_cache_is_reused_and_verified (test_publish.FetchLocalTest.test_cache_is_reused_and_verified) ... ok
|
||||
test_corrupted_cache_entry_is_healed (test_publish.FetchLocalTest.test_corrupted_cache_entry_is_healed) ... ok
|
||||
test_link_mode_hardlinks_into_the_cache (test_publish.FetchLocalTest.test_link_mode_hardlinks_into_the_cache) ... ok
|
||||
test_mtime_and_mode_are_preserved (test_publish.FetchLocalTest.test_mtime_and_mode_are_preserved) ... ok
|
||||
test_partial_fetch_by_file_and_by_prefix (test_publish.FetchLocalTest.test_partial_fetch_by_file_and_by_prefix) ... ok
|
||||
test_partial_fetch_writes_only_selected (test_publish.FetchLocalTest.test_partial_fetch_writes_only_selected) ... ok
|
||||
test_roundtrip_restores_the_tree (test_publish.FetchLocalTest.test_roundtrip_restores_the_tree) ... ok
|
||||
test_bad_manifest_format_is_rejected (test_publish.FetchOverHttpTest.test_bad_manifest_format_is_rejected) ... ok
|
||||
test_fetch_from_a_real_http_server (test_publish.FetchOverHttpTest.test_fetch_from_a_real_http_server) ... ok
|
||||
test_manifest_from_url_mismatch_is_reported (test_publish.FetchOverHttpTest.test_manifest_from_url_mismatch_is_reported) ... ok
|
||||
test_missing_object_is_reported_clearly (test_publish.FetchOverHttpTest.test_missing_object_is_reported_clearly) ... ok
|
||||
test_tampered_object_over_http_is_rejected (test_publish.FetchOverHttpTest.test_tampered_object_over_http_is_rejected) ... ok
|
||||
test_fetch_json_output (test_publish.PublishCliTest.test_fetch_json_output) ... ok
|
||||
test_fetch_missing_path_exits_nonzero (test_publish.PublishCliTest.test_fetch_missing_path_exits_nonzero) ... ok
|
||||
test_manifest_only_mode (test_publish.PublishCliTest.test_manifest_only_mode) ... ok
|
||||
test_publish_and_fetch_via_cli (test_publish.PublishCliTest.test_publish_and_fetch_via_cli) ... ok
|
||||
test_publish_missing_db_exits_nonzero (test_publish.PublishCliTest.test_publish_missing_db_exits_nonzero) ... ok
|
||||
test_publish_to_nonempty_dir_requires_overwrite (test_publish.PublishCliTest.test_publish_to_nonempty_dir_requires_overwrite) ... 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_constructor_releases_the_connection_when_snapshot_is_invalid (test_snapshots.SnapshotLifecycleTest.test_constructor_releases_the_connection_when_snapshot_is_invalid)
|
||||
构造期抛异常也要释放连接,否则 Windows 上库文件被锁住删不掉。 ... 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 343 tests in 22.328s
|
||||
|
||||
OK (skipped=52)
|
||||
|
||||
[HTTP 实测] 请求 4 次(清单 1 + 对象 3),下载 256.0 KB(清单 1.1 KB),耗时 29ms
|
||||
EXIT=0
|
||||
@@ -0,0 +1,380 @@
|
||||
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:426: 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:746: 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:1329: 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:656: 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:1231: 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_manifest_contents (test_publish.ExportTest.test_manifest_contents) ... ok
|
||||
test_manifest_is_deterministic_for_the_same_snapshot (test_publish.ExportTest.test_manifest_is_deterministic_for_the_same_snapshot)
|
||||
清单里不放"生成时间",所以同一快照导出两次得到完全一样的清单(可 diff、可签名)。 ... ok
|
||||
test_manifest_of_a_nonexistent_snapshot_is_rejected (test_publish.ExportTest.test_manifest_of_a_nonexistent_snapshot_is_rejected) ... ok
|
||||
test_object_content_is_the_original_bytes (test_publish.ExportTest.test_object_content_is_the_original_bytes)
|
||||
库里内容是压缩的,导出必须是原始字节——消费方不该需要我们的解压代码。 ... ok
|
||||
test_object_name_is_its_hash (test_publish.ExportTest.test_object_name_is_its_hash) ... ok
|
||||
test_objects_are_deduplicated (test_publish.ExportTest.test_objects_are_deduplicated) ... ok
|
||||
test_publish_a_specific_snapshot (test_publish.ExportTest.test_publish_a_specific_snapshot) ... ok
|
||||
test_publish_is_read_only_on_the_pack (test_publish.ExportTest.test_publish_is_read_only_on_the_pack) ... ok
|
||||
test_refuses_non_empty_output_without_overwrite (test_publish.ExportTest.test_refuses_non_empty_output_without_overwrite) ... ok
|
||||
test_savings_are_reported_in_separate_units (test_publish.ExportTest.test_savings_are_reported_in_separate_units)
|
||||
去重与压缩必须分开报:把"压缩省下的"算进"去重省下的"会误导选型。 ... ok
|
||||
test_shard_zero_puts_objects_flat (test_publish.ExportTest.test_shard_zero_puts_objects_flat) ... ok
|
||||
test_cache_is_reused_and_verified (test_publish.FetchLocalTest.test_cache_is_reused_and_verified) ... ok
|
||||
test_corrupted_cache_entry_is_healed (test_publish.FetchLocalTest.test_corrupted_cache_entry_is_healed) ... ok
|
||||
test_link_mode_hardlinks_into_the_cache (test_publish.FetchLocalTest.test_link_mode_hardlinks_into_the_cache) ... ok
|
||||
test_mtime_and_mode_are_preserved (test_publish.FetchLocalTest.test_mtime_and_mode_are_preserved) ... ok
|
||||
test_partial_fetch_by_file_and_by_prefix (test_publish.FetchLocalTest.test_partial_fetch_by_file_and_by_prefix) ... ok
|
||||
test_partial_fetch_writes_only_selected (test_publish.FetchLocalTest.test_partial_fetch_writes_only_selected) ... ok
|
||||
test_roundtrip_restores_the_tree (test_publish.FetchLocalTest.test_roundtrip_restores_the_tree) ... ok
|
||||
test_bad_manifest_format_is_rejected (test_publish.FetchOverHttpTest.test_bad_manifest_format_is_rejected) ... ok
|
||||
test_fetch_from_a_real_http_server (test_publish.FetchOverHttpTest.test_fetch_from_a_real_http_server) ... C:\Users\chakcy\AppData\Roaming\uv\python\cpython-3.13-windows-x86_64-none\Lib\unittest\case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method FetchOverHttpTest.test_fetch_from_a_real_http_server of <test_publish.FetchOverHttpTest testMethod=test_fetch_from_a_real_http_server>>)
|
||||
return self.run(*args, **kwds)
|
||||
ok
|
||||
test_manifest_from_url_mismatch_is_reported (test_publish.FetchOverHttpTest.test_manifest_from_url_mismatch_is_reported) ... ok
|
||||
test_missing_object_is_reported_clearly (test_publish.FetchOverHttpTest.test_missing_object_is_reported_clearly) ... ok
|
||||
test_tampered_object_over_http_is_rejected (test_publish.FetchOverHttpTest.test_tampered_object_over_http_is_rejected) ... ok
|
||||
test_fetch_json_output (test_publish.PublishCliTest.test_fetch_json_output) ... ok
|
||||
test_fetch_missing_path_exits_nonzero (test_publish.PublishCliTest.test_fetch_missing_path_exits_nonzero) ... ok
|
||||
test_manifest_only_mode (test_publish.PublishCliTest.test_manifest_only_mode) ... ok
|
||||
test_publish_and_fetch_via_cli (test_publish.PublishCliTest.test_publish_and_fetch_via_cli) ... ok
|
||||
test_publish_missing_db_exits_nonzero (test_publish.PublishCliTest.test_publish_missing_db_exits_nonzero) ... ok
|
||||
test_publish_to_nonempty_dir_requires_overwrite (test_publish.PublishCliTest.test_publish_to_nonempty_dir_requires_overwrite) ... 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_constructor_releases_the_connection_when_snapshot_is_invalid (test_snapshots.SnapshotLifecycleTest.test_constructor_releases_the_connection_when_snapshot_is_invalid)
|
||||
构造期抛异常也要释放连接,否则 Windows 上库文件被锁住删不掉。 ... 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 300 tests in 21.571s
|
||||
|
||||
OK (skipped=52)
|
||||
|
||||
[HTTP 实测] 请求 4 次(清单 1 + 对象 3),下载 256.0 KB(清单 1.1 KB),耗时 17ms
|
||||
EXIT=0
|
||||
@@ -0,0 +1,6 @@
|
||||
=== 复现 P0-1 根因:建表列名与 INSERT 列名不一致 ===
|
||||
修复前 INSERT -> OperationalError: table files has no column named compress_algo
|
||||
→ 该异常被 core.py 的 except 吞掉,只打印一行"添加文件失败",库里没有任何记录
|
||||
修复前 SELECT -> OperationalError: no such column: compress_algo
|
||||
→ read_file 因此必然失败,所有导出操作都变成"导出文件失败"
|
||||
修复后 INSERT -> ok, SELECT -> [('none',)]
|
||||
@@ -0,0 +1,342 @@
|
||||
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
|
||||
Reference in New Issue
Block a user