github.com/cnotch/ipchub@v1.1.0/media/stream_test.go (about)

     1  // Copyright (c) 2019,CAOHONGJU All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package media
     6  
     7  import (
     8  	"io"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/cnotch/ipchub/av/format/rtp"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  type emptyMulticastable struct {
    17  }
    18  
    19  func (m emptyMulticastable) AddMember(io.Closer)     {}
    20  func (m emptyMulticastable) ReleaseMember(io.Closer) {}
    21  func (m emptyMulticastable) MulticastIP() string     { return "234.0.0.1" }
    22  func (m emptyMulticastable) Port(int) int            { return 0 }
    23  func (m emptyMulticastable) SourceIP() string        { return "234.0.0.1" }
    24  func (m emptyMulticastable) TTL() int                { return 0 }
    25  
    26  type emptyConsumer struct {
    27  }
    28  
    29  func (c emptyConsumer) Consume(pack Pack) {}
    30  func (c emptyConsumer) Close() error      { return nil }
    31  
    32  type panicConsumer struct {
    33  	try int
    34  }
    35  
    36  func (c *panicConsumer) Consume(pack Pack) {
    37  	c.try++
    38  	if c.try > 3 {
    39  		panic("panicConsumer")
    40  	}
    41  }
    42  func (c *panicConsumer) Close() error { return nil }
    43  
    44  const sdpRaw = `v=0
    45  o=- 0 0 IN IP4 127.0.0.1
    46  s=No Name
    47  c=IN IP4 127.0.0.1
    48  t=0 0
    49  a=tool:libavformat 58.20.100
    50  m=video 0 RTP/AVP 96
    51  b=AS:2500
    52  a=rtpmap:96 H264/90000
    53  a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZQFAFuhAAAAMAEAAAAwPI8YMZYA==,aO+8sA==; profile-level-id=64001F
    54  a=control:streamid=0
    55  m=audio 0 RTP/AVP 97
    56  b=AS:160
    57  a=rtpmap:97 MPEG4-GENERIC/44100/2
    58  a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=121056E500
    59  a=control:streamid=1
    60  `
    61  
    62  func TestNewStream(t *testing.T) {
    63  	tests := []struct {
    64  		name    string
    65  		path    string
    66  		options []Option
    67  	}{
    68  		{
    69  			name:    "test01",
    70  			path:    "/live/enter",
    71  			options: []Option{Attr(" ok ", "ok"), Attr("name", "chj"), Multicast(emptyMulticastable{})},
    72  		},
    73  	}
    74  	for _, tt := range tests {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			got := NewStream(tt.path, sdpRaw, tt.options...)
    77  			v := got.Attr("Ok")
    78  			assert.Equal(t, "ok", v, "Must is ok")
    79  			assert.NotNil(t, got.Multicastable(), "Must is not nil")
    80  		})
    81  	}
    82  }
    83  
    84  func Test_Consumption_Consume(t *testing.T) {
    85  	s := NewStream("live/test", sdpRaw)
    86  
    87  	t.Run("Consumption_Consume", func(t *testing.T) {
    88  		closed := false
    89  		go func() {
    90  			for !closed {
    91  				s.WriteRtpPacket(&rtp.Packet{})
    92  				<-time.After(time.Millisecond * 1)
    93  			}
    94  		}()
    95  		cid := s.StartConsume(emptyConsumer{}, RTPPacket, "")
    96  		assert.Equal(t, 1, s.consumptions.Count(), "must is 1")
    97  
    98  		<-time.After(time.Millisecond * 1000)
    99  		cinfo, ok := s.GetConsumption(cid)
   100  		assert.True(t, ok, "must is true")
   101  		assert.NotZero(t, cinfo.Flow.OutBytes, "must > 0")
   102  
   103  		s.StopConsume(cid)
   104  		assert.Equal(t, 0, s.consumptions.Count(), "must is 0")
   105  		closed = true
   106  		s.Close()
   107  	})
   108  }
   109  
   110  func Test_Consumption_ConsumePanic(t *testing.T) {
   111  	s := NewStream("live/test", sdpRaw)
   112  	t.Run("Test_Consumption_ConsumePanic", func(t *testing.T) {
   113  		closed := false
   114  		go func() {
   115  			for !closed {
   116  				s.WriteRtpPacket(&rtp.Packet{})
   117  				<-time.After(time.Millisecond * 1)
   118  			}
   119  		}()
   120  		s.StartConsume(&panicConsumer{}, RTPPacket, "")
   121  		assert.Equal(t, 1, s.consumptions.Count(), "must is 1")
   122  
   123  		<-time.After(time.Millisecond * 100)
   124  		assert.Equal(t, 0, s.consumptions.Count(), "panic autoclose,must is 0")
   125  		closed = true
   126  		s.Close()
   127  	})
   128  }
   129  
   130  func benchDispatch(n int, b *testing.B) {
   131  	s := NewStream("/live/a", sdpRaw)
   132  	for i := 0; i < n; i++ {
   133  		s.StartConsume(emptyConsumer{}, RTPPacket, "")
   134  	}
   135  
   136  	b.ResetTimer()
   137  	b.RunParallel(func(pb *testing.PB) {
   138  		for pb.Next() {
   139  			s.WriteRtpPacket(&rtp.Packet{})
   140  		}
   141  	})
   142  	s.Close()
   143  }
   144  func Benchmark_Stream_Dispatch1(b *testing.B) {
   145  	benchDispatch(1, b)
   146  }
   147  func Benchmark_Stream_Dispatch5(b *testing.B) {
   148  	benchDispatch(5, b)
   149  }
   150  func Benchmark_Stream_Dispatch10(b *testing.B) {
   151  	benchDispatch(10, b)
   152  }
   153  func Benchmark_Stream_Dispatch50(b *testing.B) {
   154  	benchDispatch(50, b)
   155  }
   156  func Benchmark_Stream_Dispatch100(b *testing.B) {
   157  	benchDispatch(100, b)
   158  }
   159  func Benchmark_Stream_Dispatch500(b *testing.B) {
   160  	benchDispatch(500, b)
   161  }
   162  
   163  func Benchmark_Stream_Dispatch1000(b *testing.B) {
   164  	benchDispatch(1000, b)
   165  }
   166  
   167  func Benchmark_Stream_Dispatch10000(b *testing.B) {
   168  	benchDispatch(10000, b)
   169  }