mirror of
https://github.com/zoriya/go-astisub.git
synced 2026-08-16 02:33:21 +00:00
* fix: nil-pointer panic in WriteToSSA when Metadata is nil WriteToSSA dereferenced s.Metadata unconditionally when computing the v4plus flag, but Metadata is an optional *Metadata that only ReadFromSSA populates. Reading any other format (WebVTT, SRT, TTML, STL) and writing SSA therefore panicked with a nil-pointer dereference. Guard the read: nil Metadata now yields v4plus=false (legacy [V4 Styles] output), matching the existing nil-safe newSSAScriptInfo one line above. Adds TestWriteToSSANilMetadata as a regression test. * Address review feedback on TestWriteToSSANilMetadata Move the nil-metadata comment above the subtitles literal and simplify its wording, and replace the post-write asserts with assert.NotPanics to focus the test on the regression (writing SSA no longer panics).
156 lines
6.8 KiB
Go
156 lines
6.8 KiB
Go
package astisub_test
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/asticode/go-astikit"
|
|
"github.com/asticode/go-astisub"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func assertSSAStyle(t *testing.T, e, a astisub.Style) {
|
|
assert.Equal(t, e.ID, a.ID)
|
|
assertSSAStyleAttributes(t, *e.InlineStyle, *a.InlineStyle)
|
|
}
|
|
|
|
func assertSSAStyleAttributes(t *testing.T, e, a astisub.StyleAttributes) {
|
|
if e.SSAAlignment != nil {
|
|
assert.Equal(t, *e.SSAAlignment, *a.SSAAlignment)
|
|
}
|
|
if e.SSAAlphaLevel != nil {
|
|
assert.Equal(t, *e.SSAAlphaLevel, *a.SSAAlphaLevel)
|
|
}
|
|
if e.SSABackColour != nil {
|
|
assert.Equal(t, *e.SSABackColour, *a.SSABackColour)
|
|
}
|
|
if e.SSABold != nil {
|
|
assert.Equal(t, *e.SSABold, *a.SSABold)
|
|
}
|
|
if e.SSABorderStyle != nil {
|
|
assert.Equal(t, *e.SSABorderStyle, *a.SSABorderStyle)
|
|
}
|
|
if e.SSAFontSize != nil {
|
|
assert.Equal(t, e.SSAFontName, a.SSAFontName)
|
|
}
|
|
if e.SSAFontSize != nil {
|
|
assert.Equal(t, *e.SSAFontSize, *a.SSAFontSize)
|
|
}
|
|
if e.SSALayer != nil {
|
|
assert.Equal(t, *e.SSALayer, *a.SSALayer)
|
|
}
|
|
if e.SSAMarked != nil {
|
|
assert.Equal(t, *e.SSAMarked, *a.SSAMarked)
|
|
}
|
|
if e.SSAMarginLeft != nil {
|
|
assert.Equal(t, *e.SSAMarginLeft, *a.SSAMarginLeft)
|
|
}
|
|
if e.SSAMarginRight != nil {
|
|
assert.Equal(t, *e.SSAMarginRight, *a.SSAMarginRight)
|
|
}
|
|
if e.SSAMarginVertical != nil {
|
|
assert.Equal(t, *e.SSAMarginVertical, *a.SSAMarginVertical)
|
|
}
|
|
if e.SSAOutline != nil {
|
|
assert.Equal(t, *e.SSAOutline, *a.SSAOutline)
|
|
}
|
|
if e.SSAOutlineColour != nil {
|
|
assert.Equal(t, *e.SSAOutlineColour, *a.SSAOutlineColour)
|
|
}
|
|
if e.SSAPrimaryColour != nil {
|
|
assert.Equal(t, *e.SSAPrimaryColour, *a.SSAPrimaryColour)
|
|
}
|
|
if e.SSASecondaryColour != nil {
|
|
assert.Equal(t, *e.SSASecondaryColour, *a.SSASecondaryColour)
|
|
}
|
|
if e.SSAShadow != nil {
|
|
assert.Equal(t, *e.SSAShadow, *a.SSAShadow)
|
|
}
|
|
}
|
|
|
|
func TestSSA(t *testing.T) {
|
|
// Open
|
|
s, err := astisub.OpenFile("./testdata/example-in.ssa")
|
|
assert.NoError(t, err)
|
|
assertSubtitleItems(t, s)
|
|
// Metadata
|
|
assert.Equal(t, &astisub.Metadata{Comments: []string{"Comment 1", "Comment 2"}, SSACollisions: "Normal", SSAOriginalScript: "asticode", SSAPlayDepth: astikit.IntPtr(0), SSAPlayResY: astikit.IntPtr(600), SSAScriptType: "v4.00", SSAScriptUpdatedBy: "version 2.8.01", SSATimer: astikit.Float64Ptr(100), Title: "SSA test"}, s.Metadata)
|
|
// Styles
|
|
assert.Equal(t, 3, len(s.Styles))
|
|
assertSSAStyle(t, astisub.Style{ID: "1", InlineStyle: &astisub.StyleAttributes{SSAAlignment: astikit.IntPtr(7), SSAAlphaLevel: astikit.Float64Ptr(0.1), SSABackColour: &astisub.Color{Alpha: 128, Red: 8}, SSABold: astikit.BoolPtr(true), SSABorderStyle: astikit.IntPtr(7), SSAFontName: "f1", SSAFontSize: astikit.Float64Ptr(4), SSAOutline: astikit.Float64Ptr(1), SSAOutlineColour: &astisub.Color{Green: 255, Red: 255}, SSAMarginLeft: astikit.IntPtr(1), SSAMarginRight: astikit.IntPtr(4), SSAMarginVertical: astikit.IntPtr(7), SSAPrimaryColour: &astisub.Color{Green: 255, Red: 255}, SSASecondaryColour: &astisub.Color{Green: 255, Red: 255}, SSAShadow: astikit.Float64Ptr(4)}}, *s.Styles["1"])
|
|
assertSSAStyle(t, astisub.Style{ID: "2", InlineStyle: &astisub.StyleAttributes{SSAAlignment: astikit.IntPtr(8), SSAAlphaLevel: astikit.Float64Ptr(0.2), SSABackColour: &astisub.Color{Blue: 15, Green: 15, Red: 15}, SSABold: astikit.BoolPtr(true), SSABorderStyle: astikit.IntPtr(8), SSAEncoding: astikit.IntPtr(1), SSAFontName: "f2", SSAFontSize: astikit.Float64Ptr(5), SSAOutline: astikit.Float64Ptr(2), SSAOutlineColour: &astisub.Color{Green: 255, Red: 255}, SSAMarginLeft: astikit.IntPtr(2), SSAMarginRight: astikit.IntPtr(5), SSAMarginVertical: astikit.IntPtr(8), SSAPrimaryColour: &astisub.Color{Blue: 239, Green: 239, Red: 239}, SSASecondaryColour: &astisub.Color{Green: 255, Red: 255}, SSAShadow: astikit.Float64Ptr(5)}}, *s.Styles["2"])
|
|
assertSSAStyle(t, astisub.Style{ID: "3", InlineStyle: &astisub.StyleAttributes{SSAAlignment: astikit.IntPtr(9), SSAAlphaLevel: astikit.Float64Ptr(0.3), SSABackColour: &astisub.Color{Red: 8}, SSABorderStyle: astikit.IntPtr(9), SSAEncoding: astikit.IntPtr(2), SSAFontName: "f3", SSAFontSize: astikit.Float64Ptr(6), SSAOutline: astikit.Float64Ptr(3), SSAOutlineColour: &astisub.Color{Red: 8}, SSAMarginLeft: astikit.IntPtr(3), SSAMarginRight: astikit.IntPtr(6), SSAMarginVertical: astikit.IntPtr(9), SSAPrimaryColour: &astisub.Color{Blue: 180, Green: 252, Red: 252}, SSASecondaryColour: &astisub.Color{Blue: 180, Green: 252, Red: 252}, SSAShadow: astikit.Float64Ptr(6)}}, *s.Styles["3"])
|
|
// Items
|
|
assertSSAStyleAttributes(t, astisub.StyleAttributes{SSAEffect: "test", SSAMarked: astikit.BoolPtr(false), SSAMarginLeft: astikit.IntPtr(1234), SSAMarginRight: astikit.IntPtr(2345), SSAMarginVertical: astikit.IntPtr(3456)}, *s.Items[0].InlineStyle)
|
|
assert.Equal(t, s.Styles["1"], s.Items[0].Style)
|
|
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{SSAEffect: "{\\pos(400,570)}"}, Text: "(deep rumbling)"}}, VoiceName: "Cher"}}, s.Items[0].Lines)
|
|
assert.Equal(t, s.Styles["2"], s.Items[1].Style)
|
|
assert.Equal(t, s.Styles["3"], s.Items[2].Style)
|
|
assert.Equal(t, s.Styles["1"], s.Items[3].Style)
|
|
assert.Equal(t, s.Styles["2"], s.Items[4].Style)
|
|
assert.Equal(t, s.Styles["3"], s.Items[5].Style)
|
|
|
|
// No subtitles to write
|
|
w := &bytes.Buffer{}
|
|
err = astisub.Subtitles{}.WriteToSSA(w)
|
|
assert.EqualError(t, err, astisub.ErrNoSubtitlesToWrite.Error())
|
|
|
|
// Write
|
|
c, err := ioutil.ReadFile("./testdata/example-out.ssa")
|
|
assert.NoError(t, err)
|
|
err = s.WriteToSSA(w)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, string(c), w.String())
|
|
}
|
|
|
|
func TestSSAv4plus(t *testing.T) {
|
|
// Open
|
|
s, err := astisub.OpenFile("./testdata/example-in.ssa")
|
|
assert.NoError(t, err)
|
|
assertSubtitleItems(t, s)
|
|
// Metadata
|
|
s.Metadata.SSAScriptType = "v4.00+"
|
|
|
|
// Write
|
|
w := &bytes.Buffer{}
|
|
err = s.WriteToSSA(w)
|
|
assert.NoError(t, err)
|
|
|
|
c, err := ioutil.ReadFile("./testdata/example-out-v4plus.ssa")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, string(c), w.String())
|
|
}
|
|
|
|
func TestWriteToSSANilMetadata(t *testing.T) {
|
|
// Metadata intentionally left nil
|
|
s := &astisub.Subtitles{
|
|
Items: []*astisub.Item{
|
|
{
|
|
StartAt: time.Second,
|
|
EndAt: 3 * time.Second,
|
|
Lines: []astisub.Line{{Items: []astisub.LineItem{{Text: "Hello world"}}}},
|
|
},
|
|
},
|
|
}
|
|
|
|
w := &bytes.Buffer{}
|
|
assert.NotPanics(t, func() {
|
|
s.WriteToSSA(w)
|
|
})
|
|
}
|
|
|
|
func TestInBetweenSSAEffect(t *testing.T) {
|
|
s, err := astisub.ReadFromSSA(bytes.NewReader([]byte(`[Events]
|
|
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
|
Dialogue: Marked=0,0:01:39.00,0:01:41.04,,Cher,1234,2345,3456,test,First item{\pos(400,570)}Second item`)))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, s.Items[0].Lines[0].Items, 2)
|
|
assert.Equal(t, astisub.LineItem{Text: "First item"}, s.Items[0].Lines[0].Items[0])
|
|
assert.Equal(t, astisub.LineItem{
|
|
InlineStyle: &astisub.StyleAttributes{SSAEffect: "{\\pos(400,570)}"},
|
|
Text: "Second item",
|
|
}, s.Items[0].Lines[0].Items[1])
|
|
}
|