mirror of
https://github.com/aydencharles/onionHEN.git
synced 2026-10-19 02:19:47 -05:00
fix(lifecycle): collect Big App on EXEC before running query
This commit is contained in:
1 parent
3fedbf4a03
commit
6950517ad8
7 files changed
+488
-19
No files matched your search
+2
-2
@@ -303,7 +303,7 @@ shellui / homebrew
|
||||
|
||||
homebrew (app jailbreak)
|
||||
└─► sandbox file …/download0/etahen_jailbreak|onionhen_jailbreak
|
||||
(SceSysCore 进程生命周期事件 + 沙盒目录 vnode 事件 + 白名单 TID)
|
||||
(SceSysCore 进程事件触发 Running Big App 补扫 + 沙盒 vnode + 白名单 TID)
|
||||
```
|
||||
|
||||
### 3.1 消息格式
|
||||
@@ -387,7 +387,7 @@ struct IPCMessage {
|
||||
- 提权与分区 remount
|
||||
- 阻止系统更新(unmount `/update`)
|
||||
- **kstuff**:fself / fpkg 相关内核能力(通常 ≥ 3.00)
|
||||
- App jailbreak(按设置启停;SceSysCore 生命周期 + 沙盒 vnode 事件 + 白名单 TID,无常驻轮询)
|
||||
- App jailbreak(按设置启停;SceSysCore 生命周期事件触发 Running Big App 补扫,再跟沙盒 vnode 与白名单 TID。EXEC 身份未就绪或 NOTE_TRACK 跟丢时短重试,无沙盒常驻扫描)
|
||||
- 休息后 Toolbox 恢复(kstuff-lite:新 ShellUI PID + trophy sprx,再按 `rest_mode.resume_reinject_delay_seconds` 等待)
|
||||
- 休息后监听套接字重绑(ps5-payload-manager:IPC / TCP `accept` 失败自愈)
|
||||
- 双守护进程架构(util 可被 daemon 拉起)
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
* Accepted names:
|
||||
* - etahen_jailbreak
|
||||
* - onionhen_jailbreak
|
||||
* 3. SceSysCore NOTE_EXEC/NOTE_EXIT events identify app lifetime. Vnode
|
||||
* events then follow sandbox -> slot -> download0 -> request file.
|
||||
* 3. SceSysCore process events identify app lifetime. NOTE_TRACK does
|
||||
* deliver the game child's NOTE_EXEC, and GetAppInfo is often already
|
||||
* filled from SysCore appParam. sceSystemServiceGetAppIdOfRunningBigApp
|
||||
* is later (after ResArbitrator). A usable EXEC identity publishes
|
||||
* immediately; otherwise the running Big App query (same path FPS uses)
|
||||
* reconciles Cdlg EXEC / SysCore FORK, with short oneshot retries and a
|
||||
* 2s fallback. Vnode events then follow sandbox -> slot -> download0 ->
|
||||
* request file.
|
||||
*
|
||||
* There is no periodic foreground-app query or sandbox scan. The only scan of
|
||||
* the 51 possible slots happens when an allowed app starts, or when the
|
||||
* sandbox root reports that one of its direct children changed.
|
||||
* There is no periodic sandbox scan. The only scan of the 51 possible slots
|
||||
* happens when an allowed app is collected, or when the sandbox root reports
|
||||
* that one of its direct children changed.
|
||||
*/
|
||||
|
||||
#include "daemon_ops.hpp"
|
||||
@@ -23,6 +29,7 @@
|
||||
|
||||
#include <onion/app_jailbreak_policy.hpp>
|
||||
#include <onion/app_lifecycle.hpp>
|
||||
#include <onion/big_app_collect_policy.hpp>
|
||||
#include <onion/platform.h>
|
||||
#include <onion/proc_query.h>
|
||||
#include <onion/settings.hpp>
|
||||
@@ -131,6 +138,8 @@ constexpr const char *kJailbreakReqNames[] = {
|
||||
};
|
||||
constexpr const char *kShellUiTitleId = "NPXS40087";
|
||||
constexpr const char *kShellUiProcessName = "SceShellUI";
|
||||
constexpr uintptr_t kReconcileBurstTimerIdent = 1;
|
||||
constexpr uintptr_t kReconcileFallbackTimerIdent = 2;
|
||||
|
||||
struct ExecIdentity {
|
||||
char process_name[64] {};
|
||||
@@ -318,25 +327,76 @@ struct TrackedBigApp {
|
||||
/** Identifies foreground Big Apps and only publishes lifecycle events. */
|
||||
class SceSysCoreAppLifecycleCollector {
|
||||
public:
|
||||
bool on_exec(pid_t pid, const ExecIdentity &id) {
|
||||
if (id.app_info_rc != 0 || id.tid.empty() || big_apps_.count(pid) != 0)
|
||||
return false;
|
||||
bool has_tracked() const { return !big_apps_.empty(); }
|
||||
|
||||
bool consider(const char *source, pid_t exec_pid, const ExecIdentity *id) {
|
||||
std::string current_title_id;
|
||||
int current_app_id = -1;
|
||||
if (!Get_Running_App_TID(current_title_id, current_app_id) ||
|
||||
current_app_id < 0 ||
|
||||
id.info.app_id != static_cast<uint32_t>(current_app_id) ||
|
||||
id.tid != current_title_id || get_game_pid() != pid)
|
||||
const bool query_ok = Get_Running_App_TID(current_title_id, current_app_id);
|
||||
const pid_t running_pid = query_ok ? get_game_pid() : -1;
|
||||
|
||||
onion::lifecycle::ExecSnapshot exec;
|
||||
exec.pid = exec_pid;
|
||||
if (id != nullptr) {
|
||||
exec.app_info_rc = id->app_info_rc;
|
||||
exec.app_id = id->info.app_id;
|
||||
exec.title_id = id->tid;
|
||||
exec.already_tracked = exec_pid > 1 && big_apps_.count(exec_pid) != 0;
|
||||
}
|
||||
|
||||
onion::lifecycle::RunningBigAppSnapshot running;
|
||||
running.query_ok = query_ok;
|
||||
running.pid = running_pid;
|
||||
running.app_id = current_app_id;
|
||||
running.title_id = current_title_id;
|
||||
const bool running_tracked =
|
||||
running_pid > 1 && big_apps_.count(running_pid) != 0;
|
||||
|
||||
const onion::lifecycle::BigAppCollectDecision decision =
|
||||
onion::lifecycle::decide_big_app_started(exec, running,
|
||||
running_tracked);
|
||||
if (decision.action !=
|
||||
onion::lifecycle::BigAppCollectAction::PublishStarted) {
|
||||
const bool quiet =
|
||||
std::strcmp(source, "timer") == 0 &&
|
||||
(decision.reason ==
|
||||
onion::lifecycle::BigAppCollectReason::RunningQueryNotReady ||
|
||||
decision.reason ==
|
||||
onion::lifecycle::BigAppCollectReason::AlreadyTracked);
|
||||
if (quiet) {
|
||||
LOG_TRACE("[lifecycle] collect skip source=%s reason=%s exec_pid=%d "
|
||||
"running_pid=%d",
|
||||
source,
|
||||
onion::lifecycle::big_app_collect_reason_name(
|
||||
decision.reason),
|
||||
static_cast<int>(exec_pid), static_cast<int>(running_pid));
|
||||
} else {
|
||||
LOG_DEBUG("[lifecycle] collect skip source=%s reason=%s exec_pid=%d "
|
||||
"exec_tid=%s running_pid=%d running_tid=%s query_ok=%d",
|
||||
source,
|
||||
onion::lifecycle::big_app_collect_reason_name(
|
||||
decision.reason),
|
||||
static_cast<int>(exec_pid),
|
||||
id != nullptr ? id->tid.c_str() : "-",
|
||||
static_cast<int>(running_pid),
|
||||
current_title_id.empty() ? "-" : current_title_id.c_str(),
|
||||
query_ok ? 1 : 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!onion::daemon::app_lifecycle::publish_big_app_started(
|
||||
pid, id.info.app_id, id.tid))
|
||||
decision.pid, decision.app_id, decision.title_id))
|
||||
return false;
|
||||
|
||||
big_apps_[pid] = {id.info.app_id, id.tid};
|
||||
LOG_INFO("[lifecycle] Big App started pid=%d appid=%u tid=%s",
|
||||
static_cast<int>(pid), id.info.app_id, id.tid.c_str());
|
||||
const std::string started_tid(decision.title_id);
|
||||
big_apps_[decision.pid] = {decision.app_id, started_tid};
|
||||
LOG_INFO("[lifecycle] Big App started pid=%d appid=%u tid=%s via=%s "
|
||||
"source=%s",
|
||||
static_cast<int>(decision.pid), decision.app_id,
|
||||
started_tid.c_str(),
|
||||
onion::lifecycle::big_app_collect_reason_name(decision.reason),
|
||||
source);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -402,6 +462,10 @@ public:
|
||||
static_cast<long long>(event.data));
|
||||
continue;
|
||||
}
|
||||
if (event.filter == EVFILT_TIMER) {
|
||||
handle_reconcile_timer(event);
|
||||
continue;
|
||||
}
|
||||
if (event.filter == EVFILT_PROC && !handle_process_event(event))
|
||||
return;
|
||||
}
|
||||
@@ -441,6 +505,14 @@ private:
|
||||
|
||||
LOG_INFO("[lifecycle] SceSysCore listener active pid=%d",
|
||||
static_cast<int>(syscore_pid_));
|
||||
|
||||
EV_SET(&event, kReconcileFallbackTimerIdent, EVFILT_TIMER,
|
||||
EV_ADD | EV_ENABLE, 0, onion::lifecycle::kBigAppReconcileFallbackMs,
|
||||
nullptr);
|
||||
if (kevent(kq_, &event, 1, nullptr, 0, nullptr) != 0) {
|
||||
LOG_WARN("[lifecycle] Big App fallback timer failed: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -452,6 +524,12 @@ private:
|
||||
|
||||
bool handle_process_event(const struct kevent &event) {
|
||||
const pid_t pid = static_cast<pid_t>(event.ident);
|
||||
if (event.fflags & NOTE_TRACKERR) {
|
||||
LOG_WARN("[lifecycle] NOTE_TRACKERR pid=%d child=%lld",
|
||||
static_cast<int>(pid), static_cast<long long>(event.data));
|
||||
}
|
||||
|
||||
bool spawn_activity = false;
|
||||
if (event.fflags & NOTE_EXEC) {
|
||||
const ExecIdentity id = read_exec_identity(pid);
|
||||
if (identity_is_shellui(id)) {
|
||||
@@ -459,8 +537,15 @@ private:
|
||||
static_cast<int>(pid));
|
||||
toolbox_on_new_shellui(pid);
|
||||
}
|
||||
(void)collector_.on_exec(pid, id);
|
||||
spawn_activity = true;
|
||||
if (collector_.consider("exec", pid, &id))
|
||||
disarm_burst_timer();
|
||||
} else if (event.fflags & (NOTE_FORK | NOTE_CHILD)) {
|
||||
spawn_activity = true;
|
||||
if (collector_.consider("fork", pid, nullptr))
|
||||
disarm_burst_timer();
|
||||
}
|
||||
|
||||
if (event.fflags & NOTE_EXIT) {
|
||||
if (onion::lifecycle::ProcessExitPolicy::should_stop_listener(
|
||||
syscore_pid_, pid)) {
|
||||
@@ -469,12 +554,54 @@ private:
|
||||
}
|
||||
(void)collector_.on_exit(pid);
|
||||
}
|
||||
|
||||
if (spawn_activity && !collector_.has_tracked())
|
||||
arm_burst_timer(/*restart=*/true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void handle_reconcile_timer(const struct kevent &event) {
|
||||
if (collector_.consider("timer", -1, nullptr)) {
|
||||
disarm_burst_timer();
|
||||
return;
|
||||
}
|
||||
if (event.ident == kReconcileBurstTimerIdent)
|
||||
arm_burst_timer(/*restart=*/false);
|
||||
}
|
||||
|
||||
void arm_burst_timer(bool restart) {
|
||||
if (kq_ < 0)
|
||||
return;
|
||||
if (restart)
|
||||
burst_index_ = 0;
|
||||
if (burst_index_ >= onion::lifecycle::kBigAppReconcileBurstCount)
|
||||
return;
|
||||
|
||||
struct kevent event;
|
||||
EV_SET(&event, kReconcileBurstTimerIdent, EVFILT_TIMER,
|
||||
EV_ADD | EV_ENABLE | EV_ONESHOT, 0,
|
||||
onion::lifecycle::kBigAppReconcileBurstMs[burst_index_], nullptr);
|
||||
if (kevent(kq_, &event, 1, nullptr, 0, nullptr) != 0) {
|
||||
LOG_WARN("[lifecycle] Big App burst timer failed: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
++burst_index_;
|
||||
}
|
||||
|
||||
void disarm_burst_timer() {
|
||||
burst_index_ = onion::lifecycle::kBigAppReconcileBurstCount;
|
||||
if (kq_ < 0)
|
||||
return;
|
||||
struct kevent event;
|
||||
EV_SET(&event, kReconcileBurstTimerIdent, EVFILT_TIMER, EV_DELETE, 0, 0,
|
||||
nullptr);
|
||||
(void)kevent(kq_, &event, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
int control_read_fd_ = -1;
|
||||
int kq_ = -1;
|
||||
pid_t syscore_pid_ = -1;
|
||||
int burst_index_ = onion::lifecycle::kBigAppReconcileBurstCount;
|
||||
SceSysCoreAppLifecycleCollector collector_;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/* Copyright (C) 2026 OnionHEN / LightningMods
|
||||
*
|
||||
* Decide when a SysCore process event should publish BigAppStarted.
|
||||
*
|
||||
* NOTE_TRACK does deliver the game child's NOTE_EXEC. GetAppInfo is often
|
||||
* already filled from SysCore appParam at that instant, but
|
||||
* sceSystemServiceGetAppIdOfRunningBigApp is not: ResArbitrator registers
|
||||
* the Big App after EXEC. Prefer a usable running-Big-App query when it is
|
||||
* ready (Cdlg EXEC, SysCore FORK). Otherwise publish from a non-system EXEC
|
||||
* identity instead of waiting for the reconcile timer.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace onion::lifecycle {
|
||||
|
||||
enum class BigAppCollectAction {
|
||||
Ignore,
|
||||
PublishStarted,
|
||||
};
|
||||
|
||||
enum class BigAppCollectReason {
|
||||
AlreadyTracked,
|
||||
ExecNotReady,
|
||||
ExecNotRunningBigApp,
|
||||
RunningQueryNotReady,
|
||||
RunningPidInvalid,
|
||||
PublishFromExec,
|
||||
PublishFromRunning,
|
||||
};
|
||||
|
||||
struct ExecSnapshot {
|
||||
pid_t pid = -1;
|
||||
int app_info_rc = -1;
|
||||
uint32_t app_id = 0;
|
||||
std::string_view title_id;
|
||||
bool already_tracked = false;
|
||||
};
|
||||
|
||||
struct RunningBigAppSnapshot {
|
||||
bool query_ok = false;
|
||||
pid_t pid = -1;
|
||||
int app_id = -1;
|
||||
std::string_view title_id;
|
||||
};
|
||||
|
||||
struct BigAppCollectDecision {
|
||||
BigAppCollectAction action = BigAppCollectAction::Ignore;
|
||||
BigAppCollectReason reason = BigAppCollectReason::RunningQueryNotReady;
|
||||
pid_t pid = -1;
|
||||
uint32_t app_id = 0;
|
||||
std::string_view title_id;
|
||||
};
|
||||
|
||||
inline constexpr int kBigAppReconcileBurstMs[] = {100, 300, 1000};
|
||||
inline constexpr int kBigAppReconcileBurstCount =
|
||||
static_cast<int>(sizeof(kBigAppReconcileBurstMs) /
|
||||
sizeof(kBigAppReconcileBurstMs[0]));
|
||||
inline constexpr int kBigAppReconcileFallbackMs = 2000;
|
||||
|
||||
inline bool running_snapshot_usable(const RunningBigAppSnapshot &running) {
|
||||
return running.query_ok && running.pid > 1 && running.app_id >= 0 &&
|
||||
!running.title_id.empty();
|
||||
}
|
||||
|
||||
inline bool exec_snapshot_usable(const ExecSnapshot &exec) {
|
||||
return exec.pid > 1 && exec.app_info_rc == 0 && !exec.title_id.empty() &&
|
||||
!exec.already_tracked;
|
||||
}
|
||||
|
||||
inline bool is_system_app_title(std::string_view title_id) {
|
||||
return title_id.size() >= 4 && title_id.compare(0, 4, "NPXS") == 0;
|
||||
}
|
||||
|
||||
inline const char *big_app_collect_reason_name(BigAppCollectReason reason) {
|
||||
switch (reason) {
|
||||
case BigAppCollectReason::AlreadyTracked:
|
||||
return "already-tracked";
|
||||
case BigAppCollectReason::ExecNotReady:
|
||||
return "exec-not-ready";
|
||||
case BigAppCollectReason::ExecNotRunningBigApp:
|
||||
return "exec-not-running-big-app";
|
||||
case BigAppCollectReason::RunningQueryNotReady:
|
||||
return "running-query-not-ready";
|
||||
case BigAppCollectReason::RunningPidInvalid:
|
||||
return "running-pid-invalid";
|
||||
case BigAppCollectReason::PublishFromExec:
|
||||
return "exec";
|
||||
case BigAppCollectReason::PublishFromRunning:
|
||||
return "running";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
inline BigAppCollectDecision
|
||||
decide_big_app_started(const ExecSnapshot &exec,
|
||||
const RunningBigAppSnapshot &running,
|
||||
bool running_pid_already_tracked) {
|
||||
BigAppCollectDecision decision;
|
||||
|
||||
if (running_snapshot_usable(running)) {
|
||||
decision.pid = running.pid;
|
||||
decision.app_id = static_cast<uint32_t>(running.app_id);
|
||||
decision.title_id = running.title_id;
|
||||
if (running_pid_already_tracked) {
|
||||
decision.action = BigAppCollectAction::Ignore;
|
||||
decision.reason = BigAppCollectReason::AlreadyTracked;
|
||||
return decision;
|
||||
}
|
||||
decision.action = BigAppCollectAction::PublishStarted;
|
||||
const bool exec_matches =
|
||||
exec.pid == running.pid && exec.app_info_rc == 0 &&
|
||||
!exec.title_id.empty() && exec.title_id == running.title_id &&
|
||||
exec.app_id == static_cast<uint32_t>(running.app_id);
|
||||
decision.reason = exec_matches ? BigAppCollectReason::PublishFromExec
|
||||
: BigAppCollectReason::PublishFromRunning;
|
||||
return decision;
|
||||
}
|
||||
|
||||
if (exec_snapshot_usable(exec) && !is_system_app_title(exec.title_id)) {
|
||||
decision.action = BigAppCollectAction::PublishStarted;
|
||||
decision.reason = BigAppCollectReason::PublishFromExec;
|
||||
decision.pid = exec.pid;
|
||||
decision.app_id = exec.app_id;
|
||||
decision.title_id = exec.title_id;
|
||||
return decision;
|
||||
}
|
||||
|
||||
decision.pid = exec.pid;
|
||||
decision.app_id = exec.app_id;
|
||||
decision.title_id = exec.title_id;
|
||||
decision.action = BigAppCollectAction::Ignore;
|
||||
if (exec.already_tracked) {
|
||||
decision.reason = BigAppCollectReason::AlreadyTracked;
|
||||
} else if (exec_snapshot_usable(exec) &&
|
||||
is_system_app_title(exec.title_id)) {
|
||||
decision.reason = BigAppCollectReason::ExecNotRunningBigApp;
|
||||
} else if (!running.query_ok) {
|
||||
decision.reason = BigAppCollectReason::RunningQueryNotReady;
|
||||
} else if (running.pid <= 1) {
|
||||
decision.reason = BigAppCollectReason::RunningPidInvalid;
|
||||
} else {
|
||||
decision.reason = BigAppCollectReason::ExecNotReady;
|
||||
}
|
||||
return decision;
|
||||
}
|
||||
|
||||
} // namespace onion::lifecycle
|
||||
@@ -138,6 +138,7 @@ TEST_CXX_SRCS := \
|
||||
test_settings.cpp \
|
||||
test_msg_protocol.cpp \
|
||||
test_app_jailbreak_policy.cpp \
|
||||
test_big_app_collect_policy.cpp \
|
||||
test_debug_settings_route_policy.cpp \
|
||||
test_ipc_harden.cpp \
|
||||
test_ps5_settings_ui.cpp \
|
||||
|
||||
@@ -56,6 +56,7 @@ Binary: `source/util/build/host-tests/onion-host-tests`
|
||||
| `test_msg_protocol` | IPC paths, magic, command ordinals, `IPC_Ret`, message POD, reply JSON body |
|
||||
| `test_util_language` | system-language cache/refresh and notification language selection |
|
||||
| `test_app_jailbreak_policy` | configurable app-jailbreak exact/prefix Title ID allowlist, including the Itemzflow compatibility ID `ITEM00001` |
|
||||
| `test_big_app_collect_policy` | Big App start collection: EXEC identity can publish before Running Big App is registered; Cdlg EXEC reconciles the homebrew pid |
|
||||
| `test_ps5_settings_ui` | fluent XML builder + escaping |
|
||||
| `test_toolbox_route` | resource → page routing + dynamic cheat enabled-state and Kstuff descriptors |
|
||||
| `test_toolbox_i18n` | locale-key parity for toolbox groups (zh-Hans, en) |
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "test_harness.h"
|
||||
|
||||
#include <onion/big_app_collect_policy.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
using onion::lifecycle::BigAppCollectAction;
|
||||
using onion::lifecycle::BigAppCollectReason;
|
||||
using onion::lifecycle::decide_big_app_started;
|
||||
using onion::lifecycle::ExecSnapshot;
|
||||
using onion::lifecycle::RunningBigAppSnapshot;
|
||||
|
||||
int test_publish_when_exec_is_running_big_app(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 179;
|
||||
exec.app_info_rc = 0;
|
||||
exec.app_id = 32792;
|
||||
exec.title_id = "LAPY20011";
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
running.query_ok = true;
|
||||
running.pid = 179;
|
||||
running.app_id = 32792;
|
||||
running.title_id = "LAPY20011";
|
||||
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::PublishStarted);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::PublishFromExec);
|
||||
TEST_ASSERT_EQ_INT(179, static_cast<int>(decision.pid));
|
||||
TEST_ASSERT_EQ_INT(32792, static_cast<int>(decision.app_id));
|
||||
TEST_ASSERT_TRUE(decision.title_id == "LAPY20011");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_reconcile_cdlg_exec_to_running_homebrew(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 180;
|
||||
exec.app_info_rc = 0;
|
||||
exec.app_id = 32793;
|
||||
exec.title_id = "NPXS40093";
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
running.query_ok = true;
|
||||
running.pid = 179;
|
||||
running.app_id = 32792;
|
||||
running.title_id = "LAPY20011";
|
||||
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::PublishStarted);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::PublishFromRunning);
|
||||
TEST_ASSERT_EQ_INT(179, static_cast<int>(decision.pid));
|
||||
TEST_ASSERT_TRUE(decision.title_id == "LAPY20011");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_reconcile_when_exec_identity_not_ready(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 179;
|
||||
exec.app_info_rc = -1;
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
running.query_ok = true;
|
||||
running.pid = 179;
|
||||
running.app_id = 32792;
|
||||
running.title_id = "LAPY20011";
|
||||
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::PublishStarted);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::PublishFromRunning);
|
||||
TEST_ASSERT_EQ_INT(179, static_cast<int>(decision.pid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_ignore_already_tracked_running_pid(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 179;
|
||||
exec.app_info_rc = 0;
|
||||
exec.app_id = 32792;
|
||||
exec.title_id = "LAPY20011";
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
running.query_ok = true;
|
||||
running.pid = 179;
|
||||
running.app_id = 32792;
|
||||
running.title_id = "LAPY20011";
|
||||
|
||||
const auto decision = decide_big_app_started(exec, running, true);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::Ignore);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::AlreadyTracked);
|
||||
TEST_ASSERT_EQ_INT(179, static_cast<int>(decision.pid));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_publish_exec_when_running_query_not_ready(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 99;
|
||||
exec.app_info_rc = 0;
|
||||
exec.app_id = 24;
|
||||
exec.title_id = "LAPY20011";
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::PublishStarted);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::PublishFromExec);
|
||||
TEST_ASSERT_EQ_INT(99, static_cast<int>(decision.pid));
|
||||
TEST_ASSERT_TRUE(decision.title_id == "LAPY20011");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_skip_fork_until_identity_or_running_query(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 99;
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::Ignore);
|
||||
TEST_ASSERT_TRUE(decision.reason ==
|
||||
BigAppCollectReason::RunningQueryNotReady);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_skip_system_exec_until_running_query(void) {
|
||||
ExecSnapshot exec;
|
||||
exec.pid = 100;
|
||||
exec.app_info_rc = 0;
|
||||
exec.app_id = 25;
|
||||
exec.title_id = "NPXS40093";
|
||||
|
||||
RunningBigAppSnapshot running;
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::Ignore);
|
||||
TEST_ASSERT_TRUE(decision.reason ==
|
||||
BigAppCollectReason::ExecNotRunningBigApp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_skip_when_running_pid_invalid(void) {
|
||||
ExecSnapshot exec;
|
||||
RunningBigAppSnapshot running;
|
||||
running.query_ok = true;
|
||||
running.pid = -1;
|
||||
running.app_id = 32792;
|
||||
running.title_id = "LAPY20011";
|
||||
|
||||
const auto decision = decide_big_app_started(exec, running, false);
|
||||
TEST_ASSERT_TRUE(decision.action == BigAppCollectAction::Ignore);
|
||||
TEST_ASSERT_TRUE(decision.reason == BigAppCollectReason::RunningPidInvalid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_reconcile_retry_delays(void) {
|
||||
TEST_ASSERT_EQ_INT(3, onion::lifecycle::kBigAppReconcileBurstCount);
|
||||
TEST_ASSERT_EQ_INT(100, onion::lifecycle::kBigAppReconcileBurstMs[0]);
|
||||
TEST_ASSERT_EQ_INT(300, onion::lifecycle::kBigAppReconcileBurstMs[1]);
|
||||
TEST_ASSERT_EQ_INT(1000, onion::lifecycle::kBigAppReconcileBurstMs[2]);
|
||||
TEST_ASSERT_EQ_INT(2000, onion::lifecycle::kBigAppReconcileFallbackMs);
|
||||
TEST_ASSERT_STREQ("running", onion::lifecycle::big_app_collect_reason_name(
|
||||
BigAppCollectReason::PublishFromRunning));
|
||||
TEST_ASSERT_STREQ("exec", onion::lifecycle::big_app_collect_reason_name(
|
||||
BigAppCollectReason::PublishFromExec));
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" int test_big_app_collect_policy_suite(void) {
|
||||
int failures = 0;
|
||||
failures += onion_test_run("big_app_collect.exec_matches_running",
|
||||
test_publish_when_exec_is_running_big_app);
|
||||
failures += onion_test_run("big_app_collect.cdlg_reconciles_homebrew",
|
||||
test_reconcile_cdlg_exec_to_running_homebrew);
|
||||
failures += onion_test_run("big_app_collect.exec_identity_not_ready",
|
||||
test_reconcile_when_exec_identity_not_ready);
|
||||
failures += onion_test_run("big_app_collect.already_tracked",
|
||||
test_ignore_already_tracked_running_pid);
|
||||
failures += onion_test_run("big_app_collect.exec_before_running_query",
|
||||
test_publish_exec_when_running_query_not_ready);
|
||||
failures += onion_test_run("big_app_collect.fork_without_identity",
|
||||
test_skip_fork_until_identity_or_running_query);
|
||||
failures += onion_test_run("big_app_collect.system_exec_without_running",
|
||||
test_skip_system_exec_until_running_query);
|
||||
failures += onion_test_run("big_app_collect.running_pid_invalid",
|
||||
test_skip_when_running_pid_invalid);
|
||||
failures += onion_test_run("big_app_collect.retry_delays",
|
||||
test_reconcile_retry_delays);
|
||||
return failures;
|
||||
}
|
||||
@@ -26,6 +26,7 @@ extern "C" int test_platform_notify_suite(void);
|
||||
extern "C" int test_util_language_suite(void);
|
||||
extern "C" int test_msg_protocol_suite(void);
|
||||
extern "C" int test_app_jailbreak_policy_suite(void);
|
||||
extern "C" int test_big_app_collect_policy_suite(void);
|
||||
extern "C" int test_debug_settings_route_policy_suite(void);
|
||||
extern "C" int test_ipc_harden_suite(void);
|
||||
extern "C" int test_toolbox_injection_suite(void);
|
||||
@@ -80,6 +81,7 @@ int main() {
|
||||
failures += test_util_language_suite();
|
||||
failures += test_msg_protocol_suite();
|
||||
failures += test_app_jailbreak_policy_suite();
|
||||
failures += test_big_app_collect_policy_suite();
|
||||
failures += test_debug_settings_route_policy_suite();
|
||||
failures += test_ipc_harden_suite();
|
||||
failures += test_toolbox_injection_suite();
|
||||
|
||||
Reference in new issue
Block a user