Skip to content

Commit

Permalink
Merge pull request #441 from MatrixAI/feature-testnet-tests
Browse files Browse the repository at this point in the history
Integration tests for `testnet.polykey.io`
  • Loading branch information
tegefaulkes authored Oct 27, 2022
2 parents b381e29 + 833c65d commit bb9f39b
Show file tree
Hide file tree
Showing 3 changed files with 313 additions and 1 deletion.
204 changes: 204 additions & 0 deletions tests/integration/testnet/testnetConnection.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import type { NodeIdEncoded } from '@/nodes/types';
import type { Host, Port } from '@/network/types';
import path from 'path';
import fs from 'fs';
import readline from 'readline';
import Logger, { LogLevel, StreamHandler } from '@matrixai/logger';
import * as testUtils from '../../utils';
import { globalRootKeyPems } from '../../fixtures/globalRootKeyPems';

describe('testnet connection', () => {
const logger = new Logger('testnet connection test', LogLevel.INFO, [
new StreamHandler(),
]);
// The testnet node ids/addresses are not fixed
// These will need to be updated whenever they change
const seedNodeId1 =
'vcfi7mgmfn5u82a3obv1gd958ei68ateu4b62i9opm8fc07jvr6dg' as NodeIdEncoded;
const seedNodeIp1 = 'testnet.polykey.io' as Host;
const seedNodePort = 1314 as Port;
let dataDir: string;
beforeEach(async () => {
dataDir = await fs.promises.mkdtemp(
path.join(globalThis.tmpDir, 'polykey-test-'),
);
});
afterEach(async () => {
await fs.promises.rm(dataDir, {
force: true,
recursive: true,
});
});
test('can connect to `testnet.polykey.io` seed node', async () => {
const password = 'abc123';
const nodePath = path.join(dataDir, 'polykey');
// Starting an agent with the testnet as a seed ndoe
const agentProcess = await testUtils.pkSpawn(
[
'agent',
'start',
'--seed-nodes',
`${seedNodeId1}@${seedNodeIp1}:${seedNodePort}`,
'--format',
'json',
'--verbose',
'--workers',
'0',
],
{
env: {
PK_NODE_PATH: nodePath,
PK_PASSWORD: password,
PK_ROOT_KEY: globalRootKeyPems[0],
},
cwd: dataDir,
},
logger,
);
try {
const rlOut = readline.createInterface(agentProcess.stdout!);
await new Promise<string>((resolve, reject) => {
rlOut.once('line', resolve);
rlOut.once('close', reject);
});

// Pinging the seed node
const { exitCode: exitCode1 } = await testUtils.pkStdio(
['nodes', 'ping', seedNodeId1, '--format', 'json'],
{
env: {
PK_NODE_PATH: nodePath,
PK_PASSWORD: password,
},
cwd: dataDir,
},
);
expect(exitCode1).toBe(0);
} finally {
await testUtils.processExit(agentProcess);
}
});
test('network expands when connecting to seed node', async () => {
const password = 'abc123';
// Starting two nodes with the testnet as the seed node
const nodePathA = path.join(dataDir, 'polykeyA');
const nodePathB = path.join(dataDir, 'polykeyB');
const agentProcessA = await testUtils.pkSpawn(
[
'agent',
'start',
'--seed-nodes',
`${seedNodeId1}@${seedNodeIp1}:${seedNodePort}`,
'--format',
'json',
'--verbose',
'--workers',
'0',
],
{
env: {
PK_NODE_PATH: nodePathA,
PK_PASSWORD: password,
PK_ROOT_KEY: globalRootKeyPems[0],
},
cwd: dataDir,
},
logger,
);
const agentProcessB = await testUtils.pkSpawn(
[
'agent',
'start',
'--seed-nodes',
`${seedNodeId1}@${seedNodeIp1}:${seedNodePort}`,
'--format',
'json',
'--verbose',
'--workers',
'0',
],
{
env: {
PK_NODE_PATH: nodePathB,
PK_PASSWORD: password,
PK_ROOT_KEY: globalRootKeyPems[1],
},
cwd: dataDir,
},
logger,
);

try {
const rlOutA = readline.createInterface(agentProcessA.stdout!);
const stdoutA = await new Promise<string>((resolve, reject) => {
rlOutA.once('line', resolve);
rlOutA.once('close', reject);
});
const statusLiveDataA = JSON.parse(stdoutA);
const nodeIdA = statusLiveDataA.nodeId;

const rlOutB = readline.createInterface(agentProcessB.stdout!);
const stdoutB = await new Promise<string>((resolve, reject) => {
rlOutB.once('line', resolve);
rlOutB.once('close', reject);
});
const statusLiveDataB = JSON.parse(stdoutB);
const nodeIdB = statusLiveDataB.nodeId;

// NodeA should ping the seed node
const { exitCode: exitCode1 } = await testUtils.pkStdio(
['nodes', 'ping', seedNodeId1, '--format', 'json'],
{
env: {
PK_NODE_PATH: nodePathA,
PK_PASSWORD: password,
},
cwd: dataDir,
},
);
expect(exitCode1).toBe(0);

// NodeB should ping the seed node
const { exitCode: exitCode2 } = await testUtils.pkStdio(
['nodes', 'ping', seedNodeId1, '--format', 'json'],
{
env: {
PK_NODE_PATH: nodePathB,
PK_PASSWORD: password,
},
cwd: dataDir,
},
);
expect(exitCode2).toBe(0);

// NodeA should be able to ping to NodeB
const { exitCode: exitCode3 } = await testUtils.pkStdio(
['nodes', 'ping', nodeIdB, '--format', 'json'],
{
env: {
PK_NODE_PATH: nodePathA,
PK_PASSWORD: password,
},
cwd: dataDir,
},
);
expect(exitCode3).toBe(0);

// NodeB should be able to ping to NodeA
const { exitCode: exitCode4 } = await testUtils.pkStdio(
['nodes', 'ping', nodeIdA, '--format', 'json'],
{
env: {
PK_NODE_PATH: nodePathB,
PK_PASSWORD: password,
},
cwd: dataDir,
},
);
expect(exitCode4).toBe(0);
} finally {
await testUtils.processExit(agentProcessA);
await testUtils.processExit(agentProcessB);
}
});
});
54 changes: 54 additions & 0 deletions tests/nat/endpointDependentNAT.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ describe('endpoint dependent NAT traversal', () => {
agent2ProxyPort,
tearDownNAT,
} = await testNatUtils.setupNAT('edm', 'dmz', logger);
// Namespace1
// ┌────────────────────────────────────────────────────┐
// │ │ Namespace2
// │ 55551<->PORT1 192.168.0.1:PORT1 │ ┌────────────────────────────────────┐
// │ ┌────────┐ ┌─────┐ ┌─────────┐ │ │ │
// │ │ │ │ ├─────────┤ │ │ │ ┌─────────┐ ┌────────┐ │
// │ │ Agent1 ├────────┤ NAT │ │ Router1 │ │ │ │ Router2 ├────────┤ Agent2 │ │
// │ │ │ │ │ │ │ │ │ └─────────┘ └────────┘ │
// │ └────────┘ └─────┘ └─────────┘ │ │ 192.168.0.2:55555 10.0.0.2:55552 │
// │ 10.0.0.2:55551 │ │ │
// │ │ └────────────────────────────────────┘
// └────────────────────────────────────────────────────┘
// Since node2 is not behind a NAT can directly add its details
await testUtils.pkExec(
[
Expand Down Expand Up @@ -106,6 +118,18 @@ describe('endpoint dependent NAT traversal', () => {
agent2NodeId,
tearDownNAT,
} = await testNatUtils.setupNAT('dmz', 'edm', logger);
// Namespace2
// ┌────────────────────────────────────────────────────┐
// Namespace1 │ │
// ┌────────────────────────────────────┐ │ 192.168.0.2:PORT1 PORT1<->55552 │
// │ │ │ ┌─────────┐ ┌─────┐ ┌────────┐ │
// │ ┌────────┐ ┌─────────┐ │ │ │ ├─────────┤ │ │ │ │
// │ │ Agent1 ├────────┤ Router1 │ │ │ │ Router2 │ │ NAT ├────────┤ Agent2 │ │
// │ └────────┘ └─────────┘ │ │ │ │ │ │ │ │ │
// │ 10.0.0.2:55551 192.168.0.1:55555 │ │ └─────────┘ └─────┘ └────────┘ │
// │ │ │ 10.0.0.2:55552 │
// └────────────────────────────────────┘ │ │
// └────────────────────────────────────────────────────┘
// Agent 2 must ping Agent 1 first, since Agent 2 is behind a NAT
await testUtils.pkExec(
[
Expand Down Expand Up @@ -190,6 +214,18 @@ describe('endpoint dependent NAT traversal', () => {
agent2NodeId,
tearDownNAT,
} = await testNatUtils.setupNATWithSeedNode('edm', 'edm', logger);
// Namespace1 Namespace3 Namespace2
// ┌────────────────────────────────────────────────────┐ ┌──────────────────┐ ┌────────────────────────────────────────────────────┐
// │ │ │ │ │ │
// │ 55551<->PORT1 192.168.0.1:PORT1 │ │ ┌──────────┐ │ │ 192.168.0.2:PORT1 PORT1<->55552 │
// │ ┌────────┐ ┌─────┐ ┌─────────┐ │ │ │ SeedNode │ │ │ ┌─────────┐ ┌─────┐ ┌────────┐ │
// │ │ │ │ ├─────────┤ │ │ │ └──────────┘ │ │ │ ├─────────┤ │ │ │ │
// │ │ Agent1 ├────────┤ NAT │ │ Router1 │ │ │ 192.168.0.3:PORT │ │ │ Router2 │ │ NAT ├────────┤ Agent2 │ │
// │ │ │ │ ├─────────┤ │ │ │ │ │ │ ├─────────┤ │ │ │ │
// │ └────────┘ └─────┘ └─────────┘ │ └──────────────────┘ │ └─────────┘ └─────┘ └────────┘ │
// │ 10.0.0.2:55551 55551<->PORT2 192.168.0.1:PORT2 │ │ 192.168.0.2:PORT2 PORT2<->55552 10.0.0.2:55552 │
// │ │ │ │
// └────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────┘
// Contact details are retrieved from the seed node, but cannot be used
// since port mapping changes between targets in EDM mapping
// Node 2 -> Node 1 ping should fail (Node 1 behind NAT)
Expand Down Expand Up @@ -254,6 +290,24 @@ describe('endpoint dependent NAT traversal', () => {
agent2NodeId,
tearDownNAT,
} = await testNatUtils.setupNATWithSeedNode('edm', 'eim', logger);
// Namespace3
// ┌──────────────────┐
// │ │
// Namespace1 │ ┌──────────┐ │
// ┌────────────────────────────────────────────────────┐ │ │ SeedNode │ │
// │ │ │ └──────────┘ │
// │ 55551<->PORT1 192.168.0.1:PORT1 │ │ 192.168.0.3:PORT │
// │ ┌────────┐ ┌─────┐ ┌─────────┐ │ │ │
// │ │ │ │ ├─────────┤ │ │ └──────────────────┘
// │ │ Agent1 ├────────┤ NAT │ │ Router1 │ │ Namespace2
// │ │ │ │ ├─────────┤ │ │ ┌──────────────────────────────────────────────────┐
// │ └────────┘ └─────┘ └─────────┘ │ │ │
// │ 10.0.0.2:55551 55551<->PORT2 192.168.0.1:PORT2 │ │ ┌─────────┐ ┌─────┐ ┌────────┐ │
// │ │ │ │ Router2 ├───────┤ NAT ├────────┤ Agent2 │ │
// └────────────────────────────────────────────────────┘ │ └─────────┘ └─────┘ └────────┘ │
// │ 192.168.0.2:PORT PORT<->55552 10.0.0.2:55552 │
// │ │
// └──────────────────────────────────────────────────┘
// Since one of the nodes uses EDM NAT we cannot punch through
let exitCode, stdout;
({ exitCode, stdout } = await testUtils.pkExec(
Expand Down
Loading

0 comments on commit bb9f39b

Please sign in to comment.