Skip to content

Commit

Permalink
chore(test): add e2e integration tests for joining the network
Browse files Browse the repository at this point in the history
  • Loading branch information
dtfiedler committed Jun 27, 2024
1 parent f221dbb commit 5983220
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 19 deletions.
35 changes: 22 additions & 13 deletions src/gar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ function gar.leaveNetwork(from, currentTimestamp, msgId)
end

function gar.increaseOperatorStake(from, qty)
assert(type(qty) == "number", "Quantity is required and must be a number!")
assert(type(qty) == "number", "Quantity is required and must be a number")
-- asssert it is an integer
assert(utils.isInteger(qty), "Quantity must be an integer!")
assert(utils.isInteger(qty), "Quantity must be an integer")
assert(qty > 0, "Quantity must be greater than 0")

local gateway = gar.getGateway(from)
Expand All @@ -156,7 +156,7 @@ function gar.increaseOperatorStake(from, qty)
end

function gar.decreaseOperatorStake(from, qty, currentTimestamp, msgId)
assert(type(qty) == "number", "Quantity is required and must be a number!")
assert(type(qty) == "number", "Quantity is required and must be a number")
assert(qty > 0, "Quantity must be greater than 0")

local gateway = gar.getGateway(from)
Expand Down Expand Up @@ -265,10 +265,10 @@ function gar.getGateways()
end

function gar.delegateStake(from, target, qty, currentTimestamp)
assert(type(qty) == "number", "Quantity is required and must be a number!")
assert(type(qty) == "number", "Quantity is required and must be a number")
assert(qty > 0, "Quantity must be greater than 0")
assert(type(target) == "string", "Target is required and must be a string!")
assert(type(from) == "string", "From is required and must be a string!")
assert(type(target) == "string", "Target is required and must be a string")
assert(type(from) == "string", "From is required and must be a string")

local gateway = gar.getGateway(target)
if gateway == nil then
Expand Down Expand Up @@ -343,7 +343,7 @@ function gar.getSettings()
end

function gar.decreaseDelegateStake(gatewayAddress, delegator, qty, currentTimestamp, messageId)
assert(type(qty) == "number", "Quantity is required and must be a number!")
assert(type(qty) == "number", "Quantity is required and must be a number")
assert(qty > 0, "Quantity must be greater than 0")

local gateway = gar.getGateway(gatewayAddress)
Expand Down Expand Up @@ -481,22 +481,31 @@ function gar.isGatewayJoined(gateway, currentTimestamp)
end

