from argparse import Namespace
from pathlib import Path
import json
import os
import sys
import xml.etree.ElementTree as ET
import pytest
from .. import pkg_parser
from .. import packer
from ..utils import pkg_utils
def test_parse_os_arch_with_arch_and_default():
os_name, os_ver, arch = pkg_parser.parse_os_arch("ubuntu20.04-aarch64")
assert os_name == "ubuntu"
assert os_ver.startswith("20")
assert arch == "aarch64"
os_name2, os_ver2, arch2 = pkg_parser.parse_os_arch("ubuntu22.04")
assert os_name2 == "ubuntu"
assert arch2 == "aarch64"
def test_replace_env_and_join_dst_path_and_apply_func():
env = {"ABC": "VALUE", "EMPTY": None}
s = pkg_parser.replace_env(env, "path/$(ABC)/$(EMPTY)")
assert "VALUE" in s and "EMPTY" not in s
joined = pkg_parser.join_dst_path("/base", "sub")
assert os.path.normpath(joined).endswith(os.path.join("base", "sub"))
assert pkg_parser.join_dst_path("/base", "real:/abs") == "/abs"
inc = lambda x: x + "_x"
assert pkg_parser.apply_func(inc, "a") == "a_x"
assert pkg_parser.apply_func(inc, ["a", "b"]) == ["a_x", "b_x"]
assert pkg_parser.apply_func(inc, {"a"}) == {"a_x"}
def test_parse_package_info_and_attr_helpers():
root = ET.Element("root")
pkg_info = ET.SubElement(root, "package_info")
ET.SubElement(pkg_info, "expand_asterisk").text = "true"
ET.SubElement(pkg_info, "suffix").text = "run"
attrs = pkg_parser.parse_package_info(pkg_info)
assert attrs["expand_asterisk"] is True
assert attrs["suffix"] == "run"
args = Namespace(chip_name="c1", suffix="deb", func_name=None)
by_args = pkg_parser.parse_package_attr_by_args(args)
assert by_args["chip_name"] == "c1"
assert by_args["suffix"] == "deb"
merged = pkg_parser.parse_package_attr(root, args)
assert merged["suffix"] == "deb"
assert "gen_version_info" in merged
def test_render_cann_version_and_semver_and_cann_version_info():
expr = pkg_parser.render_cann_version(1, 2, 3, None, None, None)
assert "(" in expr and ")" in expr
items = dict(pkg_parser.render_semver("PKG", "1.2.3-alpha.1"))
assert items["PKG_VERSION_STR"] == '"1.2.3-alpha.1"'
assert "PKG_VERSION_NUM" in items
info = dict(pkg_parser.get_cann_version_info("PKG_VER", "1.2.3"))
assert '"1.2.3"' in info.values()
def test_env_items_and_parse_env_dict():
base = dict(pkg_parser.get_default_env_items())
assert "HOME" in base
vitems = dict(pkg_parser.get_env_items_by_version("1.2.3"))
assert vitems["ASCEND_VER"] == "1.2.3"
vdir_items = dict(pkg_parser.get_env_items_by_version_dir("v1"))
assert vdir_items["VERSION_DIR"] == "v1"
os_default = dict(pkg_parser.get_os_arch_default_env_items())
assert os_default["OS_NAME"] == "linux"
ts_items = dict(pkg_parser.get_env_items_by_timestamp("20240101_000000000"))
assert ts_items["TIMESTAMP_NO"] == "20240101000000000"
env = pkg_parser.parse_env_dict(
os_arch="ubuntu20.04-aarch64",
package_attr={"default_arch": "arm64"},
version="1.2.3",
version_dir="vdir",
timestamp="20240101_000000000",
)
assert env["OS_NAME"] == "ubuntu"
assert env["ASCEND_VER"] == "1.2.3"
assert env["VERSION_DIR"] == "vdir"
def test_get_timestamp_from_args_valid_and_invalid():
args = Namespace(tag="release_20240101_000000000")
ts = pkg_parser.get_timestamp(args)
assert ts == "20240101_000000000"
args_bad = Namespace(tag="no_timestamp_here")
with pytest.raises(pkg_parser.PackageError):
pkg_parser.get_timestamp(args_bad)
def test_extract_element_attrib_and_generate_info_content():
ele = ET.Element("node", a="1", b="2")
assert pkg_parser.extract_element_attrib(ele) == {"a": "1", "b": "2"}
ge = ET.Element("generate_info")
ET.SubElement(ge, "k1").text = "$(V)"
env = {"V": "X"}
content = pkg_parser.extract_generate_info_content(ge, env)
assert content["content"]["k1"] == "X"
def test_join_pkg_inner_softlink_and_check_contain_asterisk_and_trans_to_stream():
link = pkg_parser.join_pkg_inner_softlink(["a", "b", "c"])
assert "a" in link and "c" in link
assert pkg_parser.check_contain_asterisk("a*")
assert not pkg_parser.check_contain_asterisk("abc")
stream = list(pkg_parser.trans_to_stream(1))
assert stream == [1]
def test_check_value_asterisk_when_package_check_and_suffix_run():
with pytest.raises(pkg_parser.ContainAsteriskError):
pkg_parser.check_value(
"a*",
package_check=True,
package_attr={"suffix": "run"},
)
pkg_parser.check_value("a*", package_check=False, package_attr={"suffix": "run"})
def test_get_dst_prefix_target_and_make_hash_and_config_hash(tmp_path: Path):
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None,
delivery_dir=str(tmp_path), package_attr={}
)
fi = {"dst_path": "sub", "value": "file.txt", "configurable": "TRUE"}
dst_prefix = pkg_parser.get_dst_prefix(fi, env)
assert dst_prefix.endswith("sub")
dst_file = Path(dst_prefix)
dst_file.mkdir(parents=True, exist_ok=True)
real_file = dst_file / "file.txt"
real_file.write_text("data", encoding="utf-8")
target = pkg_parser.get_dst_target(fi, env)
assert os.path.basename(target) == "file.txt"
h = pkg_parser.make_hash(str(real_file))
assert len(h) == 64
parsed = pkg_parser.FileInfoParsedResult(file_info=fi, move_infos=[], dir_infos=[], expand_infos=[])
out = pkg_parser.config_hash(parsed, env)
assert out.file_info["hash"] == h
def test_need_dereference_and_need_expand_and_expand_dir(tmp_path: Path):
base_dir = tmp_path / "dst"
base_dir.mkdir()
(base_dir / "sub").mkdir()
(base_dir / "sub" / "f.txt").write_text("x", encoding="utf-8")
fi = {
"value": "dst",
"src_path": str(tmp_path),
"dst_path": str(tmp_path),
"install_path": "",
}
def get_dst_target_func(info):
return str(base_dir)
assert not pkg_parser.need_dereference(fi)
assert pkg_parser.need_expand(fi, get_dst_target_func) is True
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
files, dirs = pkg_parser.expand_dir(fi, get_dst_target_func, env)
assert any("f.txt" in f["value"] for f in files)
assert any("dst" in d["value"] for d in dirs)
def test_expand_file_info_asterisk_and_expand_file_info(tmp_path: Path):
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
dst_dir = Path(tmp_path) / "d"
dst_dir.mkdir()
(dst_dir / "a.txt").write_text("x", encoding="utf-8")
fi = {
"dst_path": str(dst_dir),
"value": "*.txt",
"install_path": "",
"configurable": "FALSE",
"src_path": str(dst_dir),
}
parsed = pkg_parser.FileInfoParsedResult(file_info=fi, move_infos=[], dir_infos=[], expand_infos=[])
results = list(pkg_parser.expand_file_info_asterisk(parsed, env))
assert any(r.file_info["value"].endswith(".txt") for r in results)
def get_dst_target_func(info):
return str(dst_dir)
expanded = pkg_parser.expand_file_info(parsed, use_move=False, get_dst_target_func=get_dst_target_func, env=env)
assert expanded.file_info.get("is_dir") or expanded.expand_infos != []
def test_parse_file_element_and_related_helpers(tmp_path: Path):
root = ET.Element("root")
block = pkg_parser.make_loaded_block_element(root, dst_path="dst")
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
pkg_attr = {"expand_asterisk": False}
default = {"module": "m", "dst_path": "d", "src_path": "s"}
file_ele = ET.Element("file", value="v.txt")
(Path(tmp_path) / "d").mkdir(parents=True, exist_ok=True)
(Path(tmp_path) / "d" / "v.txt").write_text("x", encoding="utf-8")
results = list(
pkg_parser.parse_file_element(
file_ele=file_ele,
file_config=default,
loaded_block=block,
package_attr=pkg_attr,
env=env,
)
)
assert results and isinstance(results[0], pkg_parser.FileInfoParsedResult)
def test_path_infos_and_pkg_soft_links_and_unique_infos():
root = ET.Element("root")
e1 = ET.SubElement(root, "path", value="a", src_path="sa")
e2 = ET.SubElement(root, "path", value="b", src_path="sb")
lb = pkg_parser.make_loaded_block_element(root, dst_path="dst")
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir="", package_attr={}
)
default = {}
infos = list(pkg_parser.get_path_infos(e1, default, lb, env))
assert isinstance(infos, list)
infos2 = list(pkg_parser.get_path_infos_by_elements([e1, e2], default, lb, env))
assert isinstance(infos2, list)
soft_links = pkg_parser.parse_pkg_softlinks(
[{"value": "v1", "src_path": "s1"}, {"value": "v2", "src_path": "s2"}]
)
assert soft_links[0].dst_path == "v1"
uniq = pkg_parser.unique_infos([{"value": "x"}, {"value": "x"}])
assert len(uniq) == 1
def test_block_element_and_blocks_and_read_version_info_and_parse_xml_config(tmp_path: Path, monkeypatch):
block_info = ET.Element("block_info", dst_path="dst_root", block_conf_path="conf")
ET.SubElement(block_info, "block", name="b1")
root = ET.Element("root")
root.append(block_info)
def fake_load_block_element(parse_env, package_attr, block_element):
return pkg_parser.make_loaded_block_element(root, dst_path="dst")
monkeypatch.setattr(pkg_parser, "load_block_element", fake_load_block_element)
parse_env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir="", package_attr={}
)
blocks = pkg_parser.parse_blocks(root, package_attr={}, parse_env=parse_env)
assert blocks and isinstance(blocks[0], pkg_parser.BlockConfig)
package_attr = {"install_script": "a/b/install.sh"}
a_dir = tmp_path / "a"
a_dir.mkdir()
version_file = a_dir / "version.info"
version_file.write_text("Version=1.0.0\nversion_dir=v1\n", encoding="utf-8")
ver, vdir = pkg_parser.read_version_info(str(tmp_path), package_attr)
assert ver == "1.0.0" and vdir == "v1"
xml_file = tmp_path / "config.xml"
ET.ElementTree(root).write(xml_file)
monkeypatch.setattr(pkg_parser, "read_version_info", lambda *args, **kwargs: ("1.2.3", "dir"))
monkeypatch.setattr(
pkg_parser,
"parse_env_dict",
lambda os_arch, package_attr, version, version_dir, timestamp: {"TARGET_ENV": "arch-linux"},
)
monkeypatch.setattr(pkg_parser, "is_multi_version", lambda v: bool(v))
args = Namespace(version_dir=None, disable_multi_version=False, chip_name=None, suffix=None, func_name=None, tag=None)
parse_opt = pkg_parser.ParseOption(os_arch="ubuntu20.04-aarch64", pkg_version=None, build_type=None, package_check=False)
success, cfg = pkg_parser.parse_xml_config(str(tmp_path), "config.xml", str(tmp_path), parse_opt, args)
assert success is True
assert cfg.version == "1.2.3"
assert callable(cfg.packer_config.fill_is_common_path)
def test_packer_remove_ascend_and_get_func_name_and_package_name():
assert packer.remove_ascend("Ascend910_93") == "A3"
assert packer.remove_ascend("Ascend310") == "310"
assert packer.remove_ascend(None) is None
assert packer.get_func_name("fn", {"func_name": "other"}) == "fn"
assert packer.get_func_name("", {"func_name": "other"}) == "other"
args = Namespace(
chip_name="c1",
suffix="run",
func_name="fn",
not_in_name="deploy_type",
os_arch="ubuntu20.04-aarch64",
package_suffix="debug",
ext_name="ext",
pkg_name_style="underline",
)
pn = packer.PackageName(
package_attr={"product_name": "prod", "chip_name": "c2", "deploy_type": "dt", "chip_plat": "cp"},
args=args,
version="1.2.3",
)
name = pn.getvalue()
assert "prod" in name and "run" in name
def test_create_makeself_pkg_params_factory_and_compose_and_create_run_command(monkeypatch):
source_target = "/src"
package_name = "pkg.run"
comments = "test"
factory = packer.create_makeself_pkg_params_factory(
source_target, package_name, comments
)
params = factory(
makeself_dir="/ms",
package_attr={"cleanup": "rm -rf tmp", "install_script": "install.sh", "help": "help.txt"},
independent_pkg=True,
)
monkeypatch.setattr(packer, "get_compress_tool", lambda: "--gzip")
monkeypatch.setattr(packer, "get_compress_format", lambda: "gnu")
cmd = packer.compose_makeself_command(params)
assert "pkg.run" in cmd
assert "test" in cmd
assert "--gzip" in cmd
run_cmd, extra = packer.create_run_package_command(params)
assert package_name in run_cmd and extra is None
def test_get_compress_tool_and_format_and_softlink_before_package(monkeypatch):
calls = []
def fake_which(name):
calls.append(name)
if name == "pigz":
return "/usr/bin/pigz"
return None
monkeypatch.setattr(packer.shutil, "which", fake_which)
tool = packer.get_compress_tool()
assert tool == "--pigz"
monkeypatch.setattr(packer.shutil, "which", lambda name: None)
assert packer.get_compress_format() == "gnu"
links = []
def fake_symlink(src, dst):
links.append((src, dst))
monkeypatch.setattr(packer.os, "symlink", fake_symlink)
rel_dir = "/release"
pkg_links = [packer.PkgSoftlink(dst_path="dst/file", src_path="src/file")]
packer.softlink_before_package(pkg_links, rel_dir)
assert len(links) == 1
src, dst = links[0]
assert "src" in src.replace("\\", "/")
assert "release" in dst.replace("\\", "/")
def test_parse_env_and_cmd_and_exec_pack_cmd(monkeypatch):
env = {}
tokens = ["FOO=$PWD", "BAR=1", "python", "-c", "print('x')"]
cmd_list = packer._parse_env_and_cmd(tokens, env)
assert env["FOO"] and env["BAR"] == "1"
assert cmd_list[0] == "python"
class DummyResult:
def __init__(self, code, out):
self.returncode = code
self.stdout = out
monkeypatch.setattr(
packer,
"run_complex_cmd",
lambda cmd: DummyResult(0, "ok"),
)
name = packer.exec_pack_cmd("/tmp", "echo hi", "pkg.run")
assert name == "pkg.run"
monkeypatch.setattr(
packer.CommLog,
"cilog_error",
staticmethod(lambda *args, **kwargs: None),
)
monkeypatch.setattr(
packer,
"run_complex_cmd",
lambda cmd: DummyResult(1, "bad"),
)
with pytest.raises(packer.CompressError):
packer.exec_pack_cmd("", "echo hi", "pkg.run")
def test_parse_os_arch_invalid_format():
"""测试无效os_arch格式抛出异常"""
with pytest.raises(pkg_parser.ParseOsArchError):
pkg_parser.parse_os_arch("123_invalid")
def test_replace_env_unsupported_env_var():
"""测试不支持的环境变量抛出异常"""
env = {"SUPPORTED": "val"}
with pytest.raises(pkg_parser.EnvNotSupported):
pkg_parser.replace_env(env, "path/$(UNSUPPORTED)/")
def test_replace_env_with_file():
"""测试包含$(FILE)环境变量的替换"""
env = {"VAR": "val"}
result = pkg_parser.replace_env(env, "path/$(FILE)/$(VAR)")
assert "$(FILE)" in result and "val" in result
def test_parse_package_info_none():
"""测试None package_info元素"""
attrs = pkg_parser.parse_package_info(None)
assert attrs == {}
def test_render_cann_version_with_all_params():
"""测试所有参数的CANN版本渲染"""
expr = pkg_parser.render_cann_version(1, 2, 3, 4, 5, 6)
assert "(2 * 100000000)" in expr
assert "(3 * 1000000)" in expr
assert "(4 * 10000)" in expr
assert "((5 * 100) + 5000)" in expr
assert "(6 * 100)" in expr
assert "+ 6)" in expr
def test_render_semver_various_preleases(tmp_path: Path):
"""测试各种预发布版本"""
items = dict(pkg_parser.render_semver("PKG", "1.2.3-beta.1"))
assert "PKG_PRERELEASE" in items
assert "beta" in items["PKG_PRERELEASE"]
items = dict(pkg_parser.render_semver("PKG", "1.2.3-rc.2"))
assert "PKG_PRERELEASE" in items
assert "rc" in items["PKG_PRERELEASE"]
items = dict(pkg_parser.render_semver("PKG", "1.2.3-alpha.10"))
assert "PKG_PRERELEASE" in items
assert "alpha" in items["PKG_PRERELEASE"]
items = dict(pkg_parser.render_semver("PKG", "1.2.3"))
assert items["PKG_PRERELEASE"] == '""'
def test_render_semver_invalid_version(tmp_path: Path):
"""测试无效的版本号格式"""
with pytest.raises(pkg_parser.IllegalVersionDir):
list(pkg_parser.render_semver("PKG", "invalid"))
with pytest.raises(pkg_parser.IllegalVersionDir):
list(pkg_parser.render_semver("PKG", "a.b.c"))
with pytest.raises((pkg_parser.IllegalVersionDir, ValueError)):
list(pkg_parser.render_semver("PKG", "1.2"))
def test_get_cann_version_info_empty_version():
"""测试空版本号"""
info = dict(pkg_parser.get_cann_version_info("TEST_PKG_VERSION", ""))
assert info["TEST_PKG_VERSION_STR"] == '"0"'
def test_get_os_arch_default_env_items():
"""测试获取默认os arch环境项"""
items = list(pkg_parser.get_os_arch_default_env_items())
assert len(items) == 4
assert ('OS_NAME', 'linux') in items
assert ('ARM', 'aarch64') in items
def test_get_env_items_by_timestamp_none():
"""测试无timestamp的情况"""
items = dict(pkg_parser.get_env_items_by_timestamp(None))
assert items["TIMESTAMP"] == "0"
assert items["TIMESTAMP_NO"] == "0"
def test_get_timestamp_none():
"""测试无tag参数的情况"""
args = Namespace()
ts = pkg_parser.get_timestamp(args)
assert ts is None
def test_expand_file_info_with_pkg_inner_softlink(tmp_path: Path):
"""测试pkg_inner_softlink中$(FILE)的替换"""
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
dst_dir = Path(tmp_path) / "d"
dst_dir.mkdir()
(dst_dir / "a.txt").write_text("x", encoding="utf-8")
(dst_dir / "b.txt").write_text("y", encoding="utf-8")
fi = {
"dst_path": str(dst_dir),
"value": "*.txt",
"install_path": "",
"configurable": "FALSE",
"src_path": str(dst_dir),
"pkg_inner_softlink": "$(FILE).link",
}
parsed = pkg_parser.FileInfoParsedResult(
file_info=fi, move_infos=[], dir_infos=[], expand_infos=[]
)
results = list(pkg_parser.expand_file_info_asterisk(parsed, env))
assert len(results) == 2
links = [r.file_info.get("pkg_inner_softlink") for r in results]
assert any("a.txt.link" in link for link in links)
assert any("b.txt.link" in link for link in links)
def test_expand_file_info_with_exclude(tmp_path: Path):
"""测试exclude功能"""
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
dst_dir = Path(tmp_path) / "d"
dst_dir.mkdir()
(dst_dir / "a.txt").write_text("x", encoding="utf-8")
(dst_dir / "b.txt").write_text("y", encoding="utf-8")
(dst_dir / "c.txt").write_text("z", encoding="utf-8")
fi = {
"dst_path": str(dst_dir),
"value": "*.txt",
"install_path": "",
"configurable": "FALSE",
"src_path": str(dst_dir),
"exclude": "a.txt ; c.txt",
}
parsed = pkg_parser.FileInfoParsedResult(
file_info=fi, move_infos=[], dir_infos=[], expand_infos=[]
)
results = list(pkg_parser.expand_file_info_asterisk(parsed, env))
assert len(results) == 1
assert "b.txt" in results[0].file_info["value"]
def test_need_dereference_true():
"""测试need_dereference返回True"""
fi = {"dereference": "true"}
assert pkg_parser.need_dereference(fi) is True
def test_need_expand_with_entity():
"""测试entity为true时不展开"""
fi = {"entity": "true"}
assert pkg_parser.need_expand(fi, lambda x: "/some/path") is False
def test_expand_file_info_with_use_move(tmp_path: Path):
"""测试use_move分支"""
fi = {
"dst_path": str(tmp_path),
"value": "file.txt",
"install_path": "",
"configurable": "FALSE",
"src_path": str(tmp_path),
}
parsed = pkg_parser.FileInfoParsedResult(
file_info=fi, move_infos=[], dir_infos=[], expand_infos=[]
)
def get_dst_target_func(info):
return os.path.join(str(tmp_path), "file.txt")
env = pkg_parser.ParseEnv(
env_dict={}, parse_option=None, pkg_config_dir=None, delivery_dir=str(tmp_path),
package_attr={}
)
expanded = pkg_parser.expand_file_info(
parsed, use_move=True, get_dst_target_func=get_dst_target_func, env=env
)
assert len(expanded.move_infos) == 1
assert expanded.move_infos[0]["value"] == "file.txt"
def test_expand_dir_with_symlink(tmp_path: Path):
"""测试展开目录时处理软链接"""
base_dir = tmp_path / "dst"
base_dir.mkdir()
link_file = base_dir / "link.txt"
target_file = tmp_path / "target.txt"
target_file.write_text("content", encoding="utf-8")
try:
link_file.symlink_to(target_file)
fi = {
"value": "dst",
"src_path": str(tmp_path),
"dst_path": str(tmp_path),
"install_path": "",
}
def get_dst_target_func(info):
return str(base_dir)
env = pkg_parser.ParseEnv(env_dict={}, parse_option=None, pkg_config_dir=None,
delivery_dir=str(tmp_path), package_attr={})
files, dirs = pkg_parser.expand_dir(fi, get_dst_target_func, env=env)
assert len(files) > 0
except (OSError, NotImplementedError):
pass
def test_create_file_info_structure():
"""测试create_file_info函数的返回结构"""
fi = {
"dst_path": "/dst",
"src_path": "/src",
"install_path": "/install",
"value": "original_value",
}
result = pkg_parser.create_file_info("/dst/sub/file.txt", "/dst", fi, "file.txt", "dst")
assert result["value"] == "file.txt"
assert "sub" in result["src_path"] or "dst" in result["dst_path"]
def test_parse_block_element_missing_name():
"""测试缺少name时抛出异常"""
block_info = ET.Element("block_info", dst_path="dst", block_conf_path="conf")
block_ele = ET.SubElement(block_info, "block")
with pytest.raises(pkg_parser.BlockConfigError):
pkg_parser.parse_block_element(block_ele, block_info.attrib)
def test_parse_block_element_missing_conf_path():
"""测试缺少block_conf_path时抛出异常"""
block_info = ET.Element("block_info", dst_path="dst")
block_ele = ET.SubElement(block_info, "block", name="test")
with pytest.raises(pkg_parser.BlockConfigError):
pkg_parser.parse_block_element(block_ele, block_info.attrib)
def test_evaluate_info_with_real_prefix():
"""测试real:前缀的处理"""
block = pkg_parser.make_loaded_block_element(ET.Element("root"), dst_path="/base")
env_dict = {}
info = {"dst_path": "real:/abs/path"}
result = pkg_parser.evaluate_info(info, block, env_dict)
assert result["dst_path"] == "/abs/path"
def test_read_version_info_invalid_format(tmp_path: Path, monkeypatch):
"""测试无效的版本格式"""
package_attr = {"install_script": "a/b/install.sh"}
a_dir = tmp_path / "a"
a_dir.mkdir()
version_file = a_dir / "version.info"
version_file.write_text("Version=invalid!\nversion_dir=v1\n", encoding="utf-8")
with pytest.raises(pkg_parser.VersionFormatNotMatch):
pkg_parser.read_version_info(str(tmp_path), package_attr)
def test_parse_xml_config_invalid_xml(tmp_path: Path, monkeypatch):
"""测试无效的XML格式"""
invalid_xml = tmp_path / "invalid.xml"
invalid_xml.write_text("<invalid><xml>", encoding="utf-8")
parse_opt = pkg_parser.ParseOption(os_arch="ubuntu20.04", pkg_version=None, build_type=None, package_check=False)
args = Namespace(version_dir="1.2.3", disable_multi_version=True, chip_name=None, suffix=None, func_name=None, tag=None)
monkeypatch.setattr(pkg_parser, "read_version_info", lambda *args, **kwargs: ("1.2.3", ""))
monkeypatch.setattr(pkg_parser, "parse_env_dict", lambda *args, **kwargs: {"TARGET_ENV": "arch-linux"})
monkeypatch.setattr(pkg_parser, "is_multi_version", lambda v: bool(v))
success, result = pkg_parser.parse_xml_config(str(tmp_path), "invalid.xml", str(tmp_path), parse_opt, args)
assert success is False
assert result is None
def test_parse_xml_config_invalid_os_arch(tmp_path: Path, monkeypatch):
"""测试无效的os_arch配置"""
xml_file = tmp_path / "config.xml"
ET.ElementTree(ET.Element("root")).write(xml_file)
parse_opt = pkg_parser.ParseOption(os_arch="invalid", pkg_version=None, build_type=None, package_check=False)
args = Namespace(version_dir="1.2.3", disable_multi_version=True, chip_name=None, suffix=None, func_name=None, tag=None)
monkeypatch.setattr(pkg_parser, "read_version_info", lambda: ("1.2.3", ""))
original_exit = sys.exit
try:
sys.exit = lambda *args: None
pkg_parser.parse_xml_config(str(tmp_path), "config.xml", str(tmp_path), parse_opt, args)
finally:
sys.exit = original_exit
def test_render_semver_multisegment_prelease():
"""测试多段预发布版本"""
items = dict(pkg_parser.render_semver("PKG", "1.2.3-alpha.1.2"))
assert "PKG_PRERELEASE" in items
assert "alpha.1.2" in items["PKG_PRERELEASE"]
def test_render_semver_plus_in_version():
"""测试版本号中包含+号"""
items = dict(pkg_parser.render_semver("PKG", "1.2.3+build"))
assert "PKG_VERSION_STR" in items
assert "+build" not in items["PKG_VERSION_STR"]
def test_parse_package_info_false_values():
"""测试解析false值"""
root = ET.Element("root")
pkg_info = ET.SubElement(root, "package_info")
ET.SubElement(pkg_info, "expand_asterisk").text = "false"
ET.SubElement(pkg_info, "suffix").text = "deb"
attrs = pkg_parser.parse_package_info(pkg_info)
assert attrs["expand_asterisk"] is False
assert attrs["suffix"] == "deb"
def test_get_compress_tool_no_tools_found(monkeypatch, capsys):
"""测试当没有压缩工具时返回空字符串"""
monkeypatch.setattr(packer.shutil, "which", lambda name: None)
tool = packer.get_compress_tool()
assert tool == ""
def test_get_compress_format_with_bsdtar(monkeypatch):
"""测试检测到bsdtar时返回ustar格式"""
monkeypatch.setattr(packer.shutil, "which", lambda name: "/usr/bin/bsdtar" if name == "bsdtar" else None)
fmt = packer.get_compress_format()
assert fmt == "ustar"
def test_compose_makeself_command_with_cleanup(monkeypatch):
"""测试组装makeself命令带cleanup参数"""
monkeypatch.setattr(packer, "get_compress_tool", lambda: "--gzip")
monkeypatch.setattr(packer, "get_compress_format", lambda: "gnu")
params = packer.MakeselfPkgParams(
package_name="test.run",
comments="Test",
makeself_tool="/tools/makeself.sh",
makeself_header="/tools/makeself-header.sh",
help_info="help.txt",
source_target="/source",
install_script="install.sh",
independent_pkg=True,
cleanup="cleanup.sh"
)
cmd = packer.compose_makeself_command(params)
assert "--cleanup cleanup.sh" in cmd
assert "makeself.sh" in cmd
def test_compose_makeself_command_non_independent(monkeypatch):
"""测试非独立包的makeself命令组装"""
monkeypatch.setattr(packer, "get_compress_tool", lambda: "--gzip")
monkeypatch.setattr(packer, "get_compress_format", lambda: "gnu")
params = packer.MakeselfPkgParams(
package_name="test.run",
comments="Test",
cleanup=None,
independent_pkg=False
)
cmd = packer.compose_makeself_command(params)
assert "test.run" in cmd
assert "Test" in cmd
assert "TMPDIR" not in cmd
def test_create_makeself_pkg_params_non_independent():
"""测试创建非独立包的参数"""
factory = packer.create_makeself_pkg_params_factory("/source", "test.run", "Test")
params = factory("/makeself", {"cleanup": "clean.sh"}, independent_pkg=False)
assert params.package_name == "test.run"
assert params.comments == "Test"
assert params.makeself_tool is None
assert params.independent_pkg is False
def test_package_name_getvalue_with_all_attributes():
"""测试PackageName.getvalue使用所有属性"""
args = Namespace(
chip_name="ascend910",
suffix="run",
func_name="toolkit",
not_in_name="",
os_arch="aarch64",
package_suffix="none",
ext_name="",
pkg_name_style="common"
)
package_attr = {
"product_name": "Ascend",
"chip_plat": "",
"deploy_type": ""
}
pkg_name = packer.PackageName(package_attr, args, "1.0.0")
result = pkg_name.getvalue()
assert result.endswith(".run")
assert "ascend" in result.lower() or "910" in result
def test_package_name_getvalue_underline_style():
"""测试PackageName.getvalue使用下划线风格"""
args = Namespace(
chip_name=None,
suffix="run",
func_name="nnae",
not_in_name="os_arch,product_name",
os_arch="aarch64",
package_suffix="debug",
ext_name="",
pkg_name_style="underline"
)
package_attr = {
"product_name": "Ascend",
"chip_plat": "",
"deploy_type": ""
}
pkg_name = packer.PackageName(package_attr, args, "1.0.0")
result = pkg_name.getvalue()
assert "_" in result
assert result.endswith(".run")
def test_run_complex_cmd_with_cd(monkeypatch):
"""测试run_complex_cmd处理cd命令"""
class DummyResult:
def __init__(self):
self.returncode = 0
self.stdout = "success"
calls = []
def mock_run(*args, **kwargs):
calls.append(kwargs.get('cwd'))
return DummyResult()
monkeypatch.setattr(packer.subprocess, "run", mock_run)
result = packer.run_complex_cmd("cd /some/dir && echo test")
assert result is not None
def test_run_complex_cmd_no_cmd(monkeypatch):
"""测试run_complex_cmd没有命令时返回None"""
result = packer.run_complex_cmd("cd /tmp")
assert result is None