github.com/simpleiot/simpleiot@v0.18.3/respreader/response-reader_test.go (about)

     1  package respreader
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  )
    12  
    13  // the below test shows using a fifo with respreader
    14  func TestWithFifo(t *testing.T) {
    15  	fifo := "rrfifoo"
    16  	os.Remove(fifo)
    17  	err := exec.Command("mkfifo", fifo).Run()
    18  	if err != nil {
    19  		t.Error("mkfifo returned: ", err)
    20  	}
    21  
    22  	testString := "hi there"
    23  	done := make(chan struct{})
    24  
    25  	// need to open RDWR or open will block until fifo is opened for writing
    26  	fread, err := os.OpenFile(fifo, os.O_RDWR, 0600)
    27  	if err != nil {
    28  		t.Fatal("Error opening fifo: ", err)
    29  	}
    30  	reader := NewReadWriteCloser(fread, 2*time.Second, 50*time.Millisecond)
    31  
    32  	// read function
    33  	go func() {
    34  		for {
    35  			rdata := make([]byte, 128)
    36  			c, err := reader.Read(rdata)
    37  			if err == io.EOF {
    38  				fmt.Println("Reader returned EOF, exiting read routine")
    39  				break
    40  			}
    41  			if err != nil {
    42  				t.Error("Read error: ", err)
    43  			}
    44  			if c > 0 {
    45  				rdata = rdata[:c]
    46  				if string(rdata) == testString {
    47  					close(done)
    48  					break
    49  				}
    50  			}
    51  		}
    52  	}()
    53  
    54  	fwrite, err := os.OpenFile(fifo, os.O_WRONLY, 0644)
    55  	if err != nil {
    56  		t.Fatal("Error opening file for writing: ", err)
    57  	}
    58  
    59  	_, err = fwrite.Write([]byte(testString))
    60  
    61  	if err != nil {
    62  		t.Error("Write error: ", err)
    63  	}
    64  
    65  	select {
    66  	case <-time.After(time.Second):
    67  		t.Error("Timeout waiting for read to complete")
    68  	case <-done:
    69  		// all is well
    70  	}
    71  
    72  	fwrite.Close()
    73  	fread.Close()
    74  
    75  	err = os.Remove(fifo)
    76  	if err != nil {
    77  		t.Error("Error removing fifo")
    78  	}
    79  }
    80  
    81  // the below test illustrates out the goroutine in the reader will close if you close
    82  // the underlying file descriptor.
    83  func TestReadCloser(t *testing.T) {
    84  	fifo := "rrfifoo"
    85  	os.Remove(fifo)
    86  	err := exec.Command("mkfifo", fifo).Run()
    87  	if err != nil {
    88  		t.Error("mkfifo returned: ", err)
    89  	}
    90  
    91  	done := make(chan struct{})
    92  
    93  	// need to open RDWR or open will block until fifo is opened for writing
    94  	fread, err := os.OpenFile(fifo, os.O_RDWR, 0600)
    95  	if err != nil {
    96  		t.Fatal("Error opening fifo: ", err)
    97  	}
    98  	reader := NewReadWriteCloser(fread, 50*time.Millisecond, 20*time.Millisecond)
    99  
   100  	// read function
   101  	go func() {
   102  		for {
   103  			rdata := make([]byte, 128)
   104  			_, err := reader.Read(rdata)
   105  			if err == io.EOF {
   106  				close(done)
   107  				break
   108  			}
   109  			if err != nil {
   110  				t.Error("Read error: ", err)
   111  			}
   112  		}
   113  	}()
   114  
   115  	fread.Close()
   116  
   117  	select {
   118  	case <-time.After(time.Second):
   119  		t.Error("Timeout waiting for read to complete")
   120  	case <-done:
   121  		// all is well
   122  	}
   123  }
   124  
   125  /* the following test is for documentation only
   126  
   127  // the below test illustrates out the goroutine in the reader will close if you close
   128  // the underlying serial port descriptor.
   129  func TestResponseReaderSerialPortClose(t *testing.T) {
   130  	fmt.Println("=============================")
   131  	fmt.Println("Testing serial port close")
   132  	readCnt := make(chan int)
   133  
   134  	serialPort := "/dev/ttyUSB1"
   135  
   136  	options := serial.OpenOptions{
   137  		PortName:              serialPort,
   138  		BaudRate:              115200,
   139  		DataBits:              8,
   140  		StopBits:              1,
   141  		MinimumReadSize:       0,
   142  		InterCharacterTimeout: 100,
   143  	}
   144  
   145  	go func(readCnt chan int) {
   146  		fread, err := serial.Open(options)
   147  		if err != nil {
   148  			t.Error("Error opening serial port: ", err)
   149  		}
   150  
   151  		reader := NewReadWriteCloser(fread, 2*time.Second, 50*time.Millisecond)
   152  
   153  		fmt.Println("reader created")
   154  
   155  		fmt.Println("read thread")
   156  		closed := false
   157  		cnt := 0
   158  		for {
   159  			rdata := make([]byte, 128)
   160  			fmt.Println("calling read")
   161  			c, err := reader.Read(rdata)
   162  			if err == io.EOF {
   163  				fmt.Println("Reader returned EOF, exiting read routine")
   164  				break
   165  			}
   166  			if err != nil {
   167  				//t.Error("Read error: ", err)
   168  				fmt.Println("Read error: ", err)
   169  			}
   170  			cnt = c
   171  			fmt.Println("read count: ", c)
   172  			if !closed && c > 0 {
   173  				go func() {
   174  					time.Sleep(20 * time.Millisecond)
   175  					fmt.Println("closing read file")
   176  					reader.Close()
   177  					closed = true
   178  				}()
   179  			}
   180  		}
   181  
   182  		readCnt <- cnt
   183  	}(readCnt)
   184  
   185  	time.Sleep(500 * time.Millisecond)
   186  
   187  	options.PortName = serialPort
   188  
   189  	fwrite, err := serial.Open(options)
   190  	if err != nil {
   191  		t.Error("Error opening file for writing: ", err)
   192  	}
   193  
   194  	c, err := fwrite.Write([]byte("Hi there"))
   195  
   196  	if err != nil {
   197  		t.Error("Write error: ", err)
   198  	}
   199  
   200  	fmt.Printf("Wrote %v bytes\n", c)
   201  
   202  	readCount := <-readCnt
   203  
   204  	if readCount != 8 {
   205  		t.Errorf("only read %v chars, expected 8", readCount)
   206  	}
   207  
   208  	fmt.Println("test all done")
   209  }
   210  */
   211  
   212  type dataSource struct {
   213  	count int
   214  }
   215  
   216  func (ds *dataSource) Read(data []byte) (int, error) {
   217  	ds.count++
   218  	switch ds.count {
   219  	case 1:
   220  		time.Sleep(100 * time.Millisecond)
   221  		data[0] = 0
   222  		return 1, nil
   223  	case 2, 3, 4, 5, 6, 7, 8, 9, 10:
   224  		time.Sleep(5 * time.Millisecond)
   225  		data[0] = 1
   226  		return 1, nil
   227  	default:
   228  		time.Sleep(1000 * time.Hour)
   229  
   230  	}
   231  
   232  	return 0, nil
   233  }
   234  
   235  func TestReader(t *testing.T) {
   236  	source := &dataSource{}
   237  	reader := NewReader(source, time.Second, time.Millisecond*50)
   238  
   239  	start := time.Now()
   240  	data := make([]byte, 100)
   241  	count, err := reader.Read(data)
   242  
   243  	dur := time.Since(start)
   244  
   245  	if err != nil {
   246  		t.Error("read failed: ", err)
   247  	}
   248  
   249  	if dur < 100*time.Millisecond || dur > 400*time.Millisecond {
   250  		t.Error("expected dur to be around 150ms: ", dur)
   251  	}
   252  
   253  	if count != 10 {
   254  		t.Error("expected count to be 10: ", count)
   255  	}
   256  
   257  	data = data[0:count]
   258  
   259  	expData := []byte{0, 1, 1, 1, 1, 1, 1, 1, 1, 1}
   260  
   261  	if !reflect.DeepEqual(data, expData) {
   262  		t.Error("expected: ", expData)
   263  		t.Error("got     : ", data)
   264  	}
   265  }
   266  
   267  type dataSourceTimeout struct {
   268  }
   269  
   270  func (ds *dataSourceTimeout) Read(_ []byte) (int, error) {
   271  	time.Sleep(1000 * time.Hour)
   272  
   273  	return 0, nil
   274  }
   275  
   276  func TestResponseReaderTimeout(t *testing.T) {
   277  	source := &dataSourceTimeout{}
   278  	reader := NewReader(source, time.Second, time.Millisecond*10)
   279  
   280  	start := time.Now()
   281  	data := make([]byte, 100)
   282  	count, err := reader.Read(data)
   283  
   284  	dur := time.Since(start)
   285  
   286  	if err != io.EOF {
   287  		t.Error("expected timeout error, got: ", err)
   288  	}
   289  
   290  	if dur < 900*time.Millisecond || dur > 1100*time.Millisecond {
   291  		t.Error("expected dur to be around 1s: ", dur)
   292  	}
   293  
   294  	if count != 0 {
   295  		t.Error("expected count to be 0: ", count)
   296  	}
   297  
   298  	data = data[0:count]
   299  
   300  	expData := []byte{}
   301  
   302  	if !reflect.DeepEqual(data, expData) {
   303  		t.Error("expected: ", expData)
   304  		t.Error("got     : ", data)
   305  	}
   306  }