From e336f1a070a69e39e1f47b25312a003dc7b3568f Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Wed, 16 Mar 2016 12:22:33 -0700 Subject: [PATCH] test: use webtorrent-fixtures --- README.md | 2 +- package.json | 6 ++-- test/client-large-torrent.js | 9 +++--- test/client-magnet.js | 5 +-- test/client.js | 28 +++++++++++++--- test/filter.js | 33 ++++++++++--------- test/scrape.js | 48 +++++++++++++++------------- test/torrents/bitlove-intro.torrent | Bin 597 -> 0 bytes test/torrents/leaves.torrent | Bin 639 -> 0 bytes test/torrents/sintel-5gb.torrent | Bin 26474 -> 0 bytes 10 files changed, 75 insertions(+), 56 deletions(-) delete mode 100644 test/torrents/bitlove-intro.torrent delete mode 100644 test/torrents/leaves.torrent delete mode 100644 test/torrents/sintel-5gb.torrent diff --git a/README.md b/README.md index 2a19129..f06ebbf 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ var Client = require('bittorrent-tracker') var parseTorrent = require('parse-torrent') var fs = require('fs') -var torrent = fs.readFileSync(__dirname + '/torrents/bitlove-intro.torrent') +var torrent = fs.readFileSync(__dirname + '/torrents/name.torrent') var parsedTorrent = parseTorrent(torrent) // { infoHash: 'xxx', length: xx, announce: ['xx', 'xx'] } var peerId = new Buffer('01234567890123456789') diff --git a/package.json b/package.json index c4bb576..d5e8826 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "xtend": "^4.0.0" }, "devDependencies": { - "magnet-uri": "^5.0.0", - "parse-torrent": "^5.0.0", + "magnet-uri": "^5.1.3", "standard": "^6.0.4", - "tape": "^4.0.0" + "tape": "^4.0.0", + "webtorrent-fixtures": "^1.3.0" }, "keywords": [ "bittorrent", diff --git a/test/client-large-torrent.js b/test/client-large-torrent.js index e0c77bf..b63d482 100644 --- a/test/client-large-torrent.js +++ b/test/client-large-torrent.js @@ -1,17 +1,16 @@ var Client = require('../') var common = require('./common') -var fs = require('fs') -var parseTorrent = require('parse-torrent') -var path = require('path') +var extend = require('xtend') +var fixtures = require('webtorrent-fixtures') var test = require('tape') -var torrent = fs.readFileSync(path.join(__dirname, 'torrents/sintel-5gb.torrent')) -var parsedTorrent = parseTorrent(torrent) var peerId = new Buffer('01234567890123456789') function testLargeTorrent (t, serverType) { t.plan(9) + var parsedTorrent = extend(fixtures.sintel.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId, 6881, parsedTorrent, { wrtc: {} }) diff --git a/test/client-magnet.js b/test/client-magnet.js index a08fe29..246209d 100644 --- a/test/client-magnet.js +++ b/test/client-magnet.js @@ -1,15 +1,16 @@ var Client = require('../') var common = require('./common') +var fixtures = require('webtorrent-fixtures') var magnet = require('magnet-uri') var test = require('tape') -var uri = 'magnet:?xt=urn:btih:d2474e86c95b19b8bcfdb92bc12c9d44667cfa36&dn=Leaves+of+Grass+by+Walt+Whitman.epub' -var parsedTorrent = magnet(uri) var peerId = new Buffer('01234567890123456789') function testMagnet (t, serverType) { t.plan(9) + var parsedTorrent = magnet(fixtures.leaves.magnetURI) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] diff --git a/test/client.js b/test/client.js index 349ff51..e8488e8 100644 --- a/test/client.js +++ b/test/client.js @@ -1,12 +1,9 @@ var Client = require('../') var common = require('./common') -var fs = require('fs') -var parseTorrent = require('parse-torrent') -var path = require('path') +var extend = require('xtend') +var fixtures = require('webtorrent-fixtures') var test = require('tape') -var torrent = fs.readFileSync(path.join(__dirname, 'torrents/bitlove-intro.torrent')) -var parsedTorrent = parseTorrent(torrent) var peerId1 = new Buffer('01234567890123456789') var peerId2 = new Buffer('12345678901234567890') var peerId3 = new Buffer('23456789012345678901') @@ -14,6 +11,9 @@ var port = 6881 function testClientStart (t, serverType) { t.plan(4) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) @@ -54,6 +54,9 @@ test('ws: client.start()', function (t) { function testClientStop (t, serverType) { t.plan(3) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) @@ -94,6 +97,9 @@ test('ws: client.stop()', function (t) { function testClientUpdate (t, serverType) { t.plan(4) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) @@ -141,6 +147,9 @@ test('ws: client.update()', function (t) { function testClientScrape (t, serverType) { t.plan(4) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) @@ -178,6 +187,9 @@ test('udp: client.scrape()', function (t) { function testClientAnnounceWithParams (t, serverType) { t.plan(5) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) @@ -220,6 +232,9 @@ test('ws: client.announce() with params', function (t) { function testClientGetAnnounceOpts (t, serverType) { t.plan(5) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var opts = { @@ -268,6 +283,9 @@ test('ws: client `opts.getAnnounceOpts`', function (t) { function testClientAnnounceWithNumWant (t, serverType) { t.plan(4) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + common.createServer(t, serverType, function (server, announceUrl) { parsedTorrent.announce = [ announceUrl ] var client1 = new Client(peerId1, port, parsedTorrent, { wrtc: {} }) diff --git a/test/filter.js b/test/filter.js index a9518c3..33fb106 100644 --- a/test/filter.js +++ b/test/filter.js @@ -1,33 +1,29 @@ var Client = require('../') var common = require('./common') -var fs = require('fs') -var parseTorrent = require('parse-torrent') -var path = require('path') +var extend = require('xtend') +var fixtures = require('webtorrent-fixtures') var test = require('tape') -var bitlove = fs.readFileSync(path.join(__dirname, 'torrents/bitlove-intro.torrent')) -var parsedBitlove = parseTorrent(bitlove) - -var leaves = fs.readFileSync(path.join(__dirname, 'torrents/leaves.torrent')) -var parsedLeaves = parseTorrent(leaves) - var peerId = new Buffer('01234567890123456789') function testFilterOption (t, serverType) { t.plan(8) + var parsedAlice = extend(fixtures.alice.parsedTorrent) + var parsedLeaves = extend(fixtures.leaves.parsedTorrent) + var opts = { serverType: serverType } // this is test-suite-only option opts.filter = function (infoHash, params, cb) { process.nextTick(function () { - cb(infoHash !== parsedBitlove.infoHash) + cb(infoHash !== parsedAlice.infoHash) }) } common.createServer(t, opts, function (server, announceUrl) { - parsedBitlove.announce = [ announceUrl ] + parsedAlice.announce = [ announceUrl ] parsedLeaves.announce = [ announceUrl ] - var client = new Client(peerId, 6881, parsedBitlove, { wrtc: {} }) + var client = new Client(peerId, 6881, parsedAlice, { wrtc: {} }) client.on('error', function (err) { t.error(err) }) if (serverType === 'ws') common.mockWebsocketTracker(client) @@ -82,25 +78,28 @@ test('ws: filter option blocks tracker from tracking torrent', function (t) { function testFilterCustomError (t, serverType) { t.plan(8) + var parsedLeaves = extend(fixtures.leaves.parsedTorrent) + var parsedAlice = extend(fixtures.alice.parsedTorrent) + var opts = { serverType: serverType } // this is test-suite-only option opts.filter = function (infoHash, params, cb) { process.nextTick(function () { - if (infoHash === parsedBitlove.infoHash) cb(new Error('bitlove blocked')) + if (infoHash === parsedAlice.infoHash) cb(new Error('alice blocked')) else cb(true) }) } common.createServer(t, opts, function (server, announceUrl) { - parsedBitlove.announce = [ announceUrl ] + parsedAlice.announce = [ announceUrl ] parsedLeaves.announce = [ announceUrl ] - var client = new Client(peerId, 6881, parsedBitlove, { wrtc: {} }) + var client = new Client(peerId, 6881, parsedAlice, { wrtc: {} }) client.on('error', function (err) { t.error(err) }) if (serverType === 'ws') common.mockWebsocketTracker(client) client.once('warning', function (err) { - t.ok(/bitlove blocked/.test(err.message), 'got client warning') + t.ok(/alice blocked/.test(err.message), 'got client warning') client.destroy(function () { t.pass('client destroyed') @@ -126,7 +125,7 @@ function testFilterCustomError (t, serverType) { server.removeAllListeners('warning') server.once('warning', function (err) { - t.ok(/bitlove blocked/.test(err.message), 'got server warning') + t.ok(/alice blocked/.test(err.message), 'got server warning') t.equal(Object.keys(server.torrents).length, 0) }) diff --git a/test/scrape.js b/test/scrape.js index 49f06fb..ce7e578 100644 --- a/test/scrape.js +++ b/test/scrape.js @@ -2,27 +2,19 @@ var bencode = require('bencode') var Client = require('../') var commonLib = require('../lib/common') var commonTest = require('./common') -var fs = require('fs') +var extend = require('xtend') +var fixtures = require('webtorrent-fixtures') var get = require('simple-get') -var parseTorrent = require('parse-torrent') -var path = require('path') var test = require('tape') -var infoHash1 = 'aaa67059ed6bd08362da625b3ae77f6f4a075aaa' -var binaryInfoHash1 = commonLib.hexToBinary(infoHash1) -var infoHash2 = 'bbb67059ed6bd08362da625b3ae77f6f4a075bbb' -var binaryInfoHash2 = commonLib.hexToBinary(infoHash2) - -var bitlove = fs.readFileSync(path.join(__dirname, 'torrents/bitlove-intro.torrent')) -var parsedBitlove = parseTorrent(bitlove) -var binaryBitlove = commonLib.hexToBinary(parsedBitlove.infoHash) - var peerId = new Buffer('01234567890123456789') function testSingle (t, serverType) { + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + commonTest.createServer(t, serverType, function (server, announceUrl) { - parsedBitlove.announce = [ announceUrl ] - var client = new Client(peerId, 6881, parsedBitlove) + parsedTorrent.announce = [ announceUrl ] + var client = new Client(peerId, 6881, parsedTorrent) client.on('error', function (err) { t.error(err) @@ -36,7 +28,7 @@ function testSingle (t, serverType) { client.on('scrape', function (data) { t.equal(data.announce, announceUrl) - t.equal(data.infoHash, parsedBitlove.infoHash) + t.equal(data.infoHash, parsedTorrent.infoHash) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') t.equal(typeof data.downloaded, 'number') @@ -58,10 +50,10 @@ test('udp: single info_hash scrape', function (t) { function clientScrapeStatic (t, serverType) { commonTest.createServer(t, serverType, function (server, announceUrl) { - Client.scrape(announceUrl, infoHash1, function (err, data) { + Client.scrape(announceUrl, fixtures.leaves.parsedTorrent.infoHash, function (err, data) { t.error(err) t.equal(data.announce, announceUrl) - t.equal(data.infoHash, infoHash1) + t.equal(data.infoHash, fixtures.leaves.parsedTorrent.infoHash) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') t.equal(typeof data.downloaded, 'number') @@ -81,6 +73,9 @@ test('udp: scrape using Client.scrape static method', function (t) { }) function clientScrapeMulti (t, serverType) { + var infoHash1 = fixtures.leaves.parsedTorrent.infoHash + var infoHash2 = fixtures.alice.parsedTorrent.infoHash + commonTest.createServer(t, serverType, function (server, announceUrl) { Client.scrape(announceUrl, [ infoHash1, infoHash2 ], function (err, results) { t.error(err) @@ -115,6 +110,9 @@ test('udp: MULTI scrape using Client.scrape static method', function (t) { test('server: multiple info_hash scrape (manual http request)', function (t) { t.plan(13) + var binaryInfoHash1 = commonLib.hexToBinary(fixtures.leaves.parsedTorrent.infoHash) + var binaryInfoHash2 = commonLib.hexToBinary(fixtures.alice.parsedTorrent.infoHash) + commonTest.createServer(t, 'http', function (server, announceUrl) { var scrapeUrl = announceUrl.replace('/announce', '/scrape') @@ -148,13 +146,17 @@ test('server: multiple info_hash scrape (manual http request)', function (t) { test('server: all info_hash scrape (manual http request)', function (t) { t.plan(10) + + var parsedTorrent = extend(fixtures.leaves.parsedTorrent) + var binaryInfoHash = commonLib.hexToBinary(parsedTorrent.infoHash) + commonTest.createServer(t, 'http', function (server, announceUrl) { var scrapeUrl = announceUrl.replace('/announce', '/scrape') - parsedBitlove.announce = [ announceUrl ] + parsedTorrent.announce = [ announceUrl ] // announce a torrent to the tracker - var client = new Client(peerId, 6881, parsedBitlove) + var client = new Client(peerId, 6881, parsedTorrent) client.on('error', function (err) { t.error(err) }) client.on('warning', function (err) { t.error(err) }) @@ -170,10 +172,10 @@ test('server: all info_hash scrape (manual http request)', function (t) { t.ok(data.files) t.equal(Object.keys(data.files).length, 1) - t.ok(data.files[binaryBitlove]) - t.equal(typeof data.files[binaryBitlove].complete, 'number') - t.equal(typeof data.files[binaryBitlove].incomplete, 'number') - t.equal(typeof data.files[binaryBitlove].downloaded, 'number') + t.ok(data.files[binaryInfoHash]) + t.equal(typeof data.files[binaryInfoHash].complete, 'number') + t.equal(typeof data.files[binaryInfoHash].incomplete, 'number') + t.equal(typeof data.files[binaryInfoHash].downloaded, 'number') client.destroy(function () { t.pass('client destroyed') }) server.close(function () { t.pass('server closed') }) diff --git a/test/torrents/bitlove-intro.torrent b/test/torrents/bitlove-intro.torrent deleted file mode 100644 index 1c91bf1360446ed6fe793ff0b451437e64b8511a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 597 zcmYeXuu9C!%P-AKPBpT$$|xx*u+rBr(M!rK$;mHE)ypqR*N4fQSY_s=<)@fg<)r4N zmt5o_tmZY{?8?DSy!I8 zxmPxxPQOrTEWc84S+c88!&JN5MRw_llHqswA8PHo#+IjfT=|1EC&wFu2hYs|y*fhI z-|7=t5?5bYx23vi(}l&GPQ{zm$$Lhcik_05yq59sJ61l^5B@QFqB~b_R90$WIg8*yG;G;q(_@)U9mCUw_Bs*yNHcu+HT+Yk_S6Vnt1|_N^0a0PSNcQOTL?& zdobxp^`pzv*Y9Ur`EqITGAo-5Tdk#xYZbLbrYdyT|K3=9F1$%oY-*~ueUkBhzr`tY z%4aTY>1R82Z~BZ<)!XLBXFiF(pnoWC%|ShhV+W;u7ytGtzCW3L^W^z&Y_5K|FFq$= z$()?UsTNkHMLD`TnZ+eJW+t#iP+X9hoSKwhS*4ekTB2W^?c`-9ObyRP1a%FCGFEcYRFflVaV{&C-bZKvHAY@^5 zWoa=pH#IXhGd4ChWjH!zZewp`X>MmVI#pCgEjTnfX>Mk3WHvf%Wo~D5XlXMxGB7bW zWi&c&VQpnIHabjYVRmJ6Aa7@I2ZZ2hTbz(6xI&f)a zV`U(0Wo~D5XlXGvGdMJ5Hac)=Wn*P?G&V3gADll~zU&8=73@_RYo zOyyO3T{&dM?^V-O&q{90d-1%ldC?!G;JyY~JddjU3@f6~cGnzR0a9xt0DqpDDZa18 z6&_^~2{ECxOd-D>Xt@)QkV#%?4ZKzLa^%94OuEk|=CiJfaw*t~ub^LH>aJ?PKL^Wg zxo3RFt?f-a?edYE;3ShjtBzbm{@2GbTBi{;x4Ux+=vp{-?x}aGN$jPc| z5)UUsXWZCl=#GOp#d4r-Jb)W1^%>t&D?WDiaL;P)QxJbWIX8rZ_MG?+rD(D0#XC@8 zS?P$_ycUuz5?y!L1J+W*$}n)jZtanBt59tqu2?Ok6JwTAVdl;fv^N3psLAaWAg2zx07L+yXLet0 zJ=Mp)wY@xb^WQ2|RtjN&5l8w?$In)da5~Eb-4m5BY2 Z#+crl4Xu)x2?oF>*ug-LppWG2Wn~EL9FYJ3 diff --git a/test/torrents/sintel-5gb.torrent b/test/torrents/sintel-5gb.torrent deleted file mode 100644 index 49c35defb39de93a08a9fdf2ce3020f71d8ef807..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26474 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 Va%V4eZ*p>FZgej(F)=hTGi8TiJ~RLT