describe('modules/transactions', () => {

  let instance: TransactionsModule;
  let container: Container;
  let sandbox: SinonSandbox;

  let accountsModuleStub: AccountsModuleStub;
  let loggerStub: LoggerStub;
  let dbHelperStub: DbStub;
  let genesisBlock: SignedAndChainedBlockType;
  let transactionPoolStub: TransactionPoolStub;
  let transactionLogicStub: TransactionLogicStub;

  beforeEach(() => {
    sandbox              = sinon.createSandbox();
    container = createContainer();
    container.rebind(Symbols.modules.transactions).to(TransactionsModule);
    instance             = container.get(Symbols.modules.transactions);
    accountsModuleStub   = container.get(Symbols.modules.accounts);
    loggerStub           = container.get(Symbols.helpers.logger);
    dbHelperStub           = container.get(Symbols.helpers.db);
    genesisBlock         = container.get(Symbols.generic.genesisBlock);
    transactionPoolStub  = container.get(Symbols.logic.transactionPool);
    transactionLogicStub = container.get(Symbols.logic.transaction);

    // Reset all stubs
    [accountsModuleStub, loggerStub, dbHelperStub, transactionPoolStub, transactionLogicStub].forEach((stub: any) => {
      if (typeof stub.reset !== 'undefined') {
        stub.reset();
      }
      if (typeof stub.stubReset !== 'undefined') {
        stub.stubReset();
      }
    });
    transactionPoolStub.unconfirmed.reset();
    transactionPoolStub.multisignature.reset();
    transactionPoolStub.bundled.reset();
  });

  afterEach(() => {
    sandbox.restore();
  });

  describe('cleanup', () => {
    it('should resolve', async () => {
      await expect(instance.cleanup()).to.be.fulfilled;
    });
  });

  describe('transactionInPool', () => {
    it('should call txPool.transactionInPool and return', () => {
      transactionPoolStub.stubs.transactionInPool.returns(true);
      const retVal = instance.transactionInPool('testTxId');
      expect(transactionPoolStub.stubs.transactionInPool.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.transactionInPool.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.stubs.transactionInPool.firstCall.args[0]).to.be.equal('testTxId');
      expect(retVal).to.be.true;
    });
  });

  describe('getUnconfirmedTransaction', () => {
    it('should call txPool.unconfirmed.get and return', () => {
      const returnedTx = { test: 'tx' };
      transactionPoolStub.unconfirmed.stubs.get.returns(returnedTx);
      const retVal = instance.getUnconfirmedTransaction('testTxId');
      expect(transactionPoolStub.unconfirmed.stubs.get.calledOnce).to.be.true;
      expect(transactionPoolStub.unconfirmed.stubs.get.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.unconfirmed.stubs.get.firstCall.args[0]).to.be.equal('testTxId');
      expect(retVal).to.be.deep.equal(returnedTx);
    });
  });

  describe('getQueuedTransaction', () => {
    it('should call txPool.queued.get and return', () => {
      const returnedTx = { test: 'tx' };
      transactionPoolStub.queued.stubs.get.returns(returnedTx);
      const retVal = instance.getQueuedTransaction('testTxId');
      expect(transactionPoolStub.queued.stubs.get.calledOnce).to.be.true;
      expect(transactionPoolStub.queued.stubs.get.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.queued.stubs.get.firstCall.args[0]).to.be.equal('testTxId');
      expect(retVal).to.be.deep.equal(returnedTx);
    });
  });

  describe('getQueuedTransaction', () => {
    it('should call txPool.queued.get and return', () => {
      it('should call txPool.unconfirmed.get and return', () => {
        const returnedTx = { test: 'tx' };
        transactionPoolStub.queued.stubs.get.returns(returnedTx);
        const retVal = instance.getQueuedTransaction('testTxId');
        expect(transactionPoolStub.queued.stubs.get.calledOnce).to.be.true;
        expect(transactionPoolStub.queued.stubs.get.firstCall.args.length).to.be.equal(1);
        expect(transactionPoolStub.queued.stubs.get.firstCall.args[0]).to.be.equal('testTxId');
        expect(retVal).to.be.deep.equal(returnedTx);
      });
    });
  });

  describe('getMultisignatureTransaction', () => {
    it('should call txPool.multisignature.get and return', () => {
      const returnedTx = { test: 'tx' };
      transactionPoolStub.multisignature.stubs.get.returns(returnedTx);
      const retVal = instance.getMultisignatureTransaction('testTxId');
      expect(transactionPoolStub.multisignature.stubs.get.calledOnce).to.be.true;
      expect(transactionPoolStub.multisignature.stubs.get.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.multisignature.stubs.get.firstCall.args[0]).to.be.equal('testTxId');
      expect(retVal).to.be.deep.equal(returnedTx);
    });
  });

  describe('getUnconfirmedTransactionList', () => {
    it('should call txPool.unconfirmed.list and return', () => {
      const returnedAr = [{ test: 'tx' }];
      transactionPoolStub.unconfirmed.stubs.list.returns(returnedAr);
      const retVal = instance.getUnconfirmedTransactionList(false, 10);
      expect(transactionPoolStub.unconfirmed.stubs.list.calledOnce).to.be.true;
      expect(transactionPoolStub.unconfirmed.stubs.list.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.unconfirmed.stubs.list.firstCall.args[0]).to.be.equal(false);
      expect(transactionPoolStub.unconfirmed.stubs.list.firstCall.args[1]).to.be.equal(10);
      expect(retVal).to.be.deep.equal(returnedAr);
    });
  });

  describe('getQueuedTransactionList', () => {
    it('should call txPool.queued.list and return', () => {
      const returnedAr = [{ test: 'tx' }];
      transactionPoolStub.queued.stubs.list.returns(returnedAr);
      const retVal = instance.getQueuedTransactionList(false, 10);
      expect(transactionPoolStub.queued.stubs.list.calledOnce).to.be.true;
      expect(transactionPoolStub.queued.stubs.list.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.queued.stubs.list.firstCall.args[0]).to.be.equal(false);
      expect(transactionPoolStub.queued.stubs.list.firstCall.args[1]).to.be.equal(10);
      expect(retVal).to.be.deep.equal(returnedAr);
    });
  });

  describe('getMultisignatureTransactionList', () => {
    it('should call txPool.multisignature.list and return', () => {
      const returnedAr = [{ test: 'tx' }];
      transactionPoolStub.multisignature.stubs.list.returns(returnedAr);
      const retVal = instance.getMultisignatureTransactionList(false, 10);
      expect(transactionPoolStub.multisignature.stubs.list.calledOnce).to.be.true;
      expect(transactionPoolStub.multisignature.stubs.list.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.multisignature.stubs.list.firstCall.args[0]).to.be.equal(false);
      expect(transactionPoolStub.multisignature.stubs.list.firstCall.args[1]).to.be.equal(10);
      expect(retVal).to.be.deep.equal(returnedAr);
    });
  });

  describe('getMergedTransactionList', () => {
    it('should call txPool.getMergedTransactionList and return', () => {
      const returnedAr = [{ test: 'tx' }];
      transactionPoolStub.stubs.getMergedTransactionList.returns(returnedAr);
      const retVal = instance.getMergedTransactionList(10);
      expect(transactionPoolStub.stubs.getMergedTransactionList.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.getMergedTransactionList.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.stubs.getMergedTransactionList.firstCall.args[0]).to.be.equal(10);
      expect(retVal).to.be.deep.equal(returnedAr);
    });
  });

  describe('removeUnconfirmedTransaction', () => {
    it('should call txPool.unconfirmed.remove, txPool.queued.remove, txPool.multisignature.remove', () => {
      instance.removeUnconfirmedTransaction('txId');
      expect(transactionPoolStub.unconfirmed.stubs.remove.calledOnce).to.be.true;
      expect(transactionPoolStub.unconfirmed.stubs.remove.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.unconfirmed.stubs.remove.firstCall.args[0]).to.be.equal('txId');
      expect(transactionPoolStub.queued.stubs.remove.calledOnce).to.be.true;
      expect(transactionPoolStub.queued.stubs.remove.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.queued.stubs.remove.firstCall.args[0]).to.be.equal('txId');
      expect(transactionPoolStub.multisignature.stubs.remove.calledOnce).to.be.true;
      expect(transactionPoolStub.multisignature.stubs.remove.firstCall.args.length).to.be.equal(1);
      expect(transactionPoolStub.multisignature.stubs.remove.firstCall.args[0]).to.be.equal('txId');
    });
  });

  describe('processUnconfirmedTransaction', () => {
    it('should call txPool.processNewTransaction and return', () => {
      const tx = { the: 'tx' };
      transactionPoolStub.stubs.processNewTransaction.returns('done');
      const retVal = instance.processUnconfirmedTransaction(tx as any, false);
      expect(transactionPoolStub.stubs.processNewTransaction.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.processNewTransaction.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.stubs.processNewTransaction.firstCall.args[0]).to.be.deep.equal(tx);
      expect(transactionPoolStub.stubs.processNewTransaction.firstCall.args[1]).to.be.equal(false);
      expect(retVal).to.be.equal('done');
    });
  });

  describe('applyUnconfirmed', () => {
    let tx;
    let sender;
    const requester = { the: 'requester' };

    beforeEach(() => {
      tx     = { the: 'tx', id: 'tx1', blockId: 'blockId' };
      sender = { the: 'sender' };
      accountsModuleStub.stubs.getAccount.returns(requester);
      transactionLogicStub.stubs.applyUnconfirmed.returns('done');
      dbHelperStub.enqueueResponse('performOps', Promise.resolve());

    });

    it('should call logger.debug', async () => {
      await instance.applyUnconfirmed(tx as any, sender as any);
      expect(loggerStub.stubs.debug.calledOnce).to.be.true;
      expect(loggerStub.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(loggerStub.stubs.debug.firstCall.args[0]).to.contain('Applying unconfirmed transaction');
    });

    it('should throw if sender not set and tx not in genesis block', async () => {
      await expect(instance.applyUnconfirmed(tx as any, undefined)).to.be.rejectedWith('Invalid block id');
    });

    it('should not throw if sender not set and tx IS in genesis block', async () => {
      tx.blockId = genesisBlock.id;
      await expect(instance.applyUnconfirmed(tx as any, undefined)).to.be.fulfilled;
    });

    describe('when requesterPublicKey is set', () => {
      beforeEach(() => {
        tx.requesterPublicKey = 'requesterPublicKey';
      });

      it('should call accountsModule.getAccount', async () => {
        await instance.applyUnconfirmed(tx as any, sender);
        expect(accountsModuleStub.stubs.getAccount.calledOnce).to.be.true;
        expect(accountsModuleStub.stubs.getAccount.firstCall.args.length).to.be.equal(1);
        expect(accountsModuleStub.stubs.getAccount.firstCall.args[0]).to.be.deep
          .equal({ publicKey: tx.requesterPublicKey });
      });

      it('should throw if requester not found', async () => {
        accountsModuleStub.stubs.getAccount.returns(false);
        await expect(instance.applyUnconfirmed(tx as any, sender)).to.be.rejectedWith('Requester not found');
      });

      it('should call transactionLogic.applyUnconfirmed with 3 parameters', async () => {
        await instance.applyUnconfirmed(tx as any, sender);
        expect(transactionLogicStub.stubs.applyUnconfirmed.calledOnce).to.be.true;
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args.length).to.be.equal(3);
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args[0]).to.be.deep.equal(tx);
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args[1]).to.be.deep.equal(sender);
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args[2]).to.be.deep.equal(requester);
      });
    });
    describe('when requesterPublicKey is NOT set', () => {
      it('should call transactionLogic.applyUnconfirmed with 2 parameters', async () => {
        await instance.applyUnconfirmed(tx as any, sender);
        expect(transactionLogicStub.stubs.applyUnconfirmed.calledOnce).to.be.true;
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args.length).to.be.equal(2);
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args[0]).to.be.deep.equal(tx);
        expect(transactionLogicStub.stubs.applyUnconfirmed.firstCall.args[1]).to.be.deep.equal(sender);
      });
    });
  });

  describe('undoUnconfirmed', () => {
    const tx     = {
      id             : 'txId',
      senderPublicKey: 'pubKey',
    };
    const sender = { account: 'id' };

    beforeEach(() => {
      accountsModuleStub.stubs.getAccount.resolves(sender);
      transactionLogicStub.stubs.undoUnconfirmed.resolves();
      dbHelperStub.enqueueResponse('performOps', Promise.resolve());
    });

    it('should call logger.debug', async () => {
      await instance.undoUnconfirmed(tx);
      expect(loggerStub.stubs.debug.calledOnce).to.be.true;
      expect(loggerStub.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(loggerStub.stubs.debug.firstCall.args[0]).to.contain('Undoing unconfirmed transaction');
    });

    it('should call accountsModule.getAccount', async () => {
      await instance.undoUnconfirmed(tx);
      expect(accountsModuleStub.stubs.getAccount.calledOnce).to.be.true;
      expect(accountsModuleStub.stubs.getAccount.firstCall.args.length).to.be.equal(1);
      expect(accountsModuleStub.stubs.getAccount.firstCall.args[0]).to.be.deep.equal({ publicKey: tx.senderPublicKey });
    });

    it('should call transactionLogic.undoUnconfirmed', async () => {
      await instance.undoUnconfirmed(tx);
      expect(transactionLogicStub.stubs.undoUnconfirmed.calledOnce).to.be.true;
      expect(transactionLogicStub.stubs.undoUnconfirmed.firstCall.args.length).to.be.equal(2);
      expect(transactionLogicStub.stubs.undoUnconfirmed.firstCall.args[0]).to.be.equal(tx);
      expect(transactionLogicStub.stubs.undoUnconfirmed.firstCall.args[1]).to.be.equal(sender);
    });
  });


  describe('count', () => {
    let txModel: typeof TransactionsModel;
    let txCountStub: SinonStub;
    beforeEach(() => {
      txModel = container.get(Symbols.models.transactions);
      txCountStub = sandbox.stub(txModel, 'count').resolves(12345);
      transactionPoolStub.multisignature.count = 1;
      transactionPoolStub.queued.count         = 2;
      transactionPoolStub.unconfirmed.count    = 3;
    });

    it('should call db.query', async () => {
      await instance.count();
      expect(txCountStub.called).is.true;
    });

    it('should return the expected object', async () => {
      const retVal = await instance.count();
      expect(retVal).to.be.deep.equal({
        confirmed     : 12345,
        multisignature: transactionPoolStub.multisignature.count,
        queued        : transactionPoolStub.queued.count,
        unconfirmed   : transactionPoolStub.unconfirmed.count,
      });
    });
  });

  describe('fillPool', () => {
    const newUnconfirmedTXs = createRandomTransactions({send: 2, vote: 1})
      .map((t) => toBufferedTransaction(t));
    let filterConfIDsStub: SinonStub;
    beforeEach(() => {
      transactionPoolStub.stubs.fillPool.resolves(newUnconfirmedTXs.slice());
      transactionPoolStub.stubs.applyUnconfirmedList.resolves();
      filterConfIDsStub = sandbox.stub(instance, 'filterConfirmedIds').resolves([]);
    });

    it('should call txPool.fillPool', async () => {
      await instance.fillPool();
      expect(transactionPoolStub.stubs.fillPool.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.fillPool.firstCall.args.length).to.be.equal(0);
    });

    it('should call transactionPool.applyUnconfirmedList', async () => {
      await instance.fillPool();
      expect(transactionPoolStub.stubs.applyUnconfirmedList.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args[0]).to.be.deep.equal(newUnconfirmedTXs);
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args[1]).to.be.deep.equal(instance);
    });

    it('should query for confirmed ids', async () => {
      await instance.fillPool();
      expect(filterConfIDsStub.called).is.true;
      expect(filterConfIDsStub.firstCall.args[0]).is.deep.eq(newUnconfirmedTXs.map((t) => t.id));
    });

    it('should exclude already confirmed transaction', async () => {
      filterConfIDsStub.resolves([newUnconfirmedTXs[1].id]);
      await instance.fillPool();
      expect(transactionPoolStub.stubs.applyUnconfirmedList.calledOnce).to.be.true;
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args.length).to.be.equal(2);
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args[0]).to.be.deep.equal([
        newUnconfirmedTXs[0],
        newUnconfirmedTXs[2],
      ]);
      expect(transactionPoolStub.stubs.applyUnconfirmedList.firstCall.args[1]).to.be.deep.equal(instance);
    });
  });

  describe('getByID', () => {
    let txModel: typeof TransactionsModel;
    let findByIDStub: SinonStub;
    beforeEach(() => {
      txModel = container.get(Symbols.models.transactions);
      findByIDStub = sandbox.stub(txModel, 'findById').resolves('tx');
      transactionLogicStub.stubs.dbRead.callsFake((tx) => {
        return { dbRead: tx };
      });
    });

    it('should call db.query', async () => {
      await instance.getByID('12345');
      expect(findByIDStub.called).is.true;
      expect(findByIDStub.firstCall.args[0]).to.be.deep.equal('12345');
    });

    it('should throw if tx not found', async () => {
      findByIDStub.resolves(null);
      await expect(instance.getByID('12345')).to.be.rejectedWith('Transaction not found');
    });

    it('should return tx obj', async () => {
      const retVal = await instance.getByID('12345');
      expect(retVal).to.be.deep.equal('tx');
    });
  });
  describe('checkTransaction', () => {
    let tx: IBaseTransaction<any>;
    beforeEach(() => {
      tx = toBufferedTransaction(createRandomTransactions({send: 1})[0]);
    });
    it ('should throw if account is not found in map', async () => {
      await expect(instance.checkTransaction(tx, {}, 1))
        .to.rejectedWith('Cannot find account from accounts');
    });
    it('should throw if tx has requesterPublicKey but notin accountsMap', async () => {
      tx.requesterPublicKey = Buffer.from('abababab', 'hex');
      accountsModuleStub.stubs.generateAddressByPublicKey.returns('1111R');
      await expect(instance.checkTransaction(tx, {[tx.senderId]: new AccountsModel()}, 1))
        .to.rejectedWith('Cannot find requester from accounts');
    });
    it('should query readyness and throw if not ready', async () => {
      transactionLogicStub.stubs.ready.returns(false);
      await expect(instance.checkTransaction(tx, {[tx.senderId]: new AccountsModel()}, 1))
        .to.rejectedWith(`Transaction ${tx.id} is not ready`);
    });
    it('should query txLogic.verify with proper data', async () => {
      tx.requesterPublicKey = Buffer.from('abababab', 'hex');
      accountsModuleStub.stubs.generateAddressByPublicKey.returns('1111R');
      transactionLogicStub.stubs.ready.returns(true);
      transactionLogicStub.stubs.verify.resolves();

      const account       = new AccountsModel({ address: tx.senderId });
      const requester = new AccountsModel({address: '1111R'});
      await instance.checkTransaction(tx, {
        [tx.senderId]: account,
        '1111R'      : requester,
      }, 1);

      expect(transactionLogicStub.stubs.verify.calledOnce).true;
      expect(transactionLogicStub.stubs.verify.firstCall.args[0]).deep.eq(tx);
      expect(transactionLogicStub.stubs.verify.firstCall.args[1]).deep.eq(account);
      expect(transactionLogicStub.stubs.verify.firstCall.args[2]).deep.eq(requester);
      expect(transactionLogicStub.stubs.verify.firstCall.args[3]).deep.eq(1);
    });
  });
});
Example #2
0
 msg.encode      = (pl) => {
   const m   = oldEncode(pl);
   finishSpy = sandbox.spy(m, 'finish');
   return m;
 };
