mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-02-25 18:55:32 -06:00
Support live session in server
This commit is contained in:
@@ -388,6 +388,52 @@ describe('Test video lives API validator', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('When getting live sessions', function () {
|
||||
|
||||
it('Should fail with a bad access token', async function () {
|
||||
await command.listSessions({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||
})
|
||||
|
||||
it('Should fail without token', async function () {
|
||||
await command.listSessions({ token: null, videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||
})
|
||||
|
||||
it('Should fail with the token of another user', async function () {
|
||||
await command.listSessions({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||
})
|
||||
|
||||
it('Should fail with a bad video id', async function () {
|
||||
await command.listSessions({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown video id', async function () {
|
||||
await command.listSessions({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
|
||||
it('Should fail with a non live video', async function () {
|
||||
await command.listSessions({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
|
||||
it('Should succeed with the correct params', async function () {
|
||||
await command.listSessions({ videoId: video.id })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When getting live session of a replay', function () {
|
||||
|
||||
it('Should fail with a bad video id', async function () {
|
||||
await command.getReplaySession({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown video id', async function () {
|
||||
await command.getReplaySession({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
|
||||
it('Should fail with a non replay video', async function () {
|
||||
await command.getReplaySession({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When updating live information', async function () {
|
||||
|
||||
it('Should fail without access token', async function () {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import 'mocha'
|
||||
import * as chai from 'chai'
|
||||
import { wait } from '@shared/core-utils'
|
||||
import { VideoPrivacy } from '@shared/models'
|
||||
import { LiveVideoError, VideoPrivacy } from '@shared/models'
|
||||
import {
|
||||
cleanupTests,
|
||||
ConfigCommand,
|
||||
@@ -12,7 +12,8 @@ import {
|
||||
PeerTubeServer,
|
||||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel,
|
||||
waitJobs
|
||||
waitJobs,
|
||||
waitUntilLiveWaitingOnAllServers
|
||||
} from '@shared/server-commands'
|
||||
import { checkLiveCleanup } from '../../shared'
|
||||
|
||||
@@ -24,12 +25,18 @@ describe('Test live constraints', function () {
|
||||
let userAccessToken: string
|
||||
let userChannelId: number
|
||||
|
||||
async function createLiveWrapper (saveReplay: boolean) {
|
||||
async function createLiveWrapper (options: {
|
||||
replay: boolean
|
||||
permanent: boolean
|
||||
}) {
|
||||
const { replay, permanent } = options
|
||||
|
||||
const liveAttributes = {
|
||||
name: 'user live',
|
||||
channelId: userChannelId,
|
||||
privacy: VideoPrivacy.PUBLIC,
|
||||
saveReplay
|
||||
saveReplay: replay,
|
||||
permanentLive: permanent
|
||||
}
|
||||
|
||||
const { uuid } = await servers[0].live.create({ token: userAccessToken, fields: liveAttributes })
|
||||
@@ -97,23 +104,42 @@ describe('Test live constraints', function () {
|
||||
it('Should not have size limit if save replay is disabled', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper(false)
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: false, permanent: false })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
|
||||
})
|
||||
|
||||
it('Should have size limit depending on user global quota if save replay is enabled', async function () {
|
||||
it('Should have size limit depending on user global quota if save replay is enabled on non permanent live', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
// Wait for user quota memoize cache invalidation
|
||||
await wait(5000)
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper(true)
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||
|
||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||
await waitJobs(servers)
|
||||
|
||||
await checkSaveReplay(userVideoLiveoId)
|
||||
|
||||
const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
|
||||
expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
|
||||
})
|
||||
|
||||
it('Should have size limit depending on user global quota if save replay is enabled on a permanent live', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
// Wait for user quota memoize cache invalidation
|
||||
await wait(5000)
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: true })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||
|
||||
await waitJobs(servers)
|
||||
await waitUntilLiveWaitingOnAllServers(servers, userVideoLiveoId)
|
||||
|
||||
const session = await servers[0].live.findLatestSession({ videoId: userVideoLiveoId })
|
||||
expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
|
||||
})
|
||||
|
||||
it('Should have size limit depending on user daily quota if save replay is enabled', async function () {
|
||||
@@ -124,13 +150,16 @@ describe('Test live constraints', function () {
|
||||
|
||||
await updateQuota({ total: -1, daily: 1 })
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper(true)
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||
|
||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||
await waitJobs(servers)
|
||||
|
||||
await checkSaveReplay(userVideoLiveoId)
|
||||
|
||||
const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
|
||||
expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
|
||||
})
|
||||
|
||||
it('Should succeed without quota limit', async function () {
|
||||
@@ -141,7 +170,7 @@ describe('Test live constraints', function () {
|
||||
|
||||
await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper(true)
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
|
||||
})
|
||||
|
||||
@@ -162,13 +191,16 @@ describe('Test live constraints', function () {
|
||||
}
|
||||
})
|
||||
|
||||
const userVideoLiveoId = await createLiveWrapper(true)
|
||||
const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
|
||||
await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||
|
||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||
await waitJobs(servers)
|
||||
|
||||
await checkSaveReplay(userVideoLiveoId, [ 720, 480, 360, 240, 144 ])
|
||||
|
||||
const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
|
||||
expect(session.error).to.equal(LiveVideoError.DURATION_EXCEEDED)
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
|
||||
@@ -172,6 +172,23 @@ describe('Permanent live', function () {
|
||||
await stopFfmpeg(ffmpegCommand)
|
||||
})
|
||||
|
||||
it('Should have appropriate sessions', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await servers[0].live.waitUntilWaiting({ videoId: videoUUID })
|
||||
|
||||
const { data, total } = await servers[0].live.listSessions({ videoId: videoUUID })
|
||||
expect(total).to.equal(2)
|
||||
expect(data).to.have.lengthOf(2)
|
||||
|
||||
for (const session of data) {
|
||||
expect(session.startDate).to.exist
|
||||
expect(session.endDate).to.exist
|
||||
|
||||
expect(session.error).to.not.exist
|
||||
}
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as chai from 'chai'
|
||||
import { FfmpegCommand } from 'fluent-ffmpeg'
|
||||
import { checkLiveCleanup } from '@server/tests/shared'
|
||||
import { wait } from '@shared/core-utils'
|
||||
import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
|
||||
import { HttpStatusCode, LiveVideoCreate, LiveVideoError, VideoPrivacy, VideoState } from '@shared/models'
|
||||
import {
|
||||
cleanupTests,
|
||||
ConfigCommand,
|
||||
@@ -143,6 +143,9 @@ describe('Save replay setting', function () {
|
||||
})
|
||||
|
||||
describe('With save replay disabled', function () {
|
||||
let sessionStartDateMin: Date
|
||||
let sessionStartDateMax: Date
|
||||
let sessionEndDateMin: Date
|
||||
|
||||
it('Should correctly create and federate the "waiting for stream" live', async function () {
|
||||
this.timeout(20000)
|
||||
@@ -160,7 +163,9 @@ describe('Save replay setting', function () {
|
||||
|
||||
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||
|
||||
sessionStartDateMin = new Date()
|
||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
||||
sessionStartDateMax = new Date()
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
@@ -171,6 +176,7 @@ describe('Save replay setting', function () {
|
||||
it('Should correctly delete the video files after the stream ended', async function () {
|
||||
this.timeout(40000)
|
||||
|
||||
sessionEndDateMin = new Date()
|
||||
await stopFfmpeg(ffmpegCommand)
|
||||
|
||||
for (const server of servers) {
|
||||
@@ -186,6 +192,24 @@ describe('Save replay setting', function () {
|
||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||
})
|
||||
|
||||
it('Should have appropriate ended session', async function () {
|
||||
const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
|
||||
expect(total).to.equal(1)
|
||||
expect(data).to.have.lengthOf(1)
|
||||
|
||||
const session = data[0]
|
||||
|
||||
const startDate = new Date(session.startDate)
|
||||
expect(startDate).to.be.above(sessionStartDateMin)
|
||||
expect(startDate).to.be.below(sessionStartDateMax)
|
||||
|
||||
expect(session.endDate).to.exist
|
||||
expect(new Date(session.endDate)).to.be.above(sessionEndDateMin)
|
||||
|
||||
expect(session.error).to.not.exist
|
||||
expect(session.replayVideo).to.not.exist
|
||||
})
|
||||
|
||||
it('Should correctly terminate the stream on blacklist and delete the live', async function () {
|
||||
this.timeout(40000)
|
||||
|
||||
@@ -201,6 +225,15 @@ describe('Save replay setting', function () {
|
||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||
})
|
||||
|
||||
it('Should have blacklisted session error', async function () {
|
||||
const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID })
|
||||
expect(session.startDate).to.exist
|
||||
expect(session.endDate).to.exist
|
||||
|
||||
expect(session.error).to.equal(LiveVideoError.BLACKLISTED)
|
||||
expect(session.replayVideo).to.not.exist
|
||||
})
|
||||
|
||||
it('Should correctly terminate the stream on delete and delete the video', async function () {
|
||||
this.timeout(40000)
|
||||
|
||||
@@ -249,6 +282,22 @@ describe('Save replay setting', function () {
|
||||
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
||||
})
|
||||
|
||||
it('Should find the replay live session', async function () {
|
||||
const session = await servers[0].live.getReplaySession({ videoId: liveVideoUUID })
|
||||
|
||||
expect(session).to.exist
|
||||
|
||||
expect(session.startDate).to.exist
|
||||
expect(session.endDate).to.exist
|
||||
|
||||
expect(session.error).to.not.exist
|
||||
|
||||
expect(session.replayVideo).to.exist
|
||||
expect(session.replayVideo.id).to.exist
|
||||
expect(session.replayVideo.shortUUID).to.exist
|
||||
expect(session.replayVideo.uuid).to.equal(liveVideoUUID)
|
||||
})
|
||||
|
||||
it('Should update the saved live and correctly federate the updated attributes', async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
@@ -337,6 +386,27 @@ describe('Save replay setting', function () {
|
||||
lastReplayUUID = video.uuid
|
||||
})
|
||||
|
||||
it('Should have appropriate ended session and replay live session', async function () {
|
||||
const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
|
||||
expect(total).to.equal(1)
|
||||
expect(data).to.have.lengthOf(1)
|
||||
|
||||
const sessionFromLive = data[0]
|
||||
const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID })
|
||||
|
||||
for (const session of [ sessionFromLive, sessionFromReplay ]) {
|
||||
expect(session.startDate).to.exist
|
||||
expect(session.endDate).to.exist
|
||||
|
||||
expect(session.error).to.not.exist
|
||||
|
||||
expect(session.replayVideo).to.exist
|
||||
expect(session.replayVideo.id).to.exist
|
||||
expect(session.replayVideo.shortUUID).to.exist
|
||||
expect(session.replayVideo.uuid).to.equal(lastReplayUUID)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should have cleaned up the live files', async function () {
|
||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||
})
|
||||
|
||||
@@ -594,6 +594,8 @@ describe('Test live', function () {
|
||||
|
||||
let permanentLiveReplayName: string
|
||||
|
||||
let beforeServerRestart: Date
|
||||
|
||||
async function createLiveWrapper (options: { saveReplay: boolean, permanent: boolean }) {
|
||||
const liveAttributes: LiveVideoCreate = {
|
||||
name: 'live video',
|
||||
@@ -636,6 +638,8 @@ describe('Test live', function () {
|
||||
}
|
||||
|
||||
await killallServers([ servers[0] ])
|
||||
|
||||
beforeServerRestart = new Date()
|
||||
await servers[0].run()
|
||||
|
||||
await wait(5000)
|
||||
@@ -653,6 +657,10 @@ describe('Test live', function () {
|
||||
this.timeout(120000)
|
||||
|
||||
await commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
|
||||
|
||||
const session = await commands[0].getReplaySession({ videoId: liveVideoReplayId })
|
||||
expect(session.endDate).to.exist
|
||||
expect(new Date(session.endDate)).to.be.above(beforeServerRestart)
|
||||
})
|
||||
|
||||
it('Should have saved a permanent live replay', async function () {
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
checkMyVideoImportIsFinished,
|
||||
checkNewActorFollow,
|
||||
checkNewVideoFromSubscription,
|
||||
checkVideoStudioEditionIsFinished,
|
||||
checkVideoIsPublished,
|
||||
checkVideoStudioEditionIsFinished,
|
||||
FIXTURE_URLS,
|
||||
MockSmtpServer,
|
||||
prepareNotificationsTest,
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
} from '@server/tests/shared'
|
||||
import { wait } from '@shared/core-utils'
|
||||
import { buildUUID } from '@shared/extra-utils'
|
||||
import { UserNotification, UserNotificationType, VideoStudioTask, VideoPrivacy } from '@shared/models'
|
||||
import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
|
||||
import { UserNotification, UserNotificationType, VideoPrivacy, VideoStudioTask } from '@shared/models'
|
||||
import { cleanupTests, findExternalSavedVideo, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
@@ -323,6 +323,76 @@ describe('Test user notifications', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('My live replay is published', function () {
|
||||
|
||||
let baseParams: CheckerBaseParams
|
||||
|
||||
before(() => {
|
||||
baseParams = {
|
||||
server: servers[1],
|
||||
emails,
|
||||
socketNotifications: adminNotificationsServer2,
|
||||
token: servers[1].accessToken
|
||||
}
|
||||
})
|
||||
|
||||
it('Should send a notification is a live replay of a non permanent live is published', async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
const { shortUUID } = await servers[1].live.create({
|
||||
fields: {
|
||||
name: 'non permanent live',
|
||||
privacy: VideoPrivacy.PUBLIC,
|
||||
channelId: servers[1].store.channel.id,
|
||||
saveReplay: true,
|
||||
permanentLive: false
|
||||
}
|
||||
})
|
||||
|
||||
const ffmpegCommand = await servers[1].live.sendRTMPStreamInVideo({ videoId: shortUUID })
|
||||
|
||||
await waitJobs(servers)
|
||||
await servers[1].live.waitUntilPublished({ videoId: shortUUID })
|
||||
|
||||
await stopFfmpeg(ffmpegCommand)
|
||||
await servers[1].live.waitUntilReplacedByReplay({ videoId: shortUUID })
|
||||
|
||||
await waitJobs(servers)
|
||||
await checkVideoIsPublished({ ...baseParams, videoName: 'non permanent live', shortUUID, checkType: 'presence' })
|
||||
})
|
||||
|
||||
it('Should send a notification is a live replay of a permanent live is published', async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
const { shortUUID } = await servers[1].live.create({
|
||||
fields: {
|
||||
name: 'permanent live',
|
||||
privacy: VideoPrivacy.PUBLIC,
|
||||
channelId: servers[1].store.channel.id,
|
||||
saveReplay: true,
|
||||
permanentLive: true
|
||||
}
|
||||
})
|
||||
|
||||
const ffmpegCommand = await servers[1].live.sendRTMPStreamInVideo({ videoId: shortUUID })
|
||||
|
||||
await waitJobs(servers)
|
||||
await servers[1].live.waitUntilPublished({ videoId: shortUUID })
|
||||
|
||||
const liveDetails = await servers[1].videos.get({ id: shortUUID })
|
||||
|
||||
await stopFfmpeg(ffmpegCommand)
|
||||
|
||||
await servers[1].live.waitUntilWaiting({ videoId: shortUUID })
|
||||
await waitJobs(servers)
|
||||
|
||||
const video = await findExternalSavedVideo(servers[1], liveDetails)
|
||||
expect(video).to.exist
|
||||
|
||||
await checkVideoIsPublished({ ...baseParams, videoName: video.name, shortUUID: video.shortUUID, checkType: 'presence' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('Video studio', function () {
|
||||
let baseParams: CheckerBaseParams
|
||||
|
||||
|
||||
Reference in New Issue
Block a user