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  }