Make the network auto sufficient (eject bad pods with scores)
This commit is contained in:
parent
2e3b5b0db6
commit
3bcb78b3af
|
@ -36,7 +36,7 @@ Thanks to [webtorrent](https://github.com/feross/webtorrent), we can make P2P (t
|
||||||
- [ ] Inscription
|
- [ ] Inscription
|
||||||
- [ ] Connection
|
- [ ] Connection
|
||||||
- [ ] Account rights (upload...)
|
- [ ] Account rights (upload...)
|
||||||
- [ ] Make the network auto sufficient (eject bad pods etc)
|
- [X] Make the network auto sufficient (eject bad pods etc)
|
||||||
- [ ] Manage API breaks
|
- [ ] Manage API breaks
|
||||||
- [ ] Add "DDOS" security (check if a pod don't send too many requests for example)
|
- [ ] Add "DDOS" security (check if a pod don't send too many requests for example)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
listen:
|
||||||
|
port: 9004
|
||||||
|
|
||||||
|
webserver:
|
||||||
|
host: 'localhost'
|
||||||
|
port: 9004
|
||||||
|
|
||||||
|
database:
|
||||||
|
suffix: '-test4'
|
||||||
|
|
||||||
|
# From the project root directory
|
||||||
|
storage:
|
||||||
|
certs: 'test4/certs/'
|
||||||
|
uploads: 'test4/uploads/'
|
||||||
|
logs: 'test4/logs/'
|
||||||
|
|
||||||
|
network:
|
||||||
|
friends:
|
||||||
|
- 'http://localhost:9002'
|
|
@ -0,0 +1,20 @@
|
||||||
|
listen:
|
||||||
|
port: 9005
|
||||||
|
|
||||||
|
webserver:
|
||||||
|
host: 'localhost'
|
||||||
|
port: 9005
|
||||||
|
|
||||||
|
database:
|
||||||
|
suffix: '-test5'
|
||||||
|
|
||||||
|
# From the project root directory
|
||||||
|
storage:
|
||||||
|
certs: 'test5/certs/'
|
||||||
|
uploads: 'test5/uploads/'
|
||||||
|
logs: 'test5/logs/'
|
||||||
|
|
||||||
|
network:
|
||||||
|
friends:
|
||||||
|
- 'http://localhost:9001'
|
||||||
|
- 'http://localhost:9004'
|
|
@ -0,0 +1,21 @@
|
||||||
|
listen:
|
||||||
|
port: 9006
|
||||||
|
|
||||||
|
webserver:
|
||||||
|
host: 'localhost'
|
||||||
|
port: 9006
|
||||||
|
|
||||||
|
database:
|
||||||
|
suffix: '-test6'
|
||||||
|
|
||||||
|
# From the project root directory
|
||||||
|
storage:
|
||||||
|
certs: 'test6/certs/'
|
||||||
|
uploads: 'test6/uploads/'
|
||||||
|
logs: 'test6/logs/'
|
||||||
|
|
||||||
|
network:
|
||||||
|
friends:
|
||||||
|
- 'http://localhost:9001'
|
||||||
|
- 'http://localhost:9002'
|
||||||
|
- 'http://localhost:9003'
|
|
@ -62,7 +62,9 @@
|
||||||
"confirm",
|
"confirm",
|
||||||
"it",
|
"it",
|
||||||
"after",
|
"after",
|
||||||
|
"afterEach",
|
||||||
"before",
|
"before",
|
||||||
|
"beforeEach",
|
||||||
"describe"
|
"describe"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
printf "use peertube-test1;\ndb.dropDatabase();\nuse peertube-test2;\ndb.dropDatabase();\nuse peertube-test3;\ndb.dropDatabase();" | mongo
|
for i in $(seq 1 6); do
|
||||||
|
printf "use peertube-test%s;\ndb.dropDatabase();" "$i" | mongo
|
||||||
rm -rf ./test1 ./test2 ./test3
|
rm -rf "./test$i"
|
||||||
|
done
|
||||||
|
|
10
server.js
10
server.js
|
@ -1,9 +1,6 @@
|
||||||
;(function () {
|
;(function () {
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// ----------- Constants -----------
|
|
||||||
global.API_VERSION = 'v1'
|
|
||||||
|
|
||||||
// ----------- Node modules -----------
|
// ----------- Node modules -----------
|
||||||
var bodyParser = require('body-parser')
|
var bodyParser = require('body-parser')
|
||||||
var express = require('express')
|
var express = require('express')
|
||||||
|
@ -30,11 +27,16 @@
|
||||||
|
|
||||||
checker.createDirectoriesIfNotExist()
|
checker.createDirectoriesIfNotExist()
|
||||||
|
|
||||||
|
// ----------- Constants -----------
|
||||||
|
var utils = require('./src/utils')
|
||||||
|
|
||||||
|
global.API_VERSION = 'v1'
|
||||||
|
global.FRIEND_BASE_SCORE = utils.isTestInstance() ? 20 : 100
|
||||||
|
|
||||||
// ----------- PeerTube modules -----------
|
// ----------- PeerTube modules -----------
|
||||||
var config = require('config')
|
var config = require('config')
|
||||||
var logger = require('./src/logger')
|
var logger = require('./src/logger')
|
||||||
var routes = require('./routes')
|
var routes = require('./routes')
|
||||||
var utils = require('./src/utils')
|
|
||||||
var videos = require('./src/videos')
|
var videos = require('./src/videos')
|
||||||
var webtorrent = require('./src/webTorrentNode')
|
var webtorrent = require('./src/webTorrentNode')
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
// ----------- Pods -----------
|
// ----------- Pods -----------
|
||||||
var podsSchema = mongoose.Schema({
|
var podsSchema = mongoose.Schema({
|
||||||
url: String,
|
url: String,
|
||||||
publicKey: String
|
publicKey: String,
|
||||||
|
score: { type: Number, max: global.FRIEND_BASE_SCORE }
|
||||||
})
|
})
|
||||||
|
|
||||||
var PodsDB = mongoose.model('pods', podsSchema)
|
var PodsDB = mongoose.model('pods', podsSchema)
|
||||||
|
|
64
src/pods.js
64
src/pods.js
|
@ -16,6 +16,13 @@
|
||||||
var host = config.get('webserver.host')
|
var host = config.get('webserver.host')
|
||||||
var port = config.get('webserver.port')
|
var port = config.get('webserver.port')
|
||||||
|
|
||||||
|
// ----------- Constants -----------
|
||||||
|
|
||||||
|
var PODS_SCORE = {
|
||||||
|
MALUS: -10,
|
||||||
|
BONUS: 10
|
||||||
|
}
|
||||||
|
|
||||||
// ----------- Private functions -----------
|
// ----------- Private functions -----------
|
||||||
|
|
||||||
function getForeignPodsList (url, callback) {
|
function getForeignPodsList (url, callback) {
|
||||||
|
@ -27,6 +34,25 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updatePodsScore (good_pods, bad_pods) {
|
||||||
|
logger.info('Updating %d good pods and %d bad pods scores.', good_pods.length, bad_pods.length)
|
||||||
|
|
||||||
|
PodsDB.update({ _id: { $in: good_pods } }, { $inc: { score: PODS_SCORE.BONUS } }, { multi: true }).exec()
|
||||||
|
PodsDB.update({ _id: { $in: bad_pods } }, { $inc: { score: PODS_SCORE.MALUS } }, { multi: true }, function (err) {
|
||||||
|
if (err) throw err
|
||||||
|
removeBadPods()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeBadPods () {
|
||||||
|
PodsDB.remove({ score: 0 }, function (err, result) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
var number_removed = result.result.n
|
||||||
|
if (number_removed !== 0) logger.info('Removed %d pod.', number_removed)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ----------- Public functions -----------
|
// ----------- Public functions -----------
|
||||||
|
|
||||||
pods.list = function (callback) {
|
pods.list = function (callback) {
|
||||||
|
@ -46,7 +72,8 @@
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
url: data.url,
|
url: data.url,
|
||||||
publicKey: data.publicKey
|
publicKey: data.publicKey,
|
||||||
|
score: global.FRIEND_BASE_SCORE
|
||||||
}
|
}
|
||||||
|
|
||||||
PodsDB.create(params, function (err, pod) {
|
PodsDB.create(params, function (err, pod) {
|
||||||
|
@ -68,7 +95,9 @@
|
||||||
|
|
||||||
// { path, data }
|
// { path, data }
|
||||||
pods.makeSecureRequest = function (data, callback) {
|
pods.makeSecureRequest = function (data, callback) {
|
||||||
PodsDB.find({}, { url: 1, publicKey: 1 }).exec(function (err, urls) {
|
if (callback === undefined) callback = function () {}
|
||||||
|
|
||||||
|
PodsDB.find({}, { _id: 1, url: 1, publicKey: 1 }).exec(function (err, pods) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Cannot get the list of the pods.', { error: err })
|
logger.error('Cannot get the list of the pods.', { error: err })
|
||||||
return callback(err)
|
return callback(err)
|
||||||
|
@ -84,15 +113,23 @@
|
||||||
data: data.data
|
data: data.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bad_pods = []
|
||||||
|
var good_pods = []
|
||||||
|
|
||||||
utils.makeMultipleRetryRequest(
|
utils.makeMultipleRetryRequest(
|
||||||
params,
|
params,
|
||||||
|
|
||||||
urls,
|
pods,
|
||||||
|
|
||||||
function callbackEachPodFinished (err, response, body, url) {
|
function callbackEachPodFinished (err, response, body, pod, callback_each_pod_finished) {
|
||||||
if (err || response.statusCode !== 200) {
|
if (err || response.statusCode !== 200) {
|
||||||
logger.error('Error sending secure request to %s/%s pod.', url, data.path, { error: err })
|
bad_pods.push(pod._id)
|
||||||
|
logger.error('Error sending secure request to %s/%s pod.', pod.url, data.path, { error: err })
|
||||||
|
} else {
|
||||||
|
good_pods.push(pod._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return callback_each_pod_finished()
|
||||||
},
|
},
|
||||||
|
|
||||||
function callbackAllPodsFinished (err) {
|
function callbackAllPodsFinished (err) {
|
||||||
|
@ -102,6 +139,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('Finished')
|
logger.debug('Finished')
|
||||||
|
|
||||||
|
updatePodsScore(good_pods, bad_pods)
|
||||||
callback(null)
|
callback(null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -133,8 +172,8 @@
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
function computeForeignPodsList (url, callback) {
|
function computeForeignPodsList (url, callback) {
|
||||||
// Always add a trust pod
|
// Let's give 1 point to the pod we ask the friends list
|
||||||
pods_score[url] = Infinity
|
pods_score[url] = 1
|
||||||
|
|
||||||
getForeignPodsList(url, function (foreign_pods_list) {
|
getForeignPodsList(url, function (foreign_pods_list) {
|
||||||
if (foreign_pods_list.length === 0) return callback()
|
if (foreign_pods_list.length === 0) return callback()
|
||||||
|
@ -175,16 +214,19 @@
|
||||||
|
|
||||||
pods_list,
|
pods_list,
|
||||||
|
|
||||||
function eachRequest (err, response, body, url) {
|
function eachRequest (err, response, body, pod, callback_each_request) {
|
||||||
// We add the pod if it responded correctly with its public certificate
|
// We add the pod if it responded correctly with its public certificate
|
||||||
if (!err && response.statusCode === 200) {
|
if (!err && response.statusCode === 200) {
|
||||||
pods.add({ url: url, publicKey: body.cert }, function (err) {
|
pods.add({ url: pod.url, publicKey: body.cert, score: global.FRIEND_BASE_SCORE }, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Error with adding %s pod.', url, { error: err })
|
logger.error('Error with adding %s pod.', pod.url, { error: err })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return callback_each_request()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
logger.error('Error with adding %s pod.', url, { error: err || new Error('Status not 200') })
|
logger.error('Error with adding %s pod.', pod.url, { error: err || new Error('Status not 200') })
|
||||||
|
return callback_each_request()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
30
src/utils.js
30
src/utils.js
|
@ -1,6 +1,7 @@
|
||||||
;(function () {
|
;(function () {
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
var async = require('async')
|
||||||
var config = require('config')
|
var config = require('config')
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
|
@ -30,14 +31,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('Sending informations to %s.', to_pod.url, { params: params })
|
logger.debug('Sending informations to %s.', to_pod.url, { params: params })
|
||||||
|
// Default 10 but in tests we want to be faster
|
||||||
|
var retries = utils.isTestInstance() ? 2 : 10
|
||||||
|
|
||||||
// Replay 15 times, with factor 3
|
|
||||||
replay(
|
replay(
|
||||||
request.post(params, function (err, response, body) {
|
request.post(params, function (err, response, body) {
|
||||||
callbackEach(err, response, body, to_pod.url)
|
callbackEach(err, response, body, to_pod)
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
retries: 10,
|
retries: retries,
|
||||||
factor: 3,
|
factor: 3,
|
||||||
maxTimeout: Infinity,
|
maxTimeout: Infinity,
|
||||||
errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ]
|
errorCodes: [ 'EADDRINFO', 'ETIMEDOUT', 'ECONNRESET', 'ESOCKETTIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED' ]
|
||||||
|
@ -68,7 +70,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a request for each pod
|
// Make a request for each pod
|
||||||
for (var pod of pods) {
|
async.each(pods, function (pod, callback_each_async) {
|
||||||
|
function callbackEachRetryRequest (err, response, body, pod) {
|
||||||
|
callbackEach(err, response, body, pod, function () {
|
||||||
|
callback_each_async()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
url: pod.url + all_data.path,
|
url: pod.url + all_data.path,
|
||||||
method: all_data.method
|
method: all_data.method
|
||||||
|
@ -93,20 +101,18 @@
|
||||||
key: passwordEncrypted
|
key: passwordEncrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
makeRetryRequest(copy_params, copy_url, copy_pod, copy_signature, callbackEach)
|
makeRetryRequest(copy_params, copy_url, copy_pod, copy_signature, callbackEachRetryRequest)
|
||||||
})
|
})
|
||||||
})(crt, params, url, pod, signature)
|
})(crt, params, url, pod, signature)
|
||||||
} else {
|
} else {
|
||||||
params.json = { data: all_data.data }
|
params.json = { data: all_data.data }
|
||||||
makeRetryRequest(params, url, pod, signature, callbackEach)
|
makeRetryRequest(params, url, pod, signature, callbackEachRetryRequest)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug('Make a GET/DELETE request')
|
logger.debug('Make a GET/DELETE request')
|
||||||
makeRetryRequest(params, url, pod, signature, callbackEach)
|
makeRetryRequest(params, url, pod, signature, callbackEachRetryRequest)
|
||||||
}
|
}
|
||||||
}
|
}, callback)
|
||||||
|
|
||||||
return callback()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.certsExist = function (callback) {
|
utils.certsExist = function (callback) {
|
||||||
|
@ -192,5 +198,9 @@
|
||||||
process.kill(-webtorrent_process.pid)
|
process.kill(-webtorrent_process.pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils.isTestInstance = function () {
|
||||||
|
return (process.env.NODE_ENV === 'test')
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = utils
|
module.exports = utils
|
||||||
})()
|
})()
|
||||||
|
|
|
@ -78,14 +78,9 @@
|
||||||
data: params
|
data: params
|
||||||
}
|
}
|
||||||
|
|
||||||
pods.makeSecureRequest(data, function (err) {
|
// Do not wait the secure requests
|
||||||
if (err) {
|
pods.makeSecureRequest(data)
|
||||||
logger.error('Somes issues when sending this video to friends.', { error: err })
|
callback(null)
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(null)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -138,18 +133,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes this is a POST request because we add some informations in the body (signature, encrypt etc)
|
// Yes this is a POST request because we add some informations in the body (signature, encrypt etc)
|
||||||
pods.makeSecureRequest(data, function (err) {
|
pods.makeSecureRequest(data)
|
||||||
if (err) {
|
|
||||||
logger.error('Somes issues when sending we want to remove the video to friends.', { error: err })
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null)
|
callback(null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the magnet Uri because the _id field is not the same on different servers
|
// Use the magnet Uri because the _id field is not the same on different servers
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
;(function () {
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
var request = require('supertest')
|
||||||
|
var chai = require('chai')
|
||||||
|
var expect = chai.expect
|
||||||
|
|
||||||
|
var utils = require('../utils')
|
||||||
|
|
||||||
|
describe('Test advanced friends', function () {
|
||||||
|
var path = '/api/v1/pods/makefriends'
|
||||||
|
var apps = []
|
||||||
|
var urls = []
|
||||||
|
|
||||||
|
function makeFriend (pod_number, callback) {
|
||||||
|
// The first pod make friend with the third
|
||||||
|
request(urls[pod_number - 1])
|
||||||
|
.get(path)
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(204)
|
||||||
|
.end(function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
// Wait for the request between pods
|
||||||
|
setTimeout(function () {
|
||||||
|
callback()
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFriendsList (pod_number, end) {
|
||||||
|
var path = '/api/v1/pods/'
|
||||||
|
|
||||||
|
request(urls[pod_number - 1])
|
||||||
|
.get(path)
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.end(end)
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadVideo (pod_number, callback) {
|
||||||
|
var path = '/api/v1/videos'
|
||||||
|
|
||||||
|
request(urls[pod_number - 1])
|
||||||
|
.post(path)
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.field('name', 'my super video')
|
||||||
|
.field('description', 'my super description')
|
||||||
|
.attach('input_video', __dirname + '/../fixtures/video_short.webm')
|
||||||
|
.expect(201)
|
||||||
|
.end(function (err) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
// Wait for the retry requests
|
||||||
|
setTimeout(callback, 10000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function (done) {
|
||||||
|
this.timeout(30000)
|
||||||
|
utils.runMultipleServers(6, function (apps_run, urls_run) {
|
||||||
|
apps = apps_run
|
||||||
|
urls = urls_run
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(function (done) {
|
||||||
|
apps.forEach(function (app) {
|
||||||
|
process.kill(-app.pid)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.ok) {
|
||||||
|
utils.flushTests(function () {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should make friends with two pod each in a different group', function (done) {
|
||||||
|
this.timeout(10000)
|
||||||
|
|
||||||
|
// Pod 3 makes friend with the first one
|
||||||
|
makeFriend(3, function () {
|
||||||
|
// Pod 4 makes friend with the second one
|
||||||
|
makeFriend(4, function () {
|
||||||
|
// Now if the fifth wants to make friends with the third et the first
|
||||||
|
makeFriend(5, function () {
|
||||||
|
// It should have 0 friends
|
||||||
|
getFriendsList(5, function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
expect(res.body.length).to.equal(0)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should make friends with the pods 1, 2, 3', function (done) {
|
||||||
|
this.timeout(100000)
|
||||||
|
|
||||||
|
// Pods 1, 2, 3 and 4 become friends
|
||||||
|
makeFriend(2, function () {
|
||||||
|
makeFriend(1, function () {
|
||||||
|
makeFriend(4, function () {
|
||||||
|
// Kill the server 4
|
||||||
|
apps[3].kill()
|
||||||
|
|
||||||
|
// Expulse pod 4 from pod 1 and 2
|
||||||
|
uploadVideo(1, function () {
|
||||||
|
uploadVideo(1, function () {
|
||||||
|
uploadVideo(2, function () {
|
||||||
|
uploadVideo(2, function () {
|
||||||
|
// Rerun server 4
|
||||||
|
utils.runServer(4, function (app, url) {
|
||||||
|
apps[3] = app
|
||||||
|
getFriendsList(4, function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
// Pod 4 didn't know pod 1 and 2 removed it
|
||||||
|
expect(res.body.length).to.equal(3)
|
||||||
|
|
||||||
|
// Pod 6 ask pod 1, 2 and 3
|
||||||
|
makeFriend(6, function () {
|
||||||
|
getFriendsList(6, function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
// Pod 4 should not be our friend
|
||||||
|
var result = res.body
|
||||||
|
expect(result.length).to.equal(3)
|
||||||
|
for (var pod of result) {
|
||||||
|
expect(pod.url).not.equal(urls[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})()
|
|
@ -19,7 +19,7 @@
|
||||||
.end(end)
|
.end(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Test friends', function () {
|
describe('Test basic friends', function () {
|
||||||
var apps = []
|
var apps = []
|
||||||
var urls = []
|
var urls = []
|
||||||
|
|
|
@ -74,8 +74,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
flushTests: flushTests,
|
||||||
runMultipleServers: runMultipleServers,
|
runMultipleServers: runMultipleServers,
|
||||||
runServer: runServer,
|
runServer: runServer
|
||||||
flushTests: flushTests
|
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
Loading…
Reference in New Issue