diff --git a/.aegir.js b/.aegir.js index ea7050c5..bf61f245 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,7 +1,7 @@ 'use strict' module.exports = { - bundlesize: { maxSize: '210kB' }, + bundlesize: { maxSize: '68kB' }, karma: { files: [{ pattern: 'test/test-data/**/*', diff --git a/package.json b/package.json index d008bc6f..155846cb 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "debug": "^4.1.0", "ipfs-block": "~0.8.0", "just-debounce-it": "^1.1.0", - "lodash.isequalwith": "^4.4.0", "moving-average": "^1.0.0", "multicodec": "~0.5.0", "multihashing-async": "^0.8.0", diff --git a/src/types/message/index.js b/src/types/message/index.js index b28f5de5..c4f612f1 100644 --- a/src/types/message/index.js +++ b/src/types/message/index.js @@ -2,12 +2,11 @@ const protons = require('protons') const Block = require('ipfs-block') -const isEqualWith = require('lodash.isequalwith') const CID = require('cids') const codecName = require('multicodec/src/name-table') const vd = require('varint-decoder') const multihashing = require('multihashing-async') - +const { isMapEqual } = require('../../utils') const pbm = protons(require('./message.proto')) const Entry = require('./entry') @@ -106,15 +105,9 @@ class BitswapMessage { } equals (other) { - const cmp = (a, b) => { - if (a.equals && typeof a.equals === 'function') { - return a.equals(b) - } - } - if (this.full !== other.full || - !isEqualWith(this.wantlist, other.wantlist, cmp) || - !isEqualWith(this.blocks, other.blocks, cmp) + !isMapEqual(this.wantlist, other.wantlist) || + !isMapEqual(this.blocks, other.blocks) ) { return false } diff --git a/src/utils.js b/src/utils.js index 25f6bf32..a5f7eb26 100644 --- a/src/utils.js +++ b/src/utils.js @@ -80,11 +80,43 @@ const sortBy = (fn, list) => { }) } +/** + * Is equal for Maps of BitswapMessageEntry or Blocks + * @param {Map} a + * @param {Map} b + * @returns {boolean} + */ +const isMapEqual = (a, b) => { + if (a.size !== b.size) { + return false + } + + for (const [key, valueA] of a) { + if (!b.has(key)) { + return false + } + + const valueB = b.get(key) + + // Support BitswapMessageEntry + if (typeof valueA.equals === 'function' && !valueA.equals(valueB)) { + return false + } + // Support Blocks + if (valueA._data && !valueA._data.equals(valueB._data)) { + return false + } + } + + return true +} + module.exports = { logger, includesWith, uniqWith, groupBy, pullAllWith, - sortBy + sortBy, + isMapEqual } diff --git a/test/utils.spec.js b/test/utils.spec.js index b418e0ba..590e1d6d 100644 --- a/test/utils.spec.js +++ b/test/utils.spec.js @@ -1,9 +1,15 @@ /* eslint-env mocha */ 'use strict' const chai = require('chai') +const CID = require('cids') +const Block = require('ipfs-block') +const { Buffer } = require('buffer') +const multihashing = require('multihashing-async') +const BitswapMessageEntry = require('../src/types/message/entry') + chai.use(require('dirty-chai')) const expect = chai.expect -const { groupBy, uniqWith, pullAllWith, includesWith, sortBy } = require('../src/utils') +const { groupBy, uniqWith, pullAllWith, includesWith, sortBy, isMapEqual } = require('../src/utils') describe('utils spec', function () { it('groupBy', () => { @@ -100,4 +106,63 @@ describe('utils spec', function () { { id: 2, name: 'a' }, { id: 3, name: 'b' }]) }) + + describe('isMapEqual', () => { + it('should on be false when !== size', () => { + expect(isMapEqual( + new Map([['key1', 'value1'], ['key2', 'value2']]), + new Map([['key1', 'value1']]) + )).to.be.false() + }) + + it('should on be false if one key is missing', () => { + expect(isMapEqual( + new Map([['key1', 'value1'], ['key2', 'value2']]), + new Map([['key1', 'value1'], ['key3', 'value2']]) + )).to.be.false() + }) + + it('should on be false if BitswapMessageEntry dont match', async () => { + const hash1 = await multihashing(Buffer.from('OMG!1'), 'sha2-256') + const cid1 = new CID(1, 'dag-pb', hash1) + + expect(isMapEqual( + new Map([['key1', new BitswapMessageEntry(cid1, 1, true)], ['key2', new BitswapMessageEntry(cid1, 2, true)]]), + new Map([['key1', new BitswapMessageEntry(cid1, 1, true)], ['key2', new BitswapMessageEntry(cid1, 1, true)]]) + )).to.be.false() + }) + + it('should on be true if BitswapMessageEntry match', async () => { + const hash1 = await multihashing(Buffer.from('OMG!1'), 'sha2-256') + const cid1 = new CID(1, 'dag-pb', hash1) + + expect(isMapEqual( + new Map([['key1', new BitswapMessageEntry(cid1, 1, true)], ['key2', new BitswapMessageEntry(cid1, 1, true)]]), + new Map([['key1', new BitswapMessageEntry(cid1, 1, true)], ['key2', new BitswapMessageEntry(cid1, 1, true)]]) + )).to.be.true() + }) + + it('should on be false if Blocks dont match', async () => { + const hash1 = await multihashing(Buffer.from('OMG!1'), 'sha2-256') + const cid1 = new CID(1, 'dag-pb', hash1) + const block1 = new Block(Buffer.from('hello world'), cid1) + const block2 = new Block(Buffer.from('hello world 2'), cid1) + + expect(isMapEqual( + new Map([['key1', block1], ['key2', block1]]), + new Map([['key1', block1], ['key2', block2]]) + )).to.be.false() + }) + + it('should on be true if Blocks match', async () => { + const hash1 = await multihashing(Buffer.from('OMG!1'), 'sha2-256') + const cid1 = new CID(1, 'dag-pb', hash1) + const block1 = new Block(Buffer.from('hello world'), cid1) + + expect(isMapEqual( + new Map([['key1', block1], ['key2', block1]]), + new Map([['key1', block1], ['key2', block1]]) + )).to.be.true() + }) + }) })