Repository: pion/interceptor
Pull request #30 (2021-03-20 07:57:04)

Add mock Interceptor for testing
Call registered functions when interceptor methods are called.

### Reference issue
Used by https://github.com/pion/webrtc/pull/1721


codecov[bot]: # [Codecov](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=h1) Report
> Merging [#30](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=desc) (7f8904b) into [master](https://codecov.io/gh/pion/interceptor/commit/fb01515e49d3e7c853ebb4630e42ad0f01064a81?el=desc) (fb01515) will **increase** coverage by `0.13%`.
> The diff coverage is `82.60%`.

[![Impacted file tree graph](https://codecov.io/gh/pion/interceptor/pull/30/graphs/tree.svg?width=650&height=150&src=pr&token=FNH9xUG6AX)](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #30      +/-   ##
==========================================
+ Coverage   79.02%   79.16%   +0.13%     
==========================================
  Files          20       21       +1     
  Lines         577      600      +23     
==========================================
+ Hits          456      475      +19     
- Misses         81       85       +4     
  Partials       40       40              
```

| Flag | Coverage Δ | |
|---|---|---|
| go | `79.16% <82.60%> (+0.13%)` | :arrow_up: |
| wasm | `76.66% <82.60%> (+0.23%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/mock/interceptor.go](https://codecov.io/gh/pion/interceptor/pull/30/diff?src=pr&el=tree#diff-cGtnL21vY2svaW50ZXJjZXB0b3IuZ28=) | `82.60% <82.60%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=footer). Last update [fb01515...7f8904b](https://codecov.io/gh/pion/interceptor/pull/30?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/pkg/mock/interceptor.go b/pkg/mock/interceptor.go
new file mode 100644
index 0000000..81395fb
--- /dev/null
+++ b/pkg/mock/interceptor.go
@@ -0,0 +1,113 @@
+// Package mock provides mock Interceptor for testing.
+package mock
+
+import (
+	"github.com/pion/interceptor"
+	"github.com/pion/rtcp"
+	"github.com/pion/rtp"
+)
+
+// Interceptor is an mock Interceptor fot testing.
+type Interceptor struct {
+	BindRTCPReaderFn     func(reader interceptor.RTCPReader) interceptor.RTCPReader
+	BindRTCPWriterFn     func(writer interceptor.RTCPWriter) interceptor.RTCPWriter
+	BindLocalStreamFn    func(i *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter
+	UnbindLocalStreamFn  func(i *interceptor.StreamInfo)
+	BindRemoteStreamFn   func(i *interceptor.StreamInfo, reader interceptor.RTPReader) interceptor.RTPReader
+	UnbindRemoteStreamFn func(i *interceptor.StreamInfo)
+	CloseFn              func() error
+}
+
+// BindRTCPReader implements Interceptor.
+func (i *Interceptor) BindRTCPReader(reader interceptor.RTCPReader) interceptor.RTCPReader {
+	if i.BindRTCPReaderFn != nil {
+		return i.BindRTCPReaderFn(reader)
+	}
+	return reader
+}
+
+// BindRTCPWriter implements Interceptor.
+func (i *Interceptor) BindRTCPWriter(writer interceptor.RTCPWriter) interceptor.RTCPWriter {
+	if i.BindRTCPWriterFn != nil {
+		return i.BindRTCPWriterFn(writer)
+	}
+	return writer
+}
+
+// BindLocalStream implements Interceptor.
+func (i *Interceptor) BindLocalStream(info *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter {
+	if i.BindLocalStreamFn != nil {
+		return i.BindLocalStreamFn(info, writer)
+	}
+	return writer
+}
+
+// UnbindLocalStream implements Interceptor.
+func (i *Interceptor) UnbindLocalStream(info *interceptor.StreamInfo) {
+	if i.UnbindLocalStreamFn != nil {
+		i.UnbindLocalStreamFn(info)
+	}
+}
+
+// BindRemoteStream implements Interceptor.
+func (i *Interceptor) BindRemoteStream(info *interceptor.StreamInfo, reader interceptor.RTPReader) interceptor.RTPReader {
+	if i.BindRemoteStreamFn != nil {
+		return i.BindRemoteStreamFn(info, reader)
+	}
+	return reader
+}
+
+// UnbindRemoteStream implements Interceptor.
+func (i *Interceptor) UnbindRemoteStream(info *interceptor.StreamInfo) {
+	if i.UnbindRemoteStreamFn != nil {
+		i.UnbindRemoteStreamFn(info)
+	}
+}
+
+// Close implements Interceptor.
+func (i *Interceptor) Close() error {
+	if i.CloseFn != nil {
+		return i.CloseFn()
+	}
+	return nil
+}
+
+// RTPWriter is a mock RTPWriter.
+type RTPWriter struct {
+	WriteFn func(*rtp.Header, []byte, interceptor.Attributes) (int, error)
+}
+
+// Write implements RTPWriter.
+func (w *RTPWriter) Write(header *rtp.Header, payload []byte, attributes interceptor.Attributes) (int, error) {
+	return w.WriteFn(header, payload, attributes)
+}
+
+// RTPReader is a mock RTPReader.
+type RTPReader struct {
+	ReadFn func([]byte, interceptor.Attributes) (int, interceptor.Attributes, error)
+}
+
+// Read implements RTPReader.
+func (r *RTPReader) Read(b []byte, attributes interceptor.Attributes) (int, interceptor.Attributes, error) {
+	return r.ReadFn(b, attributes)
+}
+
+// RTCPWriter is a mock RTCPWriter.
+type RTCPWriter struct {
+	WriteFn func([]rtcp.Packet, interceptor.Attributes) (int, error)
+}
+
+// Write implements RTCPWriter.
+func (w *RTCPWriter) Write(pkts []rtcp.Packet, attributes interceptor.Attributes) (int, error) {
+	return w.WriteFn(pkts, attributes)
+}
+
+// RTCPReader is a mock RTCPReader.
+type RTCPReader struct {
+	ReadFn func([]byte, interceptor.Attributes) (int, interceptor.Attributes, error)
+}
+
+// Read implements RTCPReader.
+func (r *RTCPReader) Read(b []byte, attributes interceptor.Attributes) (int, interceptor.Attributes, error) {
+	return r.ReadFn(b, attributes)
+}


Test patch:
diff --git a/pkg/mock/interceptor_test.go b/pkg/mock/interceptor_test.go
new file mode 100644
index 0000000..bbb5750
--- /dev/null
+++ b/pkg/mock/interceptor_test.go
@@ -0,0 +1,117 @@
+package mock
+
+import (
+	"sync/atomic"
+	"testing"
+
+	"github.com/pion/interceptor"
+)
+
+func TestInterceptor(t *testing.T) {
+	dummyRTPWriter := &RTPWriter{}
+	dummyRTPReader := &RTPReader{}
+	dummyRTCPWriter := &RTCPWriter{}
+	dummyRTCPReader := &RTCPReader{}
+	dummyStreamInfo := &interceptor.StreamInfo{}
+
+	t.Run("Default", func(t *testing.T) {
+		i := &Interceptor{}
+
+		if i.BindRTCPWriter(dummyRTCPWriter) != dummyRTCPWriter {
+			t.Error("Default BindRTCPWriter should return given writer")
+		}
+		if i.BindRTCPReader(dummyRTCPReader) != dummyRTCPReader {
+			t.Error("Default BindRTCPReader should return given reader")
+		}
+		if i.BindLocalStream(dummyStreamInfo, dummyRTPWriter) != dummyRTPWriter {
+			t.Error("Default BindLocalStream should return given writer")
+		}
+		i.UnbindLocalStream(dummyStreamInfo)
+		if i.BindRemoteStream(dummyStreamInfo, dummyRTPReader) != dummyRTPReader {
+			t.Error("Default BindRemoteStream should return given reader")
+		}
+		i.UnbindRemoteStream(dummyStreamInfo)
+		if i.Close() != nil {
+			t.Error("Default Close should return nil")
+		}
+	})
+	t.Run("Custom", func(t *testing.T) {
+		var (
+			cntBindRTCPReader     uint32
+			cntBindRTCPWriter     uint32
+			cntBindLocalStream    uint32
+			cntUnbindLocalStream  uint32
+			cntBindRemoteStream   uint32
+			cntUnbindRemoteStream uint32
+			cntClose              uint32
+		)
+		i := &Interceptor{
+			BindRTCPReaderFn: func(reader interceptor.RTCPReader) interceptor.RTCPReader {
+				atomic.AddUint32(&cntBindRTCPReader, 1)
+				return reader
+			},
+			BindRTCPWriterFn: func(writer interceptor.RTCPWriter) interceptor.RTCPWriter {
+				atomic.AddUint32(&cntBindRTCPWriter, 1)
+				return writer
+			},
+			BindLocalStreamFn: func(i *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter {
+				atomic.AddUint32(&cntBindLocalStream, 1)
+				return writer
+			},
+			UnbindLocalStreamFn: func(i *interceptor.StreamInfo) {
+				atomic.AddUint32(&cntUnbindLocalStream, 1)
+			},
+			BindRemoteStreamFn: func(i *interceptor.StreamInfo, reader interceptor.RTPReader) interceptor.RTPReader {
+				atomic.AddUint32(&cntBindRemoteStream, 1)
+				return reader
+			},
+			UnbindRemoteStreamFn: func(i *interceptor.StreamInfo) {
+				atomic.AddUint32(&cntUnbindRemoteStream, 1)
+			},
+			CloseFn: func() error {
+				atomic.AddUint32(&cntClose, 1)
+				return nil
+			},
+		}
+
+		if i.BindRTCPWriter(dummyRTCPWriter) != dummyRTCPWriter {
+			t.Error("Mocked BindRTCPWriter should return given writer")
+		}
+		if i.BindRTCPReader(dummyRTCPReader) != dummyRTCPReader {
+			t.Error("Mocked BindRTCPReader should return given reader")
+		}
+		if i.BindLocalStream(dummyStreamInfo, dummyRTPWriter) != dummyRTPWriter {
+			t.Error("Mocked BindLocalStream should return given writer")
+		}
+		i.UnbindLocalStream(dummyStreamInfo)
+		if i.BindRemoteStream(dummyStreamInfo, dummyRTPReader) != dummyRTPReader {
+			t.Error("Mocked BindRemoteStream should return given reader")
+		}
+		i.UnbindRemoteStream(dummyStreamInfo)
+		if i.Close() != nil {
+			t.Error("Mocked Close should return nil")
+		}
+
+		if cnt := atomic.LoadUint32(&cntBindRTCPWriter); cnt != 1 {
+			t.Errorf("BindRTCPWriterFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntBindRTCPReader); cnt != 1 {
+			t.Errorf("BindRTCPReaderFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntBindLocalStream); cnt != 1 {
+			t.Errorf("BindLocalStreamFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntUnbindLocalStream); cnt != 1 {
+			t.Errorf("UnbindLocalStreamFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntBindRemoteStream); cnt != 1 {
+			t.Errorf("BindRemoteStreamFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntUnbindRemoteStream); cnt != 1 {
+			t.Errorf("UnbindRemoteStreamFn is expected to be called once, but called %d times", cnt)
+		}
+		if cnt := atomic.LoadUint32(&cntClose); cnt != 1 {
+			t.Errorf("CloseFn is expected to be called once, but called %d times", cnt)
+		}
+	})
+}