function gar.assertValidGatewayParameters(from, stake, settings, observerAddress)
assert(type(from) == "string", "from is required and must be a string!")
assert(type(stake) == "number", "stake is required and must be a number!")
assert(type(settings) == "table", "settings is required and must be a table!")
assert(type(observerAddress) == "string", "observerAddress is required and must be a string!")
assert(type(from) == "string", "from is required and must be a string")
assert(type(stake) == "number", "stake is required and must be a number")
assert(type(settings) == "table", "settings is required and must be a table")
assert(
type(observerAddress) == "string" and utils.isValidArweaveAddress(observerAddress),
"Observer-Address is required and must be a a valid arweave address"
)
assert(type(settings.allowDelegatedStaking) == "boolean", "allowDelegatedStaking must be a boolean")
assert(type(settings.label) == "string", "label is required and must be a string")
assert(type(settings.fqdn) == "string", "fqdn is required and must be a string")
assert(type(settings.protocol) == "string", "protocol is required and must be a string")
assert(
type(settings.protocol) == "string" and settings.protocol == "https",
"protocol is required and must be https"
)
assert(
type(settings.port) == "number"
and utils.isInteger(settings.port)
and settings.port >= 0
and settings.port <= 65535,
"port is required and must be an integer between 0 and 65535"
)
assert(type(settings.properties) == "string", "properties is required and must be a string")
assert(
type(settings.properties) == "string" and utils.isValidArweaveAddress(settings.properties),
"properties is required and must be a string"
)
assert(
stake >= gar.getSettings().operators.minStake,
"Operator stake must be greater than the minimum stake to join the network"
Expand Down
7 changes: 1 addition & 6 deletions src/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ function utils.isInteger(value)
end

function utils.isValidArweaveAddress(address)
local isValidArweaveAddress = #address == 43 and string.match(address, "^[%w-_]+$") ~= nil

if not isValidArweaveAddress then
error("Inavlid arweave address.")
end
return address
return #address == 43 and string.match(address, "^[%w-_]+$") ~= nil
end

function utils.validateFQDN(fqdn)
Expand Down
144 changes: 144 additions & 0 deletions test/gar.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
const { createAntAosLoader } = require('./utils');
const { describe, it } = require('node:test');
const assert = require('node:assert');
const {
AO_LOADER_HANDLER_ENV,
DEFAULT_HANDLE_OPTIONS,
STUB_ADDRESS,
} = require('../tools/constants');

describe('GatewayRegistry', async () => {
const { handle: originalHandle, memory: startMemory } =
await createAntAosLoader();

async function handle(options = {}, mem = startMemory) {
return originalHandle(
mem,
{
...DEFAULT_HANDLE_OPTIONS,
...options,
},
AO_LOADER_HANDLER_ENV,
);
}

describe('Join-Network', () => {
const validGatewayTags = [
{ name: 'Action', value: 'Join-Network' },
{ name: 'Label', value: 'test-gateway' },
{ name: 'Note', value: 'test-note' },
{ name: 'FQDN', value: 'test-fqdn' },
{ name: 'Operator-Stake', value: '500000000000' }, // 50K IO
{ name: 'Port', value: '443' },
{ name: 'Protocol', value: 'https' },
{ name: 'Allow-Delegated-Staking', value: 'true' },
{ name: 'Min-Delegated-Stake', value: '500000000' }, // 500 IO
{ name: 'Delegate-Reward-Share-Ratio', value: '0' },
{ name: 'Observer-Address', value: STUB_ADDRESS },
{
name: 'Properties',
value: 'FH1aVetOoulPGqgYukj0VE0wIhDy90WiQoV3U2PeY44',
},
{ name: 'Auto-Stake', value: 'true' },
];

it('should allow joining of the network record', async () => {
const joinNetworkResult = await handle({
Tags: validGatewayTags,
});

const joinNetworkData = JSON.parse(joinNetworkResult.Messages[0].Data);
// check the gateway record from contract
const gateway = await handle(
{
Tags: [
{ name: 'Action', value: 'Gateway' },
{ name: 'Address', value: STUB_ADDRESS },
],
},
joinNetworkResult.Memory,
);
const gatewayData = JSON.parse(gateway.Messages[0].Data);
assert.deepEqual(gatewayData, {
observerAddress: STUB_ADDRESS,
operatorStake: 500_000_000_000,
totalDelegatedStake: 0,
status: 'joined',
delegates: [],
vaults: [],
startTimestamp: joinNetworkData.startTimestamp,
settings: {
label: 'test-gateway',
note: 'test-note',
fqdn: 'test-fqdn',
port: 443,
protocol: 'https',
allowDelegatedStaking: true,
minDelegatedStake: 500_000_000,
delegateRewardShareRatio: 0,
properties: 'FH1aVetOoulPGqgYukj0VE0wIhDy90WiQoV3U2PeY44',
autoStake: true,
},
stats: {
passedConsecutiveEpochs: 0,
failedConsecutiveEpochs: 0,
totalEpochCount: 0,
failedEpochCount: 0,
passedEpochCount: 0,
prescribedEpochCount: 0,
observedEpochCount: 0,
},
});
});

// bad inputs
const badInputTags = [
// invalid observer
[{ name: 'Observer-Address', value: 'invalid-arweave-address' }],
// invalid stake
[{ name: 'Operator-Stake', value: '49999999999' }], // one less than the minimum
// invalid port
[{ name: 'Port', value: '65536' }],
// invalid protocol
[{ name: 'Protocol', value: 'http' }],
// invalid min-delegated-stake
[{ name: 'Min-Delegated-Stake', value: '499999999' }],
// invalid properties
[{ name: 'Properties', value: 'invalid' }],
];
// for each bad input tag append it to the good tags and verify it fails
for (const tags of badInputTags) {
it(`should fail to join the network with bad input: ${JSON.stringify(tags)}`, async () => {
const overwriteTags = validGatewayTags.filter((tag) => {
return !tags.map((t) => t.name).includes(tag.name);
});
const joinNetworkResult = await handle({
Tags: [...overwriteTags, ...tags],
});

console.log(joinNetworkResult);

// confirm there is an error tag
const errorTag = joinNetworkResult.Messages[0].Tags.find(
(tag) => tag.name === 'Error',
);
//
assert(errorTag, 'Error tag not found');

// confirm gateway did not join
const gateway = await handle(
{
Tags: [
{ name: 'Action', value: 'Gateway' },
{ name: 'Address', value: STUB_ADDRESS },
],
},
joinNetworkResult.Memory,
);
const gatewayData = JSON.parse(gateway.Messages[0].Data);
// assert it does not exist
assert.equal(gatewayData, null);
});
}
});
});

0 comments on commit 5983220

Please sign in to comment.