feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization

This commit is contained in:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

View file

@ -0,0 +1,121 @@
using System;
using System.Threading.Tasks;
using Paca.Mobile.Core;
using Paca.Server.Gateway;
using Xunit;
namespace Paca.Tests.Mobile;
/// <summary>
/// Gate 127 ~ 132: 3G/4G/5G WAN 게이트웨이 및 Wi-Fi ↔ 셀룰러 무중단 로밍 기계적 검증
/// </summary>
public class MobileWanGatewayRoamingGateTests
{
[Fact]
public void Gate127_ConnectCode_Generation_And_Validation()
{
var code = PacaConnectCodeGenerator.GenerateCode();
Assert.NotNull(code);
Assert.StartsWith("PACA-", code);
Assert.True(PacaConnectCodeGenerator.IsValid(code));
Assert.False(PacaConnectCodeGenerator.IsValid("INVALID-CODE"));
Assert.False(PacaConnectCodeGenerator.IsValid(""));
Assert.False(PacaConnectCodeGenerator.IsValid(null));
}
[Fact]
public void Gate128_WanGatewayConfig_State_Management()
{
var gateway = new WanGatewayManager(deviceName: "Encep-Studio-PC", localPort: 52100);
// 기본 상태는 비활성
Assert.False(gateway.IsActive);
Assert.Equal(GatewayMode.Disabled, gateway.CurrentMode);
// 원격 릴레이/터널 활성화 시뮬레이션
gateway.EnableCloudTunnel("https://relay.paca.app/tunnel-9876", "PACA-884123");
Assert.True(gateway.IsActive);
Assert.Equal(GatewayMode.CloudTunnel, gateway.CurrentMode);
Assert.Equal("https://relay.paca.app/tunnel-9876", gateway.PublicEndpoint);
Assert.Equal("PACA-884123", gateway.ConnectCode);
}
[Fact]
public void Gate129_Upnp_Mapping_Profile_Creation()
{
var gateway = new WanGatewayManager(deviceName: "Encep-Studio-PC", localPort: 52100);
gateway.EnableDirectPortMapping(publicIp: "203.0.113.50", externalPort: 52100);
Assert.True(gateway.IsActive);
Assert.Equal(GatewayMode.DirectPortMapping, gateway.CurrentMode);
Assert.Equal("http://203.0.113.50:52100", gateway.PublicEndpoint);
}
[Fact]
public void Gate130_RoamingProfile_Serialization()
{
var profile = new RoamingDeviceProfile(
DeviceId: "device-uuid-1234",
DeviceName: "Encep-Desktop",
LanEndpoint: "http://192.168.0.15:52100",
WanEndpoint: "https://relay.paca.app/tunnel-9876",
AuthToken: "token-secret-abc",
ConnectCode: "PACA-884123"
);
Assert.Equal("http://192.168.0.15:52100", profile.GetEndpointFor(NetworkEnvironment.LocalWifi));
Assert.Equal("https://relay.paca.app/tunnel-9876", profile.GetEndpointFor(NetworkEnvironment.CellularWan));
}
[Fact]
public void Gate131_RoamingConnectionManager_Auto_Failover()
{
var profile = new RoamingDeviceProfile(
DeviceId: "device-uuid-1234",
DeviceName: "Encep-Desktop",
LanEndpoint: "http://192.168.0.15:52100",
WanEndpoint: "https://relay.paca.app/tunnel-9876",
AuthToken: "token-secret-abc",
ConnectCode: "PACA-884123"
);
var roaming = new RoamingConnectionManager(profile);
// 초기 Wi-Fi 상태 -> LAN 우선
roaming.UpdateNetworkState(NetworkEnvironment.LocalWifi);
Assert.Equal("http://192.168.0.15:52100", roaming.ActiveEndpoint);
Assert.False(roaming.IsRoamingOnCellular);
// LAN 연결 실패 또는 셀룰러 환경 진입 -> WAN 게이트웨이로 핫-페일오버
roaming.RecordConnectionFailure();
Assert.Equal("https://relay.paca.app/tunnel-9876", roaming.ActiveEndpoint);
Assert.True(roaming.IsRoamingOnCellular);
// Wi-Fi 재접속 및 헬스체크 복구 -> LAN 복귀
roaming.UpdateNetworkState(NetworkEnvironment.LocalWifi);
roaming.RecordConnectionSuccess();
Assert.Equal("http://192.168.0.15:52100", roaming.ActiveEndpoint);
Assert.False(roaming.IsRoamingOnCellular);
}
[Fact]
public void Gate132_RoamingConnectionManager_Fallback_When_Wan_Empty()
{
var profile = new RoamingDeviceProfile(
DeviceId: "dev-only-lan",
DeviceName: "Desktop-LAN",
LanEndpoint: "http://192.168.1.10:52100",
WanEndpoint: null, // WAN 미설정 상태
AuthToken: "tok",
ConnectCode: null
);
var roaming = new RoamingConnectionManager(profile);
roaming.UpdateNetworkState(NetworkEnvironment.CellularWan);
// WAN이 없으면 LAN 주소를 유지하되 오류 상태 경고 플래그
Assert.Equal("http://192.168.1.10:52100", roaming.ActiveEndpoint);
Assert.True(roaming.RequiresWanSetup);
}
}