Files
livekit/pkg/service/roomallocator_test.go
T
Martin Njalale 2fab31691b service: start room composite egress configured in a room preset (#4926)
* service: start room composite egress configured in a room preset

StandardRoomAllocator.CreateRoom merged a room preset into a copy of the
request and discarded it. RoomInternal has no field for room composite
egress, and getOrCreateRoom started it from the caller's original request,
so a room composite egress from a preset was never started.

RoomAllocator.CreateRoom now also returns the request with the preset
applied, and getOrCreateRoom starts the egress from it.

* service: return ErrEgressNotConnected instead of calling a nil egress launcher

getOrCreateRoom started a room composite egress without checking that an
egress launcher exists. RoomService.CreateRoom rejects egress on the request
when there is none, but not egress from a room preset or a token's roomConfig.
2026-09-30 13:25:24 +02:00

131 lines
4.2 KiB
Go

// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package service_test
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/livekit"
"github.com/livekit/livekit-server/pkg/config"
"github.com/livekit/livekit-server/pkg/routing"
"github.com/livekit/livekit-server/pkg/routing/routingfakes"
"github.com/livekit/livekit-server/pkg/service"
"github.com/livekit/livekit-server/pkg/service/servicefakes"
)
func TestCreateRoom(t *testing.T) {
t.Run("ensure default room settings are applied", func(t *testing.T) {
conf, err := config.NewConfig("", true, nil, nil)
require.NoError(t, err)
node, err := routing.NewLocalNode(conf)
require.NoError(t, err)
ra, conf := newTestRoomAllocator(t, conf, node.Clone())
room, _, _, _, err := ra.CreateRoom(context.Background(), &livekit.CreateRoomRequest{Name: "myroom"}, true)
require.NoError(t, err)
require.Equal(t, conf.Room.EmptyTimeout, room.EmptyTimeout)
require.Equal(t, conf.Room.DepartureTimeout, room.DepartureTimeout)
require.NotEmpty(t, room.EnabledCodecs)
})
t.Run("return the request with the room preset applied", func(t *testing.T) {
conf, err := config.NewConfig(`
room:
room_configurations:
record:
egress:
room:
layout: grid
`, true, nil, nil)
require.NoError(t, err)
node, err := routing.NewLocalNode(conf)
require.NoError(t, err)
ra, conf := newTestRoomAllocator(t, conf, node.Clone())
// without a preset, the request itself is returned
req := &livekit.CreateRoomRequest{Name: "myroom"}
_, _, applied, _, err := ra.CreateRoom(context.Background(), req, true)
require.NoError(t, err)
require.Same(t, req, applied)
// with a preset, a copy with the preset applied is returned,
// leaving both the request and the preset unchanged
req = &livekit.CreateRoomRequest{Name: "myroom", RoomPreset: "record"}
_, _, applied, _, err = ra.CreateRoom(context.Background(), req, true)
require.NoError(t, err)
require.Nil(t, req.Egress)
require.Equal(t, "grid", applied.GetEgress().GetRoom().GetLayout())
require.NotSame(t, conf.Room.RoomConfigurations["record"].Egress.Room, applied.Egress.Room)
})
}
func SelectRoomNode(t *testing.T) {
t.Run("reject new participants when track limit has been reached", func(t *testing.T) {
conf, err := config.NewConfig("", true, nil, nil)
require.NoError(t, err)
conf.Limit.NumTracks = 10
node, err := routing.NewLocalNode(conf)
require.NoError(t, err)
node.SetStats(&livekit.NodeStats{
NumTracksIn: 100,
NumTracksOut: 100,
})
ra, _ := newTestRoomAllocator(t, conf, node.Clone())
err = ra.SelectRoomNode(context.Background(), "low-limit-room", "")
require.ErrorIs(t, err, routing.ErrNodeLimitReached)
})
t.Run("reject new participants when bandwidth limit has been reached", func(t *testing.T) {
conf, err := config.NewConfig("", true, nil, nil)
require.NoError(t, err)
conf.Limit.BytesPerSec = 100
node, err := routing.NewLocalNode(conf)
require.NoError(t, err)
node.SetStats(&livekit.NodeStats{
BytesInPerSec: 1000,
BytesOutPerSec: 1000,
})
ra, _ := newTestRoomAllocator(t, conf, node.Clone())
err = ra.SelectRoomNode(context.Background(), "low-limit-room", "")
require.ErrorIs(t, err, routing.ErrNodeLimitReached)
})
}
func newTestRoomAllocator(t *testing.T, conf *config.Config, node *livekit.Node) (service.RoomAllocator, *config.Config) {
store := &servicefakes.FakeObjectStore{}
store.LoadRoomReturns(nil, nil, service.ErrRoomNotFound)
router := &routingfakes.FakeRouter{}
router.GetNodeForRoomReturns(node, nil)
ra, err := service.NewRoomAllocator(conf, router, store)
require.NoError(t, err)
return ra, conf
}