Example #3
0
 it('should call getMessageInstance', () => {
   getMsgInstSpy = sandbox.spy(instance as any, 'getMessageInstance');
   instance.decode(buf, 'APISuccess');
   expect(getMsgInstSpy.calledOnce).to.be.true;
   expect(getMsgInstSpy.firstCall.args).to.be.deep.equal(['APISuccess', undefined]);
 });
Example #4
0
describe('src/modules/transport.ts', () => {

  let inst: TransportModule;
  let container: Container;
  let sandbox: SinonSandbox;
  const appConfig = {
    peers: { options: { timeout: 1000, }, },
  };

  before(() => {
    sandbox = sinon.createSandbox();
  });

  beforeEach(() => {
    container = createContainer();
    container.rebind(Symbols.generic.appConfig).toConstantValue(appConfig);
    container.rebind(Symbols.modules.transport).to(proxyTransportModule.TransportModule);
  });

  let constants;
  let io: SocketIOStub;
  let schemaStub: ZSchemaStub;
  let balancesSequence: SequenceStub;
  let jobsQueue: JobsQueueStub;
  let logger: LoggerStub;
  let appState: AppStateStub;
  let broadcasterLogic: BroadcasterLogicStub;
  let transactionLogic: TransactionLogicStub;
  let peersLogic: PeersLogicStub;
  let peersModule: PeersModuleStub;
  let multisigModule: MultisignaturesModuleStub;
  let transactionModule: TransactionsModuleStub;
  let systemModule: SystemModuleStub;

  let postConstrA: AppStateStub;
  beforeEach(() => {
    io         = container.get(Symbols.generic.socketIO);
    schemaStub = container.get(Symbols.generic.zschema);

    constants        = container.get(Symbols.helpers.constants);
    balancesSequence = container.getTagged(Symbols.helpers.sequence,
      Symbols.helpers.sequence, Symbols.tags.helpers.balancesSequence);
    jobsQueue        = container.get(Symbols.helpers.jobsQueue);
    logger           = container.get(Symbols.helpers.logger);

    appState         = container.get(Symbols.logic.appState);
    broadcasterLogic = container.get(Symbols.logic.broadcaster);
    transactionLogic = container.get(Symbols.logic.transaction);
    peersLogic       = container.get(Symbols.logic.peers);

    peersModule       = container.get(Symbols.modules.peers);
    multisigModule    = container.get(Symbols.modules.multisignatures);
    transactionModule = container.get(Symbols.modules.transactions);
    systemModule      = container.get(Symbols.modules.system);

    // set appState.setComputed call for @postConstruct method
    postConstrA = new AppStateStub();
    postConstrA.enqueueResponse('get', 5);
    postConstrA.enqueueResponse('get', 5);
    appState.enqueueResponse('setComputed', true);
    appState.stubs.setComputed.callsArgWith(1, postConstrA);

    inst = container.get(Symbols.modules.transport);

    (inst as  any).sequence = {
      addAndPromise: sandbox.spy((w) => Promise.resolve(w())),
    };
  });

  afterEach(() => {
    sandbox.restore();
  });

  describe('postConstructor', () => {

    let instPostConstr: TransportModule;

    beforeEach(() => {
      postConstrA = new AppStateStub();
    });

    it('should call appState.setComputed', () => {
      postConstrA.enqueueResponse('get', 5);
      postConstrA.enqueueResponse('get', 5);
      appState.reset();
      appState.stubs.setComputed.callsArgWith(1, postConstrA);
      appState.enqueueResponse('setComputed', true);
      instPostConstr = container.get(Symbols.modules.transport);

      expect(appState.stubs.setComputed.calledOnce).to.be.true;
      expect(appState.stubs.setComputed.firstCall.args.length).to.be.equal(2);
      expect(appState.stubs.setComputed.firstCall.args[0]).to.be.equal('node.poorConsensus');
      expect(appState.stubs.setComputed.firstCall.args[1]).to.be.a('function');
    });

    it('should call IAppState.get twice', () => {
      postConstrA.enqueueResponse('get', 5);
      postConstrA.enqueueResponse('get', 5);
      appState.reset();
      appState.stubs.setComputed.callsArgWith(1, postConstrA);
      appState.enqueueResponse('setComputed', true);
      instPostConstr = container.get(Symbols.modules.transport);

      expect(postConstrA.stubs.get.calledTwice).to.be.true;

      expect(postConstrA.stubs.get.firstCall.args.length).to.be.equal(1);
      expect(postConstrA.stubs.get.firstCall.args[0]).to.be.equal('node.consensus');

      expect(postConstrA.stubs.get.secondCall.args.length).to.be.equal(1);
      expect(postConstrA.stubs.get.secondCall.args[0]).to.be.equal('node.consensus');
    });

    it('check if IAppState.get result is undefined', () => {
      postConstrA.enqueueResponse('get', undefined);
      appState.reset();
      appState.stubs.setComputed.callsArgWith(1, postConstrA);
      appState.enqueueResponse('setComputed', true);
      instPostConstr = container.get(Symbols.modules.transport);

      expect(postConstrA.stubs.get.calledOnce).to.be.true;
    });
  });

  describe('getFromPeer', function () {
    this.timeout(2100);

    let peer;
    let options;
    let thePeer;
    let res;
    let headers;
    let error;

    let popsicleUseStub;
    let removePeerStub: SinonStub;

    beforeEach(() => {
      peer    = { makeRequest: sandbox.stub()};
      options = {
        method: 'put',
        url   : 'url.com',
      };
      res     = {
        body   : {},
        headers: {},
        method : 'put',
        status : 200,
        url    : 'example.com',
      };
      headers = {
        nethash: 'as8776fsg76sd87',
        version: '1.2.0',
      };

      thePeer = { applyHeaders: sandbox.stub() };
      thePeer.applyHeaders.returns(headers);

      popsicleUseStub      = { use: sandbox.stub().resolves(res) };
      popsicleStub.plugins = { parse: sandbox.stub().returns(1) };
      popsicleStub.request = sandbox.stub().returns(popsicleUseStub);

      removePeerStub = sandbox.stub(inst as any, 'removePeer');

      peersLogic.enqueueResponse('create', thePeer);
      systemModule.enqueueResponse('networkCompatible', true);
      systemModule.enqueueResponse('versionCompatible', true);
      peersModule.enqueueResponse('update', {});
    });

    it('should call peersLogic.create', async () => {
      await   inst.getFromPeer(peer, options);

      expect(peersLogic.stubs.create.calledOnce).to.be.true;
      expect(peersLogic.stubs.create.firstCall.args.length).to.be.equal(1);
      expect(peersLogic.stubs.create.firstCall.args[0]).to.be.deep.equal(peer);
    });

    it('should call popsicle"s methods', async () => {
      await   inst.getFromPeer(peer, options);

      expect(popsicleStub.request.calledOnce).to.be.true;
      expect(popsicleStub.request.firstCall.args.length).to.be.equal(1);
      expect(popsicleStub.request.firstCall.args[0]).to.be.deep.equal({
        body   : null,
        headers: undefined,
        method : 'put',
        timeout: 1000,
        url    : 'http://undefined:undefinedurl.com',
      });

      expect(popsicleUseStub.use.calledOnce).to.be.true;
      expect(popsicleUseStub.use.firstCall.args.length).to.be.equal(1);
      expect(popsicleUseStub.use.firstCall.args[0]).to.be.equal(1);

      expect(popsicleStub.plugins.parse.calledOnce).to.be.true;
      expect(popsicleStub.plugins.parse.firstCall.args.length).to.be.equal(2);
      expect(popsicleStub.plugins.parse.firstCall.args[0]).to.be.deep.equal(['json']);
      expect(popsicleStub.plugins.parse.firstCall.args[1]).to.be.equal(false);
    });

    it('check if options.api', async () => {
      options.api = 'api';

      await inst.getFromPeer(peer, options);

      expect(popsicleStub.request.firstCall.args[0]).to.be.deep.equal({
        body   : null,
        headers: undefined,
        method : 'put',
        timeout: 1000,
        url    : 'http://undefined:undefined/peerapi',
      });
    });

    it('check if options.data', async () => {
      options.data = 'data';

      await inst.getFromPeer(peer, options);

      expect(popsicleStub.request.firstCall.args[0]).to.be.deep.equal({
        body   : 'data',
        headers: undefined,
        method : 'put',
        timeout: 1000,
        url    : 'http://undefined:undefinedurl.com',
      });
    });

    it('should call popsicle twice (retry) if rejects and return 2nd result', async function () {
      this.timeout(2100);
      const start = Date.now();
      popsicleUseStub.use.onFirstCall().rejects(error);
      popsicleUseStub.use.onSecondCall().resolves({status: 500});
      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith('bad response code 500');

      expect(popsicleUseStub.use.calledTwice).is.true;
      expect(Date.now() - start).gt(2000);
    });

    it('should call removePeer and return rejected promise if popsicle throw', async () => {
      error = new Error('error');
      popsicleUseStub.use.rejects(error);

      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith(error);

      expect(removePeerStub.calledOnce).to.be.true;
      expect(removePeerStub.firstCall.args.length).to.be.equal(2);
      expect(removePeerStub.firstCall.args[0]).to.be.deep.equal({ peer: thePeer, code: 'HTTPERROR' });
      expect(removePeerStub.firstCall.args[1]).to.be.equal(error.message);
    });

    it('should call removePeer and return rejected promise if req.status !== 200', async () => {
      res.status = 609;
      popsicleUseStub.use.resolves(res);
      error = new Error(`Received bad response code ${res.status} ${res.method} ${res.url}`);

      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith(error.message);

      expect(removePeerStub.calledOnce).to.be.true;
      expect(removePeerStub.firstCall.args.length).to.be.equal(2);
      expect(removePeerStub.firstCall.args[0]).to.be.deep.equal({ peer: thePeer, code: `ERESPONSE ${res.status}` });
      expect(removePeerStub.firstCall.args[1]).to.be.equal('put http://undefined:undefinedurl.com');
    });

    it('should call thePeer.applyHeaders', async () => {
      await inst.getFromPeer(peer, options);

      expect(thePeer.applyHeaders.calledOnce).to.be.true;
      expect(thePeer.applyHeaders.firstCall.args.length).to.be.equal(1);
      expect(thePeer.applyHeaders.firstCall.args[0]).to.be.equal(res.headers);
    });

    it('should call schemaStub.validate', async () => {
      await inst.getFromPeer(peer, options);

      expect(schemaStub.stubs.validate.calledOnce).to.be.true;
      expect(schemaStub.stubs.validate.firstCall.args.length).to.be.equal(2);
      expect(schemaStub.stubs.validate.firstCall.args[0]).to.be.equal(headers);
      expect(schemaStub.stubs.validate.firstCall.args[1]).to.be.equal(schemaImport.headers);
    });

    it('should call removePeer and return rejected promise if schemaStub.validate returned false', async () => {
      schemaStub.stubs.validate.returns(false);
      error = new Error('Invalid response headers {"nethash":"as8776fsg76sd87","version":"1.2.0"} put http://undefined:undefinedurl.com');

      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith(error.message);

      expect(removePeerStub.calledOnce).to.be.true;
      expect(removePeerStub.firstCall.args.length).to.be.equal(2);
      expect(removePeerStub.firstCall.args[0]).to.be.deep.equal({ peer: thePeer, code: 'EHEADERS' });
      expect(removePeerStub.firstCall.args[1]).to.be.equal('put http://undefined:undefinedurl.com');
    });

    it('should call systemModule.networkCompatible', async () => {
      await inst.getFromPeer(peer, options);

      expect(systemModule.stubs.networkCompatible.calledOnce).to.be.true;
      expect(systemModule.stubs.networkCompatible.firstCall.args.length).to.be.equal(1);
      expect(systemModule.stubs.networkCompatible.firstCall.args[0]).to.be.equal(headers.nethash);
    });

    it('should call removePeer and return rejected promise if systemModule.networkCompatible returned false', async () => {
      error = new Error('Peer is not on the same network as8776fsg76sd87 put http://undefined:undefinedurl.com');
      systemModule.reset();
      systemModule.enqueueResponse('networkCompatible', false);

      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith(error.message);

      expect(removePeerStub.calledOnce).to.be.true;
      expect(removePeerStub.firstCall.args.length).to.be.equal(2);
      expect(removePeerStub.firstCall.args[0]).to.be.deep.equal({ peer: thePeer, code: 'ENETHASH' });
      expect(removePeerStub.firstCall.args[1]).to.be.equal('put http://undefined:undefinedurl.com');
    });

    it('should call systemModule.versionCompatible', async () => {
      await inst.getFromPeer(peer, options);

      expect(systemModule.stubs.versionCompatible.calledOnce).to.be.true;
      expect(systemModule.stubs.versionCompatible.firstCall.args.length).to.be.equal(1);
      expect(systemModule.stubs.versionCompatible.firstCall.args[0]).to.be.equal(headers.version);
    });

    it('should call removePeer and return rejected promise if systemModule.versionCompatible returned false', async () => {
      error = new Error('Peer is using incompatible version 1.2.0 put http://undefined:undefinedurl.com');
      systemModule.reset();
      systemModule.enqueueResponse('networkCompatible', true);
      systemModule.enqueueResponse('versionCompatible', false);

      await expect(inst.getFromPeer(peer, options)).to.be.rejectedWith(error.message);

      expect(removePeerStub.calledOnce).to.be.true;
      expect(removePeerStub.firstCall.args.length).to.be.equal(2);
      expect(removePeerStub.firstCall.args[0]).to.be.deep.equal({ peer: thePeer, code: 'EVERSION 1.2.0' });
      expect(removePeerStub.firstCall.args[1]).to.be.equal('put http://undefined:undefinedurl.com');

    });

    it('should call peersModule.update', async () => {
      await inst.getFromPeer(peer, options);

      expect(peersModule.stubs.update.calledOnce).to.be.true;
      expect(peersModule.stubs.update.firstCall.args.length).to.be.equal(1);
      expect(peersModule.stubs.update.firstCall.args[0]).to.be.equal(thePeer);
    });

    it('should return an object with body and peer properties if everything is ok', async () => {
      expect(await inst.getFromPeer(peer, options)).to.be.deep.equal({
        body: res.body,
        peer: thePeer,
      });
    });
  });

  describe('getFromRandomPeer', () => {

    let config;
    let peers;
    let result;
    let requestHandler;

    let getFromPeerStub;

    beforeEach(() => {
      requestHandler = new APIRequestStub();
      result  = 'hehehe';
      config  = {};
      peers   = [{makeRequest: sandbox.stub().returns(result)}];

      peersModule.enqueueResponse('list', Promise.resolve({ peers }));
    });

    it('should call peersModule.list', async () => {
      await inst.getFromRandomPeer(config, requestHandler);

      expect(peersModule.stubs.list.calledOnce).to.be.true;
      expect(peersModule.stubs.list.firstCall.args.length).to.be.equal(1);
      expect(peersModule.stubs.list.firstCall.args[0]).to.be.deep.equal({
        allowedStates: [PeerState.CONNECTED, PeerState.DISCONNECTED],
        limit        : 1,
      });
    });

    it('should call makeRequest and return result', async () => {
      expect(await inst.getFromRandomPeer(config, requestHandler)).to.be.equal(result);
      expect(peers[0].makeRequest.calledOnce).to.be.true;
      expect(peers[0].makeRequest.firstCall.args.length).to.be.equal(1);
      expect(peers[0].makeRequest.firstCall.args[0]).to.be.deep.equal(requestHandler);
      expect(peers[0].makeRequest.firstCall.args[0]).to.be.instanceOf(APIRequestStub);
    });
  });

  describe('cleanup', () => {
    it('should set loaded in false and return promise.resolve', () => {
      expect(inst.cleanup()).to.be.fulfilled;
      expect((inst as any).loaded).to.be.false;
    });
  });

  describe('onBlockchainReady', () => {
    it('should set loaded in true', () => {
      inst.onBlockchainReady();

      expect((inst as any).loaded).to.be.true;
    });
  });

  describe('onPeersReady', () => {
    let peers;
    let discoverPeersStub: SinonStub;

    beforeEach(() => {
      peers = [{
        pingAndUpdate: sandbox.stub(),
        state        : PeerState.CONNECTED,
        string       : 'string',
        updated      : false,
      }];

      throttleStub.all = sandbox.stub().callsFake((fkArray) => {
        const promiseArray = [];
        for (const fk of fkArray) {
          promiseArray.push(fk());
        }
        return Promise.all(promiseArray);
      });

      jobsQueue.stubs.register.callsArg(1);
      discoverPeersStub = sandbox.stub(inst as any, 'discoverPeers');
      peersLogic.enqueueResponse('list', peers);
    });

    it('should call logger.trace', async () => {
      await inst.onPeersReady();

      // use to async call of jobsQueue.register callback
      process.nextTick(() => {
        const loggerTraceStub = logger.stubs.trace;

        expect(loggerTraceStub.callCount).to.be.equal(4);

        expect(loggerTraceStub.getCall(0).args.length).to.be.equal(1);
        expect(loggerTraceStub.getCall(0).args[0]).to.be.equal('Peers ready');

        expect(loggerTraceStub.getCall(1).args.length).to.be.equal(2);
        expect(loggerTraceStub.getCall(1).args[0]).to.be.equal('Updating peers');
        expect(loggerTraceStub.getCall(1).args[1]).to.be.deep.equal({ count: peers.length });

        expect(loggerTraceStub.getCall(2).args.length).to.be.equal(2);
        expect(loggerTraceStub.getCall(2).args[0]).to.be.equal('Updating peer');
        expect(loggerTraceStub.getCall(2).args[1]).to.be.equal(peers[0].string);

        expect(loggerTraceStub.getCall(3).args.length).to.be.equal(1);
        expect(loggerTraceStub.getCall(3).args[0]).to.be.equal('Updated Peers');
      });
    });

    it('should call jobsQueue.register', async () => {
      await inst.onPeersReady();

      expect(jobsQueue.stubs.register.calledOnce).to.be.true;
      expect(jobsQueue.stubs.register.firstCall.args.length).to.be.equal(3);
      expect(jobsQueue.stubs.register.firstCall.args[0]).to.be.equal('peersDiscoveryAndUpdate');
      expect(jobsQueue.stubs.register.firstCall.args[1]).to.be.a('function');
      expect(jobsQueue.stubs.register.firstCall.args[2]).to.be.equal(5000);
    });

    it('should call discoverPeers', async () => {
      await inst.onPeersReady();

      expect(discoverPeersStub.calledOnce).to.be.true;
      expect(discoverPeersStub.firstCall.args.length).to.be.equal(0);
    });

    it('should logger.error if discoverPeers throw', async () => {
      const error = new Error('error');
      discoverPeersStub.rejects(error);

      await inst.onPeersReady();

      process.nextTick(() => {
        expect(logger.stubs.error.calledOnce).to.be.true;
        expect(logger.stubs.error.firstCall.args.length).to.be.equal(2);
        expect(logger.stubs.error.firstCall.args[0]).to.be.equal('Discovering new peers failed');
        expect(logger.stubs.error.firstCall.args[1]).to.be.equal(error);
      });
    });

    it('should call peersLogic.list', async () => {
      await inst.onPeersReady();

      expect(peersLogic.stubs.list.calledOnce).to.be.true;
      expect(peersLogic.stubs.list.firstCall.args.length).to.be.equal(1);
      expect(peersLogic.stubs.list.firstCall.args[0]).to.be.equal(false);
    });

    it('should call Throttle.all', async () => {
      await inst.onPeersReady();

      expect(throttleStub.all.calledOnce).to.be.true;
      expect(throttleStub.all.firstCall.args.length).to.be.equal(2);
      expect(throttleStub.all.firstCall.args[0]).to.be.a('array');
      expect(throttleStub.all.firstCall.args[1]).to.be.deep.equal({ maxInProgress: 50 });
    });

    describe('Throttle.all callback(for each peer in peers)', () => {

      it('should call pingAndUpdate(check on p.updated is false)', async () => {
        await inst.onPeersReady();

        expect(peers[0].pingAndUpdate.calledOnce).to.be.true;
        expect(peers[0].pingAndUpdate.firstCall.args.length).to.be.equal(0);
      });

      it('should call pingAndUpdate(check on Date.now() - p.updated > 3000)', async () => {
        peers[0].updated = Date.now() - 3001;

        await inst.onPeersReady();
        await wait(10);
        expect(peers[0].pingAndUpdate.calledOnce).to.be.true;
        expect(peers[0].pingAndUpdate.firstCall.args.length).to.be.equal(0);
      });

      it('should call logger.debug if pingAndUpdate throw', async () => {
        const error = new Error('error');
        peers[0].pingAndUpdate.rejects(error);

        await inst.onPeersReady();
        await wait(10);
        expect(logger.stubs.debug.calledOnce).to.be.true;
        expect(logger.stubs.debug.firstCall.args.length).to.be.equal(2);
        expect(logger.stubs.debug.firstCall.args[0]).to.be.equal('Ping failed when updating peer string');
        expect(logger.stubs.debug.firstCall.args[1]).to.be.deep.equal(error);

      });

      describe('false in condition of Throttle.all"s callback', () => {

        it('p in null', async () => {
          peers[0] = null;

          await inst.onPeersReady();
          await wait(100);
          expect(logger.stubs.trace.callCount).to.be.equal(3);
        });

        it('p.state === PeerState.BANNED', async () => {
          peers[0].state = PeerState.BANNED;

          await inst.onPeersReady();
          await wait(10);
          expect(logger.stubs.trace.callCount).to.be.equal(3);
        });

        it('p.update is true and (Date.now() - p.updated) <= 3000', async () => {
          peers[0].updated = Date.now() - 2000;

          await inst.onPeersReady();
          await wait(10);

          expect(logger.stubs.trace.callCount).to.be.equal(3);
        });
      });
    });
  });

  describe('onSignature', () => {

    let broadcast;
    let signature;

    beforeEach(() => {
      signature = { transaction: '1111111', signature: 'aaaabbbb' };
      broadcast = true;
      broadcasterLogic.enqueueResponse('maxRelays', false);
      broadcasterLogic.enqueueResponse('enqueue', false);
      (inst as any).appState = {get: () => 1000};
      const p = new PostSignaturesRequest();
      (inst as any).psrFactory = (a) => {
        p.options = a;
        return p;
      };
    });

    it('should call broadcasterLogic.maxRelays', () => {
      inst.onSignature(signature, broadcast);
      expect(broadcasterLogic.stubs.maxRelays.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args.length).to.be.equal(1);
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args[0]).to.be.deep.equal(signature);
    });

    it('should call broadcasterLogic.enqueue', async () => {
      inst.onSignature(signature, broadcast);

      expect(broadcasterLogic.stubs.enqueue.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.enqueue.firstCall.args.length).to.be.equal(2);
      expect(broadcasterLogic.stubs.enqueue.firstCall.args[0]).to.be.deep.equal({});
      expect(broadcasterLogic.stubs.enqueue.firstCall.args[1].requestHandler).to.be.instanceOf(PostSignaturesRequest);
      expect(broadcasterLogic.stubs.enqueue.firstCall.args[1].requestHandler.options).to.be.deep.equal({data: { signatures: [{
        relays: 1,
        signature: Buffer.from(signature.signature, 'hex'),
        transaction: signature.transaction,
      }] }});
    });

    it('should call io.sockets.emit', async () => {
      inst.onSignature(signature, broadcast);

      expect(io.sockets.emit.calledOnce).to.be.true;
      expect(io.sockets.emit.firstCall.args.length).to.be.equal(2);
      expect(io.sockets.emit.firstCall.args[0]).to.be.deep.equal('signature/change');
      expect(io.sockets.emit.firstCall.args[1]).to.be.deep.equal(signature);
    });

    it('should not call broadcasterLogic.enqueue if broadcast is false', () => {
      broadcast = false;

      inst.onSignature(signature, broadcast);

      expect(broadcasterLogic.stubs.enqueue.notCalled).to.be.true;
    });

    it('should not call broadcasterLogic.enqueue if this.broadcasterLogic.maxRelays returned true', () => {
      broadcasterLogic.reset();
      broadcasterLogic.enqueueResponse('maxRelays', true);

      inst.onSignature(signature, broadcast);

      expect(broadcasterLogic.stubs.enqueue.notCalled).to.be.true;
    });
  });

  describe('onUnconfirmedTransaction', () => {

    let broadcast;
    let transaction;

    beforeEach(() => {
      transaction = {};
      broadcast   = true;
      broadcasterLogic.enqueueResponse('maxRelays', false);
      broadcasterLogic.enqueueResponse('enqueue', false);
      const p = new PostTransactionsRequest();
      (inst as any).ptrFactory = (a) => {
        p.options = a;
        return p;
      };
    });

    it('should call broadcasterLogic.maxRelays', () => {
      inst.onUnconfirmedTransaction(transaction, broadcast);

      expect(broadcasterLogic.stubs.maxRelays.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args.length).to.be.equal(1);
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args[0]).to.be.deep.equal(transaction);
    });

    it('should call broadcasterLogic.enqueue', async () => {
      inst.onUnconfirmedTransaction(transaction, broadcast);

      expect(broadcasterLogic.stubs.enqueue.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.enqueue.firstCall.args.length).to.be.equal(2);
      expect(broadcasterLogic.stubs.enqueue.firstCall.args[0]).to.be.deep.equal({});
      expect(broadcasterLogic.stubs.enqueue.firstCall.args[1].requestHandler.options).to.be.deep.equal({data: {transactions:[transaction]}});
    });

    it('should call io.sockets.emit', async () => {
      inst.onUnconfirmedTransaction(transaction, broadcast);

      expect(io.sockets.emit.calledOnce).to.be.true;
      expect(io.sockets.emit.firstCall.args.length).to.be.equal(2);
      expect(io.sockets.emit.firstCall.args[0]).to.be.deep.equal('transactions/change');
      expect(io.sockets.emit.firstCall.args[1]).to.be.deep.equal(transaction);
    });

    it('should not call broadcasterLogic.enqueue if broadcast is false', () => {
      broadcast = false;

      inst.onUnconfirmedTransaction(transaction, broadcast);

      expect(broadcasterLogic.stubs.enqueue.notCalled).to.be.true;
    });

    it('should not call broadcasterLogic.enqueue if this.broadcasterLogic.maxRelays returned true', () => {
      broadcasterLogic.reset();
      broadcasterLogic.enqueueResponse('maxRelays', true);

      inst.onUnconfirmedTransaction(transaction, broadcast);

      expect(broadcasterLogic.stubs.enqueue.notCalled).to.be.true;
    });
  });

  describe('onNewBlock', () => {

    let broadcast;
    let block;

    beforeEach(() => {
      block                                = {
        blockSignature    : Buffer.from('aa', 'hex'),
        generatorPublicKey: Buffer.from('bb', 'hex'),
        payloadHash       : Buffer.from('cc', 'hex'),
        transactions      : [],
      };
      broadcast                            = true;
      (inst as any).systemModule.broadhash = 'broadhash';
      systemModule.enqueueResponse('update', Promise.resolve());
      broadcasterLogic.enqueueResponse('maxRelays', false);
      broadcasterLogic.enqueueResponse('broadcast', Promise.resolve());
      const p = new PostBlocksRequest();
      (inst as any).pblocksFactory = (a) => {
        p.options = a;
        return p;
      };
    });

    it('should call systemModule.update', async () => {
      await inst.onNewBlock(block, broadcast);

      expect(systemModule.stubs.update.calledOnce).to.be.true;
      expect(systemModule.stubs.update.firstCall.args.length).to.be.equal(0);
    });

    it('should call broadcasterLogic.maxRelays', async () => {
      await inst.onNewBlock(block, broadcast);

      expect(broadcasterLogic.stubs.maxRelays.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args.length).to.be.equal(1);
      expect(broadcasterLogic.stubs.maxRelays.firstCall.args[0]).to.be.deep.equal(block);
    });

    it('should call broadcasterLogic.broadcast', async () => {
      await inst.onNewBlock(block, broadcast);

      expect(broadcasterLogic.stubs.broadcast.calledOnce).to.be.true;
      expect(broadcasterLogic.stubs.broadcast.firstCall.args.length).to.be.equal(2);
      expect(broadcasterLogic.stubs.broadcast.firstCall.args[0]).to.be.deep.equal({
        broadhash: 'broadhash',
        limit    : constants.maxPeers,
      });
      expect(broadcasterLogic.stubs.broadcast.firstCall.args[1].requestHandler.options).to.be.deep.equal({
          data     : {
            block: {
              blockSignature    : Buffer.from('aa', 'hex'),
              generatorPublicKey: Buffer.from('bb', 'hex'),
              payloadHash       : Buffer.from('cc', 'hex'),
              transactions      : [],
            },
          },
      });
    });

    it('should call io.sockets.emit', async () => {
      await inst.onNewBlock(block, broadcast);

      expect(io.sockets.emit.calledOnce).to.be.true;
      expect(io.sockets.emit.firstCall.args.length).to.be.equal(2);
      expect(io.sockets.emit.firstCall.args[0]).to.be.deep.equal('blocks/change');
      expect(io.sockets.emit.firstCall.args[1]).to.be.deep.equal(block);
    });

    it('should not call broadcasterLogic.broadcast if broadcasterLogic.maxRelays returns true', async () => {
      broadcasterLogic.reset();
      broadcasterLogic.enqueueResponse('maxRelays', true);

      await inst.onNewBlock(block, broadcast);

      expect(broadcasterLogic.stubs.broadcast.notCalled).to.be.true;
    });

    it('check if broadcast is false', () => {
      broadcast = false;

      const p = inst.onNewBlock(block, broadcast);

      expect(p).to.be.fulfilled;
      expect(broadcasterLogic.stubs.enqueue.notCalled).to.be.true;
    });
    it('should ignore broadcast error if any and, more importantly avoid waiting for broadcaster result', async () => {
      broadcasterLogic.reset();
      broadcasterLogic.enqueueResponse('maxRelays', false);
      let finished  = false;
      const promise = wait(1000)
        .then(() => finished = true);

      broadcasterLogic.enqueueResponse('broadcast', promise);

      await inst.onNewBlock(block, true);
      expect(finished).to.be.false;
      await promise;
    });
  });

  describe('receiveSignatures', () => {

    let receiveSignatureStub: SinonStub;
    let query;

    beforeEach(() => {
      query                = [{ transaction: 'transaction', signature: 'signature' }];
      receiveSignatureStub = sandbox.stub(inst as any, 'receiveSignature');
    });

    it('should call receiveSignature', async () => {
      await inst.receiveSignatures(query);

      expect(receiveSignatureStub.calledOnce).to.be.true;
      expect(receiveSignatureStub.firstCall.args.length).to.be.equal(1);
      expect(receiveSignatureStub.firstCall.args[0]).to.be.deep.equal(query[0]);
    });

    it('should call logger.debug if receiveSignature throw error', async () => {
      const error = new Error('error');
      receiveSignatureStub.rejects(error);

      await inst.receiveSignatures(query);

      expect(logger.stubs.debug.calledOnce).to.be.true;
      expect(logger.stubs.debug.firstCall.args.length).to.be.equal(2);
      expect(logger.stubs.debug.firstCall.args[0]).to.be.equal(error);
      expect(logger.stubs.debug.firstCall.args[1]).to.be.deep.equal(query[0]);
    });
  });

  describe('receiveSignature', () => {

    let signature;

    beforeEach(() => {
      signature = { transaction: 'transaction', signature: 'signature' };

      multisigModule.enqueueResponse('processSignature', Promise.resolve());
    });

    it('should call multisigModule.processSignature', async () => {
      await inst.receiveSignature(signature);

      expect(multisigModule.stubs.processSignature.calledOnce).to.be.true;
      expect(multisigModule.stubs.processSignature.firstCall.args.length).to.be.equal(1);
      expect(multisigModule.stubs.processSignature.firstCall.args[0]).to.be.deep.equal(signature);
    });

    it('should throw error multisigModule.processSignature throw error', async () => {
      const error = new Error('error');
      multisigModule.reset();
      multisigModule.enqueueResponse('processSignature', Promise.reject(error));

      await  expect(inst.receiveSignature(signature)).to.be.rejectedWith('Error processing signature: error');
    });
  });

  describe('receiveTransactions', () => {

    let transactions;
    let peer;
    let extraLogMessage;

    beforeEach(() => {
      transactions    = createRandomTransactions({send: 2});
      peer            = { ip: 'ip', port: 'port' };
      extraLogMessage = 'extraLogMessage';
      transactionLogic.stubs.objectNormalize.callsFake((tx) => tx);
      transactionModule.stubs.filterConfirmedIds.resolves([]);
      transactionModule.stubs.processUnconfirmedTransaction.resolves();
      peersModule.stubs.remove.returns(null);
    });

    describe('transactionLogic.objectNormalize throw error', () => {

      let error;

      beforeEach(() => {
        error = new Error('error');
        transactionLogic.stubs.objectNormalize.throws(error);
      });

      it('should throw error', async () => {
        await expect(inst.receiveTransactions(transactions, peer, false)).to.be.rejectedWith('Invalid transaction body error');
      });

      it('should call removePeer', async () => {
        await expect(inst.receiveTransactions(transactions, peer, false)).to.be.rejectedWith('Invalid transaction body error');

        expect(peersModule.stubs.remove.calledOnce).to.be.true;
        expect(peersModule.stubs.remove.firstCall.args.length).to.be.equal(2);
        expect(peersModule.stubs.remove.firstCall.args[0]).to.be.deep.equal(peer.ip);
        expect(peersModule.stubs.remove.firstCall.args[1]).to.be.deep.equal(peer.port);
      });

    });

    it('should call balancesSequence.addAndPromise', async () => {
      await inst.receiveTransactions(transactions, peer, false);

      expect(balancesSequence.spies.addAndPromise.calledOnce).to.be.true;
      expect(balancesSequence.spies.addAndPromise.firstCall.args.length).to.be.equal(1);
      expect(balancesSequence.spies.addAndPromise.firstCall.args[0]).to.be.a('function');
    });

    it('should call transactionModule.processUnconfirmedTransaction', async () => {
      await inst.receiveTransactions(transactions, peer, false);

      expect(transactionModule.stubs.processUnconfirmedTransaction.calledTwice).to.be.true;
      expect(transactionModule.stubs.processUnconfirmedTransaction.firstCall.args.length).to.be.equal(2);
      expect(transactionModule.stubs.processUnconfirmedTransaction.firstCall.args[0]).to.be.deep.equal(transactions[0]);
      expect(transactionModule.stubs.processUnconfirmedTransaction.firstCall.args[1]).to.be.equal(false);

      expect(transactionModule.stubs.processUnconfirmedTransaction.secondCall.args.length).to.be.equal(2);
      expect(transactionModule.stubs.processUnconfirmedTransaction.secondCall.args[0]).to.be.deep.equal(transactions[1]);
      expect(transactionModule.stubs.processUnconfirmedTransaction.secondCall.args[1]).to.be.equal(false);
    });

    it('should filter out already confirmed ids', async () => {
      transactionModule.stubs.filterConfirmedIds.resolves([transactions[1].id]);
      await inst.receiveTransactions(transactions, peer, true);
      expect(transactionModule.stubs.processUnconfirmedTransaction.calledOnce).is.true;
      expect(transactionModule.stubs.processUnconfirmedTransaction.firstCall.args).deep.eq([
        transactions[0],
        true,
      ]);
    });

    describe('peer null', () => {
      it('should not remove null peer if failed to objectNormalize', async () => {
        transactionLogic.stubs.objectNormalize.throws(new Error('error'));
        await expect(inst.receiveTransactions(transactions, null, false)).to.be
          .rejectedWith('Invalid transaction body error');

        expect(peersModule.stubs.remove.calledOnce).to.be.false;
      });
      it('not throw for peer.* access if txs are ok', async () => {
        await inst.receiveTransactions(transactions, null, false)
      });
    });
  });

  describe('removePeer', () => {

    let options;
    let extraMessage;

    beforeEach(() => {
      extraMessage = 'eeeemessage';
      options      = {
        code: 'code',
        peer: {
          ip  : 'ip',
          port: 'port',
        },
      };
      peersModule.enqueueResponse('remove', {});
    });

    it('should call logger.debug', () => {
      (inst as any).removePeer(options, extraMessage);

      expect(logger.stubs.debug.calledOnce).to.be.true;
      expect(logger.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.debug.firstCall.args[0]).to.be.equal('code Removing peer undefined eeeemessage');
    });

    it('should call peersModule.remove', () => {
      (inst as any).removePeer(options, extraMessage);

      expect(peersModule.stubs.remove.calledOnce).to.be.true;
      expect(peersModule.stubs.remove.firstCall.args.length).to.be.equal(2);
      expect(peersModule.stubs.remove.firstCall.args[0]).to.be.equal('ip');
      expect(peersModule.stubs.remove.firstCall.args[1]).to.be.equal('port');
    });
  });

  describe('discoverPeers', () => {

    let response;
    let acceptablePeers;
    let peer;

    let getFromRandomPeerStub: SinonStub;

    beforeEach(() => {
      response        = {
        body: {
          peers: 'peers',
        },
      };
      acceptablePeers = [{}];
      peer            = { string: 'string' };

      schemaStub.stubs.validate.onCall(0).callsArg(2);
      peersLogic.enqueueResponse('acceptable', acceptablePeers);
      peersLogic.enqueueResponse('create', peer);
      peersLogic.enqueueResponse('upsert', true);
      getFromRandomPeerStub = sandbox.stub(inst as any, 'getFromRandomPeer').resolves(response);
      const p = new PeersListRequest();
      (inst as any).plFactory = (a) => {
        p.options = a;
        return p;
      };
    });

    it('should call logger.trace', async () => {
      await (inst as any).discoverPeers();

      expect(logger.stubs.trace.calledOnce).to.be.true;
      expect(logger.stubs.trace.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.trace.firstCall.args[0]).to.be.equal('Transport->discoverPeers');
    });

    it('should call getFromRandomPeer', async () => {
      await (inst as any).discoverPeers();

      expect(getFromRandomPeerStub.calledOnce).to.be.true;
      expect(getFromRandomPeerStub.firstCall.args.length).to.be.equal(2);
      expect(getFromRandomPeerStub.firstCall.args[0]).to.be.deep.equal({});
      expect(getFromRandomPeerStub.firstCall.args[1]).to.be.deep.equal(new PeersListRequest());
    });

    it('should call schemaStub.validate resolves', async () => {
      await (inst as any).discoverPeers();

      expect(schemaStub.stubs.validate.calledTwice).to.be.true;
      expect(schemaStub.stubs.validate.firstCall.args.length).to.be.equal(3);
      expect(schemaStub.stubs.validate.firstCall.args[0]).to.be.equal(response);
      expect(schemaStub.stubs.validate.firstCall.args[1]).to.be.equal(peersSchema.discover.peers);
      expect(schemaStub.stubs.validate.firstCall.args[2]).to.be.a('function');
    });

    it('should call peersLogic.acceptable', async () => {
      await (inst as any).discoverPeers();

      expect(peersLogic.stubs.acceptable.calledOnce).to.be.true;
      expect(peersLogic.stubs.acceptable.firstCall.args.length).to.be.equal(1);
      expect(peersLogic.stubs.acceptable.firstCall.args[0]).to.be.equal(response.peers);
    });

    it('should call peersLogic.create', async () => {
      await (inst as any).discoverPeers();

      expect(peersLogic.stubs.create.calledOnce).to.be.true;
      expect(peersLogic.stubs.create.firstCall.args.length).to.be.equal(1);
      expect(peersLogic.stubs.create.firstCall.args[0]).to.be.equal(acceptablePeers[0]);
    });

    it('should call schemaStub.validate', async () => {
      await (inst as any).discoverPeers();

      expect(schemaStub.stubs.validate.calledTwice).to.be.true;
      expect(schemaStub.stubs.validate.secondCall.args.length).to.be.equal(2);
      expect(schemaStub.stubs.validate.secondCall.args[0]).to.be.equal(peer);
      expect(schemaStub.stubs.validate.secondCall.args[1]).to.be.equal(peersSchema.discover.peer);
    });

    it('should call peersLogic.upsert', async () => {
      await (inst as any).discoverPeers();

      expect(peersLogic.stubs.upsert.calledOnce).to.be.true;
      expect(peersLogic.stubs.upsert.firstCall.args.length).to.be.equal(2);
      expect(peersLogic.stubs.upsert.firstCall.args[0]).to.be.equal(peer);
      expect(peersLogic.stubs.upsert.firstCall.args[1]).to.be.equal(true);
    });

    it('should call logger.debug', async () => {
      await (inst as any).discoverPeers();

      expect(logger.stubs.debug.calledOnce).to.be.true;
      expect(logger.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.debug.firstCall.args[0]).to.be.equal('Discovered 1 peers - Rejected 0 - AlreadyKnown 0');
    });

    it('check if schemaStub.validate returns false then call logger.warn', async () => {
      schemaStub.stubs.validate.onCall(1).returns(false);

      await (inst as any).discoverPeers();

      expect(logger.stubs.warn.calledOnce).to.be.true;
      expect(logger.stubs.warn.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.warn.firstCall.args[0]).to.be.equal('Rejecting invalid peer: string');

      expect(logger.stubs.debug.calledOnce).to.be.true;
      expect(logger.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.debug.firstCall.args[0]).to.be.equal('Discovered 0 peers - Rejected 1 - AlreadyKnown 0');
    });

    it('check if peersLogic.upsert check that current peer already known', async () => {
      peersLogic.reset();
      peersLogic.enqueueResponse('acceptable', acceptablePeers);
      peersLogic.enqueueResponse('create', peer);
      peersLogic.enqueueResponse('upsert', undefined);

      await (inst as any).discoverPeers();

      expect(logger.stubs.debug.calledOnce).to.be.true;
      expect(logger.stubs.debug.firstCall.args.length).to.be.equal(1);
      expect(logger.stubs.debug.firstCall.args[0]).to.be.equal('Discovered 0 peers - Rejected 0 - AlreadyKnown 1');
    });
  });

});
Example #5
0
 (instance as any).getMessageInstance = (namespace, messageType) => {
   msg        = (instance2 as any).getMessageInstance(namespace, messageType);
   verifyStub = sandbox.stub(msg, 'verify').returns('Test Err');
   return msg;
 };
