streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

commit b5f85f89121f617dfded624f2c2d3ee1ddd9a703
parent a510c142ef4a06df8f8af87a87b13a26d2e78b01
Author: Oliver Lowe <o@olowe.co>
Date:   Mon, 22 Jul 2024 20:02:43 +1000

sdp: only test SDP duration parsing

All other durations are handed over to time.ParseDuration, so we
can let the standard library take care of it. Since this part of
SDP is rarely - if ever - used in the wild, I'd rather have less
code.

While here don't bother with subtests; letting it all run one after
the other is just as clear and less code. We're not doing parallel
testing either.

Diffstat:
Msdp/sdp_test.go | 163-------------------------------------------------------------------------------
Msdp/time.go | 3+++
Asdp/time_test.go | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+), 163 deletions(-)

diff --git a/sdp/sdp_test.go b/sdp/sdp_test.go @@ -6,7 +6,6 @@ import ( "os" "reflect" "testing" - "time" ) func TestReadSession(t *testing.T) { @@ -154,165 +153,3 @@ func TestConnInfo(t *testing.T) { }) } } - -func TestParseTimes(t *testing.T) { - var cases = []struct { - when string - want [2]time.Time - }{ - {"0 0", [2]time.Time{time.Time{}, time.Time{}}}, - { - "3930082049 0", - [2]time.Time{ - time.Date(2024, time.July, 16, 1, 27, 29, 0, time.UTC), - time.Time{}, - }, - }, - { - "3724394400 3724398000", - [2]time.Time{ - time.Date(2018, time.January, 8, 10, 0, 0, 0, time.UTC), - time.Date(2018, time.January, 8, 11, 0, 0, 0, time.UTC), - }, - }, - { - "3724484400 3724488000", - [2]time.Time{ - time.Date(2018, time.January, 9, 11, 0, 0, 0, time.UTC), - time.Date(2018, time.January, 9, 12, 0, 0, 0, time.UTC), - }, - }, - } - - for _, tt := range cases { - t.Run(tt.when, func(t *testing.T) { - got, err := parseTimes(tt.when) - if err != nil { - t.Fatal(err) - } - if got != tt.want { - t.Errorf("parseTimes(%q) = %v, want %v", tt.when, got, tt.want) - } - }) - } -} - -// TODO(otl): tests for invalid repeat lines, e.g. missing fields, negative values - -func TestParseRepeat(t *testing.T) { - line := "604800 3600 0 90000" - want := Repeat{7 * 24 * time.Hour, time.Hour, []time.Duration{0, 25 * time.Hour}} - got, err := parseRepeat(line) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("parse repeat %s: got %v, want %v", line, got, want) - } -} - -// TODO(otl): tests for invalid duration strings e.g. bad suffix, no numbers - -func TestDuration(t *testing.T) { - var cases = []struct { - name string - s string - want time.Duration - wantErr bool - }{ - { - name: "dayOfSeconds", - s: "86400", - want: 24 * time.Hour, - }, - { - name: "twentyFourHours", - s: "24h", - want: 24 * time.Hour, - }, - { - name: "oneDay", - s: "1d", - want: 24 * time.Hour, - }, - { - name: "nice", - s: "69s", - want: 69 * time.Second, - }, - { - name: "negative", - s: "-01s", - want: time.Duration(-1) * time.Second, - }, - { - name: "decimal", - s: "1.5h", - want: time.Duration(5400) * time.Second, - }, - { - name: "badSuffix", - s: "13k", - want: 0, - wantErr: true, - }, - { - name: "2Days", - s: "2d", - want: 48 * time.Hour, - }, - { - name: "aDay", - s: "Ad", - want: 0, - wantErr: true, - }, - } - - for _, tt := range cases { - t.Run(tt.s, func(t *testing.T) { - got, err := parseDuration(tt.s) - if (err != nil) != tt.wantErr { - t.Fatal(err) - } - if got != tt.want { - t.Errorf("parseDuration(%q) = %s, want %s", tt.s, got, tt.want) - } - }) - } -} - -func TestParseAdjustments(t *testing.T) { - var cases = []struct { - name string - line string - want []TimeAdjustment - wantErr bool - }{ - {"uneven", "3730922900 -2h 123456789", nil, true}, - {"missing offset", "3730922900 ", nil, true}, - {"garbage", "hello world!", nil, true}, - { - "from rfc", - "3730928400 -1h 3749680800 0", - []TimeAdjustment{ - {time.Date(2018, time.March, 25, 1, 0, 0, 0, time.UTC), -time.Hour}, - {time.Date(2018, time.October, 28, 2, 0, 0, 0, time.UTC), 0}, - }, - false, - }, - } - for _, tt := range cases { - t.Run(tt.name, func(t *testing.T) { - got, err := parseAdjustments(tt.line) - if err != nil && !tt.wantErr { - t.Fatal(err) - } else if err == nil && tt.wantErr { - t.Error("unexpected nil error") - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("parseAdjustments(%q) = %v, want %v", tt.line, got, tt.want) - } - }) - } -} diff --git a/sdp/time.go b/sdp/time.go @@ -88,6 +88,9 @@ func parseRepeat(s string) (Repeat, error) { return repeat, nil } +// parseDuration wraps time.ParseDuration to account for +// bare integers (seconds) and +// the day prefix ("d"). func parseDuration(s string) (time.Duration, error) { // a bare int, like 86400 i, err := strconv.Atoi(s) diff --git a/sdp/time_test.go b/sdp/time_test.go @@ -0,0 +1,115 @@ +package sdp + +import ( + "reflect" + "testing" + "time" +) + +func TestParseTimes(t *testing.T) { + var cases = []struct { + when string + want [2]time.Time + }{ + {"0 0", [2]time.Time{time.Time{}, time.Time{}}}, + { + "3930082049 0", + [2]time.Time{ + time.Date(2024, time.July, 16, 1, 27, 29, 0, time.UTC), + time.Time{}, + }, + }, + { + "3724394400 3724398000", + [2]time.Time{ + time.Date(2018, time.January, 8, 10, 0, 0, 0, time.UTC), + time.Date(2018, time.January, 8, 11, 0, 0, 0, time.UTC), + }, + }, + { + "3724484400 3724488000", + [2]time.Time{ + time.Date(2018, time.January, 9, 11, 0, 0, 0, time.UTC), + time.Date(2018, time.January, 9, 12, 0, 0, 0, time.UTC), + }, + }, + } + + for _, tt := range cases { + got, err := parseTimes(tt.when) + if err != nil { + t.Fatal(err) + } + if got != tt.want { + t.Errorf("parseTimes(%q) = %v, want %v", tt.when, got, tt.want) + } + } +} + +// TODO(otl): tests for invalid repeat lines, e.g. missing fields, negative values + +func TestParseRepeat(t *testing.T) { + line := "604800 3600 0 90000" + want := Repeat{7 * 24 * time.Hour, time.Hour, []time.Duration{0, 25 * time.Hour}} + got, err := parseRepeat(line) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("parse repeat %s: got %v, want %v", line, got, want) + } +} + +func TestDuration(t *testing.T) { + var cases = []struct{ + s string + want time.Duration + }{ + {"2d", 48*time.Hour}, + {"-1d", -24*time.Hour}, + } + for _, tt := range cases { + got, err := parseDuration(tt.s) + if err != nil { + t.Fatalf("parse %q: %v", tt.s, err) + } + if got != tt.want { + t.Errorf("parseDuration(%q) = %s, want %s", tt.s, got, tt.want) + } + } +} + +func TestParseAdjustments(t *testing.T) { + var cases = []struct { + name string + line string + want []TimeAdjustment + wantErr bool + }{ + {"uneven", "3730922900 -2h 123456789", nil, true}, + {"missing offset", "3730922900 ", nil, true}, + {"garbage", "hello world!", nil, true}, + { + "from rfc", + "3730928400 -1h 3749680800 0", + []TimeAdjustment{ + {time.Date(2018, time.March, 25, 1, 0, 0, 0, time.UTC), -time.Hour}, + {time.Date(2018, time.October, 28, 2, 0, 0, 0, time.UTC), 0}, + }, + false, + }, + } + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + got, err := parseAdjustments(tt.line) + if err != nil && !tt.wantErr { + t.Fatal(err) + } else if err == nil && tt.wantErr { + t.Error("unexpected nil error") + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("parseAdjustments(%q) = %v, want %v", tt.line, got, tt.want) + } + }) + } +}