Files
upstream-mirror 8acb1a3a29
Some checks failed
REUSE Compliance Check / lint (push) Failing after 0s
Browser E2E / Test (push) Failing after 3s
Test / test (1.24) (push) Failing after 0s
Test / test-i386 (1.25) (push) Failing after 0s
Test / test-i386 (1.24) (push) Failing after 0s
Test / test-windows (1.25) (push) Failing after 0s
Test / test-windows (1.24) (push) Failing after 0s
Test / test (1.25) (push) Failing after 0s
Examples Tests / Test (push) Failing after 3s
Test / test-macos (1.25) (push) Failing after 0s
Test / test-macos (1.24) (push) Failing after 0s
Go mod tidy / tidy (push) Failing after 0s
Test / test-wasm (push) Failing after 0s
CodeQL / analyze (push) Failing after 1s
Fuzz / fuzz (push) Failing after 0s
snapshot of https://github.com/pion/webrtc.git (main, 2026-09-15; blobs > 131072B omitted)
2026-09-15 20:06:07 +05:00

769 lines
14 KiB
Go

// SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package fmtp
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseParameters(t *testing.T) {
for _, ca := range []struct {
name string
line string
parameters map[string]string
}{
{
"one param",
"key-name=value",
map[string]string{
"key-name": "value",
},
},
{
"one param with white spaces",
"\tkey-name=value ",
map[string]string{
"key-name": "value",
},
},
{
"two params",
"key-name=value;key2=value2",
map[string]string{
"key-name": "value",
"key2": "value2",
},
},
{
"two params with white spaces",
"key-name=value; \n\tkey2=value2 ",
map[string]string{
"key-name": "value",
"key2": "value2",
},
},
} {
t.Run(ca.name, func(t *testing.T) {
parameters := parseParameters(ca.line)
assert.Equal(t, ca.parameters, parameters)
})
}
}
func TestParse(t *testing.T) {
for _, ca := range []struct {
name string
mimeType string
clockRate uint32
channels uint16
line string
expected FMTP
}{
{
"generic",
"generic",
90000,
2,
"key-name=value",
&genericFMTP{
mimeType: "generic",
clockRate: 90000,
channels: 2,
parameters: map[string]string{
"key-name": "value",
},
},
},
{
"generic case normalization",
"generic",
90000,
2,
"Key=value",
&genericFMTP{
mimeType: "generic",
clockRate: 90000,
channels: 2,
parameters: map[string]string{
"key": "value",
},
},
},
{
"h264",
"video/h264",
90000,
0,
"key-name=value",
&h264FMTP{
parameters: map[string]string{
"key-name": "value",
},
},
},
{
"h265",
"video/h265",
90000,
0,
"key-name=value",
&h265FMTP{
parameters: map[string]string{
"key-name": "value",
},
},
},
{
"vp9",
"video/vp9",
90000,
0,
"key-name=value",
&vp9FMTP{
parameters: map[string]string{
"key-name": "value",
},
},
},
{
"av1",
"video/av1",
90000,
0,
"key-name=value",
&av1FMTP{
parameters: map[string]string{
"key-name": "value",
},
},
},
} {
t.Run(ca.name, func(t *testing.T) {
f := Parse(ca.mimeType, ca.clockRate, ca.channels, ca.line)
assert.Equal(t, ca.expected, f)
assert.Equal(t, ca.mimeType, f.MimeType())
})
}
}
func TestMatch(t *testing.T) { //nolint:maintidx
consistString := map[bool]string{true: "consist", false: "inconsist"}
parseH265 := func(line string) FMTP {
return Parse("video/h265", 90000, 0, line)
}
for _, ca := range []struct {
name string
a FMTP
b FMTP
consist bool
}{
{
"generic equal",
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
true,
},
{
"generic one extra param",
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
},
},
true,
},
{
"generic inferred channels",
&genericFMTP{
mimeType: "generic",
channels: 1,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
true,
},
{
"generic inconsistent different kind",
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&h264FMTP{},
false,
},
{
"generic inconsistent different mime type",
&genericFMTP{
mimeType: "generic1",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic2",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
false,
},
{
"generic inconsistent different clock rate",
&genericFMTP{
mimeType: "generic",
clockRate: 90000,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
clockRate: 48000,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
false,
},
{
"generic inconsistent different channels",
&genericFMTP{
mimeType: "generic",
clockRate: 90000,
channels: 2,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
clockRate: 90000,
channels: 1,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
false,
},
{
"generic inconsistent different parameters",
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "generic",
parameters: map[string]string{
"key1": "value1",
"key2": "different_value",
"key3": "value3",
},
},
false,
},
{
"h264 equal",
&h264FMTP{
parameters: map[string]string{
"level-asymmetry-allowed": "1",
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"level-asymmetry-allowed": "1",
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
true,
},
{
"h264 one extra param",
&h264FMTP{
parameters: map[string]string{
"level-asymmetry-allowed": "1",
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
true,
},
{
"h264 different profile level ids version",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e029",
},
},
true,
},
{
"h264 inconsistent different kind",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "0",
"profile-level-id": "42e01f",
},
},
&genericFMTP{},
false,
},
{
"h264 inconsistent different parameters",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "0",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
false,
},
{
"h264 inconsistent missing packetization mode",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "0",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"profile-level-id": "42e01f",
},
},
false,
},
{
"h264 inconsistent missing profile level id",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e01f",
},
},
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
},
},
false,
},
{
"h264 inconsistent invalid profile level id",
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "42e029",
},
},
&h264FMTP{
parameters: map[string]string{
"packetization-mode": "1",
"profile-level-id": "41e029",
},
},
false,
},
{
"h265 downgraded level",
parseH265("level-id=186;profile-id=1;tier-flag=0;tx-mode=SRST"),
parseH265("level-id=93;profile-id=1;tier-flag=0;tx-mode=SRST"),
true,
},
{
"h265 inferred defaults and ignored sprop parameter",
parseH265(""),
parseH265("profile-id=1;tier-flag=0;tx-mode=srst;sprop-vps=ignored"),
true,
},
{
"h265 inconsistent different kind",
parseH265(""),
&genericFMTP{},
false,
},
{
"h265 inconsistent different profile",
parseH265("profile-id=1"),
parseH265("profile-id=2"),
false,
},
{
"h265 inconsistent different tier",
parseH265("tier-flag=0"),
parseH265("tier-flag=1"),
false,
},
{
"h265 inconsistent different transmission mode",
parseH265("tx-mode=SRST"),
parseH265("tx-mode=MRST"),
false,
},
{
"vp9 equal",
&vp9FMTP{
parameters: map[string]string{
"profile-id": "1",
},
},
&vp9FMTP{
parameters: map[string]string{
"profile-id": "1",
},
},
true,
},
{
"vp9 missing profile",
&vp9FMTP{
parameters: map[string]string{},
},
&vp9FMTP{
parameters: map[string]string{},
},
true,
},
{
"vp9 inferred profile",
&vp9FMTP{
parameters: map[string]string{
"profile-id": "0",
},
},
&vp9FMTP{
parameters: map[string]string{},
},
true,
},
{
"vp9 inconsistent different kind",
&vp9FMTP{
parameters: map[string]string{
"profile-id": "0",
},
},
&genericFMTP{},
false,
},
{
"vp9 inconsistent different profile",
&vp9FMTP{
parameters: map[string]string{
"profile-id": "0",
},
},
&vp9FMTP{
parameters: map[string]string{
"profile-id": "1",
},
},
false,
},
{
"vp9 inconsistent different inferred profile",
&vp9FMTP{
parameters: map[string]string{},
},
&vp9FMTP{
parameters: map[string]string{
"profile-id": "1",
},
},
false,
},
{
"av1 equal",
&av1FMTP{
parameters: map[string]string{
"profile": "1",
},
},
&av1FMTP{
parameters: map[string]string{
"profile": "1",
},
},
true,
},
{
"av1 missing profile",
&av1FMTP{
parameters: map[string]string{},
},
&av1FMTP{
parameters: map[string]string{},
},
true,
},
{
"av1 inferred profile",
&av1FMTP{
parameters: map[string]string{
"profile": "0",
},
},
&av1FMTP{
parameters: map[string]string{},
},
true,
},
{
"av1 inconsistent different kind",
&av1FMTP{
parameters: map[string]string{
"profile": "0",
},
},
&genericFMTP{},
false,
},
{
"av1 inconsistent different profile",
&av1FMTP{
parameters: map[string]string{
"profile": "0",
},
},
&av1FMTP{
parameters: map[string]string{
"profile": "1",
},
},
false,
},
{
"av1 inconsistent different inferred profile",
&av1FMTP{
parameters: map[string]string{},
},
&av1FMTP{
parameters: map[string]string{
"profile": "1",
},
},
false,
},
{
"pcmu channels",
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 8000,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 8000,
channels: 1,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
true,
},
{
"pcmu inconsistent channels",
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 8000,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 8000,
channels: 2,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
false,
},
{
"pcmu clockrate",
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 0,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 8000,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
true,
},
{
"pcmu inconsistent clockrate",
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 0,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "audio/pcmu",
clockRate: 16000,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
false,
},
{
"opus clockrate",
&genericFMTP{
mimeType: "audio/opus",
clockRate: 0,
channels: 0,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
&genericFMTP{
mimeType: "audio/opus",
clockRate: 48000,
channels: 2,
parameters: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
true,
},
} {
t.Run(ca.name, func(t *testing.T) {
c := ca.a.Match(ca.b)
assert.Equal(t, ca.consist, c)
assert.Equal(
t, ca.consist, c,
"'%s' and '%s' are expected to be %s, but treated as %s",
ca.a, ca.b, consistString[ca.consist], consistString[c],
)
c = ca.b.Match(ca.a)
assert.Equalf(
t, ca.consist, c,
"'%s' and '%s' are expected to be %s, but treated as %s",
ca.b, ca.a, consistString[ca.consist], consistString[c],
)
})
}
}