use crate::common;
use common::{copy_dir_recursive, copy_fixture_to_temp, loader_fixtures_path, value_as_str};
use pasta_lua::loader::{LoaderError, PastaConfig, PastaLoader};
use std::path::PathBuf;
use tempfile::TempDir;
#[test]
fn test_load_minimal() {
let temp = copy_fixture_to_temp("minimal");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime.exec("return 1 + 1").unwrap();
assert_eq!(result.as_i64(), Some(2));
}
#[test]
fn test_load_with_config() {
let temp = copy_fixture_to_temp("with_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime.exec("return 'hello'").unwrap();
assert_eq!(value_as_str(&result).as_deref(), Some("hello"));
}
#[test]
fn test_load_with_custom_config() {
let temp = copy_fixture_to_temp("with_custom_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("@pasta_config")
return config.ghost_name
"#,
)
.unwrap();
assert_eq!(value_as_str(&result).as_deref(), Some("TestGhost"));
}
#[test]
fn test_pasta_config_nested_table() {
let temp = copy_fixture_to_temp("with_custom_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("@pasta_config")
return config.user_data.key2
"#,
)
.unwrap();
assert_eq!(result.as_i64(), Some(42));
}
#[test]
fn test_pasta_config_deeply_nested() {
let temp = copy_fixture_to_temp("with_custom_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("@pasta_config")
return config.user_data.nested.inner
"#,
)
.unwrap();
assert_eq!(value_as_str(&result).as_deref(), Some("data"));
}
#[test]
fn test_pasta_config_excludes_loader() {
let temp = copy_fixture_to_temp("with_custom_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("@pasta_config")
return config.loader
"#,
)
.unwrap();
assert!(result.is_nil());
}
#[test]
fn test_pasta_config_ghost_section() {
let temp = copy_fixture_to_temp("with_ghost_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("pasta.config")
return config.get("ghost", "spot_newlines", 1.5)
"#,
)
.unwrap();
let numeric_result = result
.as_f64()
.or_else(|| result.as_i64().map(|v| v as f64));
assert_eq!(numeric_result, Some(2.0));
}
#[test]
fn test_pasta_config_returns_default_for_missing_section() {
let temp = copy_fixture_to_temp("minimal");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local config = require("pasta.config")
return config.get("ghost", "spot_newlines", 1.5)
"#,
)
.unwrap();
assert_eq!(result.as_f64(), Some(1.5));
}
#[test]
fn test_shiori_act_uses_config_spot_newlines() {
let temp = copy_fixture_to_temp("with_ghost_config");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime
.exec(
r#"
local SHIORI_ACT = require("pasta.shiori.act")
local actors = {
sakura = { name = "さくら" },
kero = { name = "うにゅう" },
}
local act = SHIORI_ACT.new(actors)
-- 新アーキテクチャ: set_spot()でスポット位置を明示的に設定
act:set_spot("sakura", 0)
act:set_spot("kero", 1)
act:talk(actors.sakura, "Hello")
act:talk(actors.kero, "Hi")
return act:build()
"#,
)
.unwrap();
let script = value_as_str(&result).unwrap();
assert!(
script.contains("\\n[200]"),
"Expected \\n[200] but got: {}",
script
);
}
#[test]
fn test_package_path_set() {
let temp = copy_fixture_to_temp("minimal");
let runtime = PastaLoader::load(temp.path()).unwrap();
let result = runtime.exec("return package.path").unwrap();
let path = value_as_str(&result).unwrap();
assert!(path.contains("profile/pasta/save/lua") || path.contains("profile\\pasta\\save\\lua"));
assert!(path.contains("scripts"));
assert!(
path.contains("profile/pasta/cache/lua") || path.contains("profile\\pasta\\cache\\lua")
);
assert!(path.contains("scriptlibs"));
}
#[test]
fn test_load_nonexistent_directory() {
let temp = TempDir::new().unwrap();
let nonexistent = temp.path().join("definitely_nonexistent_subdir");
let result = PastaLoader::load(&nonexistent);
assert!(result.is_err());
match result {
Err(LoaderError::DirectoryNotFound(path)) => {
assert!(path.to_string_lossy().contains("definitely_nonexistent"));
}
_ => panic!("Expected DirectoryNotFound error"),
}
}
#[test]
fn test_load_empty_dic() {
let temp = TempDir::new().unwrap();
let base_dir = temp.path();
std::fs::create_dir_all(base_dir.join("dic/empty")).unwrap();
std::fs::write(base_dir.join("pasta.toml"), "[loader]\ndebug_mode = true\n").unwrap();
let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let scripts_src = crate_root.join("pasta_scripts");
let scripts_dst = base_dir.join("pasta_scripts");
if scripts_src.exists() {
std::fs::create_dir_all(&scripts_dst).unwrap();
copy_dir_recursive(&scripts_src, &scripts_dst).unwrap();
}
let scriptlibs_src = crate_root.join("scriptlibs");
let scriptlibs_dst = base_dir.join("scriptlibs");
if scriptlibs_src.exists() {
std::fs::create_dir_all(&scriptlibs_dst).unwrap();
copy_dir_recursive(&scriptlibs_src, &scriptlibs_dst).unwrap();
}
let runtime = PastaLoader::load(base_dir).unwrap();
let result = runtime.exec("return 42").unwrap();
assert_eq!(result.as_i64(), Some(42));
}
#[test]
fn test_load_missing_pasta_toml() {
let temp = TempDir::new().unwrap();
let result = PastaLoader::load(temp.path());
assert!(result.is_err());
match result {
Err(LoaderError::ConfigNotFound(path)) => {
assert_eq!(path, temp.path().join("pasta.toml"));
}
Err(other) => panic!("Expected ConfigNotFound error, got: {}", other),
Ok(_) => panic!("Expected ConfigNotFound error, got Ok"),
}
}
#[test]
fn test_load_custom_pasta_patterns() {
let temp = TempDir::new().unwrap();
let base_dir = temp.path();
std::fs::write(
base_dir.join("pasta.toml"),
"[loader]\ndebug_mode = true\npasta_patterns = [\"dic/*/*.pasta\", \"extra/*.pasta\"]\n",
)
.unwrap();
std::fs::create_dir_all(base_dir.join("dic/talk")).unwrap();
std::fs::write(
base_dir.join("dic/talk/hello.pasta"),
"*テスト\n ゴースト:「こんにちは」\n",
)
.unwrap();
std::fs::create_dir_all(base_dir.join("extra")).unwrap();
std::fs::write(
base_dir.join("extra/foo.pasta"),
"*エクストラ\n ゴースト:「extra」\n",
)
.unwrap();
std::fs::write(base_dir.join("extra/bar.lua"), "return { bar = true }\n").unwrap();
let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
for dir_name in &["pasta_scripts", "scriptlibs"] {
let src = crate_root.join(dir_name);
let dst = base_dir.join(dir_name);
if src.exists() {
std::fs::create_dir_all(&dst).unwrap();
copy_dir_recursive(&src, &dst).unwrap();
}
}
let _runtime = PastaLoader::load(base_dir).unwrap();
let scene_dic_path = base_dir.join("profile/pasta/cache/lua/pasta/scene_dic.lua");
let scene_dic = std::fs::read_to_string(&scene_dic_path).unwrap();
assert!(
scene_dic.contains("pasta.scene.talk.hello"),
"default-pattern module missing: {}",
scene_dic
);
assert!(
scene_dic.contains("pasta.scene.extra.foo"),
"custom-pattern .pasta module missing: {}",
scene_dic
);
assert!(
scene_dic.contains("pasta.scene.extra.bar"),
"derived .lua pattern module missing: {}",
scene_dic
);
}
#[test]
fn test_config_load_not_found() {
let temp = TempDir::new().unwrap();
let result = PastaConfig::load(temp.path());
assert!(result.is_err());
match result.unwrap_err() {
LoaderError::ConfigNotFound(path) => {
assert_eq!(path, temp.path().join("pasta.toml"));
}
_ => panic!("Expected ConfigNotFound error"),
}
}
#[test]
fn test_config_load_with_file() {
let base_dir = loader_fixtures_path("with_custom_config");
let config = PastaConfig::load(&base_dir).unwrap();
assert!(config.loader.debug_mode);
assert_eq!(
config.custom_fields.get("ghost_name"),
Some(&toml::Value::String("TestGhost".to_string()))
);
}