From ad5db1044c8599eaaaa2a578b350777ae996b068 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 18 Nov 2021 14:35:08 +0100 Subject: Add ability to run transcoding jobs --- server/tests/api/check-params/index.ts | 1 + server/tests/api/check-params/transcoding.ts | 104 ++++++++++++++ server/tests/api/check-params/video-files.ts | 17 ++- server/tests/api/videos/index.ts | 1 + .../tests/api/videos/video-create-transcoding.ts | 156 +++++++++++++++++++++ 5 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 server/tests/api/check-params/transcoding.ts create mode 100644 server/tests/api/videos/video-create-transcoding.ts (limited to 'server/tests/api') diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index ff7dc4abb..e052296db 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts @@ -15,6 +15,7 @@ import './plugins' import './redundancy' import './search' import './services' +import './transcoding' import './upload-quota' import './user-notifications' import './user-subscriptions' diff --git a/server/tests/api/check-params/transcoding.ts b/server/tests/api/check-params/transcoding.ts new file mode 100644 index 000000000..a8daafe3e --- /dev/null +++ b/server/tests/api/check-params/transcoding.ts @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import 'mocha' +import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils' +import { HttpStatusCode, UserRole } from '@shared/models' + +describe('Test transcoding API validators', function () { + let servers: PeerTubeServer[] + + let userToken: string + let moderatorToken: string + + let remoteId: string + let validId: string + + // --------------------------------------------------------------- + + before(async function () { + this.timeout(60000) + + servers = await createMultipleServers(2) + await setAccessTokensToServers(servers) + + await doubleFollow(servers[0], servers[1]) + + userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER) + moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR) + + { + const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' }) + remoteId = uuid + } + + { + const { uuid } = await servers[0].videos.quickUpload({ name: 'both 1' }) + validId = uuid + } + + await waitJobs(servers) + + await servers[0].config.enableTranscoding() + }) + + it('Should not run transcoding of a unknown video', async function () { + await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'hls', expectedStatus: HttpStatusCode.NOT_FOUND_404 }) + await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'webtorrent', expectedStatus: HttpStatusCode.NOT_FOUND_404 }) + }) + + it('Should not run transcoding of a remote video', async function () { + const expectedStatus = HttpStatusCode.BAD_REQUEST_400 + + await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'hls', expectedStatus }) + await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'webtorrent', expectedStatus }) + }) + + it('Should not run transcoding by a non admin user', async function () { + const expectedStatus = HttpStatusCode.FORBIDDEN_403 + + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', token: userToken, expectedStatus }) + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', token: moderatorToken, expectedStatus }) + }) + + it('Should not run transcoding without transcoding type', async function () { + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) + }) + + it('Should not run transcoding with an incorrect transcoding type', async function () { + const expectedStatus = HttpStatusCode.BAD_REQUEST_400 + + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'toto' as any, expectedStatus }) + }) + + it('Should not run transcoding if the instance disabled it', async function () { + const expectedStatus = HttpStatusCode.BAD_REQUEST_400 + + await servers[0].config.disableTranscoding() + + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', expectedStatus }) + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus }) + }) + + it('Should run transcoding', async function () { + this.timeout(120_000) + + await servers[0].config.enableTranscoding() + + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls' }) + await waitJobs(servers) + + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' }) + await waitJobs(servers) + }) + + it('Should not run transcoding on a video that is already being transcoded', async function () { + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' }) + + const expectedStatus = HttpStatusCode.CONFLICT_409 + await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus }) + }) + + after(async function () { + await cleanupTests(servers) + }) +}) diff --git a/server/tests/api/check-params/video-files.ts b/server/tests/api/check-params/video-files.ts index 48b10d2b5..61936d562 100644 --- a/server/tests/api/check-params/video-files.ts +++ b/server/tests/api/check-params/video-files.ts @@ -1,16 +1,19 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ import 'mocha' -import { cleanupTests, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils' +import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils' import { HttpStatusCode, UserRole } from '@shared/models' describe('Test videos files', function () { let servers: PeerTubeServer[] + let webtorrentId: string let hlsId: string let remoteId: string + let userToken: string let moderatorToken: string + let validId1: string let validId2: string @@ -22,9 +25,16 @@ describe('Test videos files', function () { servers = await createMultipleServers(2) await setAccessTokensToServers(servers) + await doubleFollow(servers[0], servers[1]) + userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER) moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR) + { + const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' }) + remoteId = uuid + } + { await servers[0].config.enableTranscoding(true, true) @@ -58,6 +68,11 @@ describe('Test videos files', function () { await waitJobs(servers) }) + it('Should not delete files of a unknown video', async function () { + await servers[0].videos.removeHLSFiles({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) + await servers[0].videos.removeWebTorrentFiles({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) + }) + it('Should not delete files of a remote video', async function () { await servers[0].videos.removeHLSFiles({ videoId: remoteId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) await servers[0].videos.removeWebTorrentFiles({ videoId: remoteId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts index f92e339e7..bedb9b8b6 100644 --- a/server/tests/api/videos/index.ts +++ b/server/tests/api/videos/index.ts @@ -6,6 +6,7 @@ import './video-captions' import './video-change-ownership' import './video-channels' import './video-comments' +import './video-create-transcoding' import './video-description' import './video-files' import './video-hls' diff --git a/server/tests/api/videos/video-create-transcoding.ts b/server/tests/api/videos/video-create-transcoding.ts new file mode 100644 index 000000000..bae06ac6c --- /dev/null +++ b/server/tests/api/videos/video-create-transcoding.ts @@ -0,0 +1,156 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ + +import 'mocha' +import * as chai from 'chai' +import { + areObjectStorageTestsDisabled, + cleanupTests, + createMultipleServers, + doubleFollow, + expectStartWith, + makeRawRequest, + ObjectStorageCommand, + PeerTubeServer, + setAccessTokensToServers, + waitJobs +} from '@shared/extra-utils' +import { HttpStatusCode, VideoDetails } from '@shared/models' + +const expect = chai.expect + +async function checkFilesInObjectStorage (video: VideoDetails) { + for (const file of video.files) { + expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) + await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) + } + + for (const file of video.streamingPlaylists[0].files) { + expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) + await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) + } +} + +async function expectNoFailedTranscodingJob (server: PeerTubeServer) { + const { data } = await server.jobs.listFailed({ jobType: 'video-transcoding' }) + expect(data).to.have.lengthOf(0) +} + +function runTests (objectStorage: boolean) { + let servers: PeerTubeServer[] = [] + let videoUUID: string + let publishedAt: string + + before(async function () { + this.timeout(120000) + + const config = objectStorage + ? ObjectStorageCommand.getDefaultConfig() + : {} + + // Run server 2 to have transcoding enabled + servers = await createMultipleServers(2, config) + await setAccessTokensToServers(servers) + + await servers[0].config.disableTranscoding() + + await doubleFollow(servers[0], servers[1]) + + if (objectStorage) await ObjectStorageCommand.prepareDefaultBuckets() + + const { shortUUID } = await servers[0].videos.quickUpload({ name: 'video' }) + videoUUID = shortUUID + + const video = await servers[0].videos.get({ id: videoUUID }) + publishedAt = video.publishedAt as string + + await servers[0].config.enableTranscoding() + + await waitJobs(servers) + }) + + it('Should generate HLS', async function () { + this.timeout(60000) + + await servers[0].videos.runTranscoding({ + videoId: videoUUID, + transcodingType: 'hls' + }) + + await waitJobs(servers) + await expectNoFailedTranscodingJob(servers[0]) + + for (const server of servers) { + const videoDetails = await server.videos.get({ id: videoUUID }) + + expect(videoDetails.files).to.have.lengthOf(1) + expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) + expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5) + + if (objectStorage) await checkFilesInObjectStorage(videoDetails) + } + }) + + it('Should generate WebTorrent', async function () { + this.timeout(60000) + + await servers[0].videos.runTranscoding({ + videoId: videoUUID, + transcodingType: 'webtorrent' + }) + + await waitJobs(servers) + + for (const server of servers) { + const videoDetails = await server.videos.get({ id: videoUUID }) + + expect(videoDetails.files).to.have.lengthOf(5) + expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) + expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5) + + if (objectStorage) await checkFilesInObjectStorage(videoDetails) + } + }) + + it('Should generate WebTorrent from HLS only video', async function () { + this.timeout(60000) + + await servers[0].videos.removeWebTorrentFiles({ videoId: videoUUID }) + await waitJobs(servers) + + await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'webtorrent' }) + await waitJobs(servers) + + for (const server of servers) { + const videoDetails = await server.videos.get({ id: videoUUID }) + + expect(videoDetails.files).to.have.lengthOf(5) + expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) + expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5) + + if (objectStorage) await checkFilesInObjectStorage(videoDetails) + } + }) + + it('Should not have updated published at attributes', async function () { + const video = await servers[0].videos.get({ id: videoUUID }) + + expect(video.publishedAt).to.equal(publishedAt) + }) + + after(async function () { + await cleanupTests(servers) + }) +} + +describe('Test create transcoding jobs from API', function () { + + describe('On filesystem', function () { + runTests(false) + }) + + describe('On object storage', function () { + if (areObjectStorageTestsDisabled()) return + + runTests(true) + }) +}) -- cgit v1.2.3