/* NAME client_test.go DESCRIPTION client_test.go provides testing utilities to check RTP client functionality provided in client.go. AUTHOR Saxon A. Nelson-Milton LICENSE This is Copyright (C) 2019 the Australian Ocean Lab (AusOcean). It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License in gpl.txt. If not, see http://www.gnu.org/licenses. */ package rtp import ( "bytes" "fmt" "io" "net" "testing" "time" "bitbucket.org/ausocean/utils/logger" ) // dummyLogger will allow logging to be done by the testing pkg. type dummyLogger testing.T func (dl *dummyLogger) log(lvl int8, msg string, args ...interface{}) { var l string switch lvl { case logger.Warning: l = "warning" case logger.Debug: l = "debug" case logger.Info: l = "info" case logger.Error: l = "error" case logger.Fatal: l = "fatal" } msg = l + ": " + msg for i := 0; i < len(args); i++ { msg += " %v" } if len(args) == 0 { dl.Log(msg + "\n") return } dl.Logf(msg+"\n", args...) } // TestReceive checks that the Client can correctly receive RTP packets and // perform a specificed operation on the packets before storing in the ringBuffer. func TestReceive(t *testing.T) { const ( clientAddr = "localhost:8000" packetsToSend = 20 ) for _, op := range []func([]byte) ([]byte, error){nil, Payload} { testErr := make(chan error) serverErr := make(chan error) done := make(chan struct{}) clientReady := make(chan struct{}) var c *Client // Start routine to read from client. go func() { // Create and start the client. var err error c, err = NewClient(clientAddr, op, (*dummyLogger)(t).log, 1*time.Millisecond) if err != nil { testErr <- fmt.Errorf("could not create client, failed with error: %v\n", err) } c.Start() close(clientReady) // Read packets using the client and check them with expected. var packetsReceived int buf := make([]byte, 4096) for packetsReceived != packetsToSend { n, err := c.Read(buf) switch err { case nil: case io.EOF: continue default: testErr <- fmt.Errorf("unexpected error from c.Read: %v\n", err) } // Create expected data and apply operation if there is one. expect := (&Pkt{V: rtpVer, Payload: []byte{byte(packetsReceived)}}).Bytes(nil) if op != nil { expect, err = op(expect) if err != nil { testErr <- fmt.Errorf("unexpected error when applying op: %v\n", err) } } // Compare. got := buf[:n] if !bytes.Equal(got, expect) { testErr <- fmt.Errorf("did not get expected result. \nGot: %v\n Want: %v\n", got, expect) } packetsReceived++ } c.Stop() close(done) }() // Start the RTP server. go func() { <-clientReady cAddr, err := net.ResolveUDPAddr("udp", clientAddr) if err != nil { serverErr <- fmt.Errorf("could not resolve server address, failed with err: %v\n", err) } conn, err := net.DialUDP("udp", nil, cAddr) if err != nil { serverErr <- fmt.Errorf("could not dial udp, failed with err: %v\n", err) } // Send packets to the client. for i := 0; i < packetsToSend; i++ { p := (&Pkt{V: rtpVer, Payload: []byte{byte(i)}}).Bytes(nil) _, err := conn.Write(p) if err != nil { serverErr <- fmt.Errorf("could not write packet to conn, failed with err: %v\n", err) } } }() <-clientReady loop: for { select { case err := <-c.Err(): t.Log(err) case err := <-testErr: t.Fatal(err) case err := <-serverErr: t.Fatal(err) case <-done: break loop default: } } } }