refactor: split node agent and Go control plane
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using WxAgent.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace WxAgent.Core.Tests;
|
||||
|
||||
public sealed class MemoryScanningTests
|
||||
{
|
||||
private static byte[] EncodedLiteral(string literal)
|
||||
{
|
||||
var bytes = Encoding.ASCII.GetBytes(literal);
|
||||
var mask = Convert.FromHexString("d2c7442458020000004889442450488b450048844c2448488944254048584c24");
|
||||
for (var i = 0; i < bytes.Length; i++) bytes[i] ^= mask[i % mask.Length];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigCipherDecodeFindsKeyAndEmbeddedSalt()
|
||||
{
|
||||
var key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
|
||||
var salt = "101112131415161718191a1b1c1d1e1f";
|
||||
var decoded = WcdbConfigCipher.Decode(EncodedLiteral($"x'{key}{salt}'"));
|
||||
Assert.Equal(new WcdbKeyCandidate(key, salt), Assert.Single(decoded));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigCipherDecodeWindowsOnLongRuns()
|
||||
{
|
||||
var key = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
|
||||
var salt = "101112131415161718191a1b1c1d1e1f";
|
||||
var run = key + salt + key + salt;
|
||||
var decoded = WcdbConfigCipher.Decode(EncodedLiteral($"x'{run}'"));
|
||||
Assert.Contains(decoded, item => item.EncKey == key && item.SaltHint == salt);
|
||||
Assert.Equal(4, decoded.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigCipherDecodeRejectsBoundsAndUniformKeys()
|
||||
{
|
||||
Assert.Empty(WcdbConfigCipher.Decode([]));
|
||||
Assert.Empty(WcdbConfigCipher.Decode(EncodedLiteral("x'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'" + "00000000000000000000000000000000")));
|
||||
Assert.Empty(WcdbConfigCipher.Decode(EncodedLiteral("plain")));
|
||||
Assert.Empty(WcdbConfigCipher.Decode(EncodedLiteral("x''")));
|
||||
var tooLong = EncodedLiteral($"x'{new string('e', 200)}'");
|
||||
Assert.Empty(WcdbConfigCipher.Decode(tooLong));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigCipherDecodeRejectsBlobsOverLimit()
|
||||
{
|
||||
var literal = $"x'{new string('f', 64)}{new string('1', 32)}'";
|
||||
var blob = new List<byte>(EncodedLiteral(literal));
|
||||
while (blob.Count <= WcdbConfigCipher.MaximumBlobLength) blob.Insert(0, 0x00);
|
||||
Assert.Empty(WcdbConfigCipher.Decode(blob.ToArray()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PatternScannerMatchesAcrossChunkBoundaries()
|
||||
{
|
||||
var needle = Encoding.ASCII.GetBytes("com.Tencent.WCDB.Config.Cipher");
|
||||
var content = Encoding.ASCII.GetBytes("prefix " + Encoding.ASCII.GetString(needle) + " suffix");
|
||||
var split = 10;
|
||||
var scanner = new MemoryPatternScanner(needle);
|
||||
var matches = scanner.Feed(content.AsSpan(0, split), 0x1000).ToList();
|
||||
matches.AddRange(scanner.Feed(content.AsSpan(split), 0x1000 + (ulong)split));
|
||||
Assert.Equal([0x1000 + 7UL], matches);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PatternScannerReportsMatchesInSecondChunk()
|
||||
{
|
||||
var needle = Encoding.ASCII.GetBytes("abc");
|
||||
var content = Encoding.ASCII.GetBytes("xxabc");
|
||||
var scanner = new MemoryPatternScanner(needle);
|
||||
var matches = scanner.Feed(content.AsSpan(0, 3), 0x2000).ToList();
|
||||
matches.AddRange(scanner.Feed(content.AsSpan(3), 0x2003));
|
||||
Assert.Equal([0x2002UL], matches);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PatternScannerDoesNotJoinAcrossGaps()
|
||||
{
|
||||
var needle = Encoding.ASCII.GetBytes("abc");
|
||||
var scanner = new MemoryPatternScanner(needle);
|
||||
var matches = scanner.Feed("a"u8[..1], 0x3000).ToList();
|
||||
matches.AddRange(scanner.Feed("b"u8[..1], 0x4000)); // Gap: end was 0x3001, next feed at 0x4000.
|
||||
matches.AddRange(scanner.Feed("c"u8[..1], 0x4001));
|
||||
Assert.Empty(matches);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PatternScannerFindsMatchSpanningThreeChunks()
|
||||
{
|
||||
var needle = Encoding.ASCII.GetBytes("abcde");
|
||||
var content = Encoding.ASCII.GetBytes("xxabcde");
|
||||
var scanner = new MemoryPatternScanner(needle);
|
||||
var matches = scanner.Feed(content.AsSpan(0, 3), 0x5000).ToList();
|
||||
matches.AddRange(scanner.Feed(content.AsSpan(3, 3), 0x5003));
|
||||
matches.AddRange(scanner.Feed(content.AsSpan(6), 0x5006));
|
||||
Assert.Equal([0x5002UL], matches);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecodeProducesNoMatchAfterPatternError()
|
||||
{
|
||||
// Simulates the reference's own fail-open behavior after a failed read.
|
||||
var decoded = WcdbConfigCipher.Decode(Encoding.ASCII.GetBytes("x'abc'"));
|
||||
Assert.Empty(decoded);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user