mirror of
https://github.com/aler9/rtsp-simple-server
synced 2026-04-22 23:17:11 +08:00
271 lines
5.8 KiB
Go
271 lines
5.8 KiB
Go
//go:build enable_linters
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediamtx/internal/conf"
|
|
"github.com/bluenviron/mediamtx/internal/defs"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type openAPIProperty struct {
|
|
Ref string `yaml:"$ref"`
|
|
Type string `yaml:"type"`
|
|
Format string `yaml:"format"`
|
|
Nullable bool `yaml:"nullable"`
|
|
Items *openAPIProperty `yaml:"items"`
|
|
}
|
|
|
|
type openAPISchema struct {
|
|
Type string `yaml:"type"`
|
|
Properties map[string]openAPIProperty `yaml:"properties"`
|
|
}
|
|
|
|
type openAPI struct {
|
|
Components struct {
|
|
Schemas map[string]openAPISchema `yaml:"schemas"`
|
|
} `yaml:"components"`
|
|
}
|
|
|
|
func fillProperty(t *testing.T, rt reflect.Type, existing openAPIProperty) openAPIProperty {
|
|
switch {
|
|
case rt == reflect.TypeOf(""):
|
|
return openAPIProperty{Type: "string"}
|
|
|
|
case rt == reflect.PointerTo(reflect.TypeOf("")):
|
|
return openAPIProperty{
|
|
Type: "string",
|
|
Nullable: true,
|
|
}
|
|
|
|
case rt == reflect.TypeOf(int(0)):
|
|
return openAPIProperty{Type: "integer", Format: "int64"}
|
|
|
|
case rt == reflect.TypeOf(uint(0)):
|
|
return openAPIProperty{Type: "integer", Format: "uint64"}
|
|
|
|
case rt == reflect.TypeOf(uint64(0)):
|
|
return openAPIProperty{Type: "integer", Format: "uint64"}
|
|
|
|
case rt == reflect.TypeOf(float64(0)):
|
|
return openAPIProperty{Type: "number", Format: "double"}
|
|
|
|
case rt == reflect.TypeOf(false):
|
|
return openAPIProperty{Type: "boolean"}
|
|
|
|
case rt == reflect.TypeOf(&time.Time{}):
|
|
return openAPIProperty{Type: "string", Nullable: true}
|
|
|
|
case rt == reflect.TypeOf(uuid.UUID{}):
|
|
return openAPIProperty{Type: "string", Format: "uuid"}
|
|
|
|
case rt == reflect.PointerTo(reflect.TypeOf(uuid.UUID{})):
|
|
return openAPIProperty{Type: "string", Format: "uuid", Nullable: true}
|
|
|
|
case rt == reflect.TypeOf(time.Time{}) ||
|
|
rt == reflect.TypeOf(conf.Duration(0)) ||
|
|
rt == reflect.TypeOf(conf.IPNetwork{}) ||
|
|
rt == reflect.TypeOf(conf.Credential("")) ||
|
|
rt == reflect.TypeOf(conf.RecordFormat("")) ||
|
|
rt == reflect.TypeOf(conf.AuthAction("")) ||
|
|
rt == reflect.TypeOf(conf.Encryption("")) ||
|
|
rt == reflect.TypeOf(conf.RTSPTransport{}) ||
|
|
rt == reflect.TypeOf(conf.StringSize(0)) ||
|
|
rt == reflect.TypeOf(conf.RTSPRangeType("")) ||
|
|
rt == reflect.TypeOf(conf.LogLevel(0)) ||
|
|
rt == reflect.TypeOf(conf.AuthMethod("")) ||
|
|
rt == reflect.TypeOf(conf.LogDestination(0)) ||
|
|
rt == reflect.TypeOf(conf.RTSPAuthMethod(0)) ||
|
|
rt == reflect.TypeOf(conf.HLSVariant(0)) ||
|
|
rt == reflect.TypeOf(defs.APIRTMPConnState("")) ||
|
|
rt == reflect.TypeOf(defs.APIWebRTCSessionState("")) ||
|
|
rt == reflect.TypeOf(defs.APISRTConnState("")) ||
|
|
rt == reflect.TypeOf(defs.APIRTSPSessionState("")) ||
|
|
rt == reflect.TypeOf(conf.Codec("")):
|
|
return openAPIProperty{Type: "string"}
|
|
|
|
case rt == reflect.TypeOf(conf.RTSPTransports{}):
|
|
return openAPIProperty{
|
|
Type: "array",
|
|
Items: &openAPIProperty{
|
|
Type: "string",
|
|
},
|
|
}
|
|
|
|
case rt.Kind() == reflect.Struct:
|
|
schemaName := strings.TrimPrefix(rt.Name(), "API")
|
|
if rt.PkgPath() == "github.com/bluenviron/mediamtx/internal/conf" && schemaName == "Path" {
|
|
schemaName = "PathConf"
|
|
}
|
|
|
|
return openAPIProperty{
|
|
Ref: "#/components/schemas/" + schemaName,
|
|
}
|
|
|
|
case rt.Kind() == reflect.Pointer && rt.Elem().Kind() == reflect.Struct:
|
|
prop := fillProperty(t, rt.Elem(), existing)
|
|
prop.Nullable = true
|
|
return prop
|
|
|
|
case rt.Kind() == reflect.Slice:
|
|
items := fillProperty(t, rt.Elem(), *existing.Items)
|
|
return openAPIProperty{
|
|
Type: "array",
|
|
Items: &items,
|
|
}
|
|
|
|
default:
|
|
t.Errorf("unhandled type: %v", rt)
|
|
return openAPIProperty{}
|
|
}
|
|
}
|
|
|
|
func TestGo2API(t *testing.T) {
|
|
byts, err := os.ReadFile("../../../api/openapi.yaml")
|
|
require.NoError(t, err)
|
|
|
|
var doc openAPI
|
|
err = yaml.Unmarshal(byts, &doc)
|
|
require.NoError(t, err)
|
|
|
|
for _, ca := range []struct {
|
|
openAPIKey string
|
|
goStruct any
|
|
}{
|
|
{
|
|
"AlwaysAvailableTrack",
|
|
conf.AlwaysAvailableTrack{},
|
|
},
|
|
{
|
|
"AuthInternalUser",
|
|
conf.AuthInternalUser{},
|
|
},
|
|
{
|
|
"AuthInternalUserPermission",
|
|
conf.AuthInternalUserPermission{},
|
|
},
|
|
{
|
|
"GlobalConf",
|
|
conf.Conf{},
|
|
},
|
|
{
|
|
"HLSMuxer",
|
|
defs.APIHLSMuxer{},
|
|
},
|
|
{
|
|
"HLSMuxerList",
|
|
defs.APIHLSMuxerList{},
|
|
},
|
|
{
|
|
"Info",
|
|
defs.APIInfo{},
|
|
},
|
|
{
|
|
"Path",
|
|
defs.APIPath{},
|
|
},
|
|
{
|
|
"PathConf",
|
|
conf.Path{},
|
|
},
|
|
{
|
|
"PathConfList",
|
|
defs.APIPathConfList{},
|
|
},
|
|
{
|
|
"PathList",
|
|
defs.APIPathList{},
|
|
},
|
|
{
|
|
"PathReader",
|
|
defs.APIPathReader{},
|
|
},
|
|
{
|
|
"PathSource",
|
|
defs.APIPathSource{},
|
|
},
|
|
{
|
|
"Recording",
|
|
defs.APIRecording{},
|
|
},
|
|
{
|
|
"RecordingList",
|
|
defs.APIRecordingList{},
|
|
},
|
|
{
|
|
"RecordingSegment",
|
|
defs.APIRecordingSegment{},
|
|
},
|
|
{
|
|
"RTMPConn",
|
|
defs.APIRTMPConn{},
|
|
},
|
|
{
|
|
"RTMPConnList",
|
|
defs.APIRTMPConnList{},
|
|
},
|
|
{
|
|
"RTSPConn",
|
|
defs.APIRTSPConn{},
|
|
},
|
|
{
|
|
"RTSPConnList",
|
|
defs.APIRTSPConnsList{},
|
|
},
|
|
{
|
|
"RTSPSession",
|
|
defs.APIRTSPSession{},
|
|
},
|
|
{
|
|
"RTSPSessionList",
|
|
defs.APIRTSPSessionList{},
|
|
},
|
|
{
|
|
"SRTConn",
|
|
defs.APISRTConn{},
|
|
},
|
|
{
|
|
"SRTConnList",
|
|
defs.APISRTConnList{},
|
|
},
|
|
{
|
|
"WebRTCSession",
|
|
defs.APIWebRTCSession{},
|
|
},
|
|
{
|
|
"WebRTCSessionList",
|
|
defs.APIWebRTCSessionList{},
|
|
},
|
|
} {
|
|
t.Run(ca.openAPIKey, func(t *testing.T) {
|
|
content1 := doc.Components.Schemas[ca.openAPIKey]
|
|
|
|
content2 := openAPISchema{
|
|
Type: "object",
|
|
Properties: make(map[string]openAPIProperty),
|
|
}
|
|
|
|
ty := reflect.TypeOf(ca.goStruct)
|
|
|
|
for i := range ty.NumField() {
|
|
sf := ty.Field(i)
|
|
js := sf.Tag.Get("json")
|
|
|
|
if js != "-" && js != "paths" && js != "pathDefaults" && !strings.Contains(js, ",omitempty") {
|
|
content2.Properties[js] = fillProperty(t, sf.Type, content1.Properties[js])
|
|
}
|
|
}
|
|
|
|
require.Equal(t, content2, content1)
|
|
})
|
|
}
|
|
}
|