Files
Genarrative/server-rs/crates/spacetime-module/src/active.rs
T
suzmii cc6211fd41
Project CI / Repository checks (push) Successful in 7m49s
Project CI / Frontend tests (push) Successful in 8m24s
Project CI / Backend tests (push) Successful in 9m56s
Project CI / Native shell tests (push) Successful in 19m18s
修复 Backend 与 Native shell CI 回归并恢复完整测试门禁 (#209)
## 背景

这是一个独立的 CI 修复 PR,针对 Backend 与 Native shell 测试失败进行修复,不包含资源画布功能变更。

此前 CI 失败主要集中在:

- 后台精选素材契约测试初始化缺少来源素材字段。
- `spacetime-module` host 测试因缺少 SpacetimeDB WASM 宿主 ABI 符号而无法链接。
- Native shell 自主创作模式、runtime action、provider batch 和测试初始化之间存在状态机断言不一致。
- 部分失败测试曾被临时绕过,本 PR 恢复这些测试门禁。

## 变更内容

### Backend

- 补齐后台精选素材 payload 测试所需的来源素材字段。
- 增加 camelCase 序列化断言,防止 snake_case 字段泄漏。
- 调整 server-rs workspace 测试拆分:
  - 普通 workspace host 测试继续排除 `spacetime-module`,避免其 `spacetime-types` feature 污染其他领域 crate 的 host 链接。
  - 新增独立的 `spacetime-module` 单元测试步骤,不再跳过该模块自身测试。
- 为 host 测试构建提供仅测试期的 SpacetimeDB ABI 链接支持。
- 同步更新 CI workflow 断言、开发流程文档和运维验证文档。

### Native shell

- 恢复被临时跳过的 Native shell 失败测试门禁。
- 修复自主创作模式下的完成条件、runtime action 执行、provider batch 和 finalization 状态流转。
- 修正 Tauri/native 测试初始化、恢复流程及断言,使测试与实际运行时协议保持一致。
- 保持自主创作模式的宽松行为,不通过忽略测试规避失败。

## 验证

当前提交已完成以下本地验证:

- `cargo test --locked -p spacetime-module --no-fail-fast`
  - 259 个测试
  - 258 个通过
  - 0 个失败
  - 1 个已有的外部 fixture 测试 ignored
- `cargo check --locked -p spacetime-module --target wasm32-unknown-unknown`
- `cargo build --locked -p spacetime-module --target wasm32-unknown-unknown`
- `cargo check --locked -p api-server --all-targets`
- `npm run check:server-rs-ddd`
- `npm run check:spacetime-schema`
- `npm run check:encoding`
- `npm run test -- scripts/project-ci-workflow.test.ts`
- `cargo fmt --manifest-path server-rs/Cargo.toml --all -- --check`
- `git diff --check`

没有新增 `#[ignore]` 来规避失败。

## 测试边界说明

`spacetime-module` 的 host ABI 链接支持仅用于执行纯单元测试,不是 SpacetimeDB runtime 替身。Reducer、procedure 和真实数据库事务行为仍需要通过真实 SpacetimeDB runtime/integration harness 验证。

本机 Windows 上完整 workspace 测试中的 `wallet_refund_outbox` 测试仍有 11 项因 `os error 5(拒绝访问)`失败,表现为临时文件权限/锁定问题;该问题与本 PR 的 SpacetimeDB 模块测试改动无关,也没有通过忽略这些测试来掩盖。

Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/209
Co-authored-by: suzmii <suzmii@qq.com>
Co-committed-by: suzmii <suzmii@qq.com>
2026-08-31 10:53:30 +08:00

264 lines
6.6 KiB
Rust

// 中文注释:SpacetimeDB 绑定生成依赖根模块继续公开 re-export 各领域类型;
// 少数领域 helper 同名只影响 value namespace 导出,不影响 table / reducer 类型。
#![allow(ambiguous_glob_reexports)]
pub use module_ai::*;
pub use module_assets::*;
pub use module_runtime::*;
pub(crate) use serde_json::{Map as JsonMap, Value as JsonValue, json};
pub use spacetimedb::{
Identity, ProcedureContext, ReducerContext, ScheduleAt, SpacetimeType, Table, Timestamp,
};
mod admin_account_storage;
mod admin_dashboard;
mod ai;
mod asset_metadata;
mod auth;
#[path = "legacy_schema/bark_battle.rs"]
mod bark_battle;
#[path = "legacy_schema/big_fish.rs"]
mod big_fish;
#[path = "legacy_schema/custom_world.rs"]
mod custom_world;
mod editor_agent_storage;
mod editor_project_storage;
mod external_api_key_storage;
mod external_generation;
#[path = "legacy_schema/gameplay.rs"]
mod gameplay;
#[path = "legacy_schema/jump_hop.rs"]
mod jump_hop;
#[path = "legacy_schema/match3d.rs"]
mod match3d;
mod migration;
#[path = "legacy_schema/puzzle.rs"]
mod puzzle;
#[path = "legacy_schema/puzzle_clear.rs"]
mod puzzle_clear;
mod runtime;
#[path = "legacy_schema/square_hole.rs"]
mod square_hole;
#[path = "legacy_schema/visual_novel.rs"]
mod visual_novel;
#[path = "legacy_schema/wooden_fish.rs"]
mod wooden_fish;
pub use admin_account_storage::*;
pub use admin_dashboard::*;
pub use ai::*;
pub use asset_metadata::*;
pub use auth::*;
pub use bark_battle::*;
pub use big_fish::*;
pub use custom_world::*;
pub use editor_agent_storage::*;
pub use editor_project_storage::*;
pub use external_api_key_storage::*;
pub use external_generation::*;
pub use gameplay::*;
pub use jump_hop::*;
pub use match3d::*;
pub use migration::*;
pub use puzzle_clear::*;
pub use runtime::*;
pub use square_hole::*;
pub use visual_novel::*;
pub use wooden_fish::*;
// Host-side unit tests need to link the module crate as a normal test binary.
// SpacetimeDB's raw ABI imports only exist in the WASM host, so provide
// deterministic error-returning symbols for tests that exercise pure helpers.
// Reducer/procedure integration tests must use a real SpacetimeDB runtime.
#[cfg(all(test, not(target_arch = "wasm32")))]
mod host_test_imports {
type TableId = u32;
type IndexId = u32;
type ColId = u16;
type BytesSource = u32;
type BytesSink = u32;
type RowIter = u32;
const HOST_TEST_UNSUPPORTED: u16 = 1;
#[unsafe(no_mangle)]
pub extern "C" fn table_id_from_name(_: *const u8, _: usize, _: *mut TableId) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn index_id_from_name(_: *const u8, _: usize, _: *mut IndexId) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_table_row_count(_: TableId, _: *mut u64) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_table_scan_bsatn(_: TableId, _: *mut RowIter) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_index_scan_range_bsatn(
_: IndexId,
_: *const u8,
_: usize,
_: ColId,
_: *const u8,
_: usize,
_: *const u8,
_: usize,
_: *mut RowIter,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_delete_by_index_scan_range_bsatn(
_: IndexId,
_: *const u8,
_: usize,
_: ColId,
_: *const u8,
_: usize,
_: *const u8,
_: usize,
_: *mut u32,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_delete_all_by_eq_bsatn(
_: TableId,
_: *const u8,
_: usize,
_: *mut u32,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn row_iter_bsatn_advance(_: RowIter, _: *mut u8, _: *mut usize) -> i16 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn row_iter_bsatn_close(_: RowIter) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_insert_bsatn(_: TableId, _: *mut u8, _: *mut usize) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_update_bsatn(
_: TableId,
_: IndexId,
_: *mut u8,
_: *mut usize,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn bytes_sink_write(_: BytesSink, _: *const u8, _: *mut usize) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn bytes_source_read(_: BytesSource, _: *mut u8, _: *mut usize) -> i16 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn console_log(
_: u8,
_: *const u8,
_: usize,
_: *const u8,
_: usize,
_: u32,
_: *const u8,
_: usize,
) {
}
#[unsafe(no_mangle)]
pub extern "C" fn console_timer_start(_: *const u8, _: usize) -> u32 {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn console_timer_end(_: u32) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn identity(out: *mut u8) {
if !out.is_null() {
unsafe { std::ptr::write_bytes(out, 0, 32) };
}
}
#[unsafe(no_mangle)]
pub extern "C" fn bytes_source_remaining_length(_: BytesSource, _: *mut u32) -> i16 {
HOST_TEST_UNSUPPORTED as i16
}
#[unsafe(no_mangle)]
pub extern "C" fn get_jwt(_: *const u8, _: *mut BytesSource) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn procedure_sleep_until(wake_at: i64) -> i64 {
wake_at
}
#[unsafe(no_mangle)]
pub extern "C" fn procedure_start_mut_tx(_: *mut i64) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn procedure_commit_mut_tx() -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn procedure_abort_mut_tx() -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_index_scan_point_bsatn(
_: IndexId,
_: *const u8,
_: usize,
_: *mut RowIter,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_delete_by_index_scan_point_bsatn(
_: IndexId,
_: *const u8,
_: usize,
_: *mut u32,
) -> u16 {
HOST_TEST_UNSUPPORTED
}
#[unsafe(no_mangle)]
pub extern "C" fn datastore_clear(_: TableId, _: *mut u64) -> u16 {
HOST_TEST_UNSUPPORTED
}
}