X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Ftests%2Fshared%2Flive.ts;h=31f92ef19a568b5c5396d58d31eba97784b9924a;hb=d102de1b38f2877463529c3b27bd35ffef4fd8bf;hp=4bd4786fc18564d8951a3e0037f64b75e1e8e861;hpb=ab623c0e0b4815bd69a94887241a69aaa857ed26;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/tests/shared/live.ts b/server/tests/shared/live.ts index 4bd4786fc..31f92ef19 100644 --- a/server/tests/shared/live.ts +++ b/server/tests/shared/live.ts @@ -3,39 +3,141 @@ import { expect } from 'chai' import { pathExists, readdir } from 'fs-extra' import { join } from 'path' -import { LiveVideo } from '@shared/models' -import { PeerTubeServer } from '@shared/server-commands' - -async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, savedResolutions: number[] = []) { - let live: LiveVideo - - try { - live = await server.live.get({ videoId: videoUUID }) - } catch {} +import { sha1 } from '@shared/extra-utils' +import { LiveVideo, VideoStreamingPlaylistType } from '@shared/models' +import { ObjectStorageCommand, PeerTubeServer } from '@shared/server-commands' +import { SQLCommand } from './sql-command' +import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist } from './streaming-playlists' + +async function checkLiveCleanup (options: { + server: PeerTubeServer + videoUUID: string + permanent: boolean + savedResolutions?: number[] +}) { + const { server, videoUUID, permanent, savedResolutions = [] } = options const basePath = server.servers.buildDirectory('streaming-playlists') const hlsPath = join(basePath, 'hls', videoUUID) - if (savedResolutions.length === 0) { + if (permanent) { + if (!await pathExists(hlsPath)) return - if (live?.permanentLive) { - expect(await pathExists(hlsPath)).to.be.true + const files = await readdir(hlsPath) + expect(files).to.have.lengthOf(0) + return + } - const hlsFiles = await readdir(hlsPath) - expect(hlsFiles).to.have.lengthOf(1) // Only replays directory + if (savedResolutions.length === 0) { + return checkUnsavedLiveCleanup(server, videoUUID, hlsPath) + } - const replayDir = join(hlsPath, 'replay') - expect(await pathExists(replayDir)).to.be.true + return checkSavedLiveCleanup(hlsPath, savedResolutions) +} - const replayFiles = await readdir(join(hlsPath, 'replay')) - expect(replayFiles).to.have.lengthOf(0) - } else { - expect(await pathExists(hlsPath)).to.be.false +// --------------------------------------------------------------------------- + +async function testLiveVideoResolutions (options: { + sqlCommand: SQLCommand + originServer: PeerTubeServer + + servers: PeerTubeServer[] + liveVideoId: string + resolutions: number[] + transcoded: boolean + + objectStorage: boolean + objectStorageBaseUrl?: string +}) { + const { + originServer, + sqlCommand, + servers, + liveVideoId, + resolutions, + transcoded, + objectStorage, + objectStorageBaseUrl = ObjectStorageCommand.getMockPlaylistBaseUrl() + } = options + + for (const server of servers) { + const { data } = await server.videos.list() + expect(data.find(v => v.uuid === liveVideoId)).to.exist + + const video = await server.videos.get({ id: liveVideoId }) + expect(video.streamingPlaylists).to.have.lengthOf(1) + + const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS) + expect(hlsPlaylist).to.exist + expect(hlsPlaylist.files).to.have.lengthOf(0) // Only fragmented mp4 files are displayed + + await checkResolutionsInMasterPlaylist({ + server, + playlistUrl: hlsPlaylist.playlistUrl, + resolutions, + transcoded, + withRetry: objectStorage + }) + + if (objectStorage) { + expect(hlsPlaylist.playlistUrl).to.contain(objectStorageBaseUrl) } - return + for (let i = 0; i < resolutions.length; i++) { + const segmentNum = 3 + const segmentName = `${i}-00000${segmentNum}.ts` + await originServer.live.waitUntilSegmentGeneration({ + server: originServer, + videoUUID: video.uuid, + playlistNumber: i, + segment: segmentNum, + objectStorage, + objectStorageBaseUrl + }) + + const baseUrl = objectStorage + ? join(objectStorageBaseUrl, 'hls') + : originServer.url + '/static/streaming-playlists/hls' + + if (objectStorage) { + expect(hlsPlaylist.segmentsSha256Url).to.contain(objectStorageBaseUrl) + } + + const subPlaylist = await originServer.streamingPlaylists.get({ + url: `${baseUrl}/${video.uuid}/${i}.m3u8`, + withRetry: objectStorage // With object storage, the request may fail because of inconsistent data in S3 + }) + + expect(subPlaylist).to.contain(segmentName) + + await checkLiveSegmentHash({ + server, + baseUrlSegment: baseUrl, + videoUUID: video.uuid, + segmentName, + hlsPlaylist + }) + + if (originServer.internalServerNumber === server.internalServerNumber) { + const infohash = sha1(`${2 + hlsPlaylist.playlistUrl}+V${i}`) + const dbInfohashes = await sqlCommand.getPlaylistInfohash(hlsPlaylist.id) + + expect(dbInfohashes).to.include(infohash) + } + } } +} + +// --------------------------------------------------------------------------- + +export { + checkLiveCleanup, + testLiveVideoResolutions +} + +// --------------------------------------------------------------------------- +async function checkSavedLiveCleanup (hlsPath: string, savedResolutions: number[] = []) { const files = await readdir(hlsPath) // fragmented file and playlist per resolution + master playlist + segments sha256 json file @@ -56,6 +158,27 @@ async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, save expect(shaFile).to.exist } -export { - checkLiveCleanup +async function checkUnsavedLiveCleanup (server: PeerTubeServer, videoUUID: string, hlsPath: string) { + let live: LiveVideo + + try { + live = await server.live.get({ videoId: videoUUID }) + } catch {} + + if (live?.permanentLive) { + expect(await pathExists(hlsPath)).to.be.true + + const hlsFiles = await readdir(hlsPath) + expect(hlsFiles).to.have.lengthOf(1) // Only replays directory + + const replayDir = join(hlsPath, 'replay') + expect(await pathExists(replayDir)).to.be.true + + const replayFiles = await readdir(join(hlsPath, 'replay')) + expect(replayFiles).to.have.lengthOf(0) + + return + } + + expect(await pathExists(hlsPath)).to.be.false }