Add src files
This commit is contained in:
142
tests/LibNftables.Tests/NftContextTests.cs
Normal file
142
tests/LibNftables.Tests/NftContextTests.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace LibNftables.Tests;
|
||||
|
||||
public sealed class NftContextTests
|
||||
{
|
||||
[Fact]
|
||||
public void ContextFlagsRoundTrip_Works()
|
||||
{
|
||||
if (!TryCreateContext(out var ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (ctx)
|
||||
{
|
||||
ctx.DryRun = true;
|
||||
Assert.True(ctx.DryRun);
|
||||
|
||||
ctx.OptimizeFlags = NftOptimizeFlags.Enabled;
|
||||
Assert.True(ctx.OptimizeFlags.HasFlag(NftOptimizeFlags.Enabled));
|
||||
|
||||
ctx.InputFlags = NftInputFlags.NoDns | NftInputFlags.Json;
|
||||
Assert.True(ctx.InputFlags.HasFlag(NftInputFlags.NoDns));
|
||||
Assert.True(ctx.InputFlags.HasFlag(NftInputFlags.Json));
|
||||
|
||||
ctx.OutputFlags = NftOutputFlags.Json | NftOutputFlags.Echo | NftOutputFlags.Terse;
|
||||
Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Json));
|
||||
Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Echo));
|
||||
Assert.True(ctx.OutputFlags.HasFlag(NftOutputFlags.Terse));
|
||||
|
||||
ctx.DebugFlags = NftDebugLevel.Parser | NftDebugLevel.Scanner;
|
||||
Assert.True(ctx.DebugFlags.HasFlag(NftDebugLevel.Parser));
|
||||
Assert.True(ctx.DebugFlags.HasFlag(NftDebugLevel.Scanner));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidCommand_ThrowsNftExceptionWithErrorBuffer()
|
||||
{
|
||||
if (!TryCreateContext(out var ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (ctx)
|
||||
{
|
||||
ctx.DryRun = true;
|
||||
ctx.BufferError();
|
||||
|
||||
var ex = Assert.ThrowsAny<NftException>(() => ctx.RunCommand("this is not valid nft syntax"));
|
||||
Assert.NotEqual(0, ex.NativeErrorCode);
|
||||
Assert.False(string.IsNullOrWhiteSpace(ex.NativeErrorOutput));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidDryRunCommand_CanExecuteAndBufferOutput()
|
||||
{
|
||||
if (!TryCreateContext(out var ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasCapNetAdmin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (ctx)
|
||||
{
|
||||
ctx.DryRun = true;
|
||||
ctx.BufferOutput();
|
||||
ctx.BufferError();
|
||||
|
||||
ctx.RunCommand("add table inet swig_test");
|
||||
var output = ctx.GetOutputBuffer();
|
||||
var error = ctx.GetErrorBuffer();
|
||||
|
||||
Assert.NotNull(output);
|
||||
Assert.True(string.IsNullOrEmpty(error), $"Unexpected error buffer: {error}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasCapNetAdmin()
|
||||
{
|
||||
const int capNetAdminBit = 12;
|
||||
const ulong mask = 1UL << capNetAdminBit;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var line in File.ReadLines("/proc/self/status"))
|
||||
{
|
||||
if (!line.StartsWith("CapEff:", StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var hex = line["CapEff:".Length..].Trim();
|
||||
if (ulong.TryParse(hex, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var value))
|
||||
{
|
||||
return (value & mask) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If capability probing fails, keep test conservative.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryCreateContext(out NftContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
context = new NftContext();
|
||||
return true;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
context = null!;
|
||||
return false;
|
||||
}
|
||||
catch (TypeInitializationException ex) when (ex.InnerException is DllNotFoundException)
|
||||
{
|
||||
context = null!;
|
||||
return false;
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
context = null!;
|
||||
return false;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
context = null!;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user