From 522ebc098604f2e7e356d493bd8e77d7b39e9d12 Mon Sep 17 00:00:00 2001 From: Max Qian <64824374+AstroAir@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:38:09 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20CMake=20=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=BA=93=E5=88=9B=E5=BB=BA=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E5=88=A0=E9=99=A4=E4=B8=8D=E5=86=8D=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E8=84=9A=E6=9C=AC=E6=96=87=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20Python=20=E6=8E=A5=E5=8F=A3=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=BC=BA=E5=A4=9A=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E5=92=8C=E6=80=A7=E8=83=BD=E5=88=86=E6=9E=90?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pysrc/target/__init__.py | 0 src/script/CMakeLists.txt | 66 ++++++++++ src/script/custom/hotspot.ps1 | 189 ----------------------------- src/script/custom/hotspot.sh | 128 -------------------- src/script/custom/nginx.ps1 | 80 ------------- src/script/custom/nginx.sh | 155 ------------------------ src/script/pycaller.hpp | 97 +++++++++++++++ src/task/CMakeLists.txt | 32 ++--- tests/script/checker.cpp | 107 +++++++++++++++++ tests/script/sheller.cpp | 220 ++++++++++++++++++++++++++++++++++ 10 files changed, 506 insertions(+), 568 deletions(-) delete mode 100644 pysrc/target/__init__.py create mode 100644 src/script/CMakeLists.txt delete mode 100644 src/script/custom/hotspot.ps1 delete mode 100644 src/script/custom/hotspot.sh delete mode 100644 src/script/custom/nginx.ps1 delete mode 100644 src/script/custom/nginx.sh create mode 100644 tests/script/checker.cpp create mode 100644 tests/script/sheller.cpp diff --git a/pysrc/target/__init__.py b/pysrc/target/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt new file mode 100644 index 00000000..7d1ab66b --- /dev/null +++ b/src/script/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt for Lithium-Task +# This project is licensed under the terms of the GPL3 license. +# +# Project Name: Lithium-Task +# Description: The official config module for lithium server +# Author: Max Qian +# License: GPL3 + +cmake_minimum_required(VERSION 3.20) +project(lithium-task VERSION 1.0.0 LANGUAGES C CXX) + +# Include subdirectories +add_subdirectory(simple) + +# Sources and Headers +set(PROJECT_SOURCES + container.cpp + generator.cpp + loader.cpp + manager.cpp + singlepool.cpp + task.cpp +) + +set(PROJECT_HEADERS + container.hpp + generator.hpp + loader.hpp + manager.hpp + singlepool.hpp + task.hpp +) + +# Required libraries +set(PROJECT_LIBS + atom-component + atom-function + atom-utils + atom-error + loguru + ${CMAKE_THREAD_LIBS_INIT} +) + +# Function to create a library target +function(create_library TARGET_NAME) + add_library(${TARGET_NAME} STATIC ${ARGN}) + target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${TARGET_NAME} PRIVATE ${PROJECT_LIBS}) + set_target_properties(${TARGET_NAME} PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 + OUTPUT_NAME ${TARGET_NAME} + ) +endfunction() + +# Create Object Library +add_library(${PROJECT_NAME}_OBJECT OBJECT ${PROJECT_SOURCES} ${PROJECT_HEADERS}) +set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE ON) + +# Create Static Library +create_library(${PROJECT_NAME} $) + +# Install target +install(TARGETS ${PROJECT_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) \ No newline at end of file diff --git a/src/script/custom/hotspot.ps1 b/src/script/custom/hotspot.ps1 deleted file mode 100644 index 120f2723..00000000 --- a/src/script/custom/hotspot.ps1 +++ /dev/null @@ -1,189 +0,0 @@ -<# -使用说明 - -此脚本用于管理Windows上的Wi-Fi热点,包括启动、停止、查看状态和设置配置文件。以下是详细的使用说明: - -参数说明 -- Action: 指定要执行的操作。有效值包括 "Start", "Stop", "Status", "List", "Set"。这是一个必选参数。 -- Name: 热点的名称,默认为 "MyHotspot"。这是一个可选参数。 -- Password: 热点的密码,必须是一个SecureString。当启动或设置热点时,这是一个必需参数。 -- Authentication: 认证类型,有效值为 "WPA2PSK" 和 "WPA2",默认为 "WPA2PSK"。这是一个可选参数。 -- Encryption: 加密类型,有效值为 "AES" 和 "TKIP",默认为 "AES"。这是一个可选参数。 -- Channel: 无线信道,默认为 11。有效值范围为 1 到 11。 这是一个可选参数。 -- MaxClients: 最大连接客户端数量,默认为 10。 这是一个可选参数。 - -操作说明 - -启动热点 -启动热点并配置相关参数。 -powershell.exe -File "HotspotScript.ps1" -Action Start -Password (ConvertTo-SecureString -String 'YourSecurePasswordHere' -AsPlainText -Force) -注意:必须提供热点的密码。 - -停止热点 -停止当前运行的热点。 -powershell.exe -File "HotspotScript.ps1" -Action Stop - -查看热点状态 -查看当前热点的运行状态。 -powershell.exe -File "HotspotScript.ps1" -Action Status - -列出当前配置 -列出当前热点的所有配置信息。 -powershell.exe -File "HotspotScript.ps1" -Action List - -设置热点配置 -配置热点的详细信息。 -powershell.exe -File "HotspotScript.ps1" -Action Set -Password (ConvertTo-SecureString -String 'YourSecurePasswordHere' -AsPlainText -Force) -注意:必须提供热点的密码。 - -热点自动刷新 -为了确保热点的持续可用性,脚本会自动创建一个批处理文件并在后台运行。 - -创建批处理文件 -脚本会自动在桌面上创建一个名为 StartMobileHotspot.bat 的批处理文件。该文件包含启动热点的命令并自动刷新。 - -#> - -[CmdletBinding()] -Param( - [Parameter(Position = 0, Mandatory = $true)] - [ValidateSet("Start", "Stop", "Status", "List", "Set")] - [string]$Action, - - [Parameter(Position = 1, Mandatory = $false)] - [string]$Name = "MyHotspot", - - [Parameter(Position = 2, Mandatory = $false)] - [SecureString]$Password, - - [Parameter(Mandatory = $false)] - [ValidateSet("WPA2PSK", "WPA2")] - [string]$Authentication = "WPA2PSK", - - [Parameter(Mandatory = $false)] - [ValidateSet("AES", "TKIP")] - [string]$Encryption = "AES", - - [Parameter(Mandatory = $false)] - [int]$Channel = 11, - - [Parameter(Mandatory = $false)] - [int]$MaxClients = 10 -) - -# Define hotspot adapter name -$hotspotAdapterName = "Wi-Fi" - -function Start-Hotspot { - param ( - [string]$Name, - [string]$Password, - [string]$Authentication, - [string]$Encryption, - [int]$Channel, - [int]$MaxClients - ) - - netsh wlan set hostednetwork mode=allow ssid=$Name key=$Password keyUsage=persistent auth=$Authentication cipher=$Encryption channel=$Channel - netsh wlan start hostednetwork -} - -function Stop-Hotspot { - netsh wlan stop hostednetwork -} - -function Get-HotspotStatus { - netsh wlan show hostednetwork -} - -switch ($Action) { - "Start" { - if (-not $Password) { - Write-Error "Password is required when starting a hotspot" - exit 1 - } - - $plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) - - Start-Hotspot -Name $Name -Password $plainPassword -Authentication $Authentication -Encryption $Encryption -Channel $Channel -MaxClients $MaxClients - - Start-Sleep -Seconds 2 - $status = Get-HotspotStatus - if ($status -match "Status\s*:\s*Started") { - Write-Output "Hotspot $Name is now running with password $plainPassword" - } else { - Write-Error "Failed to start hotspot $Name" - exit 1 - } - } - - "Stop" { - Stop-Hotspot - - Start-Sleep -Seconds 2 - $status = Get-HotspotStatus - if ($status -match "Status\s*:\s*Not started") { - Write-Output "Hotspot has been stopped" - } else { - Write-Error "Failed to stop hotspot" - exit 1 - } - } - - "Status" { - $status = Get-HotspotStatus - if ($status -match "Status\s*:\s*Started") { - Write-Output "Hotspot is running" - Write-Output "Hotspot settings:" - Write-Output $status - } else { - Write-Output "Hotspot is not running" - } - } - - "List" { - Write-Output "Current hosted network configuration:" - $status = Get-HotspotStatus - Write-Output $status - } - - "Set" { - if (-not $Password) { - Write-Error "Password is required when setting a hotspot profile" - exit 1 - } - - $plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) - - netsh wlan set hostednetwork mode=allow ssid=$Name key=$plainPassword keyUsage=persistent auth=$Authentication cipher=$Encryption channel=$Channel - Write-Output "Hotspot profile '$Name' has been updated" - } -} - -# Script to auto-refresh and ensure hotspot availability -if ($MyInvocation.InvocationName -eq $PSCommandPath) { - start mshta vbscript:createobject("wscript.shell").run("""$PSCommandPath"" hide",0)(window.close)&&exit - goto :CmdBegin -} - -:CmdBegin - -$CurrentUserPath = [System.Environment]::GetFolderPath('Desktop') -$BatchFilePath = Join-Path $CurrentUserPath "StartMobileHotspot.bat" - -# Create or update the batch file -$batchContent = @" -@echo off -powershell.exe -File `"$PSCommandPath`" Start -Password (ConvertTo-SecureString -String 'YourSecurePasswordHere' -AsPlainText -Force) -choice /t 10 /d y /n >nul -goto autoRefreshWeb -:autoRefreshWeb -start "" `"$BatchFilePath`" -choice /t 10 /d y /n >nul -goto autoRefreshWeb -"@ - -Set-Content -Path $BatchFilePath -Value $batchContent - -# Start the batch file for auto-refresh -Start-Process -FilePath $BatchFilePath diff --git a/src/script/custom/hotspot.sh b/src/script/custom/hotspot.sh deleted file mode 100644 index 2b3072fc..00000000 --- a/src/script/custom/hotspot.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/bash - -# hotspot.sh -# -# 用于在 Linux 上管理无线热点的 Shell 脚本 -# 使用 nmcli (NetworkManager 命令行接口) -# -# 使用方法: -# ./hotspot.sh {Start|Stop|Status|List|Set} [Name] [Password] [Authentication] [Encryption] [Channel] [MaxClients] -# -# 参数: -# - Action: 必需。操作类型。可选值为 Start、Stop、Status、List、Set。 -# - Name: 热点名称。默认值为 "MyHotspot"。 -# - Password: 热点的密码。在 Start 和 Set 操作中是必需的。 -# - Authentication: 认证类型。可选值为 wpa-psk 或 wpa2。默认值为 wpa-psk。 -# - Encryption: 加密类型。可选值为 aes 或 tkip。默认值为 aes。 -# - Channel: 热点使用的频道号。默认值为 11。 -# - MaxClients: 最大客户端数量。默认值为 10。 -# -# 使用示例: -# 启动热点: -# ./hotspot.sh Start MyHotspot MyPassword -# -# 停止热点: -# ./hotspot.sh Stop -# -# 查看热点状态: -# ./hotspot.sh Status -# -# 列出所有热点配置: -# ./hotspot.sh List -# -# 设置热点配置文件: -# ./hotspot.sh Set MyHotspot MyPassword wpa-psk aes 11 10 - -# 参数解析 -ACTION=$1 -NAME=${2:-MyHotspot} -PASSWORD=$3 -AUTHENTICATION=${4:-wpa-psk} -ENCRYPTION=${5:-aes} -CHANNEL=${6:-11} -MAX_CLIENTS=${7:-10} - -# 启动热点 -function start_hotspot { - if [ -z "$PASSWORD" ]; then - echo "Password is required when starting a hotspot" - exit 1 - fi - - # 创建热点连接 - nmcli dev wifi hotspot ifname wlan0 ssid "$NAME" password "$PASSWORD" - - # 设置其他参数 - nmcli connection modify Hotspot 802-11-wireless.security "$AUTHENTICATION" - nmcli connection modify Hotspot 802-11-wireless.band bg - nmcli connection modify Hotspot 802-11-wireless.channel "$CHANNEL" - nmcli connection modify Hotspot 802-11-wireless.cloned-mac-address stable - nmcli connection modify Hotspot 802-11-wireless.mac-address-randomization no - - echo "Hotspot $NAME is now running with password $PASSWORD" -} - -# 停止热点 -function stop_hotspot { - nmcli connection down Hotspot - echo "Hotspot has been stopped" -} - -# 查看热点状态 -function status_hotspot { - status=$(nmcli dev status | grep wlan0) - if echo "$status" | grep -q "connected"; then - echo "Hotspot is running" - nmcli connection show Hotspot - else - echo "Hotspot is not running" - fi -} - -# 列出所有热点配置 -function list_hotspot { - nmcli connection show --active | grep wifi -} - -# 设置热点配置文件 -function set_hotspot { - if [ -z "$PASSWORD" ]; then - echo "Password is required when setting a hotspot profile" - exit 1 - fi - - # 创建或修改热点连接 - nmcli connection modify Hotspot 802-11-wireless.ssid "$NAME" - nmcli connection modify Hotspot 802-11-wireless-security.key-mgmt "$AUTHENTICATION" - nmcli connection modify Hotspot 802-11-wireless-security.proto rsn - nmcli connection modify Hotspot 802-11-wireless-security.group "$ENCRYPTION" - nmcli connection modify Hotspot 802-11-wireless-security.pairwise "$ENCRYPTION" - nmcli connection modify Hotspot 802-11-wireless-security.psk "$PASSWORD" - nmcli connection modify Hotspot 802-11-wireless.band bg - nmcli connection modify Hotspot 802-11-wireless.channel "$CHANNEL" - nmcli connection modify Hotspot 802-11-wireless.mac-address-randomization no - - echo "Hotspot profile '$NAME' has been updated" -} - -# 主程序入口 -case $ACTION in - Start) - start_hotspot - ;; - Stop) - stop_hotspot - ;; - Status) - status_hotspot - ;; - List) - list_hotspot - ;; - Set) - set_hotspot - ;; - *) - echo "Usage: $0 {Start|Stop|Status|List|Set} [Name] [Password] [Authentication] [Encryption] [Channel] [MaxClients]" - ;; -esac diff --git a/src/script/custom/nginx.ps1 b/src/script/custom/nginx.ps1 deleted file mode 100644 index fd29c79b..00000000 --- a/src/script/custom/nginx.ps1 +++ /dev/null @@ -1,80 +0,0 @@ -# 定义 Nginx 路径 -$NginxPath = "C:\nginx" -$NginxConfPath = "$NginxPath\conf\nginx.conf" -$NginxBinary = "$NginxPath\nginx.exe" - -# 函数: 启动 Nginx -function Start-Nginx { - if (Test-Path $NginxBinary) { - & $NginxBinary - Write-Host "Nginx 已启动" -ForegroundColor Green - } else { - Write-Host "无法找到 Nginx 二进制文件" -ForegroundColor Red - } -} - -# 函数: 停止 Nginx -function Stop-Nginx { - if (Test-Path $NginxBinary) { - $nginxProcess = Get-Process | Where-Object {$_.Path -eq $NginxBinary} - if ($nginxProcess) { - $nginxProcess | Stop-Process -Force - Write-Host "Nginx 已停止" -ForegroundColor Green - } else { - Write-Host "Nginx 未运行" -ForegroundColor Red - } - } else { - Write-Host "无法找到 Nginx 二进制文件" -ForegroundColor Red - } -} - -# 函数: 重新加载 Nginx 配置 -function Reload-Nginx { - if (Test-Path $NginxBinary) { - $nginxProcess = Get-Process | Where-Object {$_.Path -eq $NginxBinary} - if ($nginxProcess) { - $nginxProcess.Refresh() - Write-Host "Nginx 配置已重新加载" -ForegroundColor Green - } else { - Write-Host "Nginx 未运行" -ForegroundColor Red - } - } else { - Write-Host "无法找到 Nginx 二进制文件" -ForegroundColor Red - } -} - -# 函数: 检查 Nginx 配置文件语法 -function Test-NginxConfig { - if (Test-Path $NginxConfPath) { - & $NginxBinary -t -c $NginxConfPath - } else { - Write-Host "无法找到 Nginx 配置文件" -ForegroundColor Red - } -} - -# 函数: 显示帮助信息 -function Show-Help { - Write-Host "Usage: .\nginx.ps1 [start|stop|reload|check|help]" - Write-Host " start 启动 Nginx" - Write-Host " stop 停止 Nginx" - Write-Host " reload 重新加载 Nginx 配置" - Write-Host " check 检查 Nginx 配置文件语法" - Write-Host " help 显示帮助信息" -} - -# 主函数 -function Main { - param($Command) - - switch ($Command) { - "start" { Start-Nginx } - "stop" { Stop-Nginx } - "reload" { Reload-Nginx } - "check" { Test-NginxConfig } - "help" { Show-Help } - default { Write-Host "无效的命令" -ForegroundColor Red; Show-Help } - } -} - -# 执行主函数 -Main $args[0] diff --git a/src/script/custom/nginx.sh b/src/script/custom/nginx.sh deleted file mode 100644 index 8e89d096..00000000 --- a/src/script/custom/nginx.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash - -# Nginx 管理脚本 -# 用途: 安装、启动、停止、重载、检查Nginx配置,并显示Nginx状态 -# -# 使用方法: -# ./nginx_manager.sh [start|stop|reload|check|status|help] -# -# 参数说明: -# start - 启动Nginx -# stop - 停止Nginx -# reload - 重载Nginx配置 -# check - 检查Nginx配置语法 -# status - 显示Nginx运行状态 -# help - 显示此帮助信息 -# -# 脚本功能: -# 1. 自动检测并安装Nginx(支持Debian和Red Hat系统) -# 2. 启动、停止和重载Nginx服务 -# 3. 检查Nginx配置文件的语法 -# 4. 显示Nginx的当前运行状态 -# -# 示例: -# ./nginx_manager.sh start -# ./nginx_manager.sh stop -# ./nginx_manager.sh reload -# ./nginx_manager.sh check -# ./nginx_manager.sh status -# ./nginx_manager.sh help - -# Define colors for output -GREEN='\033[0;32m' -RED='\033[0;31m' -NC='\033[0m' # No Color - -# Define Nginx paths -NGINX_PATH="/etc/nginx" -NGINX_CONF="$NGINX_PATH/nginx.conf" -NGINX_BINARY="/usr/sbin/nginx" - -# Function: Install Nginx if not installed -install_nginx() { - if ! command -v nginx &>/dev/null; then - echo "Installing Nginx..." - if [ -f /etc/debian_version ]; then - # Debian-based system (e.g., Ubuntu) - sudo apt-get update - sudo apt-get install nginx -y - elif [ -f /etc/redhat-release ]; then - # Red Hat-based system (e.g., CentOS) - sudo yum update - sudo yum install nginx -y - else - echo -e "${RED}Unsupported platform. Please install Nginx manually.${NC}" - exit 1 - fi - fi -} - -# Function: Start Nginx -start_nginx() { - if [ -f "$NGINX_BINARY" ]; then - sudo $NGINX_BINARY - echo -e "${GREEN}Nginx has been started${NC}" - else - echo -e "${RED}Nginx binary not found${NC}" - fi -} - -# Function: Stop Nginx -stop_nginx() { - if [ -f "$NGINX_BINARY" ]; then - sudo $NGINX_BINARY -s stop - echo -e "${GREEN}Nginx has been stopped${NC}" - else - echo -e "${RED}Nginx binary not found${NC}" - fi -} - -# Function: Reload Nginx configuration -reload_nginx() { - if [ -f "$NGINX_BINARY" ]; then - sudo $NGINX_BINARY -s reload - echo -e "${GREEN}Nginx configuration has been reloaded${NC}" - else - echo -e "${RED}Nginx binary not found${NC}" - fi -} - -# Function: Check Nginx configuration syntax -check_config() { - if [ -f "$NGINX_CONF" ]; then - sudo $NGINX_BINARY -t -c "$NGINX_CONF" - else - echo -e "${RED}Nginx configuration file not found${NC}" - fi -} - -# Function: Show Nginx status -status_nginx() { - if pgrep nginx &>/dev/null; then - echo -e "${GREEN}Nginx is running${NC}" - else - echo -e "${RED}Nginx is not running${NC}" - fi -} - -# Function: Show help message -show_help() { - echo "Usage: $0 [start|stop|reload|check|status|help]" - echo " start Start Nginx" - echo " stop Stop Nginx" - echo " reload Reload Nginx configuration" - echo " check Check Nginx configuration syntax" - echo " status Show Nginx status" - echo " help Show help message" -} - -# Main function -main() { - if [ "$1" == "help" ]; then - show_help - exit 0 - fi - - # Check if Nginx is installed - install_nginx - - # Execute the command - case "$1" in - start) - start_nginx - ;; - stop) - stop_nginx - ;; - reload) - reload_nginx - ;; - check) - check_config - ;; - status) - status_nginx - ;; - *) - echo -e "${RED}Invalid command${NC}" - show_help - exit 1 - ;; - esac -} - -# Execute main function with the provided argument -main "$1" diff --git a/src/script/pycaller.hpp b/src/script/pycaller.hpp index 6ab1c96d..41af3e60 100644 --- a/src/script/pycaller.hpp +++ b/src/script/pycaller.hpp @@ -158,6 +158,103 @@ class PythonWrapper { */ std::vector list_scripts() const; + void add_sys_path(const std::string &path) { + py::module_ sys = py::module_::import("sys"); + py::list sys_path = sys.attr("path"); + sys_path.append(path); + } + + // 同步变量到 Python 全局变量 + void sync_variable_to_python(const std::string &name, py::object value) { + py::globals()[name.c_str()] = value; + } + + // 从 Python 全局变量同步到 C++ + py::object sync_variable_from_python(const std::string &name) { + return py::globals()[name.c_str()]; + } + + // 多线程运行 Python 脚本 + void execute_script_multithreaded(const std::vector &scripts) { + std::vector threads; + std::mutex print_mutex; + + for (const auto &script : scripts) { + threads.emplace_back([&, script]() { + try { + py::exec(script); + } catch (const py::error_already_set &e) { + std::lock_guard lock(print_mutex); + std::cerr << "Error in thread: " << e.what() << std::endl; + } + }); + } + + for (auto &t : threads) { + t.join(); + } + } + + // 执行并统计脚本性能 + void execute_with_profiling(const std::string &script_content) { + auto start_time = std::chrono::high_resolution_clock::now(); + + try { + py::exec(script_content); + } catch (const py::error_already_set &e) { + handle_exception(e); + } + + auto end_time = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end_time - start_time; + + std::cout << "Execution time: " << duration.count() << " seconds." << std::endl; + } + + // 动态代码注入 + void inject_code(const std::string &code_snippet) { + try { + py::exec(code_snippet); + } catch (const py::error_already_set &e) { + handle_exception(e); + } + } + + // Python 调用 C++ 方法支持 + void register_function(const std::string &name, std::function func) { + py::globals()[name.c_str()] = py::cpp_function(func); + } + + // 内存诊断工具 + py::object get_memory_usage() { + py::module_ gc = py::module_::import("gc"); + return gc.attr("get_objects")(); + } + + // 捕获详细异常信息 + static void handle_exception(const py::error_already_set &e) { + std::cerr << "Python Exception:\n" << e.what() << "\n"; + + py::module_ traceback = py::module_::import("traceback"); + py::object tb = traceback.attr("format_exc")(); + std::cerr << "Traceback:\n" << py::cast(tb) << std::endl; + } + + // 执行带日志支持的脚本 + void execute_script_with_logging(const std::string &script_content, const std::string &log_file) { + std::ofstream log_stream(log_file, std::ios::app); + if (!log_stream.is_open()) { + throw std::runtime_error("Cannot open log file: " + log_file); + } + + py::scoped_ostream_redirect stream_redirect(log_stream, py::module_::import("sys").attr("stdout")); + try { + py::exec(script_content); + } catch (const py::error_already_set &e) { + handle_exception(e); + } + } + private: class Impl; std::unique_ptr pImpl; diff --git a/src/task/CMakeLists.txt b/src/task/CMakeLists.txt index 337fa83c..7d1ab66b 100644 --- a/src/task/CMakeLists.txt +++ b/src/task/CMakeLists.txt @@ -9,9 +9,10 @@ cmake_minimum_required(VERSION 3.20) project(lithium-task VERSION 1.0.0 LANGUAGES C CXX) +# Include subdirectories add_subdirectory(simple) -# Sources +# Sources and Headers set(PROJECT_SOURCES container.cpp generator.cpp @@ -21,7 +22,6 @@ set(PROJECT_SOURCES task.cpp ) -# Headers set(PROJECT_HEADERS container.hpp generator.hpp @@ -41,26 +41,26 @@ set(PROJECT_LIBS ${CMAKE_THREAD_LIBS_INIT} ) +# Function to create a library target +function(create_library TARGET_NAME) + add_library(${TARGET_NAME} STATIC ${ARGN}) + target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${TARGET_NAME} PRIVATE ${PROJECT_LIBS}) + set_target_properties(${TARGET_NAME} PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 + OUTPUT_NAME ${TARGET_NAME} + ) +endfunction() + # Create Object Library add_library(${PROJECT_NAME}_OBJECT OBJECT ${PROJECT_SOURCES} ${PROJECT_HEADERS}) set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE ON) # Create Static Library -add_library(${PROJECT_NAME} STATIC $) - -# Include directories -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_LIBS}) - -# Set version properties -set_target_properties(${PROJECT_NAME} PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION 1 - OUTPUT_NAME ${PROJECT_NAME} -) +create_library(${PROJECT_NAME} $) # Install target install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) +) \ No newline at end of file diff --git a/tests/script/checker.cpp b/tests/script/checker.cpp new file mode 100644 index 00000000..437f64fb --- /dev/null +++ b/tests/script/checker.cpp @@ -0,0 +1,107 @@ +#include "script/checker.hpp" +#include +#include +#include + +using namespace lithium; + +class ScriptAnalyzerTest : public ::testing::Test { +protected: + void SetUp() override { + // Create a temporary config file for testing + std::ofstream configFile("test_config.json"); + configFile << R"({ + "powershell_danger_patterns": [ + {"pattern": "Remove-Item -Recurse -Force", "reason": "Dangerous command"} + ], + "windows_cmd_danger_patterns": [ + {"pattern": "del /F /Q", "reason": "Dangerous command"} + ], + "python_danger_patterns": [ + {"pattern": "import os", "reason": "Potentially dangerous import"} + ], + "ruby_danger_patterns": [ + {"pattern": "require 'open-uri'", "reason": "Potentially dangerous import"} + ], + "bash_danger_patterns": [ + {"pattern": "rm -rf /", "reason": "Dangerous command"} + ] + })"; + configFile.close(); + } + + void TearDown() override { + // Remove the temporary config file + std::remove("test_config.json"); + } +}; + +TEST_F(ScriptAnalyzerTest, LoadConfigValidFile) { + ASSERT_NO_THROW({ ScriptAnalyzer analyzer("test_config.json"); }); +} + +TEST_F(ScriptAnalyzerTest, LoadConfigInvalidFile) { + ASSERT_THROW( + { ScriptAnalyzer analyzer("invalid_config.json"); }, + std::runtime_error); +} + +TEST_F(ScriptAnalyzerTest, AnalyzePowerShellScript) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "Remove-Item -Recurse -Force"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzePythonScript) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "import os"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeRubyScript) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "require 'open-uri'"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeBashScript) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "rm -rf /"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeComplexScript) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = R"( + import os + def dangerous_function(): + os.system('rm -rf /') + )"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeScriptWithExternalCommands) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "curl http://example.com"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeScriptWithEnvironmentVariables) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "echo $HOME"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} + +TEST_F(ScriptAnalyzerTest, AnalyzeScriptWithFileOperations) { + ScriptAnalyzer analyzer("test_config.json"); + std::string script = "open('file.txt', 'r')"; + + ASSERT_NO_THROW({ analyzer.analyze(script, true, ReportFormat::JSON); }); +} diff --git a/tests/script/sheller.cpp b/tests/script/sheller.cpp new file mode 100644 index 00000000..202d2c33 --- /dev/null +++ b/tests/script/sheller.cpp @@ -0,0 +1,220 @@ +#include "script/sheller.hpp" +#include +#include +#include +#include +#include + + +using namespace lithium; + +class ScriptManagerTest : public ::testing::Test { +protected: + ScriptManager scriptManager; + + void SetUp() override { + // Setup code if needed + } + + void TearDown() override { + // Cleanup code if needed + } +}; + +TEST_F(ScriptManagerTest, RegisterScript) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_script")); + ASSERT_EQ(scripts["test_script"], script); +} + +TEST_F(ScriptManagerTest, RegisterPowerShellScript) { + Script script = "Write-Output 'Hello, World!'"; + scriptManager.registerPowerShellScript("test_ps_script", script); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_ps_script")); + ASSERT_EQ(scripts["test_ps_script"], script); +} + +TEST_F(ScriptManagerTest, DeleteScript) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.deleteScript("test_script"); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_FALSE(scripts.contains("test_script")); +} + +TEST_F(ScriptManagerTest, UpdateScript) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + Script updatedScript = "echo Updated Script"; + scriptManager.updateScript("test_script", updatedScript); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_script")); + ASSERT_EQ(scripts["test_script"], updatedScript); +} + +TEST_F(ScriptManagerTest, RunScript) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + auto result = scriptManager.runScript("test_script", {}); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(result->second, 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, RunScriptWithArgs) { + Script script = "echo $1"; + scriptManager.registerScript("test_script", script); + + std::unordered_map args = { + {"1", "Hello, World!"}}; + auto result = scriptManager.runScript("test_script", args); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(result->second, 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, RunScriptWithTimeout) { + Script script = "sleep 2 && echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + auto result = scriptManager.runScript("test_script", {}, true, + 1000); // 1 second timeout + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(result->second, -1); // Assuming -1 is the timeout status code +} + +TEST_F(ScriptManagerTest, GetScriptOutput) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.runScript("test_script", {}); + auto output = scriptManager.getScriptOutput("test_script"); + ASSERT_TRUE(output.has_value()); + ASSERT_EQ(output.value(), "Hello, World!\n"); +} + +TEST_F(ScriptManagerTest, GetScriptStatus) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.runScript("test_script", {}); + auto status = scriptManager.getScriptStatus("test_script"); + ASSERT_TRUE(status.has_value()); + ASSERT_EQ(status.value(), 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, RunScriptsSequentially) { + Script script1 = "echo Script 1"; + Script script2 = "echo Script 2"; + scriptManager.registerScript("script1", script1); + scriptManager.registerScript("script2", script2); + + std::vector< + std::pair>> + scripts = {{"script1", {}}, {"script2", {}}}; + + auto results = scriptManager.runScriptsSequentially(scripts); + ASSERT_EQ(results.size(), 2); + ASSERT_TRUE(results[0].has_value()); + ASSERT_TRUE(results[1].has_value()); + ASSERT_EQ(results[0]->second, 0); // Assuming 0 is the success status code + ASSERT_EQ(results[1]->second, 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, RunScriptsConcurrently) { + Script script1 = "echo Script 1"; + Script script2 = "echo Script 2"; + scriptManager.registerScript("script1", script1); + scriptManager.registerScript("script2", script2); + + std::vector< + std::pair>> + scripts = {{"script1", {}}, {"script2", {}}}; + + auto results = scriptManager.runScriptsConcurrently(scripts); + ASSERT_EQ(results.size(), 2); + ASSERT_TRUE(results[0].has_value()); + ASSERT_TRUE(results[1].has_value()); + ASSERT_EQ(results[0]->second, 0); // Assuming 0 is the success status code + ASSERT_EQ(results[1]->second, 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, EnableVersioning) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.enableVersioning(); + scriptManager.updateScript("test_script", "echo Updated Script"); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_script")); + ASSERT_EQ(scripts["test_script"], "echo Updated Script"); +} + +TEST_F(ScriptManagerTest, RollbackScript) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.enableVersioning(); + scriptManager.updateScript("test_script", "echo Updated Script"); + + bool rollbackSuccess = scriptManager.rollbackScript("test_script", 0); + ASSERT_TRUE(rollbackSuccess); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_script")); + ASSERT_EQ(scripts["test_script"], "echo Hello, World!"); +} + +TEST_F(ScriptManagerTest, SetScriptCondition) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.setScriptCondition("test_script", []() { return false; }); + + auto result = scriptManager.runScript("test_script", {}); + ASSERT_FALSE(result.has_value()); +} + +TEST_F(ScriptManagerTest, SetExecutionEnvironment) { + Script script = "echo $MY_ENV_VAR"; + scriptManager.registerScript("test_script", script); + + scriptManager.setExecutionEnvironment("test_script", "MY_ENV_VAR=Hello"); + + auto result = scriptManager.runScript("test_script", {}); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(result->second, 0); // Assuming 0 is the success status code +} + +TEST_F(ScriptManagerTest, SetMaxScriptVersions) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + scriptManager.setMaxScriptVersions(1); + scriptManager.updateScript("test_script", "echo Updated Script"); + + auto scripts = scriptManager.getAllScripts(); + ASSERT_TRUE(scripts.contains("test_script")); + ASSERT_EQ(scripts["test_script"], "echo Updated Script"); + + bool rollbackSuccess = scriptManager.rollbackScript("test_script", 0); + ASSERT_FALSE(rollbackSuccess); +} + +TEST_F(ScriptManagerTest, GetScriptLogs) { + Script script = "echo Hello, World!"; + scriptManager.registerScript("test_script", script); + + auto logs = scriptManager.getScriptLogs("test_script"); + ASSERT_FALSE(logs.empty()); + ASSERT_EQ(logs.back(), "Script registered/updated."); +}