]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - scripts/benchmark.ts
Add log to regenerate thumbnails
[github/Chocobozzz/PeerTube.git] / scripts / benchmark.ts
CommitLineData
4abbeff5
C
1import { registerTSPaths } from '../server/helpers/register-ts-paths'
2registerTSPaths()
3
4import * as autocannon from 'autocannon'
5import {
6 addVideoCommentReply,
7 addVideoCommentThread,
8 createVideoCaption,
9 flushAndRunServer,
10 getVideosList,
11 killallServers,
12 ServerInfo,
13 setAccessTokensToServers,
14 uploadVideo
15} from '@shared/extra-utils'
16import { Video, VideoPrivacy } from '@shared/models'
17import { writeJson } from 'fs-extra'
18
19let server: ServerInfo
20let video: Video
21let threadId: number
22
23const outfile = process.argv[2]
24
25run()
26 .catch(err => console.error(err))
27 .finally(() => {
28 if (server) killallServers([ server ])
29 })
30
31function buildAuthorizationHeader () {
32 return {
33 Authorization: 'Bearer ' + server.accessToken
34 }
35}
36
0ce8d34e
C
37function buildAPHeader () {
38 return {
39 Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
40 }
41}
42
4abbeff5
C
43async function run () {
44 console.log('Preparing server...')
45
46 await prepare()
47
48 const tests = [
0ce8d34e
C
49 {
50 title: 'AP - account peertube',
51 path: '/accounts/peertube',
52 headers: buildAPHeader(),
53 expecter: (client, statusCode) => {
54 const body = client.resData[0].body
55
56 return statusCode === 200 && body.startsWith('{"type":')
57 }
58 },
59 {
60 title: 'AP - video',
61 path: '/videos/watch/' + video.uuid,
62 headers: buildAPHeader(),
63 expecter: (client, statusCode) => {
64 const body = client.resData[0].body
65
66 return statusCode === 200 && body.startsWith('{"type":"Video"')
67 }
68 },
69 {
70 title: 'Misc - webfinger peertube',
71 path: '/.well-known/webfinger?resource=acct:peertube@' + server.host,
72 expecter: (client, statusCode) => {
73 const body = client.resData[0].body
74
75 return statusCode === 200 && body.startsWith('{"subject":')
76 }
77 },
4abbeff5
C
78 {
79 title: 'API - unread notifications',
80 path: '/api/v1/users/me/notifications?start=0&count=0&unread=true',
81 headers: buildAuthorizationHeader(),
82 expecter: (_client, statusCode) => {
83 return statusCode === 200
84 }
85 },
86 {
87 title: 'API - me',
88 path: '/api/v1/users/me',
89 headers: buildAuthorizationHeader(),
90 expecter: (client, statusCode) => {
91 const body = client.resData[0].body
92
93 return statusCode === 200 && body.startsWith('{"id":')
94 }
95 },
96 {
97 title: 'API - videos list',
98 path: '/api/v1/videos',
99 expecter: (client, statusCode) => {
100 const body = client.resData[0].body
101
102 return statusCode === 200 && body.startsWith('{"total":10')
103 }
104 },
105 {
106 title: 'API - video get',
107 path: '/api/v1/videos/' + video.uuid,
108 expecter: (client, statusCode) => {
109 const body = client.resData[0].body
110
111 return statusCode === 200 && body.startsWith('{"id":')
112 }
113 },
114 {
115 title: 'API - video captions',
116 path: '/api/v1/videos/' + video.uuid + '/captions',
117 expecter: (client, statusCode) => {
118 const body = client.resData[0].body
119
120 return statusCode === 200 && body.startsWith('{"total":4')
121 }
122 },
123 {
124 title: 'API - video threads',
125 path: '/api/v1/videos/' + video.uuid + '/comment-threads',
126 expecter: (client, statusCode) => {
127 const body = client.resData[0].body
128
129 return statusCode === 200 && body.startsWith('{"total":10')
130 }
131 },
132 {
133 title: 'API - video replies',
134 path: '/api/v1/videos/' + video.uuid + '/comment-threads/' + threadId,
135 expecter: (client, statusCode) => {
136 const body = client.resData[0].body
137
138 return statusCode === 200 && body.startsWith('{"comment":{')
139 }
140 },
141 {
142 title: 'HTML - video watch',
143 path: '/videos/watch/' + video.uuid,
144 expecter: (client, statusCode) => {
145 const body = client.resData[0].body
146
147 return statusCode === 200 && body.includes('<title>my super')
148 }
149 },
0ce8d34e
C
150 {
151 title: 'HTML - video embed',
152 path: '/videos/embed/' + video.uuid,
153 expecter: (client, statusCode) => {
154 const body = client.resData[0].body
155
156 return statusCode === 200 && body.includes('embed')
157 }
158 },
4abbeff5
C
159 {
160 title: 'HTML - homepage',
161 path: '/',
162 expecter: (_client, statusCode) => {
163 return statusCode === 200
164 }
165 },
166 {
167 title: 'API - config',
168 path: '/api/v1/config',
169 expecter: (client, statusCode) => {
170 const body = client.resData[0].body
171
172 return statusCode === 200 && body.startsWith('{"instance":')
173 }
174 }
175 ]
176
177 const finalResult: any[] = []
178
179 for (const test of tests) {
180 console.log('Running against %s.', test.path)
181 const testResult = await runBenchmark(test)
182
183 Object.assign(testResult, { title: test.title, path: test.path })
184 finalResult.push(testResult)
185
186 console.log(autocannon.printResult(testResult))
187 }
188
189 if (outfile) await writeJson(outfile, finalResult)
190}
191
192function runBenchmark (options: {
193 path: string
194 headers?: { [ id: string ]: string }
195 expecter: Function
196}) {
197 const { path, expecter, headers } = options
198
199 return new Promise((res, rej) => {
200 const instance = autocannon({
201 url: server.url + path,
202 connections: 20,
203 headers,
204 pipelining: 1,
205 duration: 10
206 }, (err, result) => {
207 if (err) return rej(err)
208
209 return res(result)
210 })
211
212 instance.on('response', (client, statusCode) => {
213 if (expecter(client, statusCode) !== true) {
214 console.error('Expected result failed.', { data: client.resData })
215 process.exit(-1)
216 }
217 })
218 })
219}
220
221async function prepare () {
222 server = await flushAndRunServer(1, {
223 rates_limit: {
224 api: {
225 max: 5_000_000
226 }
227 }
228 })
229 await setAccessTokensToServers([ server ])
230
231 const videoAttributes = {
232 name: 'my super video',
233 category: 2,
234 nsfw: true,
235 licence: 6,
236 language: 'fr',
237 privacy: VideoPrivacy.PUBLIC,
238 support: 'please give me a coffee',
239 description: 'my super description'.repeat(10),
240 tags: [ 'tag1', 'tag2', 'tag3' ]
241 }
242
243 for (let i = 0; i < 10; i++) {
244 Object.assign(videoAttributes, { name: 'my super video ' + i })
245 await uploadVideo(server.url, server.accessToken, videoAttributes)
246 }
247
248 const resVideos = await getVideosList(server.url)
249 video = resVideos.body.data.find(v => v.name === 'my super video 1')
250
251 for (let i = 0; i < 10; i++) {
252 const text = 'my super first comment'
253 const res = await addVideoCommentThread(server.url, server.accessToken, video.id, text)
254 threadId = res.body.comment.id
255
256 const text1 = 'my super answer to thread 1'
257 const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text1)
258 const childCommentId = childCommentRes.body.comment.id
259
260 const text2 = 'my super answer to answer of thread 1'
261 await addVideoCommentReply(server.url, server.accessToken, video.id, childCommentId, text2)
262
263 const text3 = 'my second answer to thread 1'
264 await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text3)
265 }
266
267 for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
268 await createVideoCaption({
269 url: server.url,
270 accessToken: server.accessToken,
271 language: caption,
272 videoId: video.id,
273 fixture: 'subtitle-good2.vtt'
274 })
275 }
276
277 return { server, video, threadId }
278}