Skip to content

Commit

Permalink
Merge pull request #43 from yongenaelf/load-test
Browse files Browse the repository at this point in the history
Load test
  • Loading branch information
yongenaelf authored Oct 21, 2024
2 parents ac30433 + eaaf32d commit da94f85
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/load-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Artillery Load Test

on:
workflow_dispatch:

jobs:
artillery:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Execute load tests
uses: artilleryio/action-cli@v1
with:
command: run tests/performance/main.yml --record
env:
ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_KEY }}
Binary file added tests/performance/Archive.zip
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/performance/helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
var JSONFile= require('fs').readFileSync("./tests/performance/requestBody.json");

exports.setJSONBody = (req, context, events, next) => {
const requestJSON= JSON.parse(JSONFile);

context.vars.requestBody = requestJSON;
return next();
};
15 changes: 15 additions & 0 deletions tests/performance/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
config:
processor: "./helper.js"
http:
timeout: 60000
target: "https://playground-next.test.aelf.dev"
phases:
- duration: 10
arrivalRate: 5 # Start with 5 requests per second
scenarios:
- flow:
- post:
url: "/playground/test"
formData:
contractFiles:
fromFile: "./Archive.zip"
52 changes: 52 additions & 0 deletions tests/performance/requestBody.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"files": [
{
"path": "src/HelloWorld.cs",
"contents": "using AElf.Sdk.CSharp;\nusing Google.Protobuf.WellKnownTypes;\n\nnamespace AElf.Contracts.HelloWorld\n{\n // Contract class must inherit the base class generated from the proto file\n public class HelloWorld : HelloWorldContainer.HelloWorldBase\n {\n // A method that modifies the contract state\n public override Empty Update(StringValue input)\n {\n // Set the message value in the contract state\n State.Message.Value = input.Value;\n // Emit an event to notify listeners about something happened during the execution of this method\n Context.Fire(new UpdatedMessage\n {\n Value = input.Value\n });\n return new Empty();\n }\n\n // A method that read the contract state\n public override StringValue Read(Empty input)\n {\n // Retrieve the value from the state\n var value = State.Message.Value;\n // Wrap the value in the return type\n return new StringValue\n {\n Value = value\n };\n }\n }\n \n}"
},
{
"path": "src/HelloWorld.csproj",
"contents": "<Project Sdk=\"Microsoft.NET.Sdk\">\n <PropertyGroup>\n <TargetFramework>net6.0</TargetFramework>\n <RootNamespace>AElf.Contracts.HelloWorld</RootNamespace>\n <IsContract>true</IsContract>\n <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>\n </PropertyGroup>\n <PropertyGroup>\n <ObjPath>$(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/</ObjPath>\n </PropertyGroup>\n\n <Target Name=\"ProtoGeneratedRecognition\" AfterTargets=\"CoreCompile\">\n <ItemGroup>\n <Compile Include=\"$(ObjPath)Protobuf/**/*.cs\" />\n </ItemGroup>\n </Target>\n\n <ItemGroup>\n <PackageReference Include=\"AElf.Sdk.CSharp\" Version=\"1.5.0\" />\n <PackageReference Include=\"AElf.Tools\" Version=\"1.0.2\">\n <PrivateAssets>all</PrivateAssets>\n <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n </PackageReference>\n </ItemGroup>\n\n</Project>\n "
},
{
"path": "src/HelloWorldState.cs",
"contents": "using AElf.Sdk.CSharp.State;\n\nnamespace AElf.Contracts.HelloWorld\n{\n // The state class is access the blockchain state\n public class HelloWorldState : ContractState \n {\n // A state that holds string value\n public StringState Message { get; set; }\n }\n}"
},
{
"path": "src/Protobuf/contract/hello_world_contract.proto",
"contents": "syntax = \"proto3\";\n\nimport \"aelf/options.proto\";\nimport \"google/protobuf/empty.proto\";\nimport \"google/protobuf/wrappers.proto\";\nimport \"Protobuf/reference/acs12.proto\";\n// The namespace of this class\noption csharp_namespace = \"AElf.Contracts.HelloWorld\";\n\nservice HelloWorld {\n // The name of the state class the smart contract is going to use to access blockchain state\n option (aelf.csharp_state) = \"AElf.Contracts.HelloWorld.HelloWorldState\";\n option (aelf.base) = \"Protobuf/reference/acs12.proto\";\n \n // Actions (methods that modify contract state)\n // Stores the value in contract state\n rpc Update (google.protobuf.StringValue) returns (google.protobuf.Empty) {\n }\n\n // Views (methods that don't modify contract state)\n // Get the value stored from contract state\n rpc Read (google.protobuf.Empty) returns (google.protobuf.StringValue) {\n option (aelf.is_view) = true;\n }\n}\n\n// An event that will be emitted from contract method call\nmessage UpdatedMessage {\n option (aelf.is_event) = true;\n string value = 1;\n}"
},
{
"path": "src/Protobuf/message/authority_info.proto",
"contents": "syntax = \"proto3\";\n\nimport \"aelf/core.proto\";\n\noption csharp_namespace = \"AElf.Contracts.HelloWorld\";\n\nmessage AuthorityInfo {\n aelf.Address contract_address = 1;\n aelf.Address owner_address = 2;\n}"
},
{
"path": "src/Protobuf/reference/acs12.proto",
"contents": "/**\n * AElf Standards ACS12(User Contract Standard)\n *\n * Used to manage user contract.\n */\nsyntax = \"proto3\";\n\npackage acs12;\n\nimport public \"aelf/options.proto\";\nimport public \"google/protobuf/empty.proto\";\nimport public \"google/protobuf/wrappers.proto\";\nimport \"aelf/core.proto\";\n\noption (aelf.identity) = \"acs12\";\noption csharp_namespace = \"AElf.Standards.ACS12\";\n\nservice UserContract{\n\n}\n\n//Specified method fee for user contract.\nmessage UserContractMethodFees {\n // List of fees to be charged.\n repeated UserContractMethodFee fees = 2;\n // Optional based on the implementation of SetConfiguration method.\n bool is_size_fee_free = 3;\n}\n\nmessage UserContractMethodFee {\n // The token symbol of the method fee.\n string symbol = 1;\n // The amount of fees to be charged.\n int64 basic_fee = 2;\n}"
},
{
"path": "test/HelloWorld.Tests.csproj",
"contents": "<Project Sdk=\"Microsoft.NET.Sdk\">\n <PropertyGroup>\n <TargetFramework>net6.0</TargetFramework>\n <RootNamespace>AElf.Contracts.HelloWorld</RootNamespace>\n </PropertyGroup>\n\n <PropertyGroup>\n <NoWarn>0436;CS2002</NoWarn>\n </PropertyGroup>\n <PropertyGroup>\n <ObjPath>$(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/</ObjPath>\n </PropertyGroup>\n\n <ItemGroup>\n <PackageReference Include=\"AElf.Testing.TestBase\" Version=\"1.0.0\" />\n <PackageReference Include=\"AElf.EconomicSystem\" Version=\"1.5.0\" />\n <PackageReference Include=\"AElf.GovernmentSystem\" Version=\"1.5.0\" />\n <PackageReference Include=\"coverlet.msbuild\" Version=\"2.5.1\" />\n <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"16.3.0\" />\n <PackageReference Include=\"Shouldly\" Version=\"3.0.2\" />\n <PackageReference Include=\"xunit\" Version=\"2.4.1\" />\n <PackageReference Include=\"xunit.runner.console\" Version=\"2.4.1\" />\n <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.4.1\" />\n <PackageReference Include=\"AElf.ContractTestKit\" Version=\"1.5.0\" />\n <PackageReference Include=\"AElf.Tools\" Version=\"1.0.2\">\n <PrivateAssets>all</PrivateAssets>\n <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n </PackageReference>\n </ItemGroup>\n\n <ItemGroup>\n <Protobuf Include=\"Protobuf/base/*.proto\">\n <ContractOutputOptions>nocontract</ContractOutputOptions>\n </Protobuf>\n <Protobuf Include=\"Protobuf/message/*.proto\">\n <ContractOutputOptions>nocontract</ContractOutputOptions>\n </Protobuf>\n <Protobuf Include=\"Protobuf/stub/*.proto\">\n <ContractOutputOptions>stub</ContractOutputOptions>\n </Protobuf>\n </ItemGroup>\n\n <ItemGroup>\n <Compile Include=\"$(ObjPath)Protobuf/**/*.cs\" />\n </ItemGroup>\n\n <ItemGroup>\n <ProjectReference Include=\"../src/HelloWorld.csproj\" />\n </ItemGroup>\n \n</Project>"
},
{
"path": "test/HelloWorldTests.cs",
"contents": "using System.Threading.Tasks;\nusing Google.Protobuf.WellKnownTypes;\nusing Shouldly;\nusing Xunit;\n\nnamespace AElf.Contracts.HelloWorld\n{\n // This class is unit test class, and it inherit TestBase. Write your unit test code inside it\n public class HelloWorldTests : TestBase\n {\n [Fact]\n public async Task Update_ShouldUpdateMessageAndFireEvent()\n {\n // Arrange\n var inputValue = \"Hello, World!\";\n var input = new StringValue { Value = inputValue };\n\n // Act\n await HelloWorldStub.Update.SendAsync(input);\n\n // Assert\n var updatedMessage = await HelloWorldStub.Read.CallAsync(new Empty());\n updatedMessage.Value.ShouldBe(inputValue);\n }\n }\n \n}"
},
{
"path": "test/Protobuf/message/authority_info.proto",
"contents": "syntax = \"proto3\";\n\nimport \"aelf/core.proto\";\n\noption csharp_namespace = \"AElf.Contracts.HelloWorld\";\n\nmessage AuthorityInfo {\n aelf.Address contract_address = 1;\n aelf.Address owner_address = 2;\n}"
},
{
"path": "test/Protobuf/reference/acs12.proto",
"contents": "/**\n * AElf Standards ACS12(User Contract Standard)\n *\n * Used to manage user contract.\n */\nsyntax = \"proto3\";\n\npackage acs12;\n\nimport public \"aelf/options.proto\";\nimport public \"google/protobuf/empty.proto\";\nimport public \"google/protobuf/wrappers.proto\";\nimport \"aelf/core.proto\";\n\noption (aelf.identity) = \"acs12\";\noption csharp_namespace = \"AElf.Standards.ACS12\";\n\nservice UserContract{\n\n}\n\n//Specified method fee for user contract.\nmessage UserContractMethodFees {\n // List of fees to be charged.\n repeated UserContractMethodFee fees = 2;\n // Optional based on the implementation of SetConfiguration method.\n bool is_size_fee_free = 3;\n}\n\nmessage UserContractMethodFee {\n // The token symbol of the method fee.\n string symbol = 1;\n // The amount of fees to be charged.\n int64 basic_fee = 2;\n}"
},
{
"path": "test/Protobuf/stub/hello_world_contract.proto",
"contents": "syntax = \"proto3\";\n\nimport \"aelf/options.proto\";\nimport \"google/protobuf/empty.proto\";\nimport \"google/protobuf/wrappers.proto\";\nimport \"Protobuf/reference/acs12.proto\";\n// The namespace of this class\noption csharp_namespace = \"AElf.Contracts.HelloWorld\";\n\nservice HelloWorld {\n // The name of the state class the smart contract is going to use to access blockchain state\n option (aelf.csharp_state) = \"AElf.Contracts.HelloWorld.HelloWorldState\";\n option (aelf.base) = \"Protobuf/reference/acs12.proto\";\n\n // Actions (methods that modify contract state)\n // Stores the value in contract state\n rpc Update (google.protobuf.StringValue) returns (google.protobuf.Empty) {\n }\n\n // Views (methods that don't modify contract state)\n // Get the value stored from contract state\n rpc Read (google.protobuf.Empty) returns (google.protobuf.StringValue) {\n option (aelf.is_view) = true;\n }\n}\n\n// An event that will be emitted from contract method call\nmessage UpdatedMessage {\n option (aelf.is_event) = true;\n string value = 1;\n}"
},
{
"path": "test/_Setup.cs",
"contents": "using AElf.Cryptography.ECDSA;\nusing AElf.Testing.TestBase;\n\nnamespace AElf.Contracts.HelloWorld\n{\n // The Module class load the context required for unit testing\n public class Module : ContractTestModule<HelloWorld>\n {\n \n }\n \n // The TestBase class inherit ContractTestBase class, it defines Stub classes and gets instances required for unit testing\n public class TestBase : ContractTestBase<Module>\n {\n // The Stub class for unit testing\n internal readonly HelloWorldContainer.HelloWorldStub HelloWorldStub;\n // A key pair that can be used to interact with the contract instance\n private ECKeyPair DefaultKeyPair => Accounts[0].KeyPair;\n\n public TestBase()\n {\n HelloWorldStub = GetHelloWorldContractStub(DefaultKeyPair);\n }\n\n private HelloWorldContainer.HelloWorldStub GetHelloWorldContractStub(ECKeyPair senderKeyPair)\n {\n return GetTester<HelloWorldContainer.HelloWorldStub>(ContractAddress, senderKeyPair);\n }\n }\n \n}"
}
]
}

0 comments on commit da94f85

Please sign in to comment.