test.afterEach(function () {
  sandbox.restore();
});
describe('apis/requests/PostBlocksRequest', () => {
  let options;
  let instance: PostBlocksRequest;
  let pbHelperStub: ProtoBufHelperStub;
  let blocksModelStub: any;
  let sandbox: SinonSandbox;

  beforeEach(() => {
    const container = createContainer();
    options = {data: {block: 'b1'}};
    sandbox = sinon.createSandbox();
    instance = new PostBlocksRequest();
    instance.options = options;
    pbHelperStub = container.get(Symbols.helpers.protoBuf);
    (instance as any).protoBufHelper = pbHelperStub;
    blocksModelStub = {toStringBlockType: sandbox.stub().callsFake((a) => a) };
    (instance as any).blocksModel = blocksModelStub;
    (instance as any).generateBytesBlock = sandbox.stub().callsFake((a) => a);
    pbHelperStub.enqueueResponse('validate', true);
    pbHelperStub.enqueueResponse('encode', 'encodedValue');
  });

  afterEach(() => {
    sandbox.restore();
  });

  describe('getRequestOptions', () => {
    describe('protoBuf = false', () => {
      it('should return request options as json', () => {
        const reqOpts = instance.getRequestOptions(false);
        expect(reqOpts).to.be.deep.equal({
          data: { block: 'b1' },
          isProtoBuf: false,
          method: 'POST',
          url: '/peer/blocks',
        });
      });
    });
    describe('protoBuf = true', () => {
      it('should call protoBufHelper.validate', () => {
        instance.getRequestOptions(true);
        expect(pbHelperStub.stubs.validate.calledOnce)
          .to.be.true;
        expect(pbHelperStub.stubs.validate.firstCall.args)
          .to.be.deep.equal([options.data, 'transportBlocks', 'transportBlock']);
      });

      it('should call protoBufHelper.encode if validate is true', () => {
        instance.getRequestOptions(true);
        expect(pbHelperStub.stubs.encode.calledOnce)
          .to.be.true;
        expect(pbHelperStub.stubs.encode.firstCall.args)
          .to.be.deep.equal([options.data, 'transportBlocks', 'transportBlock']);
      });

      it('should return from protoBufHelper.encode into .data if validate is true', () => {
        const val = instance.getRequestOptions(true);
        expect(val.data).to.be.equal('encodedValue');
      });

      it('should throw if validate is false', () => {
        pbHelperStub.stubs.validate.returns(false);
        expect(() => { instance.getRequestOptions(true); }).to.throw('Failed to encode ProtoBuf');
      });
    });
  });

  describe('getBaseUrl', () => {
    describe('protoBuf = false', () => {
      it('should return the right URL', () => {
        const url = (instance as any).getBaseUrl(false);
        expect(url).to.be.equal('/peer/blocks');
      });
    });
    describe('protoBuf = true', () => {
      it('should return the right URL', () => {
        const url = (instance as any).getBaseUrl(true);
        expect(url).to.be.equal('/v2/peer/blocks');
      });
    });
  });

  describe('getResponseData', () => {
    let supportsStub: SinonStub;
    let decodeStub: SinonStub;
    beforeEach(() => {
      supportsStub = sandbox.stub();
      decodeStub = sandbox.stub().returns('decodedValue');
      (instance as any).peerSupportsProtoBuf = supportsStub;
      (instance as any).decodeProtoBufResponse = decodeStub;
    });

    describe('protoBuf = false', () => {
      it('should return the response body', () => {
        supportsStub.returns(false);
        const ret = instance.getResponseData({body: 'responseBody'});
        expect(ret).to.be.equal('responseBody');
      });
    });
    describe('protoBuf = true', () => {
      it('should return the decoded response body', () => {
        supportsStub.returns(true);
        decodeStub.returns('decodedValue');
        const ret = instance.getResponseData({body: 'requestBody'});
        expect(ret).to.be.equal('decodedValue');
      });
    });
  });

  // TODO: Move this test to APIRequest
  /*
  describe('generateBytesBlock()', () => {
    const block = {
      transactions: ['tx1', 'tx2'],
    };

    beforeEach(() => {
      blockLogicStub.stubs.getBytes.returns(Buffer.from('112233', 'hex'));
      generateBytesTransactionStub = sandbox.stub(instance as any, 'generateBytesTransaction')
        .returns(Buffer.from('0123', 'hex'));
    });

    it('should call getBytes', () => {
      (instance as any).generateBytesBlock(block);
      expect(blockLogicStub.stubs.getBytes.calledOnce).to.be.true;
      expect(blockLogicStub.stubs.getBytes.firstCall.args).to.be.deep.equal([block]);
    });

    it('should call generateBytesTransaction for each tx', () => {
      (instance as any).generateBytesBlock(block);
      expect(generateBytesTransactionStub.callCount).to.be.equal(block.transactions.length);
      expect(generateBytesTransactionStub.args).to.be.deep.equal(block.transactions.map((t) => [t]));
    });

    it('should included all fields', () => {
      const val = (instance as any).generateBytesBlock(block);
      expect(val).to.be.deep.equal({
        bytes       : Buffer.from('112233', 'hex'),
        height      : block.height,
        transactions: block.transactions.map(() => Buffer.from('0123', 'hex')),
      });
    });
  });
  */
});
Example #8
0
 afterEach(function () {
     sandbox.restore();
     mockery.deregisterAll();
     mockery.disable();
 });
