clone

a desktop tv and program guide for over-the-air broadcasts: what's on air, what your tuner gets, live tv, recordings

main
airwaves / internal / cc / chunk_test.go
chunk_test.go 5.2K
1package cc23import (4 "slices"5 "strings"6 "testing"7 "time"8)910func TestChunkAtPhrases(t *testing.T) {11 for _, c := range []struct {12 text string13 want []string14 }{15 // Sentences and clauses end captions; lines are about even.16 {"I told you before, we can't go back there. The bridge is out and the road is flooded all the way to town.",17 []string{"I told you before,\nwe can't go back there.", "The bridge is out and the road\nis flooded all the way to town."}},18 {"This line is a good deal longer than thirty-two characters",19 []string{"This line is a good deal longer\nthan thirty-two characters"}},20 // Lines that fit stay as written, one speaker to a line.21 {"- Who's there?\n- It's me, open the door.", []string{"- Who's there?\n- It's me, open the door."}},22 {"- Who's there?\n- It's me.\n- Who is me?", []string{"- Who's there?\n- It's me.", "- Who is me?"}},23 {"[thunder rumbling]", []string{"[thunder rumbling]"}},24 // What 608 lacks is folded, and a word too long for a line is cut.25 {"Wait… “what”?", []string{"Wait... “what”?"}},26 {"Supercalifragilisticexpialidocious-and-then-some words", []string{"Supercalifragilisticexpialidocio\nus-and-then-some words"}},27 {" \n ", nil},28 } {29 got := chunk(c.text)30 if !slices.Equal(got, c.want) {31 t.Errorf("chunk(%q)\n got %q\nwant %q", c.text, got, c.want)32 }33 for _, ch := range got {34 lines := strings.Split(ch, "\n")35 if len(lines) > Rows || slices.ContainsFunc(lines, func(l string) bool { return len([]rune(l)) > Columns }) {36 t.Errorf("%q doesn't fit", ch)37 }38 }39 }40}4142func TestPace(t *testing.T) {43 s := func(sec float64) time.Duration { return time.Duration(sec * float64(time.Second)) }44 // Too short to read: runs on into the gap, but not over the next cue.45 got := captions608([]Cue{46 {Start: s(1), End: s(1.4), Text: "Hi there"},47 {Start: s(5), End: s(5.2), Text: "Wait"},48 {Start: s(5.5), End: s(8), Text: "What?"},49 })50 want := []Cue{51 {Start: s(1), End: s(2), Text: "Hi there"},52 {Start: s(5), End: s(5.5), Text: "Wait"},53 {Start: s(5.5), End: s(8), Text: "What?"},54 }55 if !equalCues(got, want) {56 t.Errorf("got %v\nwant %v", got, want)57 }58 // A long cue's captions follow each other, sharing out its time by59 // length, and longer when there's room to.60 long := "Well, I suppose if you really want to know what happened that night, you should ask your mother, because she was there and I wasn't."61 got = captions608([]Cue{{Start: s(10), End: s(14), Text: long}})62 if len(got) != 3 || got[0].Start != s(10) || got[0].End != got[1].Start || got[1].End != got[2].Start {63 t.Fatalf("captions %v", got)64 }65 if end := got[2].End; end < s(10)+showFor(len(long))-time.Second || end > s(18) {66 t.Errorf("ends at %v", end)67 }68 for _, c := range got {69 if c.End-c.Start < showFor(len([]rune(c.Text)))*9/10 {70 t.Errorf("%q shows for %v", c.Text, c.End-c.Start)71 }72 }73 // Squeezed by the next cue, they share what time there is.74 got = captions608([]Cue{{Start: s(10), End: s(14), Text: long}, {Start: s(13), End: s(14), Text: "Oh."}})75 if len(got) != 4 || got[2].End != s(13) || got[3].Start != s(13) {76 t.Errorf("squeezed %v", got)77 }78 // Cues starting together show together.79 got = captions608([]Cue{{Start: s(1), End: s(3), Text: "[door slams]"}, {Start: s(1), End: s(2), Text: "Who's there?"}})80 if len(got) != 1 || got[0].Text != "[door slams]\nWho's there?" || got[0].End != s(3) {81 t.Errorf("together %v", got)82 }83}8485func TestScript(t *testing.T) {86 s := func(sec float64) time.Duration { return time.Duration(sec * float64(time.Second)) }87 var sc Script88 sc.Set(0, s(100), []Cue{89 {Start: s(1), End: s(3), Text: "one"},90 {Start: s(8), End: s(12), Text: "two"},91 {Start: s(20), End: s(22), Text: "three"},92 })93 // The next video starts at 10: what was due after then goes.94 sc.Set(s(10), s(1e6), nil)95 sc.Set(s(10), s(1e6), []Cue{{Start: s(11), End: s(13), Text: "four"}, {Start: s(9), End: s(10), Text: "too early"}})96 texts := func(cs []Cue) (out []string) {97 for _, c := range cs {98 out = append(out, c.Text)99 }100 return out101 }102 if got := texts(sc.Between(0, s(100))); !slices.Equal(got, []string{"one", "two", "four"}) {103 t.Errorf("script %q", got)104 }105 if got := sc.Between(s(9), s(10)); len(got) != 1 || got[0].End != s(10) {106 t.Errorf("cut short: %v", got)107 }108 if got := texts(sc.Between(s(3), s(8))); got != nil {109 t.Errorf("between captions: %q", got)110 }111 if got := texts(sc.Between(s(12), s(12.5))); !slices.Equal(got, []string{"four"}) {112 t.Errorf("at 12: %q", got)113 }114 sc.Forget(s(5))115 if got := texts(sc.Between(0, s(100))); !slices.Equal(got, []string{"two", "four"}) {116 t.Errorf("after forgetting: %q", got)117 }118}119120func TestAppendVTT(t *testing.T) {121 s := func(sec float64) time.Duration { return time.Duration(sec * float64(time.Second)) }122 got := string(AppendVTT(nil, Cue{Start: s(3661.5), End: s(3663), Text: "Tom & Jerry\n<3 cats>"}))123 if want := "01:01:01.500 --> 01:01:03.000\nTom &amp; Jerry\n&lt;3 cats&gt;\n\n"; got != want {124 t.Errorf("got %q, want %q", got, want)125 }126 got = string(AppendVTT(nil, Cue{Start: s(1), End: s(3), Text: "all right gamers",127 Words: []Word{{s(1), "all"}, {s(1.25), "right"}, {s(1.25), "gamers"}, {s(5), "late"}}}))128 if want := "00:00:01.000 --> 00:00:03.000\nall <00:00:01.250>right gamers late\n\n"; got != want {129 t.Errorf("got %q, want %q", got, want)130 }131}