releases/tests/Paca.Tests/Browser/PacaUniqueBrowserFeaturesGateTests.cs

206 lines
8.5 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Paca.Core;
using Xunit;
namespace Paca.Tests.Browser;
/// <summary>
/// 크롬/파이어폭스 대비 Paca만의 초강력 차별화 브라우저 10대 기능 및 진짜 파비콘 게이트 (Gate 136 ~ Gate 145)
/// </summary>
public class PacaUniqueBrowserFeaturesGateTests
{
[Fact]
public void Gate136_RealFaviconFetcher_FallbackLadder_Audit()
{
var fetcher = new RealFaviconFetcher();
// 1. HTML 내에 고해상도 apple-touch-icon 이 있는 경우 최우선 추출
var htmlWithApple = @"<html><head>
<link rel='icon' href='/favicon.ico'>
<link rel='apple-touch-icon' sizes='180x180' href='/icons/apple-180.png'>
</head></html>";
var iconUrl = fetcher.ExtractBestFaviconUrl("https://example.com/page", htmlWithApple);
Assert.Equal("https://example.com/icons/apple-180.png", iconUrl);
// 2. 일반 link rel='icon' 만 있는 경우
var htmlWithRelIcon = @"<html><head><link rel='icon' href='/static/icon.png'></head></html>";
var relIconUrl = fetcher.ExtractBestFaviconUrl("https://example.com/page", htmlWithRelIcon);
Assert.Equal("https://example.com/static/icon.png", relIconUrl);
// 3. HTML 에 아이콘 태그가 전혀 없는 경우 -> 도메인 루트 /favicon.ico 로 폴백
var emptyHtml = "<html><head><title>No Icon</title></head></html>";
var fallbackUrl = fetcher.ExtractBestFaviconUrl("https://myblog.org/sub/article", emptyHtml);
Assert.Equal("https://myblog.org/favicon.ico", fallbackUrl);
}
[Fact]
public void Gate137_SmartMediaSnifferV2_StreamDetection_Audit()
{
var sniffer = new SmartMediaSnifferV2();
// 일반 웹 리소스는 무시
Assert.Null(sniffer.SniffRequest("https://example.com/style.css", "text/css"));
Assert.Null(sniffer.SniffRequest("https://example.com/script.js", "application/javascript"));
// HLS m3u8 스트림 감지
var hls = sniffer.SniffRequest("https://stream.cdn.com/live/playlist.m3u8", "application/vnd.apple.mpegurl");
Assert.NotNull(hls);
Assert.Equal(SniffedMediaType.HlsStream, hls.Type);
// DASH mpd 스트림 감지
var dash = sniffer.SniffRequest("https://stream.cdn.com/dash/manifest.mpd", "application/dash+xml");
Assert.NotNull(dash);
Assert.Equal(SniffedMediaType.DashStream, dash.Type);
// 직접 MP4 비디오 감지
var mp4 = sniffer.SniffRequest("https://video.org/file.mp4?token=abc", "video/mp4");
Assert.NotNull(mp4);
Assert.Equal(SniffedMediaType.DirectVideo, mp4.Type);
}
[Fact]
public void Gate138_AntiTrackingFingerprintGuard_Audit()
{
var guard = new AntiTrackingFingerprintGuard();
Assert.True(guard.IsTrackingDomain("google-analytics.com"));
Assert.True(guard.IsTrackingDomain("stats.doubleclick.net"));
Assert.True(guard.IsTrackingDomain("connect.facebook.net"));
Assert.False(guard.IsTrackingDomain("youtube.com"));
// Canvas 핑거프린팅 방어 노이즈 스크립트 생성 확인
var noiseScript = guard.GenerateCanvasNoiseScript();
Assert.Contains("HTMLCanvasElement.prototype.toDataURL", noiseScript);
Assert.Contains("getImageData", noiseScript);
}
[Fact]
public void Gate139_ReaderModeExtractor_CleanArticle_Audit()
{
var extractor = new ReaderModeExtractor();
var messyHtml = @"
<html>
<body>
<header><nav>Menu 1 Menu 2</nav></header>
<div class='sidebar'>Banner Ads</div>
<article>
<h1>The Future of Video Browsers</h1>
<p>Paca browser provides built-in media streaming intelligence without third-party extensions.</p>
<p>It respects user privacy and eliminates bloated telemetry.</p>
</article>
<footer>Copyright 2026</footer>
</body>
</html>";
var article = extractor.ExtractArticle(messyHtml);
Assert.NotNull(article);
Assert.Equal("The Future of Video Browsers", article.Title);
Assert.Contains("Paca browser provides built-in", article.CleanText);
Assert.DoesNotContain("Banner Ads", article.CleanText);
Assert.DoesNotContain("Menu 1", article.CleanText);
}
[Fact]
public void Gate140_VideoPiPOverlayController_ForcePiP_Audit()
{
var pip = new VideoPiPOverlayController();
var bypassScript = pip.GenerateForcePiPScript();
// 사이트의 disablePictureInPicture 속성 무력화 스크립트
Assert.Contains("disablePictureInPicture", bypassScript);
Assert.Contains("requestPictureInPicture", bypassScript);
}
[Fact]
public void Gate141_SpeedBoostTurboCache_Prefetch_Audit()
{
var cache = new SpeedBoostTurboCache();
Assert.Equal(0, cache.PreloadedCount);
cache.RegisterPrefetchTarget("https://example.com/next-video-page");
Assert.Equal(1, cache.PreloadedCount);
Assert.True(cache.IsPrefetched("https://example.com/next-video-page"));
Assert.False(cache.IsPrefetched("https://example.com/random-page"));
}
[Fact]
public void Gate142_OneClickAudioExtractor_AudioOnlyStreamFilter_Audit()
{
var extractor = new OneClickAudioExtractor();
var streams = new List<MediaStreamTrackInfo>
{
new("v1", "video", "1080p 60fps", 6000),
new("v2", "video", "720p", 3000),
new("a1", "audio", "AAC 128k", 128),
new("a2", "audio", "Opus 192k High-Res", 192)
};
var bestAudio = extractor.SelectHighestQualityAudioTrack(streams);
Assert.NotNull(bestAudio);
Assert.Equal("a2", bestAudio.TrackId);
Assert.Equal("Opus 192k High-Res", bestAudio.FormatLabel);
}
[Fact]
public void Gate143_CrossPlatformTabHandshake_Payload_Audit()
{
var handshake = new CrossPlatformTabHandshake();
var packet = handshake.CreatePushPacket(
sourceDeviceId: "GALAXY-Z-FOLD-6",
sourcePlatform: "Android",
targetDeviceId: "DESKTOP-PACA-WIN",
pageUrl: "https://www.youtube.com/watch?v=sample123",
pageTitle: "Epic 4K Nature",
scrollPositionRatio: 0.42
);
Assert.Equal("PACA_TAB_PUSH_V1", packet.ProtocolHeader);
Assert.Equal("Android", packet.SourcePlatform);
Assert.Equal(0.42, packet.ScrollPositionRatio);
var restored = handshake.ParsePushPacket(handshake.Serialize(packet));
Assert.NotNull(restored);
Assert.Equal("Epic 4K Nature", restored.PageTitle);
Assert.Equal("https://www.youtube.com/watch?v=sample123", restored.PageUrl);
}
[Fact]
public void Gate144_AutoFillFormSecureVault_MasterKey_Audit()
{
var vault = new AutoFillFormSecureVault();
var masterKey = "MyMasterPassword2026!";
vault.SaveCredential("https://github.com/login", "pacadev", "SecretP@ss!", masterKey);
var retrieved = vault.RetrieveCredential("https://github.com/login", masterKey);
Assert.NotNull(retrieved);
Assert.Equal("pacadev", retrieved.Username);
Assert.Equal("SecretP@ss!", retrieved.Password);
// 잘못된 비밀번호 시도 시 복호화 실패(null)
var failed = vault.RetrieveCredential("https://github.com/login", "WrongPassword");
Assert.Null(failed);
}
[Fact]
public void Gate145_EndToEndInteractiveJourneyAudit_Audit()
{
// Favicon 추출 -> 스니핑 -> 읽기모드 -> PiP 스크립트 -> 오디오 분리 -> 탭 푸시 전체 파이프라인
var fetcher = new RealFaviconFetcher();
var sniffer = new SmartMediaSnifferV2();
var extractor = new OneClickAudioExtractor();
var handshake = new CrossPlatformTabHandshake();
var sampleHtml = "<html><head><link rel='apple-touch-icon' href='/paca.png'></head><body><article><h1>Title</h1><p>Body</p></article></body></html>";
var faviconUrl = fetcher.ExtractBestFaviconUrl("https://paca.tv/watch/1", sampleHtml);
Assert.Equal("https://paca.tv/paca.png", faviconUrl);
var stream = sniffer.SniffRequest("https://paca.tv/live.m3u8", "application/x-mpegURL");
Assert.NotNull(stream);
var pushPacket = handshake.CreatePushPacket("PC", "Windows", "Mobile", "https://paca.tv/watch/1", "Title", 0.5);
Assert.Equal("PACA_TAB_PUSH_V1", pushPacket.ProtocolHeader);
}
}