Skip to content

Commit b394f46

Browse files
author
shadowy-pycoder
committed
Added basic tests for parsers
1 parent 874e430 commit b394f46

File tree

19 files changed

+374
-70
lines changed

19 files changed

+374
-70
lines changed

Makefile

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,38 @@ build:
1010
setcap:
1111
sudo setcap cap_net_raw+ep ./bin/${APP_NAME}
1212

13-
.PHONY: create
14-
create:
15-
go test -c -race && sudo setcap cap_net_raw+ep mshark.test
13+
mshark.test:
14+
go test -c -race && sudo setcap cap_net_raw+ep mshark.test
1615

1716
.PHONY: bench
18-
bench: create
17+
bench: mshark.test
1918
./mshark.test -test.bench=. -test.benchmem -test.run=^$$ -test.benchtime 1000x \
2019
-test.cpuprofile='cpu.prof' -test.memprofile='mem.prof'
2120

21+
.PHONY: benchall
22+
benchall:
23+
for package in $$(go list ./... | tail -n +2); do \
24+
go test $${package} -bench=. -benchmem -run=^$$ -benchtime 1000x \
25+
-cpuprofile="$$(basename $${package})/cpu.prof" -memprofile="$$(basename $${package})/mem.prof"; done
26+
27+
.PHONY: test
28+
test:
29+
go test ./... -v -count=1
30+
31+
.PHONY: test100
32+
test100:
33+
go test ./... -count=100
34+
35+
.PHONY: race
36+
race:
37+
go test ./... -v -race -count=1
38+
39+
.PHONY: cover
40+
cover:
41+
go test ./... -short -count=1 -race -coverprofile=coverage.out
42+
go tool cover -html=coverage.out
43+
rm coverage.out
44+
2245
.PHONY: clean
2346
clean:
2447
rm -v *.txt *.pcap*

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ go 1.23.0
55
require (
66
github.com/mdlayher/packet v1.1.2
77
github.com/packetcap/go-pcap v0.0.0-20240528124601-8c87ecf5dbc5
8+
github.com/stretchr/testify v1.9.0
89
golang.org/x/net v0.28.0
910
)
1011