Example #9
0
describe('modules/accounts', () => {
  let sandbox: SinonSandbox;
  let accountLogicStub: AccountLogicStub;
  let accountModule: IAccountsModule;
  let container: Container;

  beforeEach(() => {
    sandbox          = sinon.createSandbox();
    container        = createContainer();
    accountLogicStub = container.get(Symbols.logic.account);
    container.rebind<IAccountsModule>(Symbols.modules.accounts).to(AccountsModule).inSingletonScope();
    accountModule = container.get<any>(Symbols.modules.accounts);
  });

  afterEach(() => {
    sandbox.restore();
  });

  describe('cleanup', () => {
    it('should return resolved promise', async () => {
      await expect(accountModule.cleanup()).to.be.fulfilled;
    });
  });

  describe('.getAccount', () => {
    it('should call accountLogic.get', async () => {
      accountLogicStub.enqueueResponse('get', 'meow');
      await accountModule.getAccount({address: '1L'});
      expect(accountLogicStub.stubs.get.called).is.true;
    });
    it('should derive address from publicKey if not provided', async () => {
      accountLogicStub.enqueueResponse('generateAddressByPublicKey', '123L');
      accountLogicStub.enqueueResponse('get', 'result');
      await accountModule.getAccount({publicKey: Buffer.from('1235', 'hex')});

      expect(accountLogicStub.stubs.generateAddressByPublicKey.called).is.true;
      expect(accountLogicStub.stubs.generateAddressByPublicKey.firstCall.args[0]).is.deep.eq(Buffer.from('1235', 'hex'));
      expect(accountLogicStub.stubs.get.called).is.true;
      expect(accountLogicStub.stubs.get.firstCall.args[0]).to.be.deep.eq({
        address: '123L',
      });
    });
    it('shoul return what accountLogic.get returns', async () => {
      accountLogicStub.enqueueResponse('get', 'result');
      expect(await accountModule.getAccount({address: '123L'}))
        .to.be.eq('result');
    });
  });

  describe('.getAccounts', () => {
    it('should directly pass params to accountLogic.getAll', async () => {
      accountLogicStub.enqueueResponse('getAll', null);
      await accountModule.getAccounts({address: '1L'}, ['address']);

      expect(accountLogicStub.stubs.getAll.called).is.true;
      expect(accountLogicStub.stubs.getAll.firstCall.args.length).is.eq(2);
      expect(accountLogicStub.stubs.getAll.firstCall.args[0])
        .to.be.deep.eq({address: '1L'});
      expect(accountLogicStub.stubs.getAll.firstCall.args[1])
        .to.be.deep.eq(['address']);
    });
    it('should return what accountLogic.getAll returns', async () => {
      const theRes = {the: 'result'};
      accountLogicStub.enqueueResponse('getAll', theRes);
      const res = await accountModule.getAccounts({address: '1L'}, ['address']);

      expect(res).to.be.deep.eq(theRes);
    });
  });

  describe('.setAccountAndGet', () => {
    it('should throw if no publicKey and address is provided', async () => {
      await expect(accountModule.setAccountAndGet({} as any))
        .to.be.rejectedWith('Missing address and public key');
    });
    it('should derive address from publicKey if not provided', async () => {
      accountLogicStub.enqueueResponse('generateAddressByPublicKey', '1L');
      accountLogicStub.enqueueResponse('set', null);
      accountLogicStub.enqueueResponse('get', null);
      await accountModule.setAccountAndGet({publicKey: Buffer.from('public')});
      expect(accountLogicStub.stubs.generateAddressByPublicKey.called).is.true;
      expect(accountLogicStub.stubs.generateAddressByPublicKey.firstCall.args[0])
        .to.be.deep.eq(Buffer.from('public'));
    });
    it('should call accountLogic.set with address and data', async () => {
      accountLogicStub.enqueueResponse('set', null);
      accountLogicStub.enqueueResponse('get', null);
      await accountModule.setAccountAndGet({address: '1L'});

      expect(accountLogicStub.stubs.set.calledOnce).is.true;
      expect(accountLogicStub.stubs.get.calledOnce).is.true;

      expect(accountLogicStub.stubs.set.firstCall.args[0]).to.be.eq('1L');
      expect(accountLogicStub.stubs.set.firstCall.args[1]).to.be.deep.eq({});

      expect(accountLogicStub.stubs.get.firstCall.args[0]).to.be.deep.eq({address: '1L'});
    });
    it('should accountLogi.get with address and return its value', async () => {
      accountLogicStub.enqueueResponse('set', null);
      accountLogicStub.enqueueResponse('get', 'antani');
      const toRet = await accountModule.setAccountAndGet({address: '1L'});

      expect(toRet).to.be.eq('antani');
    });
  });

  describe('.mergeAccountAndGetOPs', () => {
    it('should throw if no publicKey and address is provided', async () => {
      expect(() => accountModule.mergeAccountAndGetOPs({} as any))
        .to.be.throw('Missing address and public key');
    });
    it('should derive address from publicKey if not provided', () => {
      accountLogicStub.enqueueResponse('generateAddressByPublicKey', '1L');
      accountLogicStub.enqueueResponse('merge', null);
      accountModule.mergeAccountAndGetOPs({publicKey: Buffer.from('public')});
      expect(accountLogicStub.stubs.generateAddressByPublicKey.called).is.true;
      expect(accountLogicStub.stubs.generateAddressByPublicKey.firstCall.args[0])
        .to.be.deep.eq(Buffer.from('public'));
    });
    it('should call accountLogic.merge with address and return its value', async () => {
      accountLogicStub.enqueueResponse('merge', 'mergeResult');
      const toRet = accountModule.mergeAccountAndGetOPs({address: '1L'});
      expect(toRet).to.be.eq('mergeResult');
    });
  });

  describe('.generateAddressByPublicKey', () => {
    it('should call accountLogic.generateAddressByPublicKey', () => {
      accountLogicStub.enqueueResponse('generateAddressByPublicKey', 'addressResult');
      const res = accountModule.generateAddressByPublicKey('pubKey');

      expect(res).to.be.eq('addressResult');
      expect(accountLogicStub.stubs.generateAddressByPublicKey.called).is.true;
      expect(accountLogicStub.stubs.generateAddressByPublicKey.firstCall.args[0]).to.be.eq('pubKey');
    });
  });

  describe('resolveAccountsForTransactions', () => {
    let accountsModel: typeof AccountsModel;
    let findAllStub: SinonStub;
    let setAccountAndGetStub: SinonStub;
    beforeEach(() => {
      accountsModel = container.get(Symbols.models.accounts);
      findAllStub   = sandbox.stub().resolves([]);
      sandbox.stub(accountsModel, 'scope')
        .returns({findAll: findAllStub});
      setAccountAndGetStub = sandbox.stub(accountModule, 'setAccountAndGet')
        .callsFake(
          ({publicKey}) => Promise
            .resolve({publicKey, address: `add${publicKey.toString('hex')}`})
        );
    });
    it('shouldnt complain about empty txs array', async () => {
      const res = await accountModule.resolveAccountsForTransactions([]);
      expect(res).to.be.deep.eq({});

      // should call findAll with empty array
      expect(findAllStub.calledOnce).is.true;
      expect(findAllStub.firstCall.args[0]).deep.eq({where: {address: []}});
    });
    it('should throw if account is not found in db', async () => {
      await expect(accountModule.resolveAccountsForTransactions([
        {senderId: 'add11', senderPublicKey: Buffer.from('11', 'hex')} as any
      ])).rejectedWith('Account add11 not found in db');
    });
    it('should throw if account has diff publicKey in db', async () => {
      findAllStub.resolves([{address: 'add11', publicKey: Buffer.from('22', 'hex')}]);
      await expect(accountModule.resolveAccountsForTransactions([
        {senderId: 'add11', senderPublicKey: Buffer.from('11', 'hex')} as any
      ])).rejectedWith('Stealing attempt type.2 for add11');
    });
    it('should setAccountAndGet if nopublickey set in db and throw if address does not match', async () => {
      findAllStub.resolves([{address: 'add11'}]);
      await expect(accountModule.resolveAccountsForTransactions([
        {senderId: 'add11', senderPublicKey: Buffer.from('22', 'hex')} as any
      ])).rejectedWith('Stealing attempt type.1 for add11');
      expect(setAccountAndGetStub.called).is.true;
      expect(setAccountAndGetStub.firstCall.args[0])
        .is.deep.eq({publicKey: Buffer.from('22', 'hex')});
    });
    it('should also query for requesterPublicKey', async () => {
      accountLogicStub.stubs.generateAddressByPublicKey.returns('add33');
      findAllStub.resolves([
        {address: 'add11', publicKey: Buffer.from('11', 'hex')},
        {address: 'add33', publicKey: Buffer.from('33', 'hex')},
        ]);
      await accountModule.resolveAccountsForTransactions([{
        senderId: 'add11',
          senderPublicKey: Buffer.from('11', 'hex'),
          requesterPublicKey: Buffer.from('33', 'hex')} as any
      ]);
      expect(findAllStub.calledOnce).is.true;
      expect(findAllStub.firstCall.args[0]).is.deep.eq({
        where: { address: ['add11', 'add33']}
      });
    });

  });

});
Example #10
0
describe("bst-test", function() {

    let globalModule = {
        Global: {
            initializeCLI: sinon.spy(async function () {

            }),
            config: function () {
                return { sourceID: () => "mySource" };
            },
            running : function() {
                let p = new BSTProcess();
                p.port = 9999;
                return p;
            },

            version: function () {
                return "0.0.0";
            }
        }
    };

    let sandbox: SinonSandbox = null;
    beforeEach(function () {
        mockery.enable({useCleanCache: true});
        mockery.warnOnUnregistered(false);
        mockery.warnOnReplace(false);
        mockery.registerMock("../lib/core/global", globalModule);
        sandbox = sinon.sandbox.create();
        globalModule.Global.initializeCLI.reset();
    });

    afterEach(function () {
        sandbox.restore();
        mockery.deregisterAll();
        mockery.disable();
    });

    describe("test command", function() {
        it("call initializeCLI with false", function() {
            return new Promise((resolve, reject) => {

                process.argv = command("node bst-test.js");
                mockery.registerMock("skill-testing-ml", {
                        CLI: function() {
                            return {
                                run: async function () {
                                }
                            };
                        },
                        ConfigurationKeys: [
                            {
                                key: "platform",
                                text: "Set platform"
                            },
                            {
                                key: "type",
                                text: "Set type"
                            }
                        ]
                });
                NodeUtil.load("../../bin/bst-test.js");
                assert.equal(globalModule.Global.initializeCLI.getCall(0).args[0], false);
                resolve();
            });
        });

        it("call with parameters", function() {
            return new Promise((resolve, reject) => {
                const mockRun = function(a, b){
                    assert.equal(b.platform, "google");
                    resolve();
                };
                const mockCli = function() {
                    return {
                        run: mockRun
                    };
                };
                const skillTestingMock = {
                    CLI: mockCli,
                    ConfigurationKeys: [
                        {
                            key: "platform",
                            text: "Set platform"
                        },
                        {
                            key: "type",
                            text: "Set type"
                        }
                    ]
                };
                mockery.registerMock("skill-testing-ml", skillTestingMock);
                process.argv = command("node bst-test.js --platform google");
                NodeUtil.load("../../bin/bst-test.js");
                assert.equal(globalModule.Global.initializeCLI.getCall(0).args[0], false);
            });
        });
    });
});