feat(test): Added e2e test simulating a consumer of JSON RPC

This commit is contained in:
Chris Troutner
2021-07-18 15:46:32 -07:00
parent f9846e95fd
commit fa05fcf3d4
6 changed files with 229 additions and 150 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ class BCHRPC {
*/
async balance (rpcData) {
try {
console.log('createUser rpcData: ', rpcData)
// console.log('createUser rpcData: ', rpcData)
const addrs = rpcData.payload.params.addresses
-145
View File
@@ -1,145 +0,0 @@
/*
A class library of test utility functions.
*/
const BCHJS = require('@psf/bch-js')
const IpfsCoord = require('ipfs-coord')
const IPFS = require('ipfs')
const EventEmitter = require('events')
let _this
class TestUtils {
constructor (localConfig = {}) {
this.bchjs = new BCHJS()
this.eventEmitter = new EventEmitter()
_this = this
}
rpcHandler (inData) {
try {
console.log('inData: ', inData)
_this.eventEmitter.emit('rpcData', inData)
} catch (err) {
console.error('Error in rpcHandler: ', err)
// Do not throw an error. This is a top-level function.
}
}
async sendRPC (ipfsId, cmdStr) {
try {
await this.ipfsCoord.ipfs.orbitdb.sendToDb(ipfsId, cmdStr)
let retData
this.eventEmitter.on('rpcData', inData => {
retData = inData
})
const start = new Date()
let now = start
let timeDiff = 0
do {
await this.bchjs.Util.sleep(1000)
now = new Date()
timeDiff = now.getTime() - start.getTime()
console.log('timeDiff: ', timeDiff)
} while (!retData || timeDiff > 10000) // eslint-disable-line no-unmodified-loop-condition
return retData
} catch (err) {
console.error('Error in sendRPC')
throw err
}
}
async startIpfs () {
try {
// Start the IPFS node.
this.ipfs = await IPFS.create()
await this.ipfs.config.profiles.apply('server')
// Start ipfs-coord.
this.ipfsCoord = new IpfsCoord({
ipfs: this.ipfs,
type: 'node.js',
// type: 'browser',
bchjs: this.bchjs,
privateLog: this.rpcHandler, // Default to console.log
isCircuitRelay: false,
apiInfo: 'none',
announceJsonLd: announceJsonLd
})
await this.ipfsCoord.ipfs.start()
await this.ipfsCoord.isReady()
// Wait to let ipfs-coord connect to subnet peers.
await this.bchjs.Util.sleep(30000)
} catch (err) {
console.error('Error in startIpfs().')
throw err
}
}
async connectToUut (addr) {
try {
await this.ipfs.swarm.connect(addr)
console.log(`E2E TEST: Connected to IPFS node ${addr}`)
} catch (err) {
console.error('Error in connectToUut()')
throw err
}
}
// Get the balance for a BCH address over JSON RPC.
async getBalance (ipfsId) {
try {
const cmd = {
jsonrpc: '2.0',
id: '832',
method: 'bch',
params: {
endpoint: 'balance',
addresses: ['bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj']
}
}
const cmdStr = JSON.stringify(cmd)
console.log(
'ipfs-coord peer info: ',
this.ipfsCoord.ipfs.peers.state.peers[ipfsId]
)
console.log(`Publishing message to ${ipfsId}`)
// await this.ipfsCoord.ipfs.pubsub.publishToPubsubChannel(ipfsId, cmdStr)
// await this.ipfsCoord.ipfs.orbitdb.sendToDb(ipfsId, cmdStr)
const result = await this.sendRPC(ipfsId, cmdStr)
console.log('E2E TEST: Balance command sent.')
console.log('result: ', result)
} catch (err) {
console.error('Error in getBalance()')
throw err
}
}
}
const announceJsonLd = {
'@context': 'https://schema.org/',
'@type': 'WebAPI',
name: 'e2e-test-client',
description: 'A test client runing e2e tests on ipfs-bch-wallet-service.',
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
provider: {
'@type': 'Organization',
name: 'Permissionless Software Foundation',
url: 'https://PSFoundation.cash'
}
}
module.exports = TestUtils
@@ -1,6 +1,6 @@
# Client Simulation E2E Test
# Consumer Simulation E2E Test
The file in this directory simulates a client using JSON RPC over IPFS. It starts a new IPFS node that connects to the ipfs-bch-wallet-service and exercises each JSON RPC endpoint.
The files in this directory simulates a consumer of web services, using JSON RPC over IPFS. It starts a new IPFS node that connects to the ipfs-bch-wallet-service and exercises each JSON RPC endpoint.
## Instructions
@@ -10,11 +10,18 @@ const testData = require('./test-data.json')
async function startTest () {
try {
console.log('E2E TEST: Starting consumer E2E tests...')
await testUtils.startIpfs()
await testUtils.connectToUut(testData.uutAddr)
await testUtils.connectToUut(testData.uutAddr, testData.uutId)
await testUtils.getBalance(testData.uutId)
await testUtils.testBalance(testData.uutId)
await testUtils.testTransaction(testData.uutId)
console.log('E2E TEST: Tests completed successfully!')
process.exit()
} catch (err) {
console.error('Error in startTest(): ', err)
}
+217
View File
@@ -0,0 +1,217 @@
/*
A class library of test utility functions.
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
const IpfsCoord = require('ipfs-coord')
const IPFS = require('ipfs')
const EventEmitter = require('events')
const { v4: uid } = require('uuid')
const jsonrpc = require('jsonrpc-lite')
let _this
class TestUtils {
constructor (localConfig = {}) {
// Encapsulate dependencies.
this.bchjs = new BCHJS()
this.eventEmitter = new EventEmitter()
this.uid = uid
this.jsonrpc = jsonrpc
_this = this
}
// This handler function recieves data from other ipfs-coord peers, like
// the ipfs-bch-wallet-service that we're testing.
// It emits the data as an 'rpcData' event. The tests will listen for this
// event.
rpcHandler (inData) {
try {
// console.log('Data recieved by rpcHandler: ', inData)
const jsonData = JSON.parse(inData)
_this.eventEmitter.emit('rpcData', jsonData)
} catch (err) {
console.error('Error in rpcHandler: ', err)
// Do not throw an error. This is a top-level function.
}
}
// Send the RPC command to the service, wait a period of time for a response.
// Timeout if a response is not recieved.
async sendRPC (ipfsId, cmdStr) {
try {
// Send the RPC command to the server/service.
await this.ipfsCoord.ipfs.orbitdb.sendToDb(ipfsId, cmdStr)
let retData
// This event is triggered when the response comes back.
this.eventEmitter.on('rpcData', inData => {
retData = inData
})
// Used for calculating the timeout.
const start = new Date()
let now = start
let timeDiff = 0
// Wait for the response from the server. Exit once the response is
// recieved, or a timeout occurs.
do {
await this.bchjs.Util.sleep(1000)
now = new Date()
timeDiff = now.getTime() - start.getTime()
// console.log('timeDiff: ', timeDiff)
} while (
// Exit once the RPC data comes back, or if a period of time passes.
!retData || // eslint-disable-line no-unmodified-loop-condition
timeDiff > 10000
)
return retData
} catch (err) {
console.error('Error in sendRPC')
throw err
}
}
async startIpfs () {
try {
// Start the IPFS node.
this.ipfs = await IPFS.create()
await this.ipfs.config.profiles.apply('server')
// Start ipfs-coord.
this.ipfsCoord = new IpfsCoord({
ipfs: this.ipfs,
type: 'node.js',
// type: 'browser',
bchjs: this.bchjs,
privateLog: this.rpcHandler, // Default to console.log
isCircuitRelay: false,
apiInfo: 'none',
announceJsonLd: announceJsonLd
})
await this.ipfsCoord.ipfs.start()
await this.ipfsCoord.isReady()
// Wait to let ipfs-coord connect to subnet peers.
await this.bchjs.Util.sleep(30000)
} catch (err) {
console.error('Error in startIpfs().')
throw err
}
}
// Connect to the unit under test (uut)
async connectToUut (addr, ipfsId) {
try {
try {
await this.ipfs.swarm.connect(addr)
console.log(`E2E TEST: Connected to IPFS node ${addr}`)
} catch (err) {
throw new Error('Could not connect to UUT IPFS node.')
}
// console.log(
// 'ipfs-coord peer info: ',
// this.ipfsCoord.ipfs.peers.state.peers[ipfsId]
// )
if (!this.ipfsCoord.ipfs.peers.state.peers[ipfsId]) {
throw new Error('Could not find UUT in ipfs-coord list of peers.')
}
} catch (err) {
console.error('Error in connectToUut()')
console.log(
'Is the service running? Did you update the test-data.json file?'
)
process.exit()
}
}
// Get the balance for a BCH address over JSON RPC.
async testBalance (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'balance',
addresses: ['bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj']
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Balance command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result: ', result)
if (result.result.value.success && result.result.value.balances) {
console.log('E2E TEST: balance test passed.')
return true
} else {
console.log('E2E TEST: balance test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testBalance()')
throw err
}
}
// Get the info a on transaction over JSON RPC.
async testTransaction (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'transaction',
txid: '01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b'
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Transaction command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result: ', result)
if (result.result.value.status && result.result.value.confirmations) {
console.log('E2E TEST: transaction test passed.')
return true
} else {
console.log('E2E TEST: transaction test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testTransaction()')
throw err
}
}
failTest () {
console.log('Exiting test program.')
process.exit()
}
}
const announceJsonLd = {
'@context': 'https://schema.org/',
'@type': 'WebAPI',
name: 'e2e-test-client',
description: 'A test client runing e2e tests on ipfs-bch-wallet-service.',
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
provider: {
'@type': 'Organization',
name: 'Permissionless Software Foundation',
url: 'https://PSFoundation.cash'
}
}
module.exports = TestUtils