1// Copyright 2019 The GoPacket Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree.
6package pcapgo
7
8import (
9	"bytes"
10	"fmt"
11	"reflect"
12	"testing"
13	"time"
14)
15
16var (
17	spHeader = []byte{
18		0x73, 0x6E, 0x6F, 0x6F, 0x70, 0x00, 0x00, 0x00,
19		0x00, 0x00, 0x00, 0x02,
20		0x00, 0x00, 0x00, 0x04,
21	}
22
23	pack = []byte{
24		0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x5C, 0xBE, 0xB8, 0x4C, 0x00, 0x0C, 0xB1, 0x47,
25		0x7c, 0x5a, 0x1c, 0x49, 0x3c, 0xd1, 0x1e, 0x65, 0x50, 0x7f, 0xb9, 0xca, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x1e, 0x65,
26		0x50, 0x7f, 0xb9, 0xca, 0x0a, 0x00, 0x33, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x33, 0x01, 0x00, 0x00,
27	}
28)
29
30func OpenHandlePack() (buf []byte, handle *SnoopReader, err error) {
31	buf = make([]byte, len(spHeader)+len(pack))
32	copy(buf, append(spHeader, pack...))
33	handle, err = NewSnoopReader(bytes.NewReader(buf))
34	return buf, handle, err
35}
36
37func equalError(t *testing.T, err error, eq error) {
38	if err.Error() != eq.Error() {
39		t.Error(err)
40	}
41}
42
43func equalNil(t *testing.T, err error) {
44	if err != nil {
45		t.Error(err)
46	}
47}
48
49func equal(t *testing.T, expected, actual interface{}) {
50	if !reflect.DeepEqual(expected, actual) {
51		t.Error(fmt.Errorf("Not equal: \nexpected: %s\nactual  : %s", expected, actual))
52	}
53}
54
55func TestReadHeader(t *testing.T) {
56	_, err := NewSnoopReader(bytes.NewReader(spHeader))
57	equalNil(t, err)
58}
59
60func TestBadHeader(t *testing.T) {
61	buf := make([]byte, len(spHeader))
62	copy(buf, spHeader)
63	buf[6] = 0xff
64	_, err := NewSnoopReader(bytes.NewReader(buf))
65	equalError(t, err, fmt.Errorf("%s: %s", unknownMagic, "736e6f6f7000ff00"))
66
67	buf[6] = 0x00
68	buf[11] = 0x03
69	_, err = NewSnoopReader(bytes.NewReader(buf))
70	equalError(t, err, fmt.Errorf("%s: %d", unknownVersion, 3))
71
72	buf[11] = 0x02
73	buf[15] = 0x0b // linktype 11 is undefined
74	_, err = NewSnoopReader(bytes.NewReader(buf))
75	equalError(t, err, fmt.Errorf("%s, Code:%d", unkownLinkType, 11))
76
77	buf[15] = 0x04
78}
79
80func TestReadPacket(t *testing.T) {
81	_, handle, err := OpenHandlePack()
82	equalNil(t, err)
83
84	_, _, err = handle.ReadPacketData()
85	equalNil(t, err)
86}
87
88func TestZeroCopy(t *testing.T) {
89	_, handle, err := OpenHandlePack()
90	equalNil(t, err)
91
92	var cnt int
93	for cnt = 0; ; cnt++ {
94		_, _, err := handle.ZeroCopyReadPacketData()
95		if err != nil {
96			equalError(t, err, fmt.Errorf("EOF"))
97			break
98		}
99	}
100	if cnt != 1 {
101		t.Error(err)
102	}
103}
104
105func TestPacketHeader(t *testing.T) {
106	_, handle, err := OpenHandlePack()
107	equalNil(t, err)
108	_, ci, err := handle.ReadPacketData()
109	equalNil(t, err)
110
111	equal(t, ci.CaptureLength, 42)
112	equal(t, ci.Length, 42)
113	equal(t, ci.Timestamp, time.Date(2019, 04, 23, 07, 01, 32, 831815*1000, time.UTC)) //with nanosec
114
115}
116
117func TestBadPacketHeader(t *testing.T) {
118	buf, handle, err := OpenHandlePack()
119	equalNil(t, err)
120	buf[23] = 0x2C
121	_, _, err = handle.ReadPacketData()
122	equalError(t, err, fmt.Errorf(originalLenExceeded))
123	buf[23] = 0x2A
124}
125
126func TestBigPacketData(t *testing.T) {
127	buf, handle, err := OpenHandlePack()
128	equalNil(t, err)
129	// increase OriginalLen
130	buf[19] = 0x00
131	buf[18] = 0x11
132	// increase includedLen
133	buf[23] = 0x00
134	buf[22] = 0x11
135	_, _, err = handle.ReadPacketData()
136	equalError(t, err, fmt.Errorf(captureLenExceeded))
137	buf[23] = 0x44
138	buf[22] = 0x00
139	buf[19] = 0x44
140	buf[18] = 0x00
141}
142
143func TestLinkType(t *testing.T) {
144	_, handle, err := OpenHandlePack()
145	equalNil(t, err)
146	_, err = handle.LinkType()
147	equalNil(t, err)
148}
149
150func TestNotOverlapBuf(t *testing.T) {
151	buf := make([]byte, len(spHeader)+len(pack)*2)
152	packs := append(spHeader, pack...)
153	copy(buf, append(packs, pack...))
154	handle, err := NewSnoopReader(bytes.NewReader(buf))
155	equalNil(t, err)
156	overlap, _, err := handle.ReadPacketData()
157	equalNil(t, err)
158	overlap2, _, err := handle.ReadPacketData()
159	equalNil(t, err)
160	overlap[30] = 0xff
161	if overlap[30] == overlap2[30] {
162		t.Error(fmt.Errorf("Should not be: %x", overlap[30]))
163	}
164
165}
166
167func GeneratePacks(num int) []byte {
168	buf := make([]byte, len(spHeader)+(len(pack)*num))
169	packs := append(spHeader, pack...)
170	for i := 1; i < num; i++ {
171		packs = append(packs, pack...)
172	}
173	copy(buf, packs)
174	return buf
175}
176func BenchmarkReadPacketData(b *testing.B) {
177	buf := GeneratePacks(100)
178	handle, _ := NewSnoopReader(bytes.NewReader(buf))
179	for n := 0; n < b.N; n++ {
180		_, _, _ = handle.ReadPacketData()
181	}
182}
183
184func BenchmarkZeroCopyReadPacketData(b *testing.B) {
185	buf := GeneratePacks(100)
186	handle, _ := NewSnoopReader(bytes.NewReader(buf))
187	for n := 0; n < b.N; n++ {
188		_, _, _ = handle.ZeroCopyReadPacketData()
189	}
190}
191