Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f87ca0a
Adding pocketic
Gekctek Oct 15, 2024
57e287b
Copy binaries to output
Gekctek Oct 15, 2024
5e53c10
Fixing
Gekctek Oct 15, 2024
fa9a29d
Adding line test
Gekctek Oct 15, 2024
72b7991
Client
Gekctek Oct 15, 2024
1565400
Update EdjCase.ICP.PocketIC.csproj
Gekctek Oct 15, 2024
0885450
Update PocketIcClient.cs
Gekctek Oct 15, 2024
6c7b0b8
Update PocketIcClient.cs
Gekctek Oct 15, 2024
4af2e59
Removing lf enforcement
Gekctek Oct 16, 2024
64abf2d
Rename folder
Gekctek Oct 16, 2024
b661ae7
Fixing tests
Gekctek Oct 16, 2024
9296984
a
Gekctek Oct 17, 2024
bcc169f
Tests work
Gekctek Oct 17, 2024
e4eaf00
Fixing tests
Gekctek Oct 17, 2024
9cdc1ab
Removing dead code
Gekctek Oct 17, 2024
c874ba4
Merge remote-tracking branch 'edjcase/main' into PocketIC
Gekctek Oct 21, 2024
f50c364
Adding missing doc
Gekctek Oct 21, 2024
d52760d
Adding PocketIC Tests and .net8
Gekctek Oct 21, 2024
1cdbc9f
Adding to solution and XUnit
Gekctek Oct 21, 2024
84065af
Adding tests
Gekctek Oct 21, 2024
8cd83f3
Adding more methods
Gekctek Oct 23, 2024
e55f827
Merge remote-tracking branch 'edjcase/main' into PocketIC
Gekctek Oct 28, 2024
f36087f
IPocketIcHttpClient
Gekctek Oct 28, 2024
5257f54
Adding tests
Gekctek Oct 28, 2024
043b3ce
Adding routes
Gekctek Oct 30, 2024
665a023
HttpGateway
Gekctek Nov 3, 2024
7121c41
Auto progress time
Gekctek Nov 4, 2024
82a25a7
Documenting PocketIc.cs
Gekctek Nov 4, 2024
2b4dd97
IPocketIcHttpClient.cs docs
Gekctek Nov 4, 2024
f776c51
PocketIcHttpClient.cs docs
Gekctek Nov 4, 2024
57dcc3e
PocketIcServer + Request/Response models docs
Gekctek Nov 4, 2024
b648c76
Docs
Gekctek Nov 4, 2024
14fe501
Misc Candid/PocketIC tweaks and tests
Gekctek Nov 4, 2024
164f617
Updating README for pocketic
Gekctek Nov 4, 2024
51f764c
Fixing Async
Gekctek Nov 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
- uses: actions/checkout@v2

- name: Setup Dotnet
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
dotnet-version: 8.0.x

