github.com/bluenviron/gomavlib/v2@v2.2.1-0.20240308101627-2c07e3da629c/endpoint_custom_test.go (about)

     1  package gomavlib
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/bluenviron/gomavlib/v2/pkg/dialect"
    11  	"github.com/bluenviron/gomavlib/v2/pkg/frame"
    12  )
    13  
    14  var _ endpointChannelSingle = (*endpointCustom)(nil)
    15  
    16  type dummyReadWriter struct {
    17  	chOut     chan []byte
    18  	chIn      chan []byte
    19  	chReadErr chan struct{}
    20  }
    21  
    22  func newDummyReadWriterPair() (*dummyReadWriter, *dummyReadWriter) {
    23  	one := &dummyReadWriter{
    24  		chOut:     make(chan []byte),
    25  		chIn:      make(chan []byte),
    26  		chReadErr: make(chan struct{}),
    27  	}
    28  
    29  	two := &dummyReadWriter{
    30  		chOut:     one.chIn,
    31  		chIn:      one.chOut,
    32  		chReadErr: make(chan struct{}),
    33  	}
    34  
    35  	return one, two
    36  }
    37  
    38  func (e *dummyReadWriter) simulateReadError() {
    39  	close(e.chReadErr)
    40  }
    41  
    42  func (e *dummyReadWriter) Close() error {
    43  	close(e.chOut)
    44  	close(e.chIn)
    45  	return nil
    46  }
    47  
    48  func (e *dummyReadWriter) Read(p []byte) (int, error) {
    49  	select {
    50  	case buf, ok := <-e.chOut:
    51  		if !ok {
    52  			return 0, io.EOF
    53  		}
    54  		return copy(p, buf), nil
    55  	case <-e.chReadErr:
    56  		return 0, errors.New("custom error")
    57  	}
    58  }
    59  
    60  func (e *dummyReadWriter) Write(p []byte) (int, error) {
    61  	e.chIn <- p
    62  	return len(p), nil
    63  }
    64  
    65  func TestEndpointCustom(t *testing.T) {
    66  	remote, local := newDummyReadWriterPair()
    67  
    68  	node, err := NewNode(NodeConf{
    69  		Dialect:          testDialect,
    70  		OutVersion:       V2,
    71  		OutSystemID:      10,
    72  		Endpoints:        []EndpointConf{EndpointCustom{remote}},
    73  		HeartbeatDisable: true,
    74  	})
    75  	require.NoError(t, err)
    76  	defer node.Close()
    77  
    78  	evt := <-node.Events()
    79  	require.Equal(t, &EventChannelOpen{
    80  		Channel: evt.(*EventChannelOpen).Channel,
    81  	}, evt)
    82  
    83  	dialectRW, err := dialect.NewReadWriter(testDialect)
    84  	require.NoError(t, err)
    85  
    86  	rw, err := frame.NewReadWriter(frame.ReadWriterConf{
    87  		ReadWriter:  local,
    88  		DialectRW:   dialectRW,
    89  		OutVersion:  frame.V2,
    90  		OutSystemID: 11,
    91  	})
    92  	require.NoError(t, err)
    93  
    94  	for i := 0; i < 3; i++ { //nolint:dupl
    95  		msg := &MessageHeartbeat{
    96  			Type:           1,
    97  			Autopilot:      2,
    98  			BaseMode:       3,
    99  			CustomMode:     6,
   100  			SystemStatus:   4,
   101  			MavlinkVersion: 5,
   102  		}
   103  		err = rw.WriteMessage(msg)
   104  		require.NoError(t, err)
   105  
   106  		evt = <-node.Events()
   107  		require.Equal(t, &EventFrame{
   108  			Frame: &frame.V2Frame{
   109  				SequenceID:  byte(i),
   110  				SystemID:    11,
   111  				ComponentID: 1,
   112  				Message:     msg,
   113  				Checksum:    evt.(*EventFrame).Frame.GetChecksum(),
   114  			},
   115  			Channel: evt.(*EventFrame).Channel,
   116  		}, evt)
   117  
   118  		msg = &MessageHeartbeat{
   119  			Type:           6,
   120  			Autopilot:      5,
   121  			BaseMode:       4,
   122  			CustomMode:     3,
   123  			SystemStatus:   2,
   124  			MavlinkVersion: 1,
   125  		}
   126  		err := node.WriteMessageAll(msg)
   127  		require.NoError(t, err)
   128  
   129  		fr, err := rw.Read()
   130  		require.NoError(t, err)
   131  		require.Equal(t, &frame.V2Frame{
   132  			SequenceID:  byte(i),
   133  			SystemID:    10,
   134  			ComponentID: 1,
   135  			Message:     msg,
   136  			Checksum:    fr.GetChecksum(),
   137  		}, fr)
   138  	}
   139  }