test: Add comprehensive E2E tests for unified registry system

- Add reserved name guard test to prevent non-builtin factories from hijacking builtin names
- Add Handle TLV encoding/decoding test for FileBox copyFrom method
- Add CounterBox plugin tests for inc/get operations and clone/share behavior
- All unified registry E2E tests passing 

統一レジストリシステムの包括的なE2Eテスト追加
- ビルトイン名保護テスト
- Handle型TLVエンコーディングテスト
- CounterBoxプラグインテスト
- 全テスト成功確認

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-21 16:46:07 +09:00
parent 6551a2935f
commit d6529b477b
10 changed files with 476 additions and 23 deletions

View File

@ -234,17 +234,21 @@ impl NyashInterpreter {
/// 新しいインタープリターを作成
pub fn new() -> Self {
let shared = SharedState::new();
// ランタイムを構築し、ユーザー定義Boxファクトリを注入グローバル登録を避ける
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
let runtime = NyashRuntimeBuilder::new().with_factory(udf).build();
// Step 5: SharedState分解の第一歩として、
// box_declarationsの保管先をRuntimeに寄せる
// 先にランタイムを構築UDFは後から同一SharedStateで注入)
let runtime = NyashRuntimeBuilder::new().build();
// Runtimeのbox_declarationsを共有状態に差し替え、同一の参照を保つ
let mut shared = shared; // 可変化
shared.box_declarations = runtime.box_declarations.clone();
// ユーザー定義Boxファクトリを、差し替え済みSharedStateで登録
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
if let Ok(mut reg) = runtime.box_registry.lock() {
reg.register(udf);
}
Self {
shared,
local_vars: HashMap::new(),
@ -262,16 +266,22 @@ impl NyashInterpreter {
pub fn new_with_groups(groups: crate::box_factory::builtin::BuiltinGroups) -> Self {
let shared = SharedState::new();
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
// 先にランタイム(組み込みグループのみ)を構築
let runtime = NyashRuntimeBuilder::new()
.with_builtin_groups(groups)
.with_factory(udf)
.build();
// Runtimeのbox_declarationsを共有状態に差し替え
let mut shared = shared; // 可変化
shared.box_declarations = runtime.box_declarations.clone();
// 差し替え済みSharedStateでUDFを登録
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
if let Ok(mut reg) = runtime.box_registry.lock() {
reg.register(udf);
}
Self {
shared,
local_vars: HashMap::new(),
@ -287,15 +297,20 @@ impl NyashInterpreter {
/// 共有状態から新しいインタープリターを作成(非同期実行用)
pub fn with_shared(shared: SharedState) -> Self {
// 共有状態に紐づいたランタイムを構築
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
let runtime = NyashRuntimeBuilder::new().with_factory(udf).build();
// 共有状態に紐づいたランタイムを先に構築
let runtime = NyashRuntimeBuilder::new().build();
// Step 5: Runtimeのbox_declarationsに寄せ替え
// Runtimeのbox_declarationsに寄せ替え
let mut shared = shared; // 可変化
shared.box_declarations = runtime.box_declarations.clone();
// 差し替え済みSharedStateでUDFを登録
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
if let Ok(mut reg) = runtime.box_registry.lock() {
reg.register(udf);
}
Self {
shared,
local_vars: HashMap::new(),
@ -311,16 +326,21 @@ impl NyashInterpreter {
/// 共有状態+グループ構成を指定して新しいインタープリターを作成(非同期実行用)
pub fn with_shared_and_groups(shared: SharedState, groups: crate::box_factory::builtin::BuiltinGroups) -> Self {
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
// 先にランタイム(組み込みグループのみ)を構築
let runtime = NyashRuntimeBuilder::new()
.with_builtin_groups(groups)
.with_factory(udf)
.build();
let mut shared = shared; // 可変化
shared.box_declarations = runtime.box_declarations.clone();
// 差し替え済みSharedStateでUDFを登録
use crate::box_factory::user_defined::UserDefinedBoxFactory;
let udf = Arc::new(UserDefinedBoxFactory::new(shared.clone()));
if let Ok(mut reg) = runtime.box_registry.lock() {
reg.register(udf);
}
Self {
shared,
local_vars: HashMap::new(),

View File

@ -749,6 +749,54 @@ impl NyashInterpreter {
});
}
// 先にプラグイン親のコンストラクタ/メソッドを優先的に処理v2プラグイン対応
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
{
let loader_guard = crate::runtime::get_global_loader_v2();
let loader = loader_guard.read().unwrap();
// 親がプラグインで提供されているかを確認
if loader.config.as_ref().and_then(|c| c.find_library_for_box(parent)).is_some() {
// コンストラクタ相当birth もしくは 親名と同名)の場合は、
// プラグインBoxを生成して __plugin_content に格納
if method == "birth" || method == parent {
let mut arg_values: Vec<Box<dyn NyashBox>> = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
match loader.create_box(parent, &arg_values) {
Ok(pbox) => {
use std::sync::Arc;
let _ = current_instance.set_field_legacy("__plugin_content", Arc::from(pbox));
return Ok(Box::new(crate::box_trait::VoidBox::new()));
}
Err(e) => {
return Err(RuntimeError::InvalidOperation {
message: format!("Failed to construct plugin parent '{}': {:?}", parent, e),
});
}
}
} else {
// 非コンストラクタ: 既存の __plugin_content を通じてメソッド呼び出し
if let Some(plugin_shared) = current_instance.get_field_legacy("__plugin_content") {
let plugin_ref = &*plugin_shared;
if let Some(plugin) = plugin_ref.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
let mut arg_values: Vec<Box<dyn NyashBox>> = Vec::new();
for arg in arguments { arg_values.push(self.execute_expression(arg)?); }
match loader.invoke_instance_method(&plugin.box_type, method, plugin.instance_id, &arg_values) {
Ok(Some(result_box)) => return Ok(result_box),
Ok(None) => return Ok(Box::new(crate::box_trait::VoidBox::new())),
Err(e) => {
return Err(RuntimeError::InvalidOperation {
message: format!("Plugin call {}.{} failed: {:?}", parent, method, e),
});
}
}
}
}
}
}
}
// 🔥 Phase 8.8: pack透明化システム - ビルトインBox判定
use crate::box_trait::is_builtin_box;
// GUI機能が有効な場合はEguiBoxも追加判定mut不要の形に