diff --git a/net/Directory.Packages.props b/net/Directory.Packages.props
index c5b61101..ede6c379 100644
--- a/net/Directory.Packages.props
+++ b/net/Directory.Packages.props
@@ -33,7 +33,7 @@
-
-
+
+
diff --git a/net/tests/Sails.Client.Tests/GlobalUsings.cs b/net/tests/Sails.Client.Tests/GlobalUsings.cs
index 51244d1c..ad4d8e84 100644
--- a/net/tests/Sails.Client.Tests/GlobalUsings.cs
+++ b/net/tests/Sails.Client.Tests/GlobalUsings.cs
@@ -1,6 +1,4 @@
-global using System;
-global using System.Collections.Generic;
-global using System.Linq;
+global using System.Collections.Generic;
global using System.Threading;
global using System.Threading.Tasks;
global using NSubstitute;
diff --git a/net/tests/Sails.DemoClient.Tests/AssemblyAttributes.cs b/net/tests/Sails.DemoClient.Tests/AssemblyAttributes.cs
index 991f08f6..140d3109 100644
--- a/net/tests/Sails.DemoClient.Tests/AssemblyAttributes.cs
+++ b/net/tests/Sails.DemoClient.Tests/AssemblyAttributes.cs
@@ -4,3 +4,5 @@
[assembly: AssemblyFixture(
typeof(Sails.DemoClient.Tests._Infra.XUnit.Fixtures.SailsFixture))]
+
+[assembly: CollectionBehavior(DisableTestParallelization = true)]
diff --git a/net/tests/Sails.DemoClient.Tests/CounterTests.cs b/net/tests/Sails.DemoClient.Tests/CounterTests.cs
new file mode 100644
index 00000000..6ec9bbb6
--- /dev/null
+++ b/net/tests/Sails.DemoClient.Tests/CounterTests.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Threading;
+using Sails.DemoClient.Tests._Infra.XUnit.Fixtures;
+using Sails.Remoting.Abstractions;
+using Substrate.NetApi.Model.Types.Base;
+using Substrate.NetApi.Model.Types.Primitive;
+
+namespace Sails.DemoClient.Tests;
+
+public class CounterTests(SailsFixture sailsFixture) : RemotingTestsBase(sailsFixture)
+{
+ [Fact]
+ public async Task Counter_Add_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var counterClient = new Demo.Counter(this.Remoting);
+ // TODO add listener
+ //var counterClient = new Demo.CounterListener(this.remoting);
+
+ // act
+ var dogPosition = new BaseOpt>(new BaseTuple(new I32(0), new I32(0)));
+ var programId = await demoFactory
+ .New(counter: new U32(42), dogPosition: dogPosition)
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var result = await counterClient.Add(new U32(10)).SendReceiveAsync(programId, CancellationToken.None);
+
+ // assert
+ Assert.NotNull(result);
+ Assert.Equal(52u, result.Value);
+ // TODO add event assert
+ }
+
+ [Fact]
+ public async Task Counter_Sub_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var counterClient = new Demo.Counter(this.Remoting);
+ // TODO add listener
+ //var counterClient = new Demo.CounterListener(this.remoting);
+
+ // act
+ var dogPosition = new BaseOpt>(new BaseTuple(new I32(0), new I32(0)));
+ var programId = await demoFactory
+ .New(counter: new U32(42), dogPosition: dogPosition)
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var result = await counterClient.Sub(new U32(10)).SendReceiveAsync(programId, CancellationToken.None);
+
+ // assert
+ Assert.NotNull(result);
+ Assert.Equal(32u, result.Value);
+ // TODO add event assert
+ }
+
+ [Fact]
+ public async Task Counter_Query_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var counterClient = new Demo.Counter(this.Remoting);
+
+ // act
+ var dogPosition = new BaseOpt>(new BaseTuple(new I32(0), new I32(0)));
+ var programId = await demoFactory
+ .New(counter: new U32(42), dogPosition: dogPosition)
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var result = await counterClient.Value().QueryAsync(programId, CancellationToken.None);
+
+ // assert
+ Assert.NotNull(result);
+ Assert.Equal(42u, result.Value);
+ }
+
+ [Fact]
+ public async Task Counter_Query_Throws_NotEnoughGas()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var counterClient = new Demo.Counter(this.Remoting);
+
+ // act
+ var dogPosition = new BaseOpt>(new BaseTuple(new I32(0), new I32(0)));
+ var programId = await demoFactory
+ .New(counter: new U32(42), dogPosition: dogPosition)
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var ex = await Assert.ThrowsAsync(() => counterClient.Value()
+ .WithGasLimit(new GasUnit(0))
+ .QueryAsync(programId, CancellationToken.None)
+ );
+
+ // assert
+ Assert.NotNull(ex);
+ }
+}
diff --git a/net/tests/Sails.DemoClient.Tests/DemoFactoryTests.cs b/net/tests/Sails.DemoClient.Tests/DemoFactoryTests.cs
index 60f4f229..7b1a2c8a 100644
--- a/net/tests/Sails.DemoClient.Tests/DemoFactoryTests.cs
+++ b/net/tests/Sails.DemoClient.Tests/DemoFactoryTests.cs
@@ -1,21 +1,51 @@
+using System;
+using System.Threading;
using Sails.DemoClient.Tests._Infra.XUnit.Fixtures;
namespace Sails.DemoClient.Tests;
-public sealed class DemoFactoryTests : IAssemblyFixture
+public sealed class DemoFactoryTests(SailsFixture fixture) : RemotingTestsBase(fixture)
{
- public DemoFactoryTests(SailsFixture fixture)
+ [Fact]
+ public async Task Test1()
{
- this.sailsFixture = fixture;
- // Assert that IDL file from the Sails.DemoClient project is the same as the one
- // from the SailsFixture
+ var demoContractCodeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
}
- private readonly SailsFixture sailsFixture;
+ [Fact]
+ public async Task Demo_DefaultConstructor_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ // act
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var activate = await demoFactory
+ .Default()
+ .ActivateAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+ var programId = await activate.ReceiveAsync(CancellationToken.None);
+
+ // assert
+ Assert.NotNull(programId);
+ }
[Fact]
- public async Task Test1()
+ public async Task Demo_Activation_Throws_NotEnoughGas()
{
- var demoContractCodeId = await this.sailsFixture.GetDemoContractCodeIdAsync();
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ // act
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var activate = await demoFactory
+ .Default()
+ .WithGasLimit(new GasUnit(0))
+ .ActivateAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+ // throws on ReceiveAsync
+ var ex = await Assert.ThrowsAsync(() => activate.ReceiveAsync(CancellationToken.None));
+
+ // assert
+ // TODO assert custom exception
+ Assert.NotNull(ex);
}
}
diff --git a/net/tests/Sails.DemoClient.Tests/GlobalUsings.cs b/net/tests/Sails.DemoClient.Tests/GlobalUsings.cs
index 8f37676d..797b115d 100644
--- a/net/tests/Sails.DemoClient.Tests/GlobalUsings.cs
+++ b/net/tests/Sails.DemoClient.Tests/GlobalUsings.cs
@@ -1,3 +1,5 @@
global using System.Threading.Tasks;
global using Sails.Tests.Shared.XUnit;
global using Xunit;
+global using GasUnit = Substrate.NetApi.Model.Types.Primitive.U64;
+global using ValueUnit = Substrate.NetApi.Model.Types.Primitive.U128;
diff --git a/net/tests/Sails.DemoClient.Tests/PingPongTests.cs b/net/tests/Sails.DemoClient.Tests/PingPongTests.cs
new file mode 100644
index 00000000..85e1ea50
--- /dev/null
+++ b/net/tests/Sails.DemoClient.Tests/PingPongTests.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Threading;
+using Sails.DemoClient.Tests._Infra.XUnit.Fixtures;
+using Sails.Remoting.Abstractions;
+using Substrate.Gear.Client.NetApi.Model.Types.Base;
+using Substrate.NetApi.Model.Types.Primitive;
+
+namespace Sails.DemoClient.Tests;
+
+public class PingPongTests(SailsFixture sailsFixture) : RemotingTestsBase(sailsFixture)
+{
+ [Fact]
+ public async Task PingPong_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var pingPongClient = new Demo.PingPong(this.Remoting);
+
+ // act
+ var programId = await demoFactory
+ .Default()
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var result = await pingPongClient.Ping(new Str("ping")).SendReceiveAsync(programId, CancellationToken.None);
+
+ // assert
+ Assert.True(result.Matches(BaseResultEnum.Ok, s => s == "pong"));
+ }
+}
diff --git a/net/tests/Sails.DemoClient.Tests/RemotingTestsBase.cs b/net/tests/Sails.DemoClient.Tests/RemotingTestsBase.cs
new file mode 100644
index 00000000..078c25bf
--- /dev/null
+++ b/net/tests/Sails.DemoClient.Tests/RemotingTestsBase.cs
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Sails.DemoClient.Tests._Infra.XUnit.Fixtures;
+using Sails.Remoting.Abstractions.Core;
+using Sails.Remoting.DependencyInjection;
+using Sails.Remoting.Options;
+
+namespace Sails.DemoClient.Tests;
+
+public class RemotingTestsBase : IAssemblyFixture
+{
+ public RemotingTestsBase(SailsFixture fixture)
+ {
+ this.SailsFixture = fixture;
+ // Assert that IDL file from the Sails.DemoClient project is the same as the one
+ // from the SailsFixture
+ var serviceCollection = new ServiceCollection();
+ serviceCollection.AddRemotingViaNodeClient(
+ new NodeClientOptions
+ {
+ GearNodeUri = this.SailsFixture.GearNodeWsUrl,
+ });
+ var serviceProvider = serviceCollection.BuildServiceProvider();
+ this.RemotingProvider = serviceProvider.GetRequiredService();
+ this.Remoting = this.RemotingProvider.CreateRemoting(SailsFixture.AliceAccount);
+ }
+
+ protected static readonly Random Random = new((int)DateTime.UtcNow.Ticks);
+
+ protected readonly SailsFixture SailsFixture;
+ protected readonly IRemotingProvider RemotingProvider;
+ protected readonly IRemoting Remoting;
+}
diff --git a/net/tests/Sails.DemoClient.Tests/Sails.DemoClient.Tests.csproj b/net/tests/Sails.DemoClient.Tests/Sails.DemoClient.Tests.csproj
index eeb8d95e..dd914419 100644
--- a/net/tests/Sails.DemoClient.Tests/Sails.DemoClient.Tests.csproj
+++ b/net/tests/Sails.DemoClient.Tests/Sails.DemoClient.Tests.csproj
@@ -9,6 +9,7 @@
+
diff --git a/net/tests/Sails.DemoClient.Tests/ValueFeeTests.cs b/net/tests/Sails.DemoClient.Tests/ValueFeeTests.cs
new file mode 100644
index 00000000..39f254cf
--- /dev/null
+++ b/net/tests/Sails.DemoClient.Tests/ValueFeeTests.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading;
+using Sails.DemoClient.Tests._Infra.XUnit.Fixtures;
+using Sails.Remoting.Abstractions;
+
+namespace Sails.DemoClient.Tests;
+
+public class ValueFeeTests(SailsFixture sailsFixture) : RemotingTestsBase(sailsFixture)
+{
+ [Fact]
+ public async Task ValueFee_Works()
+ {
+ // arrange
+ var codeId = await this.SailsFixture.GetDemoContractCodeIdAsync();
+
+ var demoFactory = new Demo.DemoFactory(this.Remoting);
+ var valueFeeClient = new Demo.ValueFee(this.Remoting);
+
+ // act
+ var programId = await demoFactory
+ .Default()
+ .SendReceiveAsync(codeId, BitConverter.GetBytes(Random.NextInt64()), CancellationToken.None);
+
+ var result = await valueFeeClient
+ .DoSomethingAndTakeFee()
+ .WithValue(new ValueUnit(15_000_000_000_000))
+ .SendReceiveAsync(programId, CancellationToken.None);
+
+ // assert
+ Assert.True(result);
+ // TODO assert balances
+ }
+}