github.com/pion/webrtc/v4@v4.0.1/internal/fmtp/fmtp_test.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 package fmtp 5 6 import ( 7 "reflect" 8 "testing" 9 ) 10 11 func TestParseParameters(t *testing.T) { 12 for _, ca := range []struct { 13 name string 14 line string 15 parameters map[string]string 16 }{ 17 { 18 "one param", 19 "key-name=value", 20 map[string]string{ 21 "key-name": "value", 22 }, 23 }, 24 { 25 "one param with white spaces", 26 "\tkey-name=value ", 27 map[string]string{ 28 "key-name": "value", 29 }, 30 }, 31 { 32 "two params", 33 "key-name=value;key2=value2", 34 map[string]string{ 35 "key-name": "value", 36 "key2": "value2", 37 }, 38 }, 39 { 40 "two params with white spaces", 41 "key-name=value; \n\tkey2=value2 ", 42 map[string]string{ 43 "key-name": "value", 44 "key2": "value2", 45 }, 46 }, 47 } { 48 t.Run(ca.name, func(t *testing.T) { 49 parameters := parseParameters(ca.line) 50 if !reflect.DeepEqual(parameters, ca.parameters) { 51 t.Errorf("expected '%v', got '%v'", ca.parameters, parameters) 52 } 53 }) 54 } 55 } 56 57 func TestParse(t *testing.T) { 58 for _, ca := range []struct { 59 name string 60 mimeType string 61 line string 62 expected FMTP 63 }{ 64 { 65 "generic", 66 "generic", 67 "key-name=value", 68 &genericFMTP{ 69 mimeType: "generic", 70 parameters: map[string]string{ 71 "key-name": "value", 72 }, 73 }, 74 }, 75 { 76 "generic case normalization", 77 "generic", 78 "Key=value", 79 &genericFMTP{ 80 mimeType: "generic", 81 parameters: map[string]string{ 82 "key": "value", 83 }, 84 }, 85 }, 86 { 87 "h264", 88 "video/h264", 89 "key-name=value", 90 &h264FMTP{ 91 parameters: map[string]string{ 92 "key-name": "value", 93 }, 94 }, 95 }, 96 { 97 "vp9", 98 "video/vp9", 99 "key-name=value", 100 &vp9FMTP{ 101 parameters: map[string]string{ 102 "key-name": "value", 103 }, 104 }, 105 }, 106 { 107 "av1", 108 "video/av1", 109 "key-name=value", 110 &av1FMTP{ 111 parameters: map[string]string{ 112 "key-name": "value", 113 }, 114 }, 115 }, 116 } { 117 t.Run(ca.name, func(t *testing.T) { 118 f := Parse(ca.mimeType, ca.line) 119 if !reflect.DeepEqual(ca.expected, f) { 120 t.Errorf("expected '%v', got '%v'", ca.expected, f) 121 } 122 123 if f.MimeType() != ca.mimeType { 124 t.Errorf("Expected '%v', got '%s'", ca.mimeType, f.MimeType()) 125 } 126 }) 127 } 128 } 129 130 func TestMatch(t *testing.T) { 131 consistString := map[bool]string{true: "consist", false: "inconsist"} 132 133 for _, ca := range []struct { 134 name string 135 a FMTP 136 b FMTP 137 consist bool 138 }{ 139 { 140 "generic equal", 141 &genericFMTP{ 142 mimeType: "generic", 143 parameters: map[string]string{ 144 "key1": "value1", 145 "key2": "value2", 146 "key3": "value3", 147 }, 148 }, 149 &genericFMTP{ 150 mimeType: "generic", 151 parameters: map[string]string{ 152 "key1": "value1", 153 "key2": "value2", 154 "key3": "value3", 155 }, 156 }, 157 true, 158 }, 159 { 160 "generic one extra param", 161 &genericFMTP{ 162 mimeType: "generic", 163 parameters: map[string]string{ 164 "key1": "value1", 165 "key2": "value2", 166 "key3": "value3", 167 }, 168 }, 169 &genericFMTP{ 170 mimeType: "generic", 171 parameters: map[string]string{ 172 "key1": "value1", 173 "key2": "value2", 174 "key3": "value3", 175 "key4": "value4", 176 }, 177 }, 178 true, 179 }, 180 { 181 "generic inconsistent different kind", 182 &genericFMTP{ 183 mimeType: "generic", 184 parameters: map[string]string{ 185 "key1": "value1", 186 "key2": "value2", 187 "key3": "value3", 188 }, 189 }, 190 &h264FMTP{}, 191 false, 192 }, 193 { 194 "generic inconsistent different mime type", 195 &genericFMTP{ 196 mimeType: "generic1", 197 parameters: map[string]string{ 198 "key1": "value1", 199 "key2": "value2", 200 "key3": "value3", 201 }, 202 }, 203 &genericFMTP{ 204 mimeType: "generic2", 205 parameters: map[string]string{ 206 "key1": "value1", 207 "key2": "value2", 208 "key3": "value3", 209 }, 210 }, 211 false, 212 }, 213 { 214 "generic inconsistent different parameters", 215 &genericFMTP{ 216 mimeType: "generic", 217 parameters: map[string]string{ 218 "key1": "value1", 219 "key2": "value2", 220 "key3": "value3", 221 }, 222 }, 223 &genericFMTP{ 224 mimeType: "generic", 225 parameters: map[string]string{ 226 "key1": "value1", 227 "key2": "different_value", 228 "key3": "value3", 229 }, 230 }, 231 false, 232 }, 233 { 234 "h264 equal", 235 &h264FMTP{ 236 parameters: map[string]string{ 237 "level-asymmetry-allowed": "1", 238 "packetization-mode": "1", 239 "profile-level-id": "42e01f", 240 }, 241 }, 242 &h264FMTP{ 243 parameters: map[string]string{ 244 "level-asymmetry-allowed": "1", 245 "packetization-mode": "1", 246 "profile-level-id": "42e01f", 247 }, 248 }, 249 true, 250 }, 251 { 252 "h264 one extra param", 253 &h264FMTP{ 254 parameters: map[string]string{ 255 "level-asymmetry-allowed": "1", 256 "packetization-mode": "1", 257 "profile-level-id": "42e01f", 258 }, 259 }, 260 &h264FMTP{ 261 parameters: map[string]string{ 262 "packetization-mode": "1", 263 "profile-level-id": "42e01f", 264 }, 265 }, 266 true, 267 }, 268 { 269 "h264 different profile level ids version", 270 &h264FMTP{ 271 parameters: map[string]string{ 272 "packetization-mode": "1", 273 "profile-level-id": "42e01f", 274 }, 275 }, 276 &h264FMTP{ 277 parameters: map[string]string{ 278 "packetization-mode": "1", 279 "profile-level-id": "42e029", 280 }, 281 }, 282 true, 283 }, 284 { 285 "h264 inconsistent different kind", 286 &h264FMTP{ 287 parameters: map[string]string{ 288 "packetization-mode": "0", 289 "profile-level-id": "42e01f", 290 }, 291 }, 292 &genericFMTP{}, 293 false, 294 }, 295 { 296 "h264 inconsistent different parameters", 297 &h264FMTP{ 298 parameters: map[string]string{ 299 "packetization-mode": "0", 300 "profile-level-id": "42e01f", 301 }, 302 }, 303 &h264FMTP{ 304 parameters: map[string]string{ 305 "packetization-mode": "1", 306 "profile-level-id": "42e01f", 307 }, 308 }, 309 false, 310 }, 311 { 312 "h264 inconsistent missing packetization mode", 313 &h264FMTP{ 314 parameters: map[string]string{ 315 "packetization-mode": "0", 316 "profile-level-id": "42e01f", 317 }, 318 }, 319 &h264FMTP{ 320 parameters: map[string]string{ 321 "profile-level-id": "42e01f", 322 }, 323 }, 324 false, 325 }, 326 { 327 "h264 inconsistent missing profile level id", 328 &h264FMTP{ 329 parameters: map[string]string{ 330 "packetization-mode": "1", 331 "profile-level-id": "42e01f", 332 }, 333 }, 334 &h264FMTP{ 335 parameters: map[string]string{ 336 "packetization-mode": "1", 337 }, 338 }, 339 false, 340 }, 341 { 342 "h264 inconsistent invalid profile level id", 343 &h264FMTP{ 344 parameters: map[string]string{ 345 "packetization-mode": "1", 346 "profile-level-id": "42e029", 347 }, 348 }, 349 &h264FMTP{ 350 parameters: map[string]string{ 351 "packetization-mode": "1", 352 "profile-level-id": "41e029", 353 }, 354 }, 355 false, 356 }, 357 { 358 "vp9 equal", 359 &vp9FMTP{ 360 parameters: map[string]string{ 361 "profile-id": "1", 362 }, 363 }, 364 &vp9FMTP{ 365 parameters: map[string]string{ 366 "profile-id": "1", 367 }, 368 }, 369 true, 370 }, 371 { 372 "vp9 missing profile", 373 &vp9FMTP{ 374 parameters: map[string]string{}, 375 }, 376 &vp9FMTP{ 377 parameters: map[string]string{}, 378 }, 379 true, 380 }, 381 { 382 "vp9 inferred profile", 383 &vp9FMTP{ 384 parameters: map[string]string{ 385 "profile-id": "0", 386 }, 387 }, 388 &vp9FMTP{ 389 parameters: map[string]string{}, 390 }, 391 true, 392 }, 393 { 394 "vp9 inconsistent different kind", 395 &vp9FMTP{ 396 parameters: map[string]string{ 397 "profile-id": "0", 398 }, 399 }, 400 &genericFMTP{}, 401 false, 402 }, 403 { 404 "vp9 inconsistent different profile", 405 &vp9FMTP{ 406 parameters: map[string]string{ 407 "profile-id": "0", 408 }, 409 }, 410 &vp9FMTP{ 411 parameters: map[string]string{ 412 "profile-id": "1", 413 }, 414 }, 415 false, 416 }, 417 { 418 "vp9 inconsistent different inferred profile", 419 &vp9FMTP{ 420 parameters: map[string]string{}, 421 }, 422 &vp9FMTP{ 423 parameters: map[string]string{ 424 "profile-id": "1", 425 }, 426 }, 427 false, 428 }, 429 { 430 "av1 equal", 431 &av1FMTP{ 432 parameters: map[string]string{ 433 "profile": "1", 434 }, 435 }, 436 &av1FMTP{ 437 parameters: map[string]string{ 438 "profile": "1", 439 }, 440 }, 441 true, 442 }, 443 { 444 "av1 missing profile", 445 &av1FMTP{ 446 parameters: map[string]string{}, 447 }, 448 &av1FMTP{ 449 parameters: map[string]string{}, 450 }, 451 true, 452 }, 453 { 454 "av1 inferred profile", 455 &av1FMTP{ 456 parameters: map[string]string{ 457 "profile": "0", 458 }, 459 }, 460 &av1FMTP{ 461 parameters: map[string]string{}, 462 }, 463 true, 464 }, 465 { 466 "av1 inconsistent different kind", 467 &av1FMTP{ 468 parameters: map[string]string{ 469 "profile": "0", 470 }, 471 }, 472 &genericFMTP{}, 473 false, 474 }, 475 { 476 "av1 inconsistent different profile", 477 &av1FMTP{ 478 parameters: map[string]string{ 479 "profile": "0", 480 }, 481 }, 482 &av1FMTP{ 483 parameters: map[string]string{ 484 "profile": "1", 485 }, 486 }, 487 false, 488 }, 489 { 490 "av1 inconsistent different inferred profile", 491 &av1FMTP{ 492 parameters: map[string]string{}, 493 }, 494 &av1FMTP{ 495 parameters: map[string]string{ 496 "profile": "1", 497 }, 498 }, 499 false, 500 }, 501 } { 502 t.Run(ca.name, func(t *testing.T) { 503 c := ca.a.Match(ca.b) 504 if c != ca.consist { 505 t.Errorf( 506 "'%s' and '%s' are expected to be %s, but treated as %s", 507 ca.a, ca.b, consistString[ca.consist], consistString[c], 508 ) 509 } 510 511 c = ca.b.Match(ca.a) 512 if c != ca.consist { 513 t.Errorf( 514 "'%s' and '%s' are expected to be %s, but treated as %s", 515 ca.a, ca.b, consistString[ca.consist], consistString[c], 516 ) 517 } 518 }) 519 } 520 }