github.com/jordan-bonecutter/can-go@v0.0.0-20230901155856-d83995b18e50/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  	"go.einride.tech/can"
    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([]byte) (n int, err error) {
   116  	return 0, e.writeErr
   117  }
   118  
   119  func (e *errCon) SetWriteDeadline(time.Time) error {
   120  	return e.deadlineErr
   121  }
   122  
   123  func (e *errCon) Read([]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(time.Time) error {
   140  	panic("should not be called")
   141  }
   142  
   143  func (e *errCon) SetReadDeadline(time.Time) error {
   144  	panic("should not be called")
   145  }