using AcDream.Core.Net.Cryptography;
namespace AcDream.Core.Net.Tests.Cryptography;
public class IsaacRandomTests
{
///
/// Golden vectors derived from ACE's reference ISAAC implementation
/// (references/ACE/Source/ACE.Common/Cryptography/ISAAC.cs) with seed
/// bytes [0x78, 0x56, 0x34, 0x12] (= 0x12345678 as little-endian uint32).
/// Ran a throwaway oracle harness that compiles ACE's ISAAC.cs + a Main
/// that calls Next() 16 times and prints the values; the numbers below
/// are factual outputs of that algorithm, not copied code.
///
private static readonly uint[] GoldenVectorsSeed12345678 =
{
0xFDD4AFEBu, 0x398311D2u, 0xC71829A4u, 0xB19DF96Au,
0x7ED4A1E7u, 0xB718A446u, 0x5FA77DF1u, 0x5CB793D2u,
0x52C95BACu, 0xA8F8FD7Eu, 0x18582C04u, 0xD257F506u,
0x4D11A3F0u, 0x919DE7A7u, 0x1D809C6Bu, 0xE97F65F8u,
};
[Fact]
public void Next_Seed12345678_MatchesAceGoldenVectors()
{
var seed = new byte[] { 0x78, 0x56, 0x34, 0x12 };
var isaac = new IsaacRandom(seed);
for (int i = 0; i < GoldenVectorsSeed12345678.Length; i++)
{
Assert.Equal(GoldenVectorsSeed12345678[i], isaac.Next());
}
}
[Fact]
public void Next_TwoInstancesSameSeed_ProduceIdenticalSequence()
{
var seed = new byte[] { 0xAA, 0xBB, 0xCC, 0xDD };
var a = new IsaacRandom(seed);
var b = new IsaacRandom(seed);
for (int i = 0; i < 1000; i++)
{
Assert.Equal(a.Next(), b.Next());
}
}
[Fact]
public void Next_DifferentSeeds_ProduceDifferentFirstOutput()
{
var a = new IsaacRandom(new byte[] { 1, 0, 0, 0 });
var b = new IsaacRandom(new byte[] { 2, 0, 0, 0 });
Assert.NotEqual(a.Next(), b.Next());
}
[Fact]
public void Next_512Calls_SpansTwoScrambleBatches()
{
// Two full scramble rounds (256 outputs each). Tests that the
// scramble boundary at offset 0 → offset 255 doesn't emit garbage or
// repeat values trivially.
var isaac = new IsaacRandom(new byte[] { 0x01, 0x02, 0x03, 0x04 });
var outputs = new uint[512];
for (int i = 0; i < 512; i++) outputs[i] = isaac.Next();
// Not a statistical test — just catch obvious bugs like "all zero"
// or "stuck at one value". A healthy PRNG produces far more than
// 100 distinct values in 512 calls.
var distinct = new HashSet(outputs);
Assert.True(distinct.Count > 400,
$"Expected >400 distinct values in 512 outputs, got {distinct.Count}");
}
[Fact]
public void Ctor_ShortSeed_Throws()
{
Assert.Throws(() => new IsaacRandom(new byte[] { 1, 2, 3 }));
}
}