/** * Standalone signaling server for the Nextcloud Spreed app. * Copyright (C) 2026 struktur AG * * @author Joachim Bauch * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package test import ( "context" "errors" "net" "net/url" "strconv" "testing" "github.com/dlintw/goconf" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/strukturag/nextcloud-spreed-signaling/v2/api" "github.com/strukturag/nextcloud-spreed-signaling/v2/grpc" "github.com/strukturag/nextcloud-spreed-signaling/v2/log" logtest "github.com/strukturag/nextcloud-spreed-signaling/v2/log/test" "github.com/strukturag/nextcloud-spreed-signaling/v2/sfu" "github.com/strukturag/nextcloud-spreed-signaling/v2/talk" "github.com/strukturag/nextcloud-spreed-signaling/v2/test" ) func NewServerForTestWithConfig(t *testing.T, config *goconf.ConfigFile) (server *grpc.Server, addr string) { logger := logtest.NewLoggerForTest(t) ctx := log.NewLoggerContext(t.Context(), logger) for port := 50000; port < 50100; port++ { addr = net.JoinHostPort("127.0.0.1", strconv.Itoa(port)) config.AddOption("grpc", "listen", addr) var err error server, err = grpc.NewServer(ctx, config, "0.0.0") if test.IsErrorAddressAlreadyInUse(err) { continue } require.NoError(t, err) break } require.NotNil(t, server, "could not find free port") // Don't match with own server id by default. server.SetServerId("dont-match") go func() { assert.NoError(t, server.Run(), "could not start GRPC server") }() t.Cleanup(func() { server.Close() }) return server, addr } func NewServerForTest(t *testing.T) (server *grpc.Server, addr string) { config := goconf.NewConfigFile() return NewServerForTestWithConfig(t, config) } type MockHub struct { } func (h *MockHub) GetSessionIdByResumeId(resumeId api.PrivateSessionId) api.PublicSessionId { return "" } func (h *MockHub) GetSessionIdByRoomSessionId(roomSessionId api.RoomSessionId) (api.PublicSessionId, error) { return "", errors.New("not implemented") } func (h *MockHub) IsSessionIdInCall(sessionId api.PublicSessionId, roomId string, backendUrl string) (bool, bool) { return false, false } func (h *MockHub) DisconnectSessionByRoomSessionId(sessionId api.PublicSessionId, roomSessionId api.RoomSessionId, reason string) { } func (h *MockHub) GetBackend(u *url.URL) *talk.Backend { return nil } func (h *MockHub) GetInternalSessions(roomId string, backend *talk.Backend) ([]*grpc.InternalSessionData, []*grpc.VirtualSessionData, bool) { return nil, nil, false } func (h *MockHub) GetTransientEntries(roomId string, backend *talk.Backend) (api.TransientDataEntries, bool) { return nil, false } func (h *MockHub) GetPublisherIdForSessionId(ctx context.Context, sessionId api.PublicSessionId, streamType sfu.StreamType) (*grpc.GetPublisherIdReply, error) { return nil, errors.New("not implemented") } func (h *MockHub) ProxySession(request grpc.RpcSessions_ProxySessionServer) error { return errors.New("not implemented") } var ( // Compile-time check that MockHub implements the interface. _ grpc.ServerHub = &MockHub{} )