aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/extra-utils/miscs
diff options
context:
space:
mode:
Diffstat (limited to 'shared/extra-utils/miscs')
-rw-r--r--shared/extra-utils/miscs/checks.ts46
-rw-r--r--shared/extra-utils/miscs/email.ts64
-rw-r--r--shared/extra-utils/miscs/generate.ts61
-rw-r--r--shared/extra-utils/miscs/index.ts5
-rw-r--r--shared/extra-utils/miscs/miscs.ts170
-rw-r--r--shared/extra-utils/miscs/sql-command.ts142
-rw-r--r--shared/extra-utils/miscs/sql.ts161
-rw-r--r--shared/extra-utils/miscs/stubs.ts14
-rw-r--r--shared/extra-utils/miscs/tests.ts94
-rw-r--r--shared/extra-utils/miscs/webtorrent.ts30
10 files changed, 378 insertions, 409 deletions
diff --git a/shared/extra-utils/miscs/checks.ts b/shared/extra-utils/miscs/checks.ts
new file mode 100644
index 000000000..7fc92f804
--- /dev/null
+++ b/shared/extra-utils/miscs/checks.ts
@@ -0,0 +1,46 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
2
3import { expect } from 'chai'
4import { pathExists, readFile } from 'fs-extra'
5import { join } from 'path'
6import { root } from '@server/helpers/core-utils'
7import { HttpStatusCode } from '@shared/models'
8import { makeGetRequest } from '../requests'
9import { PeerTubeServer } from '../server'
10
11// Default interval -> 5 minutes
12function dateIsValid (dateString: string, interval = 300000) {
13 const dateToCheck = new Date(dateString)
14 const now = new Date()
15
16 return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
17}
18
19async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
20 const res = await makeGetRequest({
21 url,
22 path: imagePath,
23 expectedStatus: HttpStatusCode.OK_200
24 })
25
26 const body = res.body
27
28 const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
29 const minLength = body.length - ((30 * body.length) / 100)
30 const maxLength = body.length + ((30 * body.length) / 100)
31
32 expect(data.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
33 expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
34}
35
36async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
37 const base = server.servers.buildDirectory(directory)
38
39 expect(await pathExists(join(base, filePath))).to.equal(exist)
40}
41
42export {
43 dateIsValid,
44 testImage,
45 testFileExistsOrNot
46}
diff --git a/shared/extra-utils/miscs/email.ts b/shared/extra-utils/miscs/email.ts
deleted file mode 100644
index 9fc9a5ad0..000000000
--- a/shared/extra-utils/miscs/email.ts
+++ /dev/null
@@ -1,64 +0,0 @@
1import { ChildProcess } from 'child_process'
2import { randomInt } from '../../core-utils/miscs/miscs'
3import { parallelTests } from '../server/servers'
4
5const MailDev = require('maildev')
6
7class MockSmtpServer {
8
9 private static instance: MockSmtpServer
10 private started = false
11 private emailChildProcess: ChildProcess
12 private emails: object[]
13
14 private constructor () { }
15
16 collectEmails (emailsCollection: object[]) {
17 return new Promise<number>((res, rej) => {
18 const port = parallelTests() ? randomInt(1000, 2000) : 1025
19 this.emails = emailsCollection
20
21 if (this.started) {
22 return res(undefined)
23 }
24
25 const maildev = new MailDev({
26 ip: '127.0.0.1',
27 smtp: port,
28 disableWeb: true,
29 silent: true
30 })
31
32 maildev.on('new', email => {
33 this.emails.push(email)
34 })
35
36 maildev.listen(err => {
37 if (err) return rej(err)
38
39 this.started = true
40
41 return res(port)
42 })
43 })
44 }
45
46 kill () {
47 if (!this.emailChildProcess) return
48
49 process.kill(this.emailChildProcess.pid)
50
51 this.emailChildProcess = null
52 MockSmtpServer.instance = null
53 }
54
55 static get Instance () {
56 return this.instance || (this.instance = new this())
57 }
58}
59
60// ---------------------------------------------------------------------------
61
62export {
63 MockSmtpServer
64}
diff --git a/shared/extra-utils/miscs/generate.ts b/shared/extra-utils/miscs/generate.ts
new file mode 100644
index 000000000..8d6435481
--- /dev/null
+++ b/shared/extra-utils/miscs/generate.ts
@@ -0,0 +1,61 @@
1import * as ffmpeg from 'fluent-ffmpeg'
2import { ensureDir, pathExists } from 'fs-extra'
3import { dirname } from 'path'
4import { buildAbsoluteFixturePath } from './tests'
5
6async function generateHighBitrateVideo () {
7 const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
8
9 await ensureDir(dirname(tempFixturePath))
10
11 const exists = await pathExists(tempFixturePath)
12 if (!exists) {
13 console.log('Generating high bitrate video.')
14
15 // Generate a random, high bitrate video on the fly, so we don't have to include
16 // a large file in the repo. The video needs to have a certain minimum length so
17 // that FFmpeg properly applies bitrate limits.
18 // https://stackoverflow.com/a/15795112
19 return new Promise<string>((res, rej) => {
20 ffmpeg()
21 .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
22 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
23 .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
24 .output(tempFixturePath)
25 .on('error', rej)
26 .on('end', () => res(tempFixturePath))
27 .run()
28 })
29 }
30
31 return tempFixturePath
32}
33
34async function generateVideoWithFramerate (fps = 60) {
35 const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
36
37 await ensureDir(dirname(tempFixturePath))
38
39 const exists = await pathExists(tempFixturePath)
40 if (!exists) {
41 console.log('Generating video with framerate %d.', fps)
42
43 return new Promise<string>((res, rej) => {
44 ffmpeg()
45 .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
46 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
47 .outputOptions([ `-r ${fps}` ])
48 .output(tempFixturePath)
49 .on('error', rej)
50 .on('end', () => res(tempFixturePath))
51 .run()
52 })
53 }
54
55 return tempFixturePath
56}
57
58export {
59 generateHighBitrateVideo,
60 generateVideoWithFramerate
61}
diff --git a/shared/extra-utils/miscs/index.ts b/shared/extra-utils/miscs/index.ts
new file mode 100644
index 000000000..4474661de
--- /dev/null
+++ b/shared/extra-utils/miscs/index.ts
@@ -0,0 +1,5 @@
1export * from './checks'
2export * from './generate'
3export * from './sql-command'
4export * from './tests'
5export * from './webtorrent'
diff --git a/shared/extra-utils/miscs/miscs.ts b/shared/extra-utils/miscs/miscs.ts
deleted file mode 100644
index 462b914d4..000000000
--- a/shared/extra-utils/miscs/miscs.ts
+++ /dev/null
@@ -1,170 +0,0 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import * as chai from 'chai'
4import * as ffmpeg from 'fluent-ffmpeg'
5import { ensureDir, pathExists, readFile, stat } from 'fs-extra'
6import { basename, dirname, isAbsolute, join, resolve } from 'path'
7import * as request from 'supertest'
8import * as WebTorrent from 'webtorrent'
9import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
10
11const expect = chai.expect
12let webtorrent: WebTorrent.Instance
13
14function immutableAssign<T, U> (target: T, source: U) {
15 return Object.assign<{}, T, U>({}, target, source)
16}
17
18// Default interval -> 5 minutes
19function dateIsValid (dateString: string, interval = 300000) {
20 const dateToCheck = new Date(dateString)
21 const now = new Date()
22
23 return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
24}
25
26function wait (milliseconds: number) {
27 return new Promise(resolve => setTimeout(resolve, milliseconds))
28}
29
30function webtorrentAdd (torrent: string, refreshWebTorrent = false) {
31 const WebTorrent = require('webtorrent')
32
33 if (!webtorrent) webtorrent = new WebTorrent()
34 if (refreshWebTorrent === true) webtorrent = new WebTorrent()
35
36 return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res))
37}
38
39function root () {
40 // We are in /miscs
41 let root = join(__dirname, '..', '..', '..')
42
43 if (basename(root) === 'dist') root = resolve(root, '..')
44
45 return root
46}
47
48function buildServerDirectory (server: { internalServerNumber: number }, directory: string) {
49 return join(root(), 'test' + server.internalServerNumber, directory)
50}
51
52async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
53 const res = await request(url)
54 .get(imagePath)
55 .expect(HttpStatusCode.OK_200)
56
57 const body = res.body
58
59 const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
60 const minLength = body.length - ((30 * body.length) / 100)
61 const maxLength = body.length + ((30 * body.length) / 100)
62
63 expect(data.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
64 expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
65}
66
67async function testFileExistsOrNot (server: { internalServerNumber: number }, directory: string, filePath: string, exist: boolean) {
68 const base = buildServerDirectory(server, directory)
69
70 expect(await pathExists(join(base, filePath))).to.equal(exist)
71}
72
73function isGithubCI () {
74 return !!process.env.GITHUB_WORKSPACE
75}
76
77function buildAbsoluteFixturePath (path: string, customCIPath = false) {
78 if (isAbsolute(path)) return path
79
80 if (customCIPath && process.env.GITHUB_WORKSPACE) {
81 return join(process.env.GITHUB_WORKSPACE, 'fixtures', path)
82 }
83
84 return join(root(), 'server', 'tests', 'fixtures', path)
85}
86
87function areHttpImportTestsDisabled () {
88 const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true'
89
90 if (disabled) console.log('Import tests are disabled')
91
92 return disabled
93}
94
95async function generateHighBitrateVideo () {
96 const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
97
98 await ensureDir(dirname(tempFixturePath))
99
100 const exists = await pathExists(tempFixturePath)
101 if (!exists) {
102 console.log('Generating high bitrate video.')
103
104 // Generate a random, high bitrate video on the fly, so we don't have to include
105 // a large file in the repo. The video needs to have a certain minimum length so
106 // that FFmpeg properly applies bitrate limits.
107 // https://stackoverflow.com/a/15795112
108 return new Promise<string>((res, rej) => {
109 ffmpeg()
110 .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
111 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
112 .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
113 .output(tempFixturePath)
114 .on('error', rej)
115 .on('end', () => res(tempFixturePath))
116 .run()
117 })
118 }
119
120 return tempFixturePath
121}
122
123async function generateVideoWithFramerate (fps = 60) {
124 const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
125
126 await ensureDir(dirname(tempFixturePath))
127
128 const exists = await pathExists(tempFixturePath)
129 if (!exists) {
130 console.log('Generating video with framerate %d.', fps)
131
132 return new Promise<string>((res, rej) => {
133 ffmpeg()
134 .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
135 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
136 .outputOptions([ `-r ${fps}` ])
137 .output(tempFixturePath)
138 .on('error', rej)
139 .on('end', () => res(tempFixturePath))
140 .run()
141 })
142 }
143
144 return tempFixturePath
145}
146
147async function getFileSize (path: string) {
148 const stats = await stat(path)
149
150 return stats.size
151}
152
153// ---------------------------------------------------------------------------
154
155export {
156 dateIsValid,
157 wait,
158 areHttpImportTestsDisabled,
159 buildServerDirectory,
160 webtorrentAdd,
161 getFileSize,
162 immutableAssign,
163 testImage,
164 isGithubCI,
165 buildAbsoluteFixturePath,
166 testFileExistsOrNot,
167 root,
168 generateHighBitrateVideo,
169 generateVideoWithFramerate
170}
diff --git a/shared/extra-utils/miscs/sql-command.ts b/shared/extra-utils/miscs/sql-command.ts
new file mode 100644
index 000000000..80c8cd271
--- /dev/null
+++ b/shared/extra-utils/miscs/sql-command.ts
@@ -0,0 +1,142 @@
1import { QueryTypes, Sequelize } from 'sequelize'
2import { AbstractCommand } from '../shared/abstract-command'
3
4export class SQLCommand extends AbstractCommand {
5 private sequelize: Sequelize
6
7 deleteAll (table: string) {
8 const seq = this.getSequelize()
9
10 const options = { type: QueryTypes.DELETE }
11
12 return seq.query(`DELETE FROM "${table}"`, options)
13 }
14
15 async getCount (table: string) {
16 const seq = this.getSequelize()
17
18 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
19
20 const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options)
21 if (total === null) return 0
22
23 return parseInt(total, 10)
24 }
25
26 setActorField (to: string, field: string, value: string) {
27 const seq = this.getSequelize()
28
29 const options = { type: QueryTypes.UPDATE }
30
31 return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options)
32 }
33
34 setVideoField (uuid: string, field: string, value: string) {
35 const seq = this.getSequelize()
36
37 const options = { type: QueryTypes.UPDATE }
38
39 return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
40 }
41
42 setPlaylistField (uuid: string, field: string, value: string) {
43 const seq = this.getSequelize()
44
45 const options = { type: QueryTypes.UPDATE }
46
47 return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
48 }
49
50 async countVideoViewsOf (uuid: string) {
51 const seq = this.getSequelize()
52
53 // tslint:disable
54 const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
55 `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'`
56
57 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
58 const [ { total } ] = await seq.query<{ total: number }>(query, options)
59
60 if (!total) return 0
61
62 return parseInt(total + '', 10)
63 }
64
65 getActorImage (filename: string) {
66 return this.selectQuery(`SELECT * FROM "actorImage" WHERE filename = '${filename}'`)
67 .then(rows => rows[0])
68 }
69
70 selectQuery (query: string) {
71 const seq = this.getSequelize()
72 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
73
74 return seq.query<any>(query, options)
75 }
76
77 updateQuery (query: string) {
78 const seq = this.getSequelize()
79 const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE }
80
81 return seq.query(query, options)
82 }
83
84 setPluginField (pluginName: string, field: string, value: string) {
85 const seq = this.getSequelize()
86
87 const options = { type: QueryTypes.UPDATE }
88
89 return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options)
90 }
91
92 setPluginVersion (pluginName: string, newVersion: string) {
93 return this.setPluginField(pluginName, 'version', newVersion)
94 }
95
96 setPluginLatestVersion (pluginName: string, newVersion: string) {
97 return this.setPluginField(pluginName, 'latestVersion', newVersion)
98 }
99
100 setActorFollowScores (newScore: number) {
101 const seq = this.getSequelize()
102
103 const options = { type: QueryTypes.UPDATE }
104
105 return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options)
106 }
107
108 setTokenField (accessToken: string, field: string, value: string) {
109 const seq = this.getSequelize()
110
111 const options = { type: QueryTypes.UPDATE }
112
113 return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options)
114 }
115
116 async cleanup () {
117 if (!this.sequelize) return
118
119 await this.sequelize.close()
120 this.sequelize = undefined
121 }
122
123 private getSequelize () {
124 if (this.sequelize) return this.sequelize
125
126 const dbname = 'peertube_test' + this.server.internalServerNumber
127 const username = 'peertube'
128 const password = 'peertube'
129 const host = 'localhost'
130 const port = 5432
131
132 this.sequelize = new Sequelize(dbname, username, password, {
133 dialect: 'postgres',
134 host,
135 port,
136 logging: false
137 })
138
139 return this.sequelize
140 }
141
142}
diff --git a/shared/extra-utils/miscs/sql.ts b/shared/extra-utils/miscs/sql.ts
deleted file mode 100644
index 65a0aa5fe..000000000
--- a/shared/extra-utils/miscs/sql.ts
+++ /dev/null
@@ -1,161 +0,0 @@
1import { QueryTypes, Sequelize } from 'sequelize'
2import { ServerInfo } from '../server/servers'
3
4const sequelizes: { [ id: number ]: Sequelize } = {}
5
6function getSequelize (internalServerNumber: number) {
7 if (sequelizes[internalServerNumber]) return sequelizes[internalServerNumber]
8
9 const dbname = 'peertube_test' + internalServerNumber
10 const username = 'peertube'
11 const password = 'peertube'
12 const host = 'localhost'
13 const port = 5432
14
15 const seq = new Sequelize(dbname, username, password, {
16 dialect: 'postgres',
17 host,
18 port,
19 logging: false
20 })
21
22 sequelizes[internalServerNumber] = seq
23
24 return seq
25}
26
27function deleteAll (internalServerNumber: number, table: string) {
28 const seq = getSequelize(internalServerNumber)
29
30 const options = { type: QueryTypes.DELETE }
31
32 return seq.query(`DELETE FROM "${table}"`, options)
33}
34
35async function getCount (internalServerNumber: number, table: string) {
36 const seq = getSequelize(internalServerNumber)
37
38 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
39
40 const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options)
41 if (total === null) return 0
42
43 return parseInt(total, 10)
44}
45
46function setActorField (internalServerNumber: number, to: string, field: string, value: string) {
47 const seq = getSequelize(internalServerNumber)
48
49 const options = { type: QueryTypes.UPDATE }
50
51 return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options)
52}
53
54function setVideoField (internalServerNumber: number, uuid: string, field: string, value: string) {
55 const seq = getSequelize(internalServerNumber)
56
57 const options = { type: QueryTypes.UPDATE }
58
59 return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
60}
61
62function setPlaylistField (internalServerNumber: number, uuid: string, field: string, value: string) {
63 const seq = getSequelize(internalServerNumber)
64
65 const options = { type: QueryTypes.UPDATE }
66
67 return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options)
68}
69
70async function countVideoViewsOf (internalServerNumber: number, uuid: string) {
71 const seq = getSequelize(internalServerNumber)
72
73 // tslint:disable
74 const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
75 `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'`
76
77 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
78 const [ { total } ] = await seq.query<{ total: number }>(query, options)
79
80 if (!total) return 0
81
82 return parseInt(total + '', 10)
83}
84
85function getActorImage (internalServerNumber: number, filename: string) {
86 return selectQuery(internalServerNumber, `SELECT * FROM "actorImage" WHERE filename = '${filename}'`)
87 .then(rows => rows[0])
88}
89
90function selectQuery (internalServerNumber: number, query: string) {
91 const seq = getSequelize(internalServerNumber)
92 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT }
93
94 return seq.query<any>(query, options)
95}
96
97function updateQuery (internalServerNumber: number, query: string) {
98 const seq = getSequelize(internalServerNumber)
99 const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE }
100
101 return seq.query(query, options)
102}
103
104async function closeAllSequelize (servers: ServerInfo[]) {
105 for (const server of servers) {
106 if (sequelizes[server.internalServerNumber]) {
107 await sequelizes[server.internalServerNumber].close()
108 // eslint-disable-next-line
109 delete sequelizes[server.internalServerNumber]
110 }
111 }
112}
113
114function setPluginField (internalServerNumber: number, pluginName: string, field: string, value: string) {
115 const seq = getSequelize(internalServerNumber)
116
117 const options = { type: QueryTypes.UPDATE }
118
119 return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options)
120}
121
122function setPluginVersion (internalServerNumber: number, pluginName: string, newVersion: string) {
123 return setPluginField(internalServerNumber, pluginName, 'version', newVersion)
124}
125
126function setPluginLatestVersion (internalServerNumber: number, pluginName: string, newVersion: string) {
127 return setPluginField(internalServerNumber, pluginName, 'latestVersion', newVersion)
128}
129
130function setActorFollowScores (internalServerNumber: number, newScore: number) {
131 const seq = getSequelize(internalServerNumber)
132
133 const options = { type: QueryTypes.UPDATE }
134
135 return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options)
136}
137
138function setTokenField (internalServerNumber: number, accessToken: string, field: string, value: string) {
139 const seq = getSequelize(internalServerNumber)
140
141 const options = { type: QueryTypes.UPDATE }
142
143 return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options)
144}
145
146export {
147 setVideoField,
148 setPlaylistField,
149 setActorField,
150 countVideoViewsOf,
151 setPluginVersion,
152 setPluginLatestVersion,
153 selectQuery,
154 getActorImage,
155 deleteAll,
156 setTokenField,
157 updateQuery,
158 setActorFollowScores,
159 closeAllSequelize,
160 getCount
161}
diff --git a/shared/extra-utils/miscs/stubs.ts b/shared/extra-utils/miscs/stubs.ts
deleted file mode 100644
index d1eb0e3b2..000000000
--- a/shared/extra-utils/miscs/stubs.ts
+++ /dev/null
@@ -1,14 +0,0 @@
1function buildRequestStub (): any {
2 return { }
3}
4
5function buildResponseStub (): any {
6 return {
7 locals: {}
8 }
9}
10
11export {
12 buildResponseStub,
13 buildRequestStub
14}
diff --git a/shared/extra-utils/miscs/tests.ts b/shared/extra-utils/miscs/tests.ts
new file mode 100644
index 000000000..3dfb2487e
--- /dev/null
+++ b/shared/extra-utils/miscs/tests.ts
@@ -0,0 +1,94 @@
1import { stat } from 'fs-extra'
2import { basename, isAbsolute, join, resolve } from 'path'
3
4const FIXTURE_URLS = {
5 youtube: 'https://www.youtube.com/watch?v=msX3jv1XdvM',
6
7 /**
8 * The video is used to check format-selection correctness wrt. HDR,
9 * which brings its own set of oddities outside of a MediaSource.
10 * FIXME: refactor once HDR is supported at playback
11 *
12 * The video needs to have the following format_ids:
13 * (which you can check by using `youtube-dl <url> -F`):
14 * - 303 (1080p webm vp9)
15 * - 299 (1080p mp4 avc1)
16 * - 335 (1080p webm vp9.2 HDR)
17 *
18 * 15 jan. 2021: TEST VIDEO NOT CURRENTLY PROVIDING
19 * - 400 (1080p mp4 av01)
20 * - 315 (2160p webm vp9 HDR)
21 * - 337 (2160p webm vp9.2 HDR)
22 * - 401 (2160p mp4 av01 HDR)
23 */
24 youtubeHDR: 'https://www.youtube.com/watch?v=qR5vOXbZsI4',
25
26 // eslint-disable-next-line max-len
27 magnet: 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4',
28
29 badVideo: 'https://download.cpy.re/peertube/bad_video.mp4',
30 goodVideo: 'https://download.cpy.re/peertube/good_video.mp4',
31 video4K: 'https://download.cpy.re/peertube/4k_file.txt'
32}
33
34function parallelTests () {
35 return process.env.MOCHA_PARALLEL === 'true'
36}
37
38function isGithubCI () {
39 return !!process.env.GITHUB_WORKSPACE
40}
41
42function areHttpImportTestsDisabled () {
43 const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true'
44
45 if (disabled) console.log('Import tests are disabled')
46
47 return disabled
48}
49
50function buildAbsoluteFixturePath (path: string, customCIPath = false) {
51 if (isAbsolute(path)) return path
52
53 if (customCIPath && process.env.GITHUB_WORKSPACE) {
54 return join(process.env.GITHUB_WORKSPACE, 'fixtures', path)
55 }
56
57 return join(root(), 'server', 'tests', 'fixtures', path)
58}
59
60function root () {
61 // We are in /miscs
62 let root = join(__dirname, '..', '..', '..')
63
64 if (basename(root) === 'dist') root = resolve(root, '..')
65
66 return root
67}
68
69function wait (milliseconds: number) {
70 return new Promise(resolve => setTimeout(resolve, milliseconds))
71}
72
73async function getFileSize (path: string) {
74 const stats = await stat(path)
75
76 return stats.size
77}
78
79function buildRequestStub (): any {
80 return { }
81}
82
83export {
84 FIXTURE_URLS,
85
86 parallelTests,
87 isGithubCI,
88 areHttpImportTestsDisabled,
89 buildAbsoluteFixturePath,
90 getFileSize,
91 buildRequestStub,
92 wait,
93 root
94}
diff --git a/shared/extra-utils/miscs/webtorrent.ts b/shared/extra-utils/miscs/webtorrent.ts
new file mode 100644
index 000000000..815ea3d56
--- /dev/null
+++ b/shared/extra-utils/miscs/webtorrent.ts
@@ -0,0 +1,30 @@
1import { readFile } from 'fs-extra'
2import * as parseTorrent from 'parse-torrent'
3import { join } from 'path'
4import * as WebTorrent from 'webtorrent'
5import { PeerTubeServer } from '../server'
6
7let webtorrent: WebTorrent.Instance
8
9function webtorrentAdd (torrent: string, refreshWebTorrent = false) {
10 const WebTorrent = require('webtorrent')
11
12 if (!webtorrent) webtorrent = new WebTorrent()
13 if (refreshWebTorrent === true) webtorrent = new WebTorrent()
14
15 return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res))
16}
17
18async function parseTorrentVideo (server: PeerTubeServer, videoUUID: string, resolution: number) {
19 const torrentName = videoUUID + '-' + resolution + '.torrent'
20 const torrentPath = server.servers.buildDirectory(join('torrents', torrentName))
21
22 const data = await readFile(torrentPath)
23
24 return parseTorrent(data)
25}
26
27export {
28 webtorrentAdd,
29 parseTorrentVideo
30}