package service import ( "testing" ) // A background (non-forced) restart — the pending-config-change cron, warp/ldap/ // outbound reconcile jobs — must not revive an Xray the admin deliberately // stopped. Only an explicit forced restart clears the manual-stop state. func TestRestartXrayRespectsManualStop(t *testing.T) { setupSettingTestDB(t) if err := (&SettingService{}).saveSetting("xrayTemplateConfig", "{ not valid json"); err != nil { t.Fatalf("seed template: %v", err) } t.Cleanup(func() { isManuallyStopped.Store(false) }) isManuallyStopped.Store(true) _ = (&XrayService{}).RestartXray(false) if !isManuallyStopped.Load() { t.Fatal("a non-forced restart cleared a deliberate manual stop and would revive xray") } } // When the pending-restart reconcile consumes the need-restart flag but the // restart itself fails, the flag must be re-armed so the config change is // retried rather than silently dropped. func TestApplyPendingRestartReArmsFlagOnFailure(t *testing.T) { setupSettingTestDB(t) if err := (&SettingService{}).saveSetting("xrayTemplateConfig", "{ not valid json"); err != nil { t.Fatalf("seed template: %v", err) } t.Cleanup(func() { isManuallyStopped.Store(false) isNeedXrayRestart.Store(false) }) isManuallyStopped.Store(false) svc := &XrayService{} svc.SetToNeedRestart() svc.ApplyPendingRestart() if !isNeedXrayRestart.Load() { t.Fatal("a failed restart must re-arm the need-restart flag so the pending config change is retried") } }