1112
require (
13+
github.com/davecgh/go-spew v1.1.1 // indirect
1214
github.com/josharian/native v1.1.0 // indirect
1315
github.com/mdlayher/socket v0.4.1 // indirect
16+
github.com/pmezard/go-difflib v1.0.0 // indirect
1417
golang.org/x/sync v0.1.0 // indirect
1518
golang.org/x/sys v0.24.0 // indirect
19+
gopkg.in/yaml.v3 v3.0.1 // indirect
1620
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
24
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
35
github.com/gopacket/gopacket v1.2.0 h1:eXbzFad7f73P1n2EJHQlsKuvIMJjVXK5tXoSca78I3A=
@@ -10,9 +12,17 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
1012
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
1113
github.com/packetcap/go-pcap v0.0.0-20240528124601-8c87ecf5dbc5 h1:p4VuaitqUAqSZSomd7Wb4BPV/Jj7Hno2/iqtfX7DZJI=
1214
github.com/packetcap/go-pcap v0.0.0-20240528124601-8c87ecf5dbc5/go.mod h1:zIAoVKeWP0mz4zXY50UYQt6NLg2uwKRswMDcGEqOms4=
15+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
16+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
17+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
18+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
1319
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
1420
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
1521
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
1622
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1723
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
1824
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
25+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
26+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
27+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
28+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

layers/arp.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ func (ap *ARPPacket) Parse(data []byte) error {
7979
}
8080
ap.HardwareType = binary.BigEndian.Uint16(data[0:2])
8181
ap.ProtocolType = binary.BigEndian.Uint16(data[2:4])
82-
ap.ProtocolTypeDesc = ap.ptype()
82+
ap.ProtocolTypeDesc = ptypedesc(ap.ProtocolType)
8383
ap.Hlen = data[4]
8484
ap.Plen = data[5]
8585
ap.Op = binary.BigEndian.Uint16(data[6:8])
86-
ap.OpDesc = ap.op()
86+
ap.OpDesc = opdesc(ap.Op)
8787
hoffset := 8 + ap.Hlen
8888
ap.SenderMAC = net.HardwareAddr(data[8:hoffset])
8989
poffset := hoffset + ap.Plen
@@ -104,9 +104,9 @@ func (ap *ARPPacket) NextLayer() (string, []byte) {
104104
return "", nil
105105
}
106106

107-
func (ap *ARPPacket) ptype() string {
107+
func ptypedesc(pt uint16) string {
108108
var proto string
109-
switch ap.ProtocolType {
109+
switch pt {
110110
case 0x0800:
111111
proto = "IPv4"
112112
case 0x86dd:
@@ -117,15 +117,15 @@ func (ap *ARPPacket) ptype() string {
117117
return proto
118118
}
119119

120-
func (ap *ARPPacket) op() string {
121-
var op string
122-
switch ap.Op {
120+
func opdesc(op uint16) string {
121+
var opdesc string
122+
switch op {
123123
case 1:
124-
op = "request"
124+
opdesc = "request"
125125
case 2:
126-
op = "reply"
126+
opdesc = "reply"
127127
default:
128-
op = "Unknown"
128+
opdesc = "Unknown"
129129
}
130-
return op
130+
return opdesc
131131
}

layers/arp_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package layers
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net"
7+
"net/netip"
8+
"os"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func openFile(path string) ([]byte, func(), error) {
16+
f, err := os.Open(filepath.FromSlash(fmt.Sprintf("testdata/%s.bin", path)))
17+
if err != nil {
18+
return nil, nil, err
19+
}
20+
data, err := io.ReadAll(f)
21+
if err != nil {
22+
return nil, nil, err
23+
}
24+
return data, func() { f.Close() }, nil
25+
}
26+
27+
func testPacket(t *testing.T, path string) ([]byte, func()) {
28+
t.Helper()
29+
packet, close, err := openFile(path)
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
return packet, close
34+
}
35+
36+
func testPacketBench(b *testing.B, path string) ([]byte, func()) {
37+
b.Helper()
38+
packet, close, err := openFile(path)
39+
if err != nil {
40+
b.Fatal(err)
41+
}
42+
return packet, close
43+
}
44+
45+
func BenchmarkParseARP(b *testing.B) {
46+
packet, close := testPacketBench(b, "arp")
47+
defer close()
48+
b.ResetTimer()
49+
arp := &ARPPacket{}
50+
for i := 0; i < b.N; i++ {
51+
_ = arp.Parse(packet)
52+
fmt.Fprint(io.Discard, arp.String())
53+
}
54+
}
55+
56+
func TestParseARP(t *testing.T) {
57+
expected := &ARPPacket{
58+
HardwareType: 0x0001,
59+
ProtocolType: 0x0800,
60+
ProtocolTypeDesc: "IPv4",
61+
Hlen: 0x06,
62+
Plen: 0x04,
63+
Op: 0x0001,
64+
OpDesc: "request",
65+
SenderMAC: net.HardwareAddr{0x7b, 0x13, 0x0b, 0x87, 0xea, 0x51},
66+
SenderIP: netip.AddrFrom4([4]byte{0x7F, 0x00, 0x00, 0x01}),
67+
TargetMAC: net.HardwareAddr{0x43, 0x40, 0x8d, 0x28, 0xca, 0x0b},
68+
TargetIP: netip.AddrFrom4([4]byte{0x7F, 0x00, 0x00, 0x02}),
69+
}
70+
arp := &ARPPacket{}
71+
packet, close := testPacket(t, "arp")
72+
defer close()
73+
if err := arp.Parse(packet); err != nil {
74+
t.Fatal(err)
75+
}
76+
require.Equal(t, expected, arp)
77+
}

layers/ethernet_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package layers
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func BenchmarkParseEthernet(b *testing.B) {
13+
packet, close := testPacketBench(b, "ethernet")
14+
defer close()
15+
b.ResetTimer()
16+
eth := &EthernetFrame{}
17+
for i := 0; i < b.N; i++ {
18+
_ = eth.Parse(packet)
19+
fmt.Fprint(io.Discard, eth.String())
20+
}
21+
}
22+
23+
func TestParseEthernet(t *testing.T) {
24+
expected := &EthernetFrame{
25+
DstMAC: net.HardwareAddr{0x7b, 0x13, 0x0b, 0x87, 0xea, 0x51},
26+
SrcMAC: net.HardwareAddr{0x43, 0x40, 0x8d, 0x28, 0xca, 0x0b},
27+
EtherType: 0x0800,
28+
EtherTypeDesc: "IPv4",
29+
payload: []byte{},
30+
}
31+
eth := &EthernetFrame{}
32+
packet, close := testPacket(t, "ethernet")
33+
defer close()
34+
if err := eth.Parse(packet); err != nil {
35+
t.Fatal(err)
36+
}
37+
require.Equal(t, expected, eth)
38+
}

layers/icmp_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package layers
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func BenchmarkParseICMP(b *testing.B) {
12+
packet, close := testPacketBench(b, "icmp")
13+
defer close()
14+
b.ResetTimer()
15+
icmp := &ICMPSegment{}
16+
for i := 0; i < b.N; i++ {
17+
_ = icmp.Parse(packet)
18+
fmt.Fprint(io.Discard, icmp.String())
19+
}
20+
}
21+
22+
func TestParseICMP(t *testing.T) {
23+
expected := &ICMPSegment{
24+
Type: 8,
25+
TypeDesc: "Echo Request",
26+
Code: 0,
27+
CodeDesc: "Echo Request (Ping)",
28+
Checksum: 9604,
29+
Data: []byte{
30+
0x00, 0x02, 0x00, 0x01, 0x70, 0x2A, 0xE5, 0x66, 0x00, 0x00, 0x00, 0x00,
31+
0xB0, 0x14, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
32+
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
33+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
34+
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37},
35+
}
36+
icmp := &ICMPSegment{}
37+
packet, close := testPacket(t, "icmp")
38+
defer close()
39+
if err := icmp.Parse(packet); err != nil {
40+
t.Fatal(err)
41+
}
42+
require.Equal(t, expected, icmp)
43+
}

layers/icmpv6_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package layers
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func BenchmarkParseICMPv6(b *testing.B) {
12+
packet, close := testPacketBench(b, "icmp")
13+
defer close()
14+
b.ResetTimer()
15+
icmp := &ICMPv6Segment{}
16+
for i := 0; i < b.N; i++ {
17+
_ = icmp.Parse(packet)
18+
fmt.Fprint(io.Discard, icmp.String())
19+
}
20+
}
21+
22+
func TestParseICMPv6(t *testing.T) {
23+
expected := &ICMPv6Segment{
24+
Type: 128,
25+
TypeDesc: "Echo Request",
26+
Code: 0,
27+
CodeDesc: "Echo Request (Ping)",
28+
Checksum: 48509,
29+
Data: []byte{
30+
0x00, 0x07, 0x00, 0x01, 0x3B, 0x2D, 0xE5, 0x66, 0x00, 0x00,
31+
0x00, 0x00, 0xdd, 0x96, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
32+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
33+
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
34+
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
35+
0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37},
36+
}
37+
icmp := &ICMPv6Segment{}
38+
packet, close := testPacket(t, "icmpv6")
39+
defer close()
40+
if err := icmp.Parse(packet); err != nil {
41+
t.Fatal(err)
42+
}
43+
require.Equal(t, expected, icmp)
44+
}

0 commit comments

Comments
 (0)