test(core/browser/platform): 26 extreme RED/GREEN TDD cycles and full regression hardening (3,235 PASS)
This commit is contained in:
parent
bcd242691f
commit
8677853822
100 changed files with 4814 additions and 333 deletions
|
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Paca.Browser.Content;
|
||||
using Paca.Browser.Extensions;
|
||||
using Paca.Core.Net;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Core;
|
||||
|
||||
public class SecurityAndRateLimitingExtremeRedTests
|
||||
{
|
||||
// ==========================================
|
||||
// 1. ExtensionCspValidator
|
||||
// ==========================================
|
||||
|
||||
[Fact]
|
||||
public void ExtensionCspValidator_Validate_ManifestV3_UnsafeInlineInScriptSrc_ReturnsInvalid()
|
||||
{
|
||||
var result = ExtensionCspValidator.Validate("script-src 'self' 'unsafe-inline'; object-src 'self';", manifestVersion: 3);
|
||||
Assert.False(result.IsValid);
|
||||
Assert.NotEmpty(result.Violations);
|
||||
Assert.Contains(result.Violations, v => v.Contains("unsafe-inline", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("script-src 'self' data:;")]
|
||||
[InlineData("script-src 'self' blob:;")]
|
||||
public void ExtensionCspValidator_Validate_ManifestV3_DataOrBlobInScriptSrc_ReturnsInvalid(string csp)
|
||||
{
|
||||
var result = ExtensionCspValidator.Validate(csp, manifestVersion: 3);
|
||||
Assert.False(result.IsValid);
|
||||
Assert.NotEmpty(result.Violations);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(";; ; ;")]
|
||||
[InlineData(" ; ; ")]
|
||||
public void ExtensionCspValidator_Validate_EmptySemicolons_FallsBackToDefaultCsp(string csp)
|
||||
{
|
||||
var result = ExtensionCspValidator.Validate(csp, manifestVersion: 3);
|
||||
Assert.True(result.IsValid);
|
||||
Assert.Equal(ExtensionCspValidator.DefaultManifestV3Csp, result.NormalizedCsp);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 2. SiteAutoMutePolicy
|
||||
// ==========================================
|
||||
|
||||
[Fact]
|
||||
public void SiteAutoMutePolicy_AddAutoMutePattern_WildcardAsterisk_MutesAllSites()
|
||||
{
|
||||
var policy = new SiteAutoMutePolicy();
|
||||
policy.AddAutoMutePattern("*");
|
||||
|
||||
Assert.True(policy.IsAutoMute("https://youtube.com/watch?v=123"));
|
||||
Assert.True(policy.IsAutoMute("https://news.naver.com"));
|
||||
Assert.True(policy.IsAutoMute("https://example.org"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteAutoMutePolicy_Save_InvalidOrReadOnlyPath_DoesNotThrowUnhandledException()
|
||||
{
|
||||
// Using an invalid directory path that cannot be created on Windows
|
||||
var policy = new SiteAutoMutePolicy("Z:\\nonexistent_drive_9999\\invalid\\mute.json");
|
||||
var ex = Record.Exception(() => policy.AddAutoMutePattern("example.com"));
|
||||
Assert.Null(ex);
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 3. HostRateLimiter
|
||||
// ==========================================
|
||||
|
||||
[Theory]
|
||||
[InlineData("example.com:8080/api/v1", "example.com")]
|
||||
[InlineData("https://sub.4cdn.org/image.png", "sub.4cdn.org")]
|
||||
[InlineData("user:pass@reddit.com:443/r/funny", "reddit.com")]
|
||||
[InlineData(null, "")]
|
||||
[InlineData(" ", "")]
|
||||
public void HostRateLimiter_NormalizeHost_VariousInputs_NormalizesCleanly(string? input, string expected)
|
||||
{
|
||||
var host = HostRateLimiter.NormalizeHost(input);
|
||||
Assert.Equal(expected, host);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("i.4cdn.org", 1200)]
|
||||
[InlineData("boards.4channel.org", 1200)]
|
||||
[InlineData("v.redd.it", 800)]
|
||||
[InlineData("www.reddit.com", 800)]
|
||||
[InlineData("generic-site.com", 200)]
|
||||
public void HostRateLimiter_GetIntervalMs_RecognizesDomainPresets(string host, int expectedMs)
|
||||
{
|
||||
var interval = HostRateLimiter.GetIntervalMs(host);
|
||||
Assert.Equal(expectedMs, interval);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue