From c842a10f738fe52ea8900456f18f8e063a8b9878 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 15:32:26 +0800
Subject: [PATCH 01/15] Create load-test.yml
---
.github/workflows/load-test.yml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 .github/workflows/load-test.yml
diff --git a/.github/workflows/load-test.yml b/.github/workflows/load-test.yml
new file mode 100644
index 0000000..5636a90
--- /dev/null
+++ b/.github/workflows/load-test.yml
@@ -0,0 +1,19 @@
+name: Artillery Load Test
+
+on:
+ push:
+ branches:
+ - load-test
+
+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
From d0dd3c4d400144b2850bf93c62d7c2aa60f5bf65 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 15:44:59 +0800
Subject: [PATCH 02/15] ci: load test script
---
tests/performance/main.yml | 103 +++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
create mode 100644 tests/performance/main.yml
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
new file mode 100644
index 0000000..0943938
--- /dev/null
+++ b/tests/performance/main.yml
@@ -0,0 +1,103 @@
+config:
+ target: "https://playground-next.test.aelf.dev"
+scenarios:
+ - flow:
+ - post:
+ url: "/api/build"
+ json:
+ 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: "\n \n net6.0\n
+ \ AElf.Contracts.HelloWorld\n true\n
+ \ true\n \n
+ \ \n $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/\n
+ \ \n\n \n
+ \ \n \n \n \n\n \n \n \n all\n runtime;
+ build; native; contentfiles; analyzers; buildtransitive\n \n
+ \ \n\n\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";
+
+ import "aelf/core.proto";
+
+ option csharp_namespace = "AElf.Contracts.HelloWorld";
+
+ message AuthorityInfo {
+ aelf.Address contract_address = 1;
+ aelf.Address owner_address = 2;
+ }
+ - path: src/Protobuf/reference/acs12.proto
+ contents: |-
+ /**
+ * AElf Standards ACS12(User Contract Standard)
+ *
+ * Used to manage user contract.
+ */
+ syntax = "proto3";
+
+ package acs12;
+
+ import public "aelf/options.proto";
+ import public "google/protobuf/empty.proto";
+ import public "google/protobuf/wrappers.proto";
+ import "aelf/core.proto";
+
+ option (aelf.identity) = "acs12";
+ option csharp_namespace = "AElf.Standards.ACS12";
+
+ service UserContract{
+
+ }
+
+ //Specified method fee for user contract.
+ message UserContractMethodFees {
+ // List of fees to be charged.
+ repeated UserContractMethodFee fees = 2;
+ // Optional based on the implementation of SetConfiguration method.
+ bool is_size_fee_free = 3;
+ }
+
+ message UserContractMethodFee {
+ // The token symbol of the method fee.
+ string symbol = 1;
+ // The amount of fees to be charged.
+ int64 basic_fee = 2;
+ }
From 8f8cd0721462aca6e9762c7660bc521cf019aae5 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 15:50:00 +0800
Subject: [PATCH 03/15] ci: add load test phases
---
tests/performance/main.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index 0943938..21a3385 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -1,5 +1,10 @@
config:
target: "https://playground-next.test.aelf.dev"
+ phases:
+ - duration: 60
+ arrivalRate: 5 # Start with 5 requests per second
+ - duration: 120
+ arrivalRate: 10 # Increase to 10 requests per second
scenarios:
- flow:
- post:
From 9c77b8bdc7ea5c58b946dcdf4e40f9b52a865294 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:00:34 +0800
Subject: [PATCH 04/15] ci: artillery cloud
---
.github/workflows/load-test.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/load-test.yml b/.github/workflows/load-test.yml
index 5636a90..415d717 100644
--- a/.github/workflows/load-test.yml
+++ b/.github/workflows/load-test.yml
@@ -16,4 +16,6 @@ jobs:
- name: Execute load tests
uses: artilleryio/action-cli@v1
with:
- command: run tests/performance/main.yml
+ command: run tests/performance/main.yml --record
+ env:
+ ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_KEY }}
\ No newline at end of file
From 81a9921a13cc60d6d0778c1fccbe66a79a592b2a Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:36:25 +0800
Subject: [PATCH 05/15] Update main.yml
try single test
---
tests/performance/main.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index 21a3385..c9026e2 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -1,10 +1,10 @@
config:
target: "https://playground-next.test.aelf.dev"
- phases:
- - duration: 60
- arrivalRate: 5 # Start with 5 requests per second
- - duration: 120
- arrivalRate: 10 # Increase to 10 requests per second
+ # phases:
+ # - duration: 60
+ # arrivalRate: 5 # Start with 5 requests per second
+ # - duration: 120
+ # arrivalRate: 10 # Increase to 10 requests per second
scenarios:
- flow:
- post:
From f57b9fd637e5e89a629bd328b7dd1805860384c5 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:52:46 +0800
Subject: [PATCH 06/15] fix: request body
---
tests/performance/helper.js | 8 +++
tests/performance/main.yml | 99 +-----------------------------
tests/performance/requestBody.json | 28 +++++++++
3 files changed, 38 insertions(+), 97 deletions(-)
create mode 100644 tests/performance/helper.js
create mode 100644 tests/performance/requestBody.json
diff --git a/tests/performance/helper.js b/tests/performance/helper.js
new file mode 100644
index 0000000..4f8a16b
--- /dev/null
+++ b/tests/performance/helper.js
@@ -0,0 +1,8 @@
+var JSONFile= require('fs').readFileSync("./requestBody.json");
+
+exports.setJSONBody = (req, context, events, next) => {
+ const requestJSON= JSON.parse(JSONFile);
+
+ context.vars.requestBody = requestJSON;
+ return next();
+};
\ No newline at end of file
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index c9026e2..7d9adbe 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -1,4 +1,5 @@
config:
+ processor: "./helper.js"
target: "https://playground-next.test.aelf.dev"
# phases:
# - duration: 60
@@ -9,100 +10,4 @@ scenarios:
- flow:
- post:
url: "/api/build"
- json:
- 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: "\n \n net6.0\n
- \ AElf.Contracts.HelloWorld\n true\n
- \ true\n \n
- \ \n $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/\n
- \ \n\n \n
- \ \n \n \n \n\n \n \n \n all\n runtime;
- build; native; contentfiles; analyzers; buildtransitive\n \n
- \ \n\n\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";
-
- import "aelf/core.proto";
-
- option csharp_namespace = "AElf.Contracts.HelloWorld";
-
- message AuthorityInfo {
- aelf.Address contract_address = 1;
- aelf.Address owner_address = 2;
- }
- - path: src/Protobuf/reference/acs12.proto
- contents: |-
- /**
- * AElf Standards ACS12(User Contract Standard)
- *
- * Used to manage user contract.
- */
- syntax = "proto3";
-
- package acs12;
-
- import public "aelf/options.proto";
- import public "google/protobuf/empty.proto";
- import public "google/protobuf/wrappers.proto";
- import "aelf/core.proto";
-
- option (aelf.identity) = "acs12";
- option csharp_namespace = "AElf.Standards.ACS12";
-
- service UserContract{
-
- }
-
- //Specified method fee for user contract.
- message UserContractMethodFees {
- // List of fees to be charged.
- repeated UserContractMethodFee fees = 2;
- // Optional based on the implementation of SetConfiguration method.
- bool is_size_fee_free = 3;
- }
-
- message UserContractMethodFee {
- // The token symbol of the method fee.
- string symbol = 1;
- // The amount of fees to be charged.
- int64 basic_fee = 2;
- }
+ json: "{{ requestBody }}"
\ No newline at end of file
diff --git a/tests/performance/requestBody.json b/tests/performance/requestBody.json
new file mode 100644
index 0000000..b62b1f0
--- /dev/null
+++ b/tests/performance/requestBody.json
@@ -0,0 +1,28 @@
+{
+ "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": "\n \n net6.0\n AElf.Contracts.HelloWorld\n true\n true\n \n \n $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/\n \n\n \n \n \n \n \n\n \n \n \n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n \n \n\n\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}"
+ }
+ ]
+}
\ No newline at end of file
From a37ebeced8dc9deefcd76c21fd707f7cd4b31b1e Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:57:11 +0800
Subject: [PATCH 07/15] fix: path
---
tests/performance/helper.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/performance/helper.js b/tests/performance/helper.js
index 4f8a16b..52301e2 100644
--- a/tests/performance/helper.js
+++ b/tests/performance/helper.js
@@ -1,4 +1,4 @@
-var JSONFile= require('fs').readFileSync("./requestBody.json");
+var JSONFile= require('fs').readFileSync("./tests/performance/requestBody.json");
exports.setJSONBody = (req, context, events, next) => {
const requestJSON= JSON.parse(JSONFile);
From 97766b298949407bc277e7a73df4074176cef93b Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Fri, 18 Oct 2024 17:02:42 +0800
Subject: [PATCH 08/15] test api
---
tests/performance/main.yml | 2 +-
tests/performance/requestBody.json | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index 7d9adbe..b8ad1a1 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -9,5 +9,5 @@ config:
scenarios:
- flow:
- post:
- url: "/api/build"
+ url: "/api/test"
json: "{{ requestBody }}"
\ No newline at end of file
diff --git a/tests/performance/requestBody.json b/tests/performance/requestBody.json
index b62b1f0..be3b4b4 100644
--- a/tests/performance/requestBody.json
+++ b/tests/performance/requestBody.json
@@ -23,6 +23,30 @@
{
"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": "\n \n net6.0\n AElf.Contracts.HelloWorld\n \n\n \n 0436;CS2002\n \n \n $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n \n \n\n \n \n nocontract\n \n \n nocontract\n \n \n stub\n \n \n\n \n \n \n\n \n \n \n \n"
+ },
+ {
+ "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\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\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(ContractAddress, senderKeyPair);\n }\n }\n \n}"
}
]
}
\ No newline at end of file
From 5d980939d56949f87b419ef7ecbad81b5096fcf2 Mon Sep 17 00:00:00 2001
From: "yongen.loong"
Date: Fri, 18 Oct 2024 17:38:20 +0800
Subject: [PATCH 09/15] ci: workflow dispatch
---
.github/workflows/load-test.yml | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/load-test.yml b/.github/workflows/load-test.yml
index 415d717..d3c3169 100644
--- a/.github/workflows/load-test.yml
+++ b/.github/workflows/load-test.yml
@@ -1,21 +1,19 @@
name: Artillery Load Test
-
+
on:
- push:
- branches:
- - load-test
-
+ 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 }}
\ No newline at end of file
+ ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_KEY }}
From 49fdeab0ae746e1514e2a5c17cbb8b605a778b35 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Sun, 20 Oct 2024 17:43:14 +0800
Subject: [PATCH 10/15] feat: update load test script
---
tests/performance/main.yml | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index b8ad1a1..9a16d8f 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -8,6 +8,8 @@ config:
# arrivalRate: 10 # Increase to 10 requests per second
scenarios:
- flow:
- - post:
- url: "/api/test"
- json: "{{ requestBody }}"
\ No newline at end of file
+ - post:
+ url: "/playground/build"
+ formData:
+ file:
+ fromFile: "./Archive.zip"
From 98a0a697a2f8ed6272c85a0bb7df04338da4d156 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Sun, 20 Oct 2024 17:44:02 +0800
Subject: [PATCH 11/15] feat: add load test source files
---
tests/performance/Archive.zip | Bin 0 -> 8764 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 tests/performance/Archive.zip
diff --git a/tests/performance/Archive.zip b/tests/performance/Archive.zip
new file mode 100644
index 0000000000000000000000000000000000000000..1906859b4bd7010b93781318d4d1611af687c030
GIT binary patch
literal 8764
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
Date: Sun, 20 Oct 2024 17:46:08 +0800
Subject: [PATCH 12/15] fix: test script
---
tests/performance/main.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index 9a16d8f..ff64bbf 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -11,5 +11,5 @@ scenarios:
- post:
url: "/playground/build"
formData:
- file:
+ contractFiles:
fromFile: "./Archive.zip"
From 8f1bb1b226b6ad232122bfde3f2ba24d70b730e1 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Sun, 20 Oct 2024 17:48:21 +0800
Subject: [PATCH 13/15] fix: increase the timeout
---
tests/performance/main.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index ff64bbf..fa17a24 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -1,5 +1,7 @@
config:
processor: "./helper.js"
+ http:
+ timeout: 60000
target: "https://playground-next.test.aelf.dev"
# phases:
# - duration: 60
From e848dbfb4a0c7fff7d775a9899c9dde7552647b8 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Sun, 20 Oct 2024 17:51:05 +0800
Subject: [PATCH 14/15] fix: use test
---
tests/performance/main.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index fa17a24..cc0d0e2 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -11,7 +11,7 @@ config:
scenarios:
- flow:
- post:
- url: "/playground/build"
+ url: "/playground/test"
formData:
contractFiles:
fromFile: "./Archive.zip"
From eaaf32dd5474b35c3d4fb64a9ada6fd3c470eea2 Mon Sep 17 00:00:00 2001
From: yongenaelf <132553186+yongenaelf@users.noreply.github.com>
Date: Sun, 20 Oct 2024 17:53:50 +0800
Subject: [PATCH 15/15] feat: simulate short burst
---
tests/performance/main.yml | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/tests/performance/main.yml b/tests/performance/main.yml
index cc0d0e2..22ef76c 100644
--- a/tests/performance/main.yml
+++ b/tests/performance/main.yml
@@ -3,11 +3,9 @@ config:
http:
timeout: 60000
target: "https://playground-next.test.aelf.dev"
- # phases:
- # - duration: 60
- # arrivalRate: 5 # Start with 5 requests per second
- # - duration: 120
- # arrivalRate: 10 # Increase to 10 requests per second
+ phases:
+ - duration: 10
+ arrivalRate: 5 # Start with 5 requests per second
scenarios:
- flow:
- post: