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,82 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Paca.Mobile.Core;
using Xunit;
namespace Paca.Tests.Mobile;
/// <summary>
/// 모바일 미디어 라이브러리 고속 무결성 검증 및 포맷 헤더 분석 게이트 (Gate 191 ~ Gate 194)
/// </summary>
public class MobileMediaIntegrityGateTests
{
[Fact]
public void Gate191_ValidateMediaHeader_Mp4_FtypBox_Audit()
{
// MP4 컨테이너: 0~3 offset box size, 4~7 offset 'ftyp'
var mp4ValidHeader = new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D };
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(mp4ValidHeader, ".mp4"));
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(mp4ValidHeader, "video.m4a"));
var invalidHeader = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x41, 0x42, 0x43, 0x44 };
Assert.False(MediaIntegrityVerifier.ValidateMediaHeader(invalidHeader, ".mp4"));
}
[Fact]
public void Gate192_ValidateMediaHeader_Webm_Ebml_Audit()
{
// WebM / MKV EBML Header: 0x1A, 0x45, 0xDF, 0xA3
var webmHeader = new byte[] { 0x1A, 0x45, 0xDF, 0xA3, 0x9F, 0x42, 0x86, 0x81 };
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(webmHeader, ".webm"));
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(webmHeader, "sample.mkv"));
var corruptedHeader = new byte[] { 0x1A, 0x45, 0x00, 0x00 };
Assert.False(MediaIntegrityVerifier.ValidateMediaHeader(corruptedHeader, ".webm"));
}
[Fact]
public void Gate193_ValidateMediaHeader_Mp3_Id3_And_FrameSync_Audit()
{
// MP3 ID3v2: 'ID3' (0x49, 0x44, 0x33)
var id3Header = new byte[] { 0x49, 0x44, 0x33, 0x04, 0x00, 0x00, 0x00, 0x00 };
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(id3Header, ".mp3"));
// MP3 Sync Word: 0xFF, 0xFB
var syncHeader = new byte[] { 0xFF, 0xFB, 0x90, 0x64 };
Assert.True(MediaIntegrityVerifier.ValidateMediaHeader(syncHeader, ".mp3"));
var badMp3 = new byte[] { 0x00, 0x11, 0x22, 0x33 };
Assert.False(MediaIntegrityVerifier.ValidateMediaHeader(badMp3, ".mp3"));
}
[Fact]
public void Gate194_InspectIntegrity_FullPayload_Audit()
{
// 유효한 mp4 가짜 데이터 생성
var mp4Data = new byte[64];
mp4Data[4] = 0x66; mp4Data[5] = 0x74; mp4Data[6] = 0x79; mp4Data[7] = 0x70; // ftyp
var actualHash = Convert.ToHexString(SHA256.HashData(mp4Data)).ToLowerInvariant();
// 1. 체크섬 일치 및 헤더 유효
var okResult = MediaIntegrityVerifier.InspectIntegrity(mp4Data, "sample.mp4", actualHash);
Assert.True(okResult.IsValid);
Assert.True(okResult.ChecksumMatch);
Assert.Equal("mp4", okResult.Format);
Assert.Null(okResult.ErrorReason);
// 2. 체크섬 불일치
var mismatchResult = MediaIntegrityVerifier.InspectIntegrity(mp4Data, "sample.mp4", "0000000000000000000000000000000000000000000000000000000000000000");
Assert.False(mismatchResult.IsValid);
Assert.False(mismatchResult.ChecksumMatch);
Assert.Contains("체크섬", mismatchResult.ErrorReason);
// 3. 헤더 손상
var corruptedData = new byte[64]; // all zeros
var corruptResult = MediaIntegrityVerifier.InspectIntegrity(corruptedData, "sample.mp4");
Assert.False(corruptResult.IsValid);
Assert.Contains("헤더", corruptResult.ErrorReason);
}
}