// SPDX-FileCopyrightText: 2023 The Pion community // 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", }, }, }, { "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"} 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, }, { "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], ) }) } }