]>
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 C |
4 | import * as ffmpeg from 'fluent-ffmpeg' |
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 | |
e6dfa586 RK |
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") | |
9ee83eb9 C |
65 | } |
66 | ||
83ef31fe C |
67 | function isGithubCI () { |
68 | return !!process.env.GITHUB_WORKSPACE | |
69 | } | |
70 | ||
2284f202 | 71 | function buildAbsoluteFixturePath (path: string, customCIPath = false) { |
b488ba1e | 72 | if (isAbsolute(path)) return path |
ac81d1a0 | 73 | |
07491f4b C |
74 | if (customCIPath && process.env.GITHUB_WORKSPACE) { |
75 | return join(process.env.GITHUB_WORKSPACE, 'fixtures', path) | |
c928e136 | 76 | } |
c1c86c15 | 77 | |
2a8c5d0a | 78 | return join(root(), 'server', 'tests', 'fixtures', path) |
ac81d1a0 C |
79 | } |
80 | ||
b488ba1e C |
81 | function areHttpImportTestsDisabled () { |
82 | const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true' | |
83 | ||
84 | if (disabled) console.log('Import tests are disabled') | |
85 | ||
86 | return disabled | |
87 | } | |
88 | ||
74cd011b C |
89 | async function generateHighBitrateVideo () { |
90 | const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true) | |
91 | ||
2284f202 C |
92 | await ensureDir(dirname(tempFixturePath)) |
93 | ||
74cd011b C |
94 | const exists = await pathExists(tempFixturePath) |
95 | if (!exists) { | |
9e3e4adc | 96 | console.log('Generating high bitrate video.') |
74cd011b C |
97 | |
98 | // Generate a random, high bitrate video on the fly, so we don't have to include | |
99 | // a large file in the repo. The video needs to have a certain minimum length so | |
100 | // that FFmpeg properly applies bitrate limits. | |
101 | // https://stackoverflow.com/a/15795112 | |
a1587156 | 102 | return new Promise<string>((res, rej) => { |
74cd011b C |
103 | ffmpeg() |
104 | .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ]) | |
105 | .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ]) | |
106 | .outputOptions([ '-maxrate 10M', '-bufsize 10M' ]) | |
107 | .output(tempFixturePath) | |
108 | .on('error', rej) | |
109 | .on('end', () => res(tempFixturePath)) | |
110 | .run() | |
111 | }) | |
112 | } | |
113 | ||
114 | return tempFixturePath | |
115 | } | |
116 | ||
837666fe RK |
117 | async function generateVideoWithFramerate (fps = 60) { |
118 | const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true) | |
119 | ||
120 | await ensureDir(dirname(tempFixturePath)) | |
121 | ||
122 | const exists = await pathExists(tempFixturePath) | |
123 | if (!exists) { | |
9e3e4adc C |
124 | console.log('Generating video with framerate %d.', fps) |
125 | ||
a1587156 | 126 | return new Promise<string>((res, rej) => { |
837666fe | 127 | ffmpeg() |
c7f36e4f | 128 | .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ]) |
837666fe RK |
129 | .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ]) |
130 | .outputOptions([ `-r ${fps}` ]) | |
131 | .output(tempFixturePath) | |
132 | .on('error', rej) | |
133 | .on('end', () => res(tempFixturePath)) | |
134 | .run() | |
135 | }) | |
136 | } | |
137 | ||
138 | return tempFixturePath | |
139 | } | |
140 | ||
d218e7de C |
141 | async function getFileSize (path: string) { |
142 | const stats = await stat(path) | |
143 | ||
144 | return stats.size | |
145 | } | |
146 | ||
0e1dc3e7 C |
147 | // --------------------------------------------------------------------------- |
148 | ||
149 | export { | |
0e1dc3e7 C |
150 | dateIsValid, |
151 | wait, | |
b488ba1e | 152 | areHttpImportTestsDisabled, |
e2600d8b | 153 | buildServerDirectory, |
26d21b78 | 154 | webtorrentAdd, |
d218e7de | 155 | getFileSize, |
f05a1c30 | 156 | immutableAssign, |
9ee83eb9 | 157 | testImage, |
83ef31fe | 158 | isGithubCI, |
ac81d1a0 | 159 | buildAbsoluteFixturePath, |
74cd011b | 160 | root, |
837666fe RK |
161 | generateHighBitrateVideo, |
162 | generateVideoWithFramerate | |
0e1dc3e7 | 163 | } |