/* NAME descriptor_test.go DESCRIPTION See Readme.md AUTHOR Saxon Nelson-Milton LICENSE descriptor_test.go is Copyright (C) 2017-2019 the Australian Ocean Lab (AusOcean) It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with revid in gpl.txt. If not, see http://www.gnu.org/licenses. */ package psi import ( "bytes" "testing" ) const ( errNotExpectedOut = "Did not get expected output: \ngot : %v, \nwant: %v" errUnexpectedErr = "Unexpected error: %v\n" ) var ( tstPsi1 = PSI{ PointerField: 0x00, TableID: 0x02, SyntaxIndicator: true, SectionLen: 0x1c, SyntaxSection: &SyntaxSection{ TableIDExt: 0x01, Version: 0, CurrentNext: true, Section: 0, LastSection: 0, SpecificData: &PMT{ ProgramClockPID: 0x0100, // wrong ProgramInfoLen: 10, Descriptors: []Descriptor{ { Tag: TimeDescTag, Len: TimeDataSize, Data: make([]byte, TimeDataSize), }, }, StreamSpecificData: &StreamSpecificData{ StreamType: 0x1b, PID: 0x0100, StreamInfoLen: 0x00, }, }, }, } tstPsi2 = PSI{ PointerField: 0x00, TableID: 0x02, SyntaxIndicator: true, SectionLen: 0x12, SyntaxSection: &SyntaxSection{ TableIDExt: 0x01, Version: 0, CurrentNext: true, Section: 0, LastSection: 0, SpecificData: &PMT{ ProgramClockPID: 0x0100, ProgramInfoLen: 0, StreamSpecificData: &StreamSpecificData{ StreamType: 0x1b, PID: 0x0100, StreamInfoLen: 0x00, }, }, }, } tstPsi3 = PSI{ PointerField: 0x00, TableID: 0x02, SyntaxIndicator: true, SectionLen: 0x3e, SyntaxSection: &SyntaxSection{ TableIDExt: 0x01, Version: 0, CurrentNext: true, Section: 0, LastSection: 0, SpecificData: &PMT{ ProgramClockPID: 0x0100, ProgramInfoLen: PmtTimeLocationPil, Descriptors: []Descriptor{ { Tag: TimeDescTag, Len: TimeDataSize, Data: make([]byte, TimeDataSize), }, { Tag: LocationDescTag, Len: LocationDataSize, Data: make([]byte, LocationDataSize), }, }, StreamSpecificData: &StreamSpecificData{ StreamType: 0x1b, PID: 0x0100, StreamInfoLen: 0x00, }, }, }, } ) var ( pmtTimeBytesResizedBigger = []byte{ 0x00, 0x02, 0xb0, 0x1e, 0x00, 0x01, 0xc1, 0x00, 0x00, 0xe1, 0x00, 0xf0, 0x0c, TimeDescTag, // Descriptor tag 0x0a, // Length of bytes to follow 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, // timestamp 0x1b, 0xe1, 0x00, 0xf0, 0x00, } pmtTimeBytesResizedSmaller = []byte{ 0x00, 0x02, 0xb0, 0x1a, 0x00, 0x01, 0xc1, 0x00, 0x00, 0xe1, 0x00, 0xf0, 0x08, TimeDescTag, // Descriptor tag 0x06, // Length of bytes to follow 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // timestamp 0x1b, 0xe1, 0x00, 0xf0, 0x00, } ) // TestHasDescriptorExists checks that PSIBytes.HasDescriptor performs as expected // when the PSI we're interested in has the descriptor of interest. HasDescriptor // should return the descriptor bytes. // TODO: HasDescriptor also returns index of descriptor - we should check this. func TestHasDescriptorExists(t *testing.T) { p := PSIBytes(tstPsi3.Bytes()) _, got := p.HasDescriptor(LocationDescTag) want := []byte{ LocationDescTag, LocationDataSize, } want = append(want, make([]byte, LocationDataSize)...) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestHasDescriptorAbsent checks that PSIBytes.HasDescriptor performs as expected // when the PSI does not have the descriptor of interest. HasDescriptor should // return a nil slice and a negative index. // TODO: check index here as well. func TestHasDescriptorAbsent(t *testing.T) { p := PSIBytes(tstPsi3.Bytes()) const fakeTag = 236 _, got := p.HasDescriptor(fakeTag) var want []byte if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestHasDescriptorNone checks that PSIBytes.HasDescriptor behaves as expected // when the PSI does not have any descriptors. HasDescriptor should return a nil // slice. // TODO: again check index here. func TestHasDescriptorNone(t *testing.T) { p := PSIBytes(tstPsi2.Bytes()) _, got := p.HasDescriptor(LocationDescTag) var want []byte if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestProgramInfoLen checks that PSIBytes.ProgramInfoLen correctly extracts // the program info length from a PSI. func TestProgramInfoLen(t *testing.T) { p := PSIBytes(tstPsi1.Bytes()) got := p.ProgramInfoLen() want := 10 if got != want { t.Errorf(errNotExpectedOut, got, want) } } // TestDescriptors checks that PSIBytes.descriptors correctly returns the descriptors // from a PSI when descriptors exist. func TestDescriptors(t *testing.T) { p := PSIBytes(tstPsi1.Bytes()) got := p.descriptors() want := []byte{ TimeDescTag, TimeDataSize, } want = append(want, make([]byte, TimeDataSize)...) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestDescriptors checks that PSIBYtes.desriptors correctly returns nil when // we try to get descriptors from a psi without any descriptors. func TestDescriptorsNone(t *testing.T) { p := PSIBytes(tstPsi2.Bytes()) got := p.descriptors() var want []byte if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestCreateDescriptorEmpty checks that PSIBytes.createDescriptor correctly adds // a descriptor to the descriptors list in a PSI when it has no descriptors already. func TestCreateDescriptorEmpty(t *testing.T) { got := PSIBytes(tstPsi2.Bytes()) got.createDescriptor(TimeDescTag, make([]byte, TimeDataSize)) UpdateCrc(got[1:]) want := PSIBytes(tstPsi1.Bytes()) if !bytes.Equal(want, got) { t.Errorf(errNotExpectedOut, got, want) } } // TestCreateDescriptorNotEmpty checks that PSIBytes.createDescriptor correctly adds // a descriptor to the descriptors list in a PSI when it already has one with // a different tag. func TestCreateDescriptorNotEmpty(t *testing.T) { got := PSIBytes(tstPsi1.Bytes()) got.createDescriptor(LocationDescTag, make([]byte, LocationDataSize)) UpdateCrc(got[1:]) want := PSIBytes(tstPsi3.Bytes()) if !bytes.Equal(want, got) { t.Errorf(errNotExpectedOut, got, want) } } // TestAddDescriptorEmpty checks that PSIBytes.AddDescriptor correctly adds a descriptor // when there are no other descriptors present in the PSI. func TestAddDescriptorEmpty(t *testing.T) { got := PSIBytes(tstPsi2.Bytes()) if err := got.AddDescriptor(TimeDescTag, make([]byte, TimeDataSize)); err != nil { t.Errorf(errUnexpectedErr, err.Error()) } want := PSIBytes(tstPsi1.Bytes()) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestAddDescriptorNonEmpty checks that PSIBytes.AddDescriptor correctly adds a // descriptor when there is already a descriptor of a differing type in a PSI. func TestAddDescriptorNonEmpty(t *testing.T) { got := PSIBytes(tstPsi1.Bytes()) if err := got.AddDescriptor(LocationDescTag, make([]byte, LocationDataSize)); err != nil { t.Errorf(errUnexpectedErr, err.Error()) } want := PSIBytes(tstPsi3.Bytes()) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestAddDescriptorUpdateSame checks that PSIBytes.AddDescriptor correctly updates data in a descriptor // with the same given tag, with data being the same size. AddDescriptor should just copy new data into // the descriptors data field. func TestAddDescriptorUpdateSame(t *testing.T) { newData := [8]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08} want := PSIBytes(tstPsi2.Bytes()) want.createDescriptor(TimeDescTag, newData[:]) got := PSIBytes(tstPsi1.Bytes()) if err := got.AddDescriptor(TimeDescTag, newData[:]); err != nil { t.Errorf(errUnexpectedErr, err.Error()) } if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestAddDescriptorUpdateBigger checks that PSIBytes.AddDescriptor correctly resizes descriptor with same given tag // to a bigger size and copies in new data. AddDescriptor should find descriptor with same tag, increase size of psi, // shift data to make room for update descriptor, and then copy in the new data. func TestAddDescriptorUpdateBigger(t *testing.T) { got := PSIBytes(tstPsi1.Bytes()) if err := got.AddDescriptor(TimeDescTag, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a}); err != nil { t.Errorf(errUnexpectedErr, err.Error()) } want := AddCRC(pmtTimeBytesResizedBigger) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } } // TestAddDescriptorUpdateSmaller checks that PSIBytes.AddDescriptor correctly resizes descriptor with same given tag // in a psi to a smaller size and copies in new data. AddDescriptor should find tag with same descrtiptor, shift data // after descriptor upwards, trim the psi to new size, and then copy in new data. func TestAddDescriptorUpdateSmaller(t *testing.T) { got := PSIBytes(tstPsi1.Bytes()) if err := got.AddDescriptor(TimeDescTag, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}); err != nil { t.Errorf(errUnexpectedErr, err.Error()) } want := AddCRC(pmtTimeBytesResizedSmaller) if !bytes.Equal(got, want) { t.Errorf(errNotExpectedOut, got, want) } }