- name: Pack Candid
run: dotnet pack src/Candid/EdjCase.ICP.Candid.csproj --configuration Release /p:Version=${{ github.event.release.tag_name }} --output . --include-symbols --include-source
Expand All @@ -33,6 +33,12 @@ jobs:
- name: Push Agent
run: dotnet nuget push EdjCase.ICP.Agent.${{ github.event.release.tag_name }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json

- name: Pack Agent
run: dotnet pack src/PocketIC/EdjCase.ICP.PocketIC.csproj --configuration Release /p:Version=${{ github.event.release.tag_name }} --output . --include-symbols --include-source

- name: Push PocketIC
run: dotnet nuget push EdjCase.ICP.PocketIC.${{ github.event.release.tag_name }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json

- name: Pack WebSockets
run: dotnet pack src/WebSockets/EdjCase.ICP.WebSockets.csproj --configuration Release /p:Version=${{ github.event.release.tag_name }} --output . --include-symbols --include-source

Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/Sample/bin/Debug/net6.0/Sample.dll",
"program": "${workspaceFolder}/src/Sample/bin/Debug/net8.0/Sample.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Sample",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
Expand Down
22 changes: 21 additions & 1 deletion ICP.sln
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.WebSockets", "sample
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSockets.Tests", "test\WebSockets.Tests\WebSockets.Tests.csproj", "{3015AFBC-B866-459F-B25C-4BEA00C2A91E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLS.Tests", "test\BLS.Tests\BLS.Tests.csproj", "{213F30BA-D147-4291-93A3-13A8A006126D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BLS.Tests", "test\BLS.Tests\BLS.Tests.csproj", "{213F30BA-D147-4291-93A3-13A8A006126D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdjCase.ICP.PocketIC", "src\PocketIC\EdjCase.ICP.PocketIC.csproj", "{051EE789-4283-48DA-81EF-4B8ADFD406D0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.PocketIC", "samples\Sample.PocketIC\Sample.PocketIC.csproj", "{E674253B-7B51-40D0-9F3D-805007174D31}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PocketIC.Tests", "test\PocketIC.Tests\PocketIC.Tests.csproj", "{02D1DDA8-7A9A-4355-BE95-DE1720D56055}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -117,6 +123,18 @@ Global
{213F30BA-D147-4291-93A3-13A8A006126D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{213F30BA-D147-4291-93A3-13A8A006126D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{213F30BA-D147-4291-93A3-13A8A006126D}.Release|Any CPU.Build.0 = Release|Any CPU
{051EE789-4283-48DA-81EF-4B8ADFD406D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{051EE789-4283-48DA-81EF-4B8ADFD406D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{051EE789-4283-48DA-81EF-4B8ADFD406D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{051EE789-4283-48DA-81EF-4B8ADFD406D0}.Release|Any CPU.Build.0 = Release|Any CPU
{E674253B-7B51-40D0-9F3D-805007174D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E674253B-7B51-40D0-9F3D-805007174D31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E674253B-7B51-40D0-9F3D-805007174D31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E674253B-7B51-40D0-9F3D-805007174D31}.Release|Any CPU.Build.0 = Release|Any CPU
{02D1DDA8-7A9A-4355-BE95-DE1720D56055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{02D1DDA8-7A9A-4355-BE95-DE1720D56055}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02D1DDA8-7A9A-4355-BE95-DE1720D56055}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02D1DDA8-7A9A-4355-BE95-DE1720D56055}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -133,6 +151,8 @@ Global
{B4F9E828-BC3D-4EFF-9E21-53DD82928AB0} = {7FADA9D9-5FDA-4CFB-8A53-A578A61FBBA9}
{3015AFBC-B866-459F-B25C-4BEA00C2A91E} = {F71B8320-C279-4A79-A8D4-4039DB39D522}
{213F30BA-D147-4291-93A3-13A8A006126D} = {F71B8320-C279-4A79-A8D4-4039DB39D522}
{E674253B-7B51-40D0-9F3D-805007174D31} = {7FADA9D9-5FDA-4CFB-8A53-A578A61FBBA9}
{02D1DDA8-7A9A-4355-BE95-DE1720D56055} = {F71B8320-C279-4A79-A8D4-4039DB39D522}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3103E11A-E792-49EE-98C5-B2F3709DB088}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion samples/Sample.CLI/Sample.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>ICP.Sample.CLI</RootNamespace>
Expand Down
Binary file not shown.
153 changes: 153 additions & 0 deletions samples/Sample.PocketIC/PocketIc.Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using System.Net;
using EdjCase.ICP.Agent.Agents;
using EdjCase.ICP.Agent.Responses;
using EdjCase.ICP.Candid.Models;
using EdjCase.ICP.PocketIC;
using EdjCase.ICP.PocketIC.Client;
using EdjCase.ICP.PocketIC.Models;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cms;
using Xunit;

namespace Sample.PocketIC
{
public class PocketIcServerFixture : IDisposable
{
public PocketIcServer Server { get; private set; }

public PocketIcServerFixture()
{
// Start the server for all tests
this.Server = PocketIcServer.Start().GetAwaiter().GetResult();
}

public void Dispose()
{
// Stop the server after all tests
if (this.Server != null)
{
this.Server.StopAsync().GetAwaiter().GetResult();
this.Server.DisposeAsync().GetAwaiter().GetResult();
}
}
}

public class PocketIcTests : IClassFixture<PocketIcServerFixture>
{
private readonly PocketIcServerFixture fixture;
private string url => this.fixture.Server.GetUrl();

public PocketIcTests(PocketIcServerFixture fixture)
{
this.fixture = fixture;
}

[Fact]
public async Task UpdateCallAsync_CounterWasm__Basic__Valid()
{
byte[] wasmModule = File.ReadAllBytes("CanisterWasmModules/counter.wasm");
CandidArg arg = CandidArg.FromCandid();

// Create new pocketic instance for test, then dispose it
await using (PocketIc pocketIc = await PocketIc.CreateAsync(this.url))
{
Principal canisterId = await pocketIc.CreateAndInstallCanisterAsync(wasmModule, arg);

UnboundedUInt value = await pocketIc.QueryCallAsync<UnboundedUInt>(
Principal.Anonymous(),
canisterId,
"get"
);
Assert.Equal((UnboundedUInt)0, value);


await pocketIc.UpdateCallNoResponseAsync(
Principal.Anonymous(),
canisterId,
"inc"
);

value = await pocketIc.QueryCallAsync<UnboundedUInt>(
Principal.Anonymous(),
canisterId,
"get"
);
Assert.Equal((UnboundedUInt)1, value);

await pocketIc.UpdateCallNoResponseAsync(
Principal.Anonymous(),
canisterId,
"set",
(UnboundedUInt)10
);

value = await pocketIc.QueryCallAsync<UnboundedUInt>(
Principal.Anonymous(),
canisterId,
"get"
);

Assert.Equal((UnboundedUInt)10, value);
}
}


[Fact]
public async Task HttpGateway_CounterWasm__Basic__Valid()
{
byte[] wasmModule = File.ReadAllBytes("CanisterWasmModules/counter.wasm");
CandidArg arg = CandidArg.FromCandid();


SubnetConfig nnsSubnet = SubnetConfig.New(); // NNS subnet required for HttpGateway

await using (PocketIc pocketIc = await PocketIc.CreateAsync(this.url, nnsSubnet: nnsSubnet))
{
Principal canisterId = await pocketIc.CreateAndInstallCanisterAsync(wasmModule, arg);

await pocketIc.StartCanisterAsync(canisterId);

// Let time progress so that update calls get processed
await using (await pocketIc.AutoProgressTimeAsync())
{
await using (HttpGateway httpGateway = await pocketIc.RunHttpGatewayAsync())
{
HttpAgent agent = httpGateway.BuildHttpAgent();
QueryResponse getResponse = await agent.QueryAsync(canisterId, "get", CandidArg.Empty());
CandidArg getResponseArg = getResponse.ThrowOrGetReply();
UnboundedUInt getResponseValue = getResponseArg.ToObjects<UnboundedUInt>();
Assert.Equal((UnboundedUInt)0, getResponseValue);


CancellationTokenSource cts = new(TimeSpan.FromSeconds(5));
CandidArg incResponseArg = await agent.CallAndWaitAsync(canisterId, "inc", CandidArg.Empty(), cancellationToken: cts.Token);
Assert.Equal(CandidArg.Empty(), incResponseArg);

// This alternative also doesnt work
// RequestId requestId = await agent.CallAsync(canisterId, "inc", CandidArg.Empty());
// ICTimestamp currentTime = await pocketIc.GetTimeAsync();
// await pocketIc.SetTimeAsync(currentTime + TimeSpan.FromSeconds(5));
// await pocketIc.TickAsync(5);
// CandidArg incResponseArg = await agent.WaitForRequestAsync(canisterId, requestId);
// Assert.Equal(CandidArg.Empty(), incResponseArg);

getResponse = await agent.QueryAsync(canisterId, "get", CandidArg.Empty());
getResponseArg = getResponse.ThrowOrGetReply();
getResponseValue = getResponseArg.ToObjects<UnboundedUInt>();
Assert.Equal((UnboundedUInt)1, getResponseValue);

CandidArg setRequestArg = CandidArg.FromObjects((UnboundedUInt)10);
CandidArg setResponseArg = await agent.CallAndWaitAsync(canisterId, "set", setRequestArg);
Assert.Equal(CandidArg.Empty(), setResponseArg);

getResponse = await agent.QueryAsync(canisterId, "get", CandidArg.Empty());
getResponseArg = getResponse.ThrowOrGetReply();
getResponseValue = getResponseArg.ToObjects<UnboundedUInt>();
Assert.Equal((UnboundedUInt)10, getResponseValue);

}
}
}
}
}
}
39 changes: 39 additions & 0 deletions samples/Sample.PocketIC/Sample.PocketIC.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.2" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.1.2" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeRefactoring.Testing.XUnit" Version="1.1.2" />
</ItemGroup>

<ItemGroup>
<Content Include="CanisterWasmModules/*.wasm">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\PocketIC\EdjCase.ICP.PocketIC.csproj" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion samples/Sample.RestAPI/Sample.RestAPI.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion samples/Sample.WebSockets/Sample.WebSockets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
14 changes: 13 additions & 1 deletion src/Agent/API.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 21 additions & 2 deletions src/Agent/Agents/IAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public static class IAgentExtensions
/// <param name="arg">The candid arg to send with the request</param>
/// <param name="effectiveCanisterId">Optional. Specifies the relevant canister id if calling the root canister</param>
/// <param name="cancellationToken">Optional. Token to cancel request</param>
/// <returns>The id of the request that can be used to look up its status with `GetRequestStatusAsync`</returns>
/// <returns>The raw candid arg response</returns>
public static async Task<CandidArg> CallAndWaitAsync(
this IAgent agent,
Principal canisterId,
Expand All @@ -100,12 +100,31 @@ public static async Task<CandidArg> CallAndWaitAsync(
CancellationToken? cancellationToken = null)
{
RequestId id = await agent.CallAsync(canisterId, method, arg, effectiveCanisterId);
return await agent.WaitForRequestAsync(canisterId, id, cancellationToken);
}

/// <summary>
/// Waits for a request to be processed and returns the candid response to the call. This is a helper
/// method built on top of `GetRequestStatusAsync` to wait for the response so it doesn't need to be
/// implemented manually
/// </summary>
/// <param name="agent">The agent to use for the call</param>
/// <param name="canisterId">Canister to read state for</param>
/// <param name="requestId">The unique identifier for the request</param>
/// <param name="cancellationToken">Optional. Token to cancel request</param>
/// <returns>The raw candid arg response</returns>
public static async Task<CandidArg> WaitForRequestAsync(
this IAgent agent,
Principal canisterId,
RequestId requestId,
CancellationToken? cancellationToken = null
)
{
while (true)
{
cancellationToken?.ThrowIfCancellationRequested();

RequestStatus? requestStatus = await agent.GetRequestStatusAsync(canisterId, id);
RequestStatus? requestStatus = await agent.GetRequestStatusAsync(canisterId, requestId);

cancellationToken?.ThrowIfCancellationRequested();

Expand Down
Loading