From d34f4600f1c5445b66ff6147a3a11b26f95399ac Mon Sep 17 00:00:00 2001 From: Phil Tsarik Date: Thu, 19 May 2016 16:38:04 +0200 Subject: [PATCH] Convert test files to .ts --- .gitignore | 2 +- app/tracker.ts | 9 +++- gulpfile.js | 16 ++++--- release/announce-params-parser.js | 24 +++++++++++ release/announce-params.js | 1 + release/event.js | 9 ++++ release/memory-torrent-store.js | 16 +++++++ release/peer.js | 1 + release/torrent-store.js | 1 + release/torrent.js | 29 +++++++++++++ release/tracker-errors.js | 42 +++++++++++++++++++ release/tracker-service.js | 34 +++++++++++++++ release/tracker.js | 40 ++++++++++++++++++ test/helpers/create-request-params.js | 35 ---------------- test/helpers/create-request-params.ts | 37 ++++++++++++++++ test/{torrent.test.js => torrent.test.ts} | 2 +- ...ervice.test.js => tracker-service.test.ts} | 6 +-- test/{tracker.test.js => tracker.test.ts} | 2 +- typings.json | 3 ++ 19 files changed, 262 insertions(+), 47 deletions(-) create mode 100644 release/announce-params-parser.js create mode 100644 release/announce-params.js create mode 100644 release/event.js create mode 100644 release/memory-torrent-store.js create mode 100644 release/peer.js create mode 100644 release/torrent-store.js create mode 100644 release/torrent.js create mode 100644 release/tracker-errors.js create mode 100644 release/tracker-service.js create mode 100644 release/tracker.js delete mode 100644 test/helpers/create-request-params.js create mode 100644 test/helpers/create-request-params.ts rename test/{torrent.test.js => torrent.test.ts} (98%) rename test/{tracker-service.test.js => tracker-service.test.ts} (95%) rename test/{tracker.test.js => tracker.test.ts} (93%) diff --git a/.gitignore b/.gitignore index 6c27980..275c97b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ +js node_modules -release typings diff --git a/app/tracker.ts b/app/tracker.ts index b041f5f..e99b917 100644 --- a/app/tracker.ts +++ b/app/tracker.ts @@ -2,11 +2,15 @@ import * as http from 'http'; import * as url from 'url'; import * as errors from './tracker-errors'; +import AnnounceParamsParser from './announce-params-parser'; +import TrackerService from './tracker-service'; export class Tracker { + private service: TrackerService; private server: http.Server; constructor () { + this.service = new TrackerService(); this.server = http.createServer(); this.server.on('request', this.onRequest.bind(this)); } @@ -26,7 +30,10 @@ export class Tracker { if (request.method !== 'GET') { throw new errors.NotFoundError(); } - if (u.pathname !== '/announce') { + if (u.pathname === '/announce') { + let params = new AnnounceParamsParser(u.query).parse(); + this.service.announce(params); + } else { throw new errors.NotFoundError(); } } catch (err) { diff --git a/gulpfile.js b/gulpfile.js index 633f893..785ab9f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,9 +6,15 @@ var tsProject = ts.createProject('tsconfig.json'); gulp.task('default', ['compile']); gulp.task('compile', function () { - return tsProject.src() + return gulp.src('app/**/*.ts') .pipe(ts(tsProject)) - .pipe(gulp.dest('release')); + .pipe(gulp.dest('js/app')); +}); + +gulp.task('compile-tests', ['compile'], function () { + return gulp.src('test/**/*.ts') + .pipe(ts(tsProject)) + .pipe(gulp.dest('js/test')); }); gulp.task('watch', function () { @@ -16,10 +22,10 @@ gulp.task('watch', function () { }); gulp.task('watch-test', function () { - gulp.watch(['app/**/*.ts', 'test/**/*.js'], ['test']); + gulp.watch(['app/**/*.ts', 'test/**/*.ts'], ['test']); }); -gulp.task('test', ['compile'], function () { - return gulp.src('test/**/*.test.js', {read: false}) +gulp.task('test', ['compile-tests'], function () { + return gulp.src('js/test/**/*.test.js', {read: false}) .pipe(mocha({reporter: 'spec'})); }); diff --git a/release/announce-params-parser.js b/release/announce-params-parser.js new file mode 100644 index 0000000..8a12079 --- /dev/null +++ b/release/announce-params-parser.js @@ -0,0 +1,24 @@ +"use strict"; +var errors = require('./tracker-errors'); +var AnnounceParamsParser = (function () { + function AnnounceParamsParser(rawParams) { + this.rawParams = rawParams; + } + AnnounceParamsParser.prototype.parse = function () { + // try { + if (Buffer.byteLength(this.rawParams['info_hash']) !== 20) { + throw new errors.RequestParamsError('Invalid info_hash'); + } + // } catch (err) { + // console.log('err', err.message); + // console.log('err', err.stack); + // } + // raise ArgumentError.new('Invalid peer id') if params[:peer_id].bytesize != 20 + // raise ArgumentError.new('Wrong info_hash for this tracker') unless same_info_hash? (params[:info_hash]) + // raise ArgumentError.new('Invalid numwant') if params[:numwant] > CONF[:max_peers] + return {}; + }; + return AnnounceParamsParser; +}()); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = AnnounceParamsParser; diff --git a/release/announce-params.js b/release/announce-params.js new file mode 100644 index 0000000..3918c74 --- /dev/null +++ b/release/announce-params.js @@ -0,0 +1 @@ +"use strict"; diff --git a/release/event.js b/release/event.js new file mode 100644 index 0000000..b5d5de9 --- /dev/null +++ b/release/event.js @@ -0,0 +1,9 @@ +"use strict"; +var Event; +(function (Event) { + Event[Event["stopped"] = 0] = "stopped"; + Event[Event["started"] = 1] = "started"; + Event[Event["completed"] = 2] = "completed"; +})(Event || (Event = {})); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Event; diff --git a/release/memory-torrent-store.js b/release/memory-torrent-store.js new file mode 100644 index 0000000..a80fbe5 --- /dev/null +++ b/release/memory-torrent-store.js @@ -0,0 +1,16 @@ +"use strict"; +var torrent_1 = require('./torrent'); +var MemoryTorrentStore = (function () { + function MemoryTorrentStore() { + this.torrents = {}; + } + MemoryTorrentStore.prototype.getTorrent = function (infoHash) { + return this.torrents[infoHash] || new torrent_1.default(infoHash); + }; + MemoryTorrentStore.prototype.saveTorrent = function (torrent) { + this.torrents[torrent.getInfoHash()] = torrent; + }; + return MemoryTorrentStore; +}()); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = MemoryTorrentStore; diff --git a/release/peer.js b/release/peer.js new file mode 100644 index 0000000..3918c74 --- /dev/null +++ b/release/peer.js @@ -0,0 +1 @@ +"use strict"; diff --git a/release/torrent-store.js b/release/torrent-store.js new file mode 100644 index 0000000..3918c74 --- /dev/null +++ b/release/torrent-store.js @@ -0,0 +1 @@ +"use strict"; diff --git a/release/torrent.js b/release/torrent.js new file mode 100644 index 0000000..c988397 --- /dev/null +++ b/release/torrent.js @@ -0,0 +1,29 @@ +"use strict"; +var _ = require('lodash'); +var Torrent = (function () { + function Torrent(infoHash) { + this.infoHash = infoHash; + this.peers = {}; + } + Torrent.prototype.getInfoHash = function () { + return this.infoHash; + }; + Torrent.prototype.getPeers = function () { + return _.values(this.peers); + }; + Torrent.prototype.setPeer = function (peer) { + this.peers[peer.peerId] = peer; + }; + Torrent.prototype.getComplete = function () { + return _.filter(this.getPeers(), function (x) { return x.left === 0; }).length; + }; + Torrent.prototype.getIncomplete = function () { + return _.reject(this.getPeers(), function (x) { return x.left === 0; }).length; + }; + Torrent.prototype.removePeer = function (peerId) { + delete this.peers[peerId]; + }; + return Torrent; +}()); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = Torrent; diff --git a/release/tracker-errors.js b/release/tracker-errors.js new file mode 100644 index 0000000..374dfd3 --- /dev/null +++ b/release/tracker-errors.js @@ -0,0 +1,42 @@ +"use strict"; +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var TrackerError = (function (_super) { + __extends(TrackerError, _super); + function TrackerError(message) { + _super.call(this, message); + this.message = message; + } + return TrackerError; +}(Error)); +exports.TrackerError = TrackerError; +var NotFoundError = (function (_super) { + __extends(NotFoundError, _super); + function NotFoundError() { + _super.apply(this, arguments); + this.statusCode = 404; + } + return NotFoundError; +}(TrackerError)); +exports.NotFoundError = NotFoundError; +var RequestParamsError = (function (_super) { + __extends(RequestParamsError, _super); + function RequestParamsError() { + _super.apply(this, arguments); + this.statusCode = 400; + } + return RequestParamsError; +}(TrackerError)); +exports.RequestParamsError = RequestParamsError; +var InternalServerError = (function (_super) { + __extends(InternalServerError, _super); + function InternalServerError() { + _super.apply(this, arguments); + this.statusCode = 500; + } + return InternalServerError; +}(TrackerError)); +exports.InternalServerError = InternalServerError; diff --git a/release/tracker-service.js b/release/tracker-service.js new file mode 100644 index 0000000..4975ce1 --- /dev/null +++ b/release/tracker-service.js @@ -0,0 +1,34 @@ +"use strict"; +var memory_torrent_store_1 = require('./memory-torrent-store'); +var event_1 = require('./event'); +var TrackerService = (function () { + function TrackerService() { + this.torrentStore = new memory_torrent_store_1.default(); + } + TrackerService.prototype.announce = function (params) { + var torrent = this.torrentStore.getTorrent(params.infoHash); + this._processEvent(params, torrent); + return { + complete: torrent.getComplete(), + incomplete: torrent.getIncomplete(), + peers: torrent.getPeers(), + }; + }; + TrackerService.prototype._processEvent = function (params, torrent) { + if (params.event === event_1.default.stopped) { + torrent.removePeer(params.peerId); + } + else { + torrent.setPeer({ + peerId: params.peerId, + ip: params.ip, + port: params.port, + left: params.left, + }); + } + this.torrentStore.saveTorrent(torrent); + }; + return TrackerService; +}()); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = TrackerService; diff --git a/release/tracker.js b/release/tracker.js new file mode 100644 index 0000000..9da0633 --- /dev/null +++ b/release/tracker.js @@ -0,0 +1,40 @@ +"use strict"; +/// +var http = require('http'); +var url = require('url'); +var errors = require('./tracker-errors'); +var Tracker = (function () { + function Tracker() { + this.server = http.createServer(); + this.server.on('request', this.onRequest.bind(this)); + } + Tracker.prototype.start = function (port) { + port = port || 8080; + this.server.listen(port); + }; + Tracker.prototype.close = function () { + this.server.close(); + }; + Tracker.prototype.onRequest = function (request, response) { + var u = url.parse(request.url, true); + try { + if (request.method !== 'GET') { + throw new errors.NotFoundError(); + } + if (u.pathname !== '/announce') { + throw new errors.NotFoundError(); + } + } + catch (err) { + if (err instanceof errors.TrackerError) { + response.statusCode = err.statusCode; + } + else { + response.statusCode = 500; + } + } + response.end(); + }; + return Tracker; +}()); +exports.Tracker = Tracker; diff --git a/test/helpers/create-request-params.js b/test/helpers/create-request-params.js deleted file mode 100644 index 70bd490..0000000 --- a/test/helpers/create-request-params.js +++ /dev/null @@ -1,35 +0,0 @@ -var Event = require('../../release/event').default; - -function createRequestParams () { - return { - infoHash: '12345678901234567890', - peerId: 'MockPeer', - port: 8788, - uploaded: 11, - downloaded: 22, - left: 33, - - withPeerId: function (peerId) { - this.peerId = peerId; - return this; - }, - withIp: function (ip) { - this.ip = ip; - return this; - }, - withPort: function (port) { - this.port = port; - return this; - }, - withLeft: function (left) { - this.left = left; - return this; - }, - withEvent: function (event) { - this.event = Event[event]; - return this; - } - }; -} - -module.exports = createRequestParams; diff --git a/test/helpers/create-request-params.ts b/test/helpers/create-request-params.ts new file mode 100644 index 0000000..c0177c9 --- /dev/null +++ b/test/helpers/create-request-params.ts @@ -0,0 +1,37 @@ +import Event from '../../app/event'; + +(function() { + function createRequestParams () { + return { + infoHash: '12345678901234567890', + peerId: 'MockPeer', + port: 8788, + uploaded: 11, + downloaded: 22, + left: 33, + + withPeerId: function (peerId) { + this.peerId = peerId; + return this; + }, + withIp: function (ip) { + this.ip = ip; + return this; + }, + withPort: function (port) { + this.port = port; + return this; + }, + withLeft: function (left) { + this.left = left; + return this; + }, + withEvent: function (event) { + this.event = Event[event]; + return this; + } + }; + } + + module.exports = createRequestParams; +})(); diff --git a/test/torrent.test.js b/test/torrent.test.ts similarity index 98% rename from test/torrent.test.js rename to test/torrent.test.ts index 64f60fb..cdf4b8c 100644 --- a/test/torrent.test.js +++ b/test/torrent.test.ts @@ -2,7 +2,7 @@ var expect = require('chai').expect; describe('Torrent', function () { - var Torrent = require('../release/torrent').default, + var Torrent = require('../app/torrent').default, torrent, result; diff --git a/test/tracker-service.test.js b/test/tracker-service.test.ts similarity index 95% rename from test/tracker-service.test.js rename to test/tracker-service.test.ts index 89cec74..6121175 100644 --- a/test/tracker-service.test.js +++ b/test/tracker-service.test.ts @@ -4,9 +4,9 @@ var sinon = require('sinon'); var createRequestParams = require('./helpers/create-request-params'); describe('TrackerService', function () { - var TrackerService = require('../release/tracker-service').default, - MemoryTorrentStore = require('../release/memory-torrent-store').default, - Torrent = require('../release/torrent').default, + var TrackerService = require('../app/tracker-service').default, + MemoryTorrentStore = require('../app/memory-torrent-store').default, + Torrent = require('../app/torrent').default, trackerService, torrentStub, memoryTorrentStoreStub, diff --git a/test/tracker.test.js b/test/tracker.test.ts similarity index 93% rename from test/tracker.test.js rename to test/tracker.test.ts index d82dc4f..353c538 100644 --- a/test/tracker.test.js +++ b/test/tracker.test.ts @@ -4,7 +4,7 @@ var http = require('http'); describe('Tracker', function () { const PORT = 8787; - var Tracker = require('../release/tracker').Tracker, + var Tracker = require('../app/tracker').Tracker, tracker; beforeEach(function () { diff --git a/typings.json b/typings.json index 695e18f..24626fe 100644 --- a/typings.json +++ b/typings.json @@ -2,5 +2,8 @@ "ambientDependencies": { "lodash": "registry:dt/lodash#3.10.0+20160330154726", "node": "registry:dt/node#4.0.0+20160423143914" + }, + "globalDependencies": { + "mocha": "registry:dt/mocha#2.2.5+20160317120654" } }