package aep import ( "bytes" "encoding/binary" "testing" ) // chunk builds a RIFX chunk: 4-byte id + BE32 size + data (+ pad to even). func chunk(id string, data []byte) []byte { b := new(bytes.Buffer) b.WriteString(id) _ = binary.Write(b, binary.BigEndian, uint32(len(data))) b.Write(data) if len(data)%2 == 1 { b.WriteByte(0) } return b.Bytes() } // list builds a LIST chunk of the given form type wrapping the body chunks. func list(formType string, body []byte) []byte { return chunk("LIST", append([]byte(formType), body...)) } func cdtaWithDuration(durFrames, scale uint32) []byte { b := make([]byte, 0x28) binary.BigEndian.PutUint32(b[0x20:0x24], durFrames) binary.BigEndian.PutUint32(b[0x24:0x28], scale) return b } func TestParseComps(t *testing.T) { // One composition (has cdta), one footage item (no cdta), inside a folder. comp := list("Item", bytes.Join([][]byte{ chunk("cdta", cdtaWithDuration(150, 30)), // 150 frames @ 30 → 5.0s chunk("Utf8", []byte("scene_intro")), }, nil)) footage := list("Item", bytes.Join([][]byte{ chunk("Utf8", []byte("clip.mp4")), chunk("sspc", make([]byte, 8)), }, nil)) folder := list("Item", bytes.Join([][]byte{ chunk("Utf8", []byte("My Folder")), comp, footage, }, nil)) body := bytes.Join([][]byte{folder}, nil) // RIFX header: "RIFX" + size + "Egg!" + body file := new(bytes.Buffer) file.WriteString("RIFX") _ = binary.Write(file, binary.BigEndian, uint32(len(body)+4)) file.WriteString("Egg!") file.Write(body) comps, err := ParseComps(file.Bytes()) if err != nil { t.Fatalf("ParseComps: %v", err) } if len(comps) != 1 { t.Fatalf("expected 1 comp, got %d: %+v", len(comps), comps) } if comps[0].Name != "scene_intro" { t.Errorf("name = %q, want scene_intro", comps[0].Name) } if comps[0].DurationSec != 5.0 { t.Errorf("duration = %v, want 5.0", comps[0].DurationSec) } } func TestParseCompsRejectsNonRifx(t *testing.T) { if _, err := ParseComps([]byte("not an aep file at all")); err == nil { t.Error("expected error for non-RIFX input") } }