8 Commits

Author SHA1 Message Date
Joel Wetzell 207a18d18e mess around with fuzzing 2026-05-23 07:43:15 -05:00
Joel Wetzell 2cb6487036 fix size check on timecode unmarshal 2026-05-23 07:42:48 -05:00
Joel Wetzell 4efa58ee25 Add LICENSE 2026-05-20 13:26:06 -05:00
Joel Wetzell baf2758f28 some byte slice cleanup 2026-05-14 20:21:11 -05:00
Joel Wetzell 744817ec17 just use marshal methods directly 2026-02-08 20:37:30 -06:00
Joel Wetzell f63b8886ce remove println 2026-01-31 16:05:29 -06:00
Joel Wetzell 4485ba3107 Merge pull request #1 from jwetzell/feat/timecode
add support for timecode packets
2026-01-31 15:55:57 -06:00
Joel Wetzell e75a4524bb add support for timecode packets 2026-01-31 15:54:36 -06:00
9 changed files with 342 additions and 52 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Joel Wetzell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+29 -3
View File
@@ -47,7 +47,7 @@ var (
OpDirectoryReply uint16 = 0x9b00
)
var ArtNetID []uint8 = []uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00}
var ArtNetID [8]uint8 = [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00}
func Decode(bytes []byte) (ArtNetPacket, error) {
if len(bytes) < 12 {
@@ -56,9 +56,35 @@ func Decode(bytes []byte) (ArtNetPacket, error) {
opCode := binary.LittleEndian.Uint16(bytes[8:10])
switch opCode {
case OpPoll:
return NewArtPoll(bytes)
artPoll := ArtPoll{}
err := artPoll.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artPoll, nil
case OpDmx:
return NewArtDmx(bytes)
artDmx := ArtDmx{}
err := artDmx.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artDmx, nil
case OpTimeCode:
artTimeCode := ArtTimeCode{}
err := artTimeCode.UnmarshalBinary(bytes)
if err != nil {
return nil, err
}
return &artTimeCode, nil
default:
return nil, fmt.Errorf("unhandled opcode: %#x", opCode)
}
+22 -24
View File
@@ -7,7 +7,7 @@ import (
)
type ArtDmx struct {
ID []uint8
ID [8]uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
@@ -15,22 +15,9 @@ type ArtDmx struct {
Physical uint8
SubUni uint8
Net uint8
Length uint16
Data []uint8
}
func NewArtDmx(data []byte) (*ArtDmx, error) {
artDmx := ArtDmx{}
err := artDmx.UnmarshalBinary(data)
if err != nil {
return nil, err
}
return &artDmx, nil
}
func (ad *ArtDmx) GetOpCode() uint16 {
return ad.OpCode
}
@@ -39,18 +26,22 @@ func (ad *ArtDmx) GetProtVer() uint16 {
return uint16(ad.ProtVerHi)<<8 + uint16(ad.ProtVerLo)
}
func (ad *ArtDmx) GetID() []uint8 {
func (ad *ArtDmx) GetID() [8]uint8 {
return ad.ID
}
func (ad *ArtDmx) Length() uint16 {
return uint16(len(ad.Data))
}
func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
if len(data) < 18 {
return errors.New("ArtDmx packet must be at least 18 bytes long")
}
ad.ID = data[0:8]
copy(ad.ID[:], data[0:8])
if !slices.Equal(ArtNetID, ad.ID) {
if !slices.Equal(ArtNetID[:], ad.ID[:]) {
return errors.New("ID does not match Art-Net ID")
}
@@ -65,23 +56,30 @@ func (ad *ArtDmx) UnmarshalBinary(data []byte) error {
ad.SubUni = data[offset+2]
ad.Net = data[offset+3]
ad.Length = uint16(data[offset+4])<<8 + uint16(data[offset+5])
length := int(data[offset+4])<<8 + int(data[offset+5])
dmxDataOffset := offset + 6
if len(data[dmxDataOffset:]) < int(ad.Length) {
if len(data[dmxDataOffset:]) < length {
return errors.New("ArtDmx packet length mismatch")
}
ad.Data = make([]uint8, ad.Length)
ad.Data = data[dmxDataOffset : dmxDataOffset+length]
copy(ad.Data, data[dmxDataOffset:dmxDataOffset+int(ad.Length)])
return nil
}
func (ad *ArtDmx) MarshalBinary() ([]byte, error) {
data := []byte(ArtNetID)
data = append(data, byte(ad.OpCode), byte(ad.OpCode>>8), ad.ProtVerHi, ad.ProtVerLo, ad.Sequence, ad.Physical, ad.SubUni, ad.Net, byte(ad.Length>>8), byte(ad.Length))
data = append(data, ad.Data...)
data := make([]byte, 8+10+ad.Length())
copy(data[0:8], ad.ID[:])
binary.LittleEndian.PutUint16(data[8:10], ad.OpCode)
data[10] = ad.ProtVerHi
data[11] = ad.ProtVerLo
data[12] = ad.Sequence
data[13] = ad.Physical
data[14] = ad.SubUni
data[15] = ad.Net
binary.BigEndian.PutUint16(data[16:18], ad.Length())
copy(data[18:], ad.Data)
return data, nil
}
+49 -6
View File
@@ -15,7 +15,7 @@ func TestGoodArtDmx(t *testing.T) {
{
Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Expected: &artnet.ArtDmx{
ID: []byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpDmx,
ProtVerHi: 0,
ProtVerLo: 14,
@@ -23,14 +23,15 @@ func TestGoodArtDmx(t *testing.T) {
Physical: 0,
SubUni: 1,
Net: 0,
Length: 512,
Data: make([]uint8, 512),
},
},
}
for _, test := range tests {
got, err := artnet.NewArtDmx(test.Data)
got := artnet.ArtDmx{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to decode ArtDmx: %s", err)
@@ -40,7 +41,7 @@ func TestGoodArtDmx(t *testing.T) {
t.Fatalf("ArtDmx OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode)
}
if !slices.Equal(got.ID, test.Expected.ID) {
if !slices.Equal(got.ID[:], test.Expected.ID[:]) {
t.Fatalf("ArtDmx ID does not match got: %+v expected: %+v", got.ID, test.Expected.ID)
}
@@ -68,8 +69,8 @@ func TestGoodArtDmx(t *testing.T) {
t.Fatalf("ArtDmx Net does not match got: %d expected: %d", got.Net, test.Expected.Net)
}
if got.Length != test.Expected.Length {
t.Fatalf("ArtDmx Length does not match got: %d expected: %d", got.Length, test.Expected.Length)
if got.Length() != test.Expected.Length() {
t.Fatalf("ArtDmx Length does not match got: %d expected: %d", got.Length(), test.Expected.Length())
}
if !slices.Equal(got.Data, test.Expected.Data) {
@@ -78,3 +79,45 @@ func TestGoodArtDmx(t *testing.T) {
}
}
func BenchmarkArtDmxUnmarshalBinary(b *testing.B) {
data := []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
for b.Loop() {
got := artnet.ArtDmx{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtDmx: %s", err)
}
}
}
func BenchmarkArtDmxMarshalBinary(b *testing.B) {
data := artnet.ArtDmx{
ID: [8]byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpDmx,
ProtVerHi: 0,
ProtVerLo: 14,
Sequence: 237,
Physical: 0,
SubUni: 1,
Net: 0,
Data: make([]uint8, 512),
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtDmx: %s", err)
}
}
}
func FuzzArtDmxUnmarshalBinary(f *testing.F) {
f.Add([]byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 237, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
f.Fuzz(func(t *testing.T, data []byte) {
artDmx := artnet.ArtDmx{}
artDmx.UnmarshalBinary(data)
})
}
+1 -1
View File
@@ -9,5 +9,5 @@ type ArtNetPacket interface {
encoding.BinaryMarshaler
GetOpCode() uint16
GetProtVer() uint16
GetID() []uint8
GetID() [8]uint8
}
+11 -18
View File
@@ -7,7 +7,7 @@ import (
)
type ArtPoll struct {
ID []uint8
ID [8]uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
@@ -23,18 +23,6 @@ type ArtPoll struct {
OemLo uint8
}
func NewArtPoll(data []byte) (*ArtPoll, error) {
artPoll := ArtPoll{}
err := artPoll.UnmarshalBinary(data)
if err != nil {
return nil, err
}
return &artPoll, nil
}
func (ap *ArtPoll) GetOpCode() uint16 {
return ap.OpCode
}
@@ -43,7 +31,7 @@ func (ap *ArtPoll) GetProtVer() uint16 {
return uint16(ap.ProtVerHi)<<8 + uint16(ap.ProtVerLo)
}
func (ap *ArtPoll) GetID() []uint8 {
func (ap *ArtPoll) GetID() [8]uint8 {
return ap.ID
}
@@ -53,9 +41,9 @@ func (ap *ArtPoll) UnmarshalBinary(data []byte) error {
return errors.New("ArtPoll packet must be at least 14 bytes long")
}
ap.ID = data[0:8]
copy(ap.ID[:], data[0:8])
if !slices.Equal(ArtNetID, ap.ID) {
if !slices.Equal(ArtNetID[:], ap.ID[:]) {
return errors.New("ID does not match Art-Net ID")
}
@@ -71,8 +59,13 @@ func (ap *ArtPoll) UnmarshalBinary(data []byte) error {
}
func (ap *ArtPoll) MarshalBinary() ([]byte, error) {
data := []byte(ArtNetID)
data = append(data, byte(ap.OpCode), byte(ap.OpCode>>8), ap.ProtVerHi, ap.ProtVerLo, ap.Flags, ap.DiagPriority)
data := make([]byte, 8+6)
copy(data[0:8], ap.ID[:])
binary.LittleEndian.PutUint16(data[8:10], ap.OpCode)
data[10] = ap.ProtVerHi
data[11] = ap.ProtVerLo
data[12] = ap.Flags
data[13] = ap.DiagPriority
//TODO(jwetzell): pack extended poll fields
return data, nil
}
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("Art-Net\x00000000")
+76
View File
@@ -0,0 +1,76 @@
package artnet
import (
"encoding/binary"
"errors"
"slices"
)
type ArtTimeCode struct {
ID [8]uint8
OpCode uint16
ProtVerHi uint8
ProtVerLo uint8
Filler1 uint8
StreamId uint8
Frames uint8
Seconds uint8
Minutes uint8
Hours uint8
Type uint8
}
func (atc *ArtTimeCode) GetOpCode() uint16 {
return atc.OpCode
}
func (atc *ArtTimeCode) GetProtVer() uint16 {
return uint16(atc.ProtVerHi)<<8 + uint16(atc.ProtVerLo)
}
func (atc *ArtTimeCode) GetID() [8]uint8 {
return atc.ID
}
func (atc *ArtTimeCode) UnmarshalBinary(data []byte) error {
if len(data) < 19 {
return errors.New("ArtTimeCode packet must be at least 14 bytes long")
}
copy(atc.ID[:], data[0:8])
if !slices.Equal(ArtNetID[:], atc.ID[:]) {
return errors.New("ID does not match Art-Net ID")
}
atc.OpCode = binary.LittleEndian.Uint16(data[8:10])
atc.ProtVerHi = data[10]
atc.ProtVerLo = data[11]
offset := 12
atc.Filler1 = data[offset]
atc.StreamId = data[offset+1]
atc.Frames = data[offset+2]
atc.Seconds = data[offset+3]
atc.Minutes = data[offset+4]
atc.Hours = data[offset+5]
atc.Type = data[offset+6]
return nil
}
func (atc *ArtTimeCode) MarshalBinary() ([]byte, error) {
data := make([]byte, 8+11)
copy(data[0:8], atc.ID[:])
binary.LittleEndian.PutUint16(data[8:10], atc.OpCode)
data[10] = atc.ProtVerHi
data[11] = atc.ProtVerLo
offset := 12
data[offset] = atc.Filler1
data[offset+1] = atc.StreamId
data[offset+2] = atc.Frames
data[offset+3] = atc.Seconds
data[offset+4] = atc.Minutes
data[offset+5] = atc.Hours
data[offset+6] = atc.Type
return data, nil
}
+131
View File
@@ -0,0 +1,131 @@
package artnet_test
import (
"slices"
"testing"
"github.com/jwetzell/artnet-go"
)
func TestGoodArtTimeCode(t *testing.T) {
tests := []struct {
Data []byte
Expected *artnet.ArtTimeCode
}{
{
Data: []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0},
Expected: &artnet.ArtTimeCode{
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpTimeCode,
ProtVerHi: 0,
ProtVerLo: 14,
Filler1: 0,
StreamId: 0,
Frames: 11,
Seconds: 17,
Minutes: 3,
Hours: 0,
Type: 0,
},
},
}
for _, test := range tests {
got := artnet.ArtTimeCode{}
err := got.UnmarshalBinary(test.Data)
if err != nil {
t.Fatalf("failed to decode ArtTimeCode: %s", err)
}
if got.OpCode != test.Expected.OpCode {
t.Fatalf("ArtTimeCode OpCode does not match got: %d expected: %d", got.OpCode, test.Expected.OpCode)
}
if !slices.Equal(got.ID[:], test.Expected.ID[:]) {
t.Fatalf("ArtTimeCode ID does not match got: %+v expected: %+v", got.ID, test.Expected.ID)
}
if got.Filler1 != test.Expected.Filler1 {
t.Fatalf("ArtTimeCode Filler1 does not match got: %d expected: %d", got.Filler1, test.Expected.Filler1)
}
if got.StreamId != test.Expected.StreamId {
t.Fatalf("ArtTimeCode StreamId does not match got: %d expected: %d", got.StreamId, test.Expected.StreamId)
}
if got.Frames != test.Expected.Frames {
t.Fatalf("ArtTimeCode Frames does not match got: %d expected: %d", got.Frames, test.Expected.Frames)
}
if got.Seconds != test.Expected.Seconds {
t.Fatalf("ArtTimeCode Seconds does not match got: %d expected: %d", got.Seconds, test.Expected.Seconds)
}
if got.Minutes != test.Expected.Minutes {
t.Fatalf("ArtTimeCode Minutes does not match got: %d expected: %d", got.Minutes, test.Expected.Minutes)
}
if got.Hours != test.Expected.Hours {
t.Fatalf("ArtTimeCode Hours does not match got: %d expected: %d", got.Hours, test.Expected.Hours)
}
if got.Type != test.Expected.Type {
t.Fatalf("ArtTimeCode Type does not match got: %d expected: %d", got.Type, test.Expected.Type)
}
if got.ProtVerHi != test.Expected.ProtVerHi {
t.Fatalf("ArtTimeCode ProtVerHi does not match got: %d expected: %d", got.ProtVerHi, test.Expected.ProtVerHi)
}
if got.ProtVerLo != test.Expected.ProtVerLo {
t.Fatalf("ArtTimeCode ProtVerLo does not match got: %d expected: %d", got.ProtVerLo, test.Expected.ProtVerLo)
}
}
}
func BenchmarkArtTimeCodeUnmarshalBinary(b *testing.B) {
data := []byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0}
for b.Loop() {
got := artnet.ArtTimeCode{}
err := got.UnmarshalBinary(data)
if err != nil {
b.Fatalf("failed to decode ArtTimeCode: %s", err)
}
}
}
func BenchmarkArtTimeCodeMarshalBinary(b *testing.B) {
data := artnet.ArtTimeCode{
ID: [8]uint8{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
OpCode: artnet.OpTimeCode,
ProtVerHi: 0,
ProtVerLo: 14,
Filler1: 0,
StreamId: 0,
Frames: 11,
Seconds: 17,
Minutes: 3,
Hours: 0,
Type: 0,
}
for b.Loop() {
_, err := data.MarshalBinary()
if err != nil {
b.Fatalf("failed to encode ArtTimeCode: %s", err)
}
}
}
func FuzzArtTimeCodeUnmarshalBinary(f *testing.F) {
f.Add([]byte{65, 114, 116, 45, 78, 101, 116, 0, 0, 151, 0, 14, 0, 0, 11, 17, 3, 0, 0})
f.Fuzz(func(t *testing.T, data []byte) {
artTimeCode := artnet.ArtTimeCode{}
artTimeCode.UnmarshalBinary(data)
})
}