github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/pkg/socketcan/transmitter_test.go (about) 1 package socketcan 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "net" 9 "testing" 10 "time" 11 12 "github.com/blueinnovationsgroup/can-go" 13 "golang.org/x/sync/errgroup" 14 "gotest.tools/v3/assert" 15 ) 16 17 func TestTransmitter_TransmitMessage(t *testing.T) { 18 testTransmit := func(opt TransmitterOption) { 19 w, r := net.Pipe() 20 f := can.Frame{ 21 ID: 0x12, 22 Length: 8, 23 Data: can.Data{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, 24 } 25 msg := &testMessage{frame: f} 26 expected := []byte{ 27 // id---------------> | dlc | padding-------> | data----------------------------------------> | 28 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 29 } 30 // write 31 var g errgroup.Group 32 g.Go(func() error { 33 tr := NewTransmitter(w, opt) 34 ctx, done := context.WithTimeout(context.Background(), time.Second) 35 defer done() 36 if err := tr.TransmitMessage(ctx, msg); err != nil { 37 return err 38 } 39 return w.Close() 40 }) 41 // read 42 actual := make([]byte, len(expected)) 43 _, err := io.ReadFull(r, actual) 44 assert.NilError(t, err) 45 assert.NilError(t, r.Close()) 46 // assert 47 assert.DeepEqual(t, expected, actual) 48 assert.NilError(t, g.Wait()) 49 } 50 51 // No opts 52 testTransmit(func(*transmitterOpts) {}) 53 54 // Frame Interceptor 55 run := false 56 intFunc := func(fr can.Frame) { 57 run = true 58 } 59 testTransmit(TransmitterFrameInterceptor(intFunc)) 60 assert.Assert(t, run) 61 } 62 63 func TestTransmitter_TransmitMessage_Error(t *testing.T) { 64 cause := fmt.Errorf("boom") 65 msg := &testMessage{err: cause} 66 tr := NewTransmitter(nil) 67 ctx, done := context.WithTimeout(context.Background(), time.Second) 68 defer done() 69 err := tr.TransmitMessage(ctx, msg) 70 assert.Error(t, err, "transmit message: boom") 71 assert.Equal(t, cause, errors.Unwrap(err)) 72 } 73 74 func TestTransmitter_TransmitFrame_Error(t *testing.T) { 75 t.Run("set deadline", func(t *testing.T) { 76 cause := fmt.Errorf("boom") 77 w := &errCon{deadlineErr: cause} 78 tr := NewTransmitter(w) 79 ctx, done := context.WithTimeout(context.Background(), time.Second) 80 defer done() 81 err := tr.TransmitFrame(ctx, can.Frame{}) 82 assert.ErrorContains(t, err, "boom") 83 assert.Equal(t, cause, errors.Unwrap(err)) 84 }) 85 t.Run("write", func(t *testing.T) { 86 cause := fmt.Errorf("boom") 87 w := &errCon{writeErr: cause} 88 tr := NewTransmitter(w) 89 ctx, done := context.WithTimeout(context.Background(), time.Second) 90 defer done() 91 err := tr.TransmitFrame(ctx, can.Frame{}) 92 assert.ErrorContains(t, err, "boom") 93 assert.Equal(t, cause, errors.Unwrap(err)) 94 }) 95 } 96 97 type testMessage struct { 98 frame can.Frame 99 err error 100 } 101 102 func (t *testMessage) MarshalFrame() (can.Frame, error) { 103 return t.frame, t.err 104 } 105 106 func (t *testMessage) UnmarshalFrame(can.Frame) error { 107 panic("should not be called") 108 } 109 110 type errCon struct { 111 deadlineErr error 112 writeErr error 113 } 114 115 func (e *errCon) Write(b []byte) (n int, err error) { 116 return 0, e.writeErr 117 } 118 119 func (e *errCon) SetWriteDeadline(t time.Time) error { 120 return e.deadlineErr 121 } 122 123 func (e *errCon) Read(b []byte) (n int, err error) { 124 panic("should not be called") 125 } 126 127 func (e *errCon) Close() error { 128 panic("should not be called") 129 } 130 131 func (e *errCon) LocalAddr() net.Addr { 132 panic("should not be called") 133 } 134 135 func (e *errCon) RemoteAddr() net.Addr { 136 panic("should not be called") 137 } 138 139 func (e *errCon) SetDeadline(t time.Time) error { 140 panic("should not be called") 141 } 142 143 func (e *errCon) SetReadDeadline(t time.Time) error { 144 panic("should not be called") 145 }