gobot.io/x/gobot/v2@v2.1.0/platforms/dji/tello/driver_test.go (about)

     1  package tello
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"gobot.io/x/gobot/v2"
    13  	"gobot.io/x/gobot/v2/gobottest"
    14  )
    15  
    16  var _ gobot.Driver = (*Driver)(nil)
    17  
    18  type WriteCloserDoNothing struct{}
    19  
    20  func (w *WriteCloserDoNothing) Write(p []byte) (n int, err error) {
    21  	return 0, nil
    22  }
    23  func (w *WriteCloserDoNothing) Close() error {
    24  	return nil
    25  }
    26  
    27  func TestTelloDriver(t *testing.T) {
    28  	d := NewDriver("8888")
    29  
    30  	gobottest.Assert(t, d.respPort, "8888")
    31  }
    32  
    33  func statusMessage(msgType uint16, msgAfter7 ...byte) []byte {
    34  	msg := make([]byte, 7, len(msgAfter7)+7)
    35  	msg[0] = messageStart
    36  	binary.LittleEndian.PutUint16(msg[5:7], msgType)
    37  	msg = append(msg, msgAfter7...)
    38  	return msg
    39  }
    40  
    41  func TestHandleResponse(t *testing.T) {
    42  	cc := []struct {
    43  		name   string
    44  		msg    io.Reader
    45  		events []gobot.Event
    46  		err    error
    47  	}{
    48  		{
    49  			name: "[empty messsage]",
    50  			msg:  bytes.NewReader(nil),
    51  			err:  io.EOF,
    52  		},
    53  		{
    54  			name:   "wifiMessage",
    55  			msg:    bytes.NewReader(statusMessage(wifiMessage)),
    56  			events: []gobot.Event{{Name: WifiDataEvent}},
    57  		},
    58  		{
    59  			name:   "lightMessage",
    60  			msg:    bytes.NewReader(statusMessage(lightMessage)),
    61  			events: []gobot.Event{{Name: LightStrengthEvent}},
    62  		},
    63  		{
    64  			name:   "logMessage",
    65  			msg:    bytes.NewReader(statusMessage(logMessage)),
    66  			events: []gobot.Event{{Name: LogEvent}},
    67  		},
    68  		{
    69  			name:   "timeCommand",
    70  			msg:    bytes.NewReader(statusMessage(timeCommand)),
    71  			events: []gobot.Event{{Name: TimeEvent}},
    72  		},
    73  		{
    74  			name:   "bounceCommand",
    75  			msg:    bytes.NewReader(statusMessage(bounceCommand)),
    76  			events: []gobot.Event{{Name: BounceEvent}},
    77  		},
    78  		{
    79  			name:   "takeoffCommand",
    80  			msg:    bytes.NewReader(statusMessage(takeoffCommand)),
    81  			events: []gobot.Event{{Name: TakeoffEvent}},
    82  		},
    83  		{
    84  			name:   "landCommand",
    85  			msg:    bytes.NewReader(statusMessage(landCommand)),
    86  			events: []gobot.Event{{Name: LandingEvent}},
    87  		},
    88  		{
    89  			name:   "palmLandCommand",
    90  			msg:    bytes.NewReader(statusMessage(palmLandCommand)),
    91  			events: []gobot.Event{{Name: PalmLandingEvent}},
    92  		},
    93  		{
    94  			name:   "flipCommand",
    95  			msg:    bytes.NewReader(statusMessage(flipCommand)),
    96  			events: []gobot.Event{{Name: FlipEvent}},
    97  		},
    98  		{
    99  			name:   "flightMessage",
   100  			msg:    bytes.NewReader(statusMessage(flightMessage)),
   101  			events: []gobot.Event{{Name: FlightDataEvent}},
   102  		},
   103  		{
   104  			name:   "exposureCommand",
   105  			msg:    bytes.NewReader(statusMessage(exposureCommand)),
   106  			events: []gobot.Event{{Name: SetExposureEvent}},
   107  		},
   108  		{
   109  			name:   "videoEncoderRateCommand",
   110  			msg:    bytes.NewReader(statusMessage(videoEncoderRateCommand)),
   111  			events: []gobot.Event{{Name: SetVideoEncoderRateEvent}},
   112  		},
   113  		{
   114  			name:   "ConnectedEvent",
   115  			msg:    bytes.NewReader([]byte{0x63, 0x6f, 0x6e}),
   116  			events: []gobot.Event{{Name: ConnectedEvent}},
   117  		},
   118  	}
   119  
   120  	for _, c := range cc {
   121  		t.Run(c.name, func(t *testing.T) {
   122  			d := NewDriver("8888")
   123  			events := d.Subscribe()
   124  			err := d.handleResponse(c.msg)
   125  			if c.err != err {
   126  				t.Errorf("expected '%v' error, got: %v", c.err, err)
   127  			}
   128  			for i, cev := range c.events {
   129  				t.Run(fmt.Sprintf("event %d", i), func(t *testing.T) {
   130  					t.Logf("expect: %#v", cev)
   131  					select {
   132  					case ev, ok := <-events:
   133  						if !ok {
   134  							t.Error("subscription channel is closed")
   135  						}
   136  						if ev.Name != cev.Name {
   137  							t.Errorf("got: %s", ev.Name)
   138  						}
   139  					case <-time.After(time.Millisecond):
   140  						t.Error("subscription channel seems empty")
   141  					}
   142  				})
   143  			}
   144  		})
   145  	}
   146  }
   147  
   148  func TestHaltShouldTerminateAllTheRelatedGoroutines(t *testing.T) {
   149  	d := NewDriver("8888")
   150  	d.cmdConn = &WriteCloserDoNothing{}
   151  
   152  	var wg sync.WaitGroup
   153  	wg.Add(3)
   154  
   155  	d.addDoneChReaderCount(1)
   156  	go func() {
   157  		<-d.doneCh
   158  		d.addDoneChReaderCount(-1)
   159  		wg.Done()
   160  		fmt.Println("Done routine 1.")
   161  	}()
   162  
   163  	d.addDoneChReaderCount(1)
   164  	go func() {
   165  		<-d.doneCh
   166  		d.addDoneChReaderCount(-1)
   167  		wg.Done()
   168  		fmt.Println("Done routine 2.")
   169  	}()
   170  
   171  	d.addDoneChReaderCount(1)
   172  	go func() {
   173  		<-d.doneCh
   174  		d.addDoneChReaderCount(-1)
   175  		wg.Done()
   176  		fmt.Println("Done routine 3.")
   177  	}()
   178  
   179  	d.Halt()
   180  	wg.Wait()
   181  
   182  	gobottest.Assert(t, d.doneChReaderCount, int32(0))
   183  }
   184  
   185  func TestHaltNotWaitForeverWhenCalledMultipleTimes(t *testing.T) {
   186  	d := NewDriver("8888")
   187  	d.cmdConn = &WriteCloserDoNothing{}
   188  
   189  	d.Halt()
   190  	d.Halt()
   191  	d.Halt()
   192  }