Files
mediamtx/internal/api/api_hls_test.go
T

338 lines
9.0 KiB
Go

package api //nolint:revive
import (
"fmt"
"net/http"
"sort"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
"github.com/bluenviron/mediamtx/internal/servers/hls"
"github.com/bluenviron/mediamtx/internal/test"
)
type testHLSServer struct {
muxers map[string]*defs.APIHLSMuxer
sessions map[string]*defs.APIHLSSession
}
var testTime = time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)
func (s *testHLSServer) APIMuxersList() (*defs.APIHLSMuxerList, error) {
items := make([]defs.APIHLSMuxer, 0, len(s.muxers))
for _, muxer := range s.muxers {
items = append(items, *muxer)
}
return &defs.APIHLSMuxerList{Items: items}, nil
}
func (s *testHLSServer) APIMuxersGet(name string) (*defs.APIHLSMuxer, error) {
muxer, ok := s.muxers[name]
if !ok {
return nil, hls.ErrMuxerNotFound
}
return muxer, nil
}
func (s *testHLSServer) APISessionsList() (*defs.APIHLSSessionList, error) {
items := make([]defs.APIHLSSession, 0, len(s.sessions))
for _, session := range s.sessions {
items = append(items, *session)
}
sort.Slice(items, func(i, j int) bool {
return items[i].Created.Before(items[j].Created)
})
return &defs.APIHLSSessionList{Items: items}, nil
}
func (s *testHLSServer) APISessionsGet(id uuid.UUID) (*defs.APIHLSSession, error) {
session, ok := s.sessions[id.String()]
if !ok {
return nil, hls.ErrSessionNotFound
}
return session, nil
}
func (s *testHLSServer) APISessionsKick(id uuid.UUID) error {
_, ok := s.sessions[id.String()]
if !ok {
return hls.ErrSessionNotFound
}
delete(s.sessions, id.String())
return nil
}
func TestHLSMuxersList(t *testing.T) {
now := testTime
hlsServer := &testHLSServer{
muxers: map[string]*defs.APIHLSMuxer{
"test1": {
Path: "test1",
Created: now,
LastRequest: now.Add(5 * time.Second),
OutboundBytes: 1234,
OutboundFramesDiscarded: 10,
BytesSent: 1234,
},
"test2": {
Path: "test2",
Created: now.Add(time.Minute),
LastRequest: now.Add(time.Minute + 10*time.Second),
OutboundBytes: 5678,
OutboundFramesDiscarded: 20,
BytesSent: 5678,
},
},
}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
var out defs.APIHLSMuxerList
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/hlsmuxers/list", nil, &out)
require.Equal(t, 2, out.ItemCount)
require.Equal(t, 1, out.PageCount)
require.Len(t, out.Items, 2)
}
func TestHLSMuxersGet(t *testing.T) {
now := testTime
hlsServer := &testHLSServer{
muxers: map[string]*defs.APIHLSMuxer{
"mypath": {
Path: "mypath",
Created: now,
LastRequest: now.Add(5 * time.Second),
OutboundBytes: 9999,
OutboundFramesDiscarded: 12,
BytesSent: 9999,
},
},
}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
var out defs.APIHLSMuxer
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/hlsmuxers/get/mypath", nil, &out)
require.Equal(t, "mypath", out.Path)
require.Equal(t, uint64(9999), out.OutboundBytes)
require.Equal(t, uint64(12), out.OutboundFramesDiscarded)
require.Equal(t, uint64(9999), out.BytesSent)
}
func TestHLSSessionsList(t *testing.T) {
now := testTime
hlsServer := &testHLSServer{
sessions: map[string]*defs.APIHLSSession{
"session1": {
ID: uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb41"),
Created: now,
RemoteAddr: "192.168.1.1:5000",
Path: "stream1",
Query: "key=val1",
User: "user1",
OutboundBytes: 111,
},
"session2": {
ID: uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb42"),
Created: now.Add(time.Minute),
RemoteAddr: "192.168.1.2:5001",
Path: "stream2",
Query: "key=val2",
User: "user2",
OutboundBytes: 222,
},
},
}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
var out defs.APIHLSSessionList
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/hlssessions/list", nil, &out)
require.Equal(t, 2, out.ItemCount)
require.Equal(t, 1, out.PageCount)
require.Len(t, out.Items, 2)
require.Equal(t, []defs.APIHLSSession{
{
ID: uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb41"),
Created: now,
RemoteAddr: "192.168.1.1:5000",
Path: "stream1",
Query: "key=val1",
User: "user1",
OutboundBytes: 111,
},
{
ID: uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb42"),
Created: now.Add(time.Minute),
RemoteAddr: "192.168.1.2:5001",
Path: "stream2",
Query: "key=val2",
User: "user2",
OutboundBytes: 222,
},
}, out.Items)
}
func TestHLSSessionsGet(t *testing.T) {
now := testTime
hlsServer := &testHLSServer{
sessions: map[string]*defs.APIHLSSession{
"18294761-f9d1-4ea9-9a35-fe265b62eb41": {
ID: uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb41"),
Created: now,
RemoteAddr: "192.168.1.100:5000",
Path: "mystream",
Query: "key=val",
User: "myuser",
OutboundBytes: 345,
},
},
}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
sessionID := "18294761-f9d1-4ea9-9a35-fe265b62eb41"
var out defs.APIHLSSession
httpRequest(t, hc, http.MethodGet, fmt.Sprintf("http://localhost:9997/v3/hlssessions/get/%s", sessionID), nil, &out)
require.Equal(t, uuid.MustParse(sessionID), out.ID)
require.Equal(t, "192.168.1.100:5000", out.RemoteAddr)
require.Equal(t, "mystream", out.Path)
require.Equal(t, "key=val", out.Query)
require.Equal(t, "myuser", out.User)
require.Equal(t, uint64(345), out.OutboundBytes)
}
func TestHLSSessionsKick(t *testing.T) {
now := testTime
sessionID := uuid.MustParse("18294761-f9d1-4ea9-9a35-fe265b62eb41")
hlsServer := &testHLSServer{
sessions: map[string]*defs.APIHLSSession{
sessionID.String(): {
ID: sessionID,
Created: now,
RemoteAddr: "192.168.1.100:5000",
Path: "mystream",
OutboundBytes: 345,
},
},
}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
httpRequest(t, hc, http.MethodPost, fmt.Sprintf("http://localhost:9997/v3/hlssessions/kick/%s", sessionID), nil, nil)
_, ok := hlsServer.sessions[sessionID.String()]
require.False(t, ok)
}
func TestHLSSessionsKickNotFound(t *testing.T) {
hlsServer := &testHLSServer{}
api := API{
Address: "localhost:9997",
ReadTimeout: conf.Duration(10 * time.Second),
WriteTimeout: conf.Duration(10 * time.Second),
AuthManager: test.NilAuthManager,
HLSServer: hlsServer,
Parent: &testParent{},
}
err := api.Initialize()
require.NoError(t, err)
defer api.Close()
tr := &http.Transport{}
defer tr.CloseIdleConnections()
hc := &http.Client{Transport: tr}
req, err := http.NewRequest(http.MethodPost,
fmt.Sprintf("http://localhost:9997/v3/hlssessions/kick/%s", uuid.New()), nil)
require.NoError(t, err)
res, err := hc.Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode)
checkError(t, res.Body, "session not found")
}