Browse Source

test(lnd): add some tests for neutrino

renovate/lint-staged-8.x
Tom Kirkpatrick 6 years ago
parent
commit
38c19ac618
No known key found for this signature in database GPG Key ID: 72203A8EC5967EA8
  1. 57
      app/lib/lnd/neutrino.js
  2. 10
      app/lib/zap/controller.js
  3. 171
      test/unit/lnd/neutrino.spec.js

57
app/lib/lnd/neutrino.js

@ -1,8 +1,11 @@
// @flow
import split2 from 'split2'
import { spawn } from 'child_process'
import EventEmitter from 'events'
import { mainLog, lndLog, lndLogGetLevel } from '../utils/log'
import { fetchBlockHeight } from './util'
import LndConfig from './config'
// Sync statuses
const CHAIN_SYNC_PENDING = 'chain-sync-pending'
@ -24,7 +27,16 @@ const GOT_LND_CFILTER_HEIGHT = 'got-lnd-cfilter-height'
* @extends EventEmitter
*/
class Neutrino extends EventEmitter {
constructor(lndConfig) {
lndConfig: LndConfig
process: any
walletUnlockerGrpcActive: boolean
lightningGrpcActive: boolean
chainSyncStatus: string
currentBlockHeight: number
lndBlockHeight: number
lndCfilterHeight: number
constructor(lndConfig: LndConfig) {
super()
this.lndConfig = lndConfig
this.process = null
@ -36,6 +48,15 @@ class Neutrino extends EventEmitter {
this.lndCfilterHeight = 0
}
static incrementIfHigher = (context: any, property: string, newVal: any): boolean => {
const { [property]: oldVal } = context
if (newVal > oldVal) {
context[property] = newVal
return true
}
return false
}
/**
* Start the Lnd process in Neutrino mode.
* @return {Number} PID of the Lnd process that was started.
@ -169,18 +190,18 @@ class Neutrino extends EventEmitter {
if (!this.lndCfilterHeight || this.lndCfilterHeight > this.currentBlockHeight - 10000) {
if ((match = line.match(/Fetching filter for height=(\d+)/))) {
cfilter = Number(match[1])
cfilter = match[1]
}
}
if (height) {
this.setState(CHAIN_SYNC_IN_PROGRESS)
this.setLndBlockHeight(height)
this.setLndBlockHeight(Number(height))
}
if (cfilter) {
this.setState(CHAIN_SYNC_IN_PROGRESS)
this.setLndCfilterHeight(cfilter)
this.setLndCfilterHeight(Number(cfilter))
}
// Lnd syncing has completed.
@ -208,7 +229,7 @@ class Neutrino extends EventEmitter {
* @param {String} state State to compare against the current state.
* @return {Boolean} Boolean indicating if the current state matches the passed in state.
*/
is(state) {
is(state: string) {
return this.chainSyncStatus === state
}
@ -216,7 +237,7 @@ class Neutrino extends EventEmitter {
* Set the current state and emit an event to notify others if te state as canged.
* @param {String} state Target state.
*/
setState(state) {
setState(state: string) {
if (state !== this.chainSyncStatus) {
this.chainSyncStatus = state
this.emit(state)
@ -227,11 +248,10 @@ class Neutrino extends EventEmitter {
* Set the current block height and emit an event to notify others if it has changed.
* @param {String|Number} height Block height
*/
setCurrentBlockHeight(height) {
const heightAsNumber = Number(height)
if (heightAsNumber > this.currentBlockHeight) {
this.currentBlockHeight = heightAsNumber
this.emit(GOT_CURRENT_BLOCK_HEIGHT, heightAsNumber)
setCurrentBlockHeight(height: number) {
const changed = Neutrino.incrementIfHigher(this, 'currentBlockHeight', height)
if (changed) {
this.emit(GOT_CURRENT_BLOCK_HEIGHT, height)
}
}
@ -239,14 +259,11 @@ class Neutrino extends EventEmitter {
* Set the lnd block height and emit an event to notify others if it has changed.
* @param {String|Number} height Block height
*/
setLndBlockHeight(height) {
const heightAsNumber = Number(height)
if (heightAsNumber > this.lndBlockHeight) {
this.lndBlockHeight = heightAsNumber
this.emit(GOT_LND_BLOCK_HEIGHT, heightAsNumber)
}
if (heightAsNumber > this.currentBlockHeight) {
this.setCurrentBlockHeight(heightAsNumber)
setLndBlockHeight(height: number) {
const changed = Neutrino.incrementIfHigher(this, 'lndBlockHeight', height)
if (changed) {
this.emit(GOT_LND_BLOCK_HEIGHT, height)
this.setCurrentBlockHeight(height)
}
}
@ -254,7 +271,7 @@ class Neutrino extends EventEmitter {
* Set the lnd cfilter height and emit an event to notify others if it has changed.
* @param {String|Number} height Block height
*/
setLndCfilterHeight(height) {
setLndCfilterHeight(height: number) {
const heightAsNumber = Number(height)
this.lndCfilterHeight = heightAsNumber
this.emit(GOT_LND_CFILTER_HEIGHT, heightAsNumber)

10
app/lib/zap/controller.js

@ -5,7 +5,6 @@ import pick from 'lodash.pick'
import Store from 'electron-store'
import StateMachine from 'javascript-state-machine'
import LndConfig from '../lnd/config'
import Neutrino from '../lnd/neutrino'
import Lightning from '../lnd/lightning'
import { initWalletUnlocker } from '../lnd/walletUnlocker'
import { mainLog } from '../utils/log'
@ -51,8 +50,8 @@ const grpcSslCipherSuites = connectionType =>
*/
class ZapController {
mainWindow: BrowserWindow
neutrino: Neutrino
lightning: Lightning
neutrino: any
lightning: any
splashScreenTime: number
lightningGrpcConnected: boolean
lndConfig: LndConfig
@ -74,10 +73,10 @@ class ZapController {
this.mainWindow = mainWindow
// Keep a reference any neutrino process started by us.
this.neutrino = null
this.neutrino = undefined
// Keep a reference to the lightning gRPC instance.
this.lightning = null
this.lightning = undefined
// Time for the splash screen to remain visible.
this.splashScreenTime = 500
@ -303,7 +302,6 @@ class ZapController {
*/
startNeutrino() {
mainLog.info('Starting Neutrino...')
this.neutrino = new Neutrino(this.lndConfig)
this.neutrino.on('error', error => {
mainLog.error(`Got error from lnd process: ${error})`)

171
test/unit/lnd/neutrino.spec.js

@ -0,0 +1,171 @@
import Neutrino from 'lib/lnd/neutrino'
jest.mock('electron', () => {
const { normalize } = require('path')
return {
app: {
getPath: name => normalize(`/tmp/zap-test/${name}`),
getAppPath: () => normalize('/tmp/zap-test')
}
}
})
describe('Neutrino', function() {
describe('Constructor', () => {
beforeAll(() => (this.neutrino = new Neutrino()))
describe('initial values', () => {
it('should set the "process" property to null', () => {
expect(this.neutrino.process).toEqual(null)
})
it('should set the "walletUnlockerGrpcActive" property to false', () => {
expect(this.neutrino.walletUnlockerGrpcActive).toEqual(false)
})
it('should set the "lightningGrpcActive" property to false', () => {
expect(this.neutrino.lightningGrpcActive).toEqual(false)
})
it('should set the "chainSyncStatus" property to "chain-sync-pending"', () => {
expect(this.neutrino.chainSyncStatus).toEqual('chain-sync-pending')
})
it('should set the "currentBlockHeight" property to 0', () => {
expect(this.neutrino.currentBlockHeight).toEqual(0)
})
it('should set the "lndBlockHeight" property to 0', () => {
expect(this.neutrino.lndBlockHeight).toEqual(0)
})
it('should set the "lndCfilterHeight" property to 0', () => {
expect(this.neutrino.lndCfilterHeight).toEqual(0)
})
})
})
describe('.setState', () => {
describe('called with new state', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = 'chain-sync-finished'
this.neutrino.on('chain-sync-finished', this.callback)
this.neutrino.setState(this.newVal)
})
it('should set the state', () => {
expect(this.neutrino.chainSyncStatus).toEqual(this.newVal)
})
it('should emit an event with the new state name', () => {
expect(this.callback).toHaveBeenCalledTimes(1)
})
})
describe('called with current state', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = 'chain-sync-pending'
this.neutrino.on('chain-sync-pending', this.callback)
this.neutrino.setState(this.newVal)
})
it('should not change the state', () => {
expect(this.neutrino.chainSyncStatus).toEqual(this.newVal)
})
it('should not emit an event with the new state name', () => {
expect(this.callback).not.toHaveBeenCalled()
})
})
})
describe('.setCurrentBlockHeight', () => {
describe('called with higher height', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = 100
this.neutrino.on('got-current-block-height', this.callback)
this.neutrino.setCurrentBlockHeight(this.newVal)
})
it('should change the current block height', () => {
expect(this.neutrino.currentBlockHeight).toEqual(this.newVal)
})
it('should emit an event with the new current block height', () => {
expect(this.callback).toHaveBeenCalledTimes(1)
expect(this.callback).toHaveBeenCalledWith(this.newVal)
})
})
describe('called with lower height', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = -1
this.neutrino.on('got-current-block-height', this.callback)
this.neutrino.setCurrentBlockHeight(this.newVal)
})
it('should not change the current block height', () => {
expect(this.neutrino.currentBlockHeight).toEqual(0)
})
it('should not emit an event with the new current block height', () => {
expect(this.callback).not.toHaveBeenCalled()
})
})
})
describe('.setLndBlockHeight', () => {
describe('called with higher height', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = 100
this.neutrino.on('got-lnd-block-height', this.callback)
this.neutrino.setCurrentBlockHeight = jest.fn()
this.neutrino.setLndBlockHeight(this.newVal)
})
it('should change the lnd block height', () => {
expect(this.neutrino.lndBlockHeight).toEqual(this.newVal)
})
it('should emit an event with the new lnd block height', () => {
expect(this.callback).toHaveBeenCalledTimes(1)
expect(this.callback).toHaveBeenCalledWith(this.newVal)
})
it('should call this.setCurrentBlockHeight', () => {
expect(this.neutrino.setCurrentBlockHeight).toHaveBeenCalledTimes(1)
expect(this.neutrino.setCurrentBlockHeight).toHaveBeenCalledWith(this.newVal)
})
})
describe('called with lower height', () => {
beforeEach(() => {
this.neutrino = new Neutrino()
this.callback = jest.fn()
this.newVal = -1
this.neutrino.on('got-lnd-block-height', this.callback)
this.neutrino.setLndBlockHeight(this.newVal)
this.neutrino.setCurrentBlockHeight = jest.fn()
})
it('should not change the lnd block height', () => {
expect(this.neutrino.lndBlockHeight).toEqual(0)
})
it('should not emit an event with the new lnd block height', () => {
expect(this.callback).not.toHaveBeenCalled()
})
it('should not call this.setCurrentBlockHeight', () => {
expect(this.neutrino.setCurrentBlockHeight).not.toHaveBeenCalled()
})
})
})
describe('.is', () => {
describe('called with current state', () => {
beforeEach(() => (this.neutrino = new Neutrino()))
it('should returnn true if the current state matches', () => {
expect(this.neutrino.is('chain-sync-pending')).toEqual(true)
})
it('should return false if the current state does not matche', () => {
expect(this.neutrino.is('some-other-state')).toEqual(false)
})
})
})
})
Loading…
Cancel
Save