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 }