]>
Commit | Line | Data |
---|---|---|
a1587156 | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
9ee83eb9 | 2 | |
7b0956ec | 3 | import * as chai from 'chai' |
ca5c612b | 4 | import * as ffmpeg from 'fluent-ffmpeg' |
f6c1251d | 5 | import { ensureDir, pathExists, readFile, stat } from 'fs-extra' |
2284f202 | 6 | import { basename, dirname, isAbsolute, join, resolve } from 'path' |
9ee83eb9 | 7 | import * as request from 'supertest' |
0e1dc3e7 | 8 | import * as WebTorrent from 'webtorrent' |
2d53be02 | 9 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
0e1dc3e7 | 10 | |
7b0956ec | 11 | const expect = chai.expect |
8d2be0ed | 12 | let webtorrent: WebTorrent.Instance |
0e1dc3e7 | 13 | |
a1587156 | 14 | function immutableAssign<T, U> (target: T, source: U) { |
26d21b78 C |
15 | return Object.assign<{}, T, U>({}, target, source) |
16 | } | |
17 | ||
a1587156 | 18 | // Default interval -> 5 minutes |
b1f5b93e | 19 | function dateIsValid (dateString: string, interval = 300000) { |
0e1dc3e7 C |
20 | const dateToCheck = new Date(dateString) |
21 | const now = new Date() | |
22 | ||
23 | return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval | |
24 | } | |
25 | ||
26 | function wait (milliseconds: number) { | |
27 | return new Promise(resolve => setTimeout(resolve, milliseconds)) | |
28 | } | |
29 | ||
30 | function webtorrentAdd (torrent: string, refreshWebTorrent = false) { | |
8d2be0ed C |
31 | const WebTorrent = require('webtorrent') |
32 | ||
33 | if (!webtorrent) webtorrent = new WebTorrent() | |
0e1dc3e7 C |
34 | if (refreshWebTorrent === true) webtorrent = new WebTorrent() |
35 | ||
36 | return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res)) | |
37 | } | |
38 | ||
f05a1c30 | 39 | function root () { |
94565d52 | 40 | // We are in /miscs |
1a12f66d C |
41 | let root = join(__dirname, '..', '..', '..') |
42 | ||
43 | if (basename(root) === 'dist') root = resolve(root, '..') | |
44 | ||
45 | return root | |
f05a1c30 C |
46 | } |
47 | ||
ca5c612b C |
48 | function buildServerDirectory (server: { internalServerNumber: number }, directory: string) { |
49 | return join(root(), 'test' + server.internalServerNumber, directory) | |
e2600d8b C |
50 | } |
51 | ||
9ee83eb9 | 52 | async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') { |
288178bf C |
53 | const res = await request(url) |
54 | .get(imagePath) | |
2d53be02 | 55 | .expect(HttpStatusCode.OK_200) |
288178bf C |
56 | |
57 | const body = res.body | |
58 | ||
2a8c5d0a | 59 | const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension)) |
e6dfa586 RK |
60 | const minLength = body.length - ((30 * body.length) / 100) |
61 | const maxLength = body.length + ((30 * body.length) / 100) | |
288178bf | 62 | |
06c27593 C |
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 | ||
67 | async 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) | |
9ee83eb9 C |
71 | } |
72 | ||
83ef31fe C |
73 | function isGithubCI () { |
74 | return !!process.env.GITHUB_WORKSPACE | |
75 | } | |
76 | ||
2284f202 | 77 | function buildAbsoluteFixturePath (path: string, customCIPath = false) { |
b488ba1e | 78 | if (isAbsolute(path)) return path |
ac81d1a0 | 79 | |
07491f4b C |
80 | if (customCIPath && process.env.GITHUB_WORKSPACE) { |
81 | return join(process.env.GITHUB_WORKSPACE, 'fixtures', path) | |
c928e136 | 82 | } |
c1c86c15 | 83 | |
2a8c5d0a | 84 | return join(root(), 'server', 'tests', 'fixtures', path) |
ac81d1a0 C |
85 | } |
86 | ||
b488ba1e C |
87 | function 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 | ||
74cd011b C |
95 | async function generateHighBitrateVideo () { |
96 | const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true) | |
97 | ||
2284f202 C |
98 | await ensureDir(dirname(tempFixturePath)) |
99 | ||
74cd011b C |
100 | const exists = await pathExists(tempFixturePath) |
101 | if (!exists) { | |
9e3e4adc | 102 | console.log('Generating high bitrate video.') |
74cd011b C |
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 | |
a1587156 | 108 | return new Promise<string>((res, rej) => { |
74cd011b C |
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 | ||
837666fe RK |
123 | async 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) { | |
9e3e4adc C |
130 | console.log('Generating video with framerate %d.', fps) |
131 | ||
a1587156 | 132 | return new Promise<string>((res, rej) => { |
837666fe | 133 | ffmpeg() |
c7f36e4f | 134 | .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ]) |
837666fe RK |
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 | ||
d218e7de C |
147 | async function getFileSize (path: string) { |
148 | const stats = await stat(path) | |
149 | ||
150 | return stats.size | |
151 | } | |
152 | ||
0e1dc3e7 C |
153 | // --------------------------------------------------------------------------- |
154 | ||
155 | export { | |
0e1dc3e7 C |
156 | dateIsValid, |
157 | wait, | |
b488ba1e | 158 | areHttpImportTestsDisabled, |
e2600d8b | 159 | buildServerDirectory, |
26d21b78 | 160 | webtorrentAdd, |
d218e7de | 161 | getFileSize, |
f05a1c30 | 162 | immutableAssign, |
9ee83eb9 | 163 | testImage, |
83ef31fe | 164 | isGithubCI, |
ac81d1a0 | 165 | buildAbsoluteFixturePath, |
06c27593 | 166 | testFileExistsOrNot, |
74cd011b | 167 | root, |
837666fe RK |
168 | generateHighBitrateVideo, |
169 | generateVideoWithFramerate | |
0e1dc3e7 | 170 | } |