1// Copyright 2018 Google, Inc. 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.
6
7package layers
8
9import (
10	"encoding/hex"
11	"testing"
12
13	"github.com/google/gopacket"
14)
15
16var (
17	fingerprint uint64 = 0x6c636d2073656c66
18
19	shortPacket = []byte{
20		0x4c, 0x43, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x43, 0x4d, 0x5f,
21		0x53, 0x45, 0x4c, 0x46, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x00, 0x6c, 0x63,
22		0x6d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x65, 0x73, 0x74,
23	}
24
25	fragmentedPacket = []byte{
26		0x4c, 0x43, 0x30, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d,
27		0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x4c, 0x43, 0x4d, 0x5f,
28		0x53, 0x45, 0x4c, 0x46, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x00, 0x6c, 0x63,
29		0x6d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x65, 0x73, 0x74,
30	}
31
32	invalidPacket = []byte{
33		0x4c, 0x43, 0x30, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34	}
35
36	expectedChannel = "LCM_SELF_TEST"
37)
38
39func TestLCMDecode(t *testing.T) {
40	testShortLCM(t)
41	testFragmentedLCM(t)
42	testInvalidLCM(t)
43}
44
45func testShortLCM(t *testing.T) {
46	lcm := &LCM{}
47
48	err := lcm.DecodeFromBytes(shortPacket, gopacket.NilDecodeFeedback)
49	if err != nil {
50		t.Fatal(err)
51	}
52
53	if lcm.Magic != LCMShortHeaderMagic {
54		t.Errorf("Expected LCM Magic %x, but decoded %x.\n",
55			LCMShortHeaderMagic, lcm.Magic)
56	}
57
58	if lcm.SequenceNumber != 0x00 {
59		t.Errorf("Expected an LCM Sequence Number of %x, but decoded %x.\n",
60			0x00, lcm.SequenceNumber)
61	}
62
63	if lcm.ChannelName != expectedChannel {
64		t.Errorf("Expected channel name %s but received %s\n",
65			expectedChannel, lcm.ChannelName)
66	}
67
68	if lcm.Fragmented {
69		t.Errorf("Misinterpreted non-fragmented packet as fragmented.")
70	}
71
72	for i, val := range lcm.LayerContents() {
73		if val != shortPacket[i] {
74			t.Errorf("\nLCM Payload: expected\n%sbut received\n%s",
75				hex.Dump(shortPacket[:22]), hex.Dump(lcm.Payload()))
76		}
77	}
78
79	for i, val := range lcm.Payload() {
80		if val != shortPacket[i+22] {
81			t.Errorf("\nLCM Payload: expected\n%sbut received\n%s",
82				hex.Dump(shortPacket[22:]), hex.Dump(lcm.Payload()))
83		}
84	}
85}
86
87func testFragmentedLCM(t *testing.T) {
88	lcm := LCM{}
89
90	err := lcm.DecodeFromBytes(fragmentedPacket, gopacket.NilDecodeFeedback)
91	if err != nil {
92		t.Fatal(err)
93	}
94
95	if lcm.Magic != LCMFragmentedHeaderMagic {
96		t.Errorf("Expected LCM Magic %x, but decoded %x.\n",
97			LCMFragmentedHeaderMagic, lcm.Magic)
98	}
99
100	if lcm.SequenceNumber != 0x01 {
101		t.Errorf("Expected an LCM Sequence Number of %x, but decoded %x.\n",
102			0x01, lcm.SequenceNumber)
103	}
104
105	if lcm.PayloadSize != 0x0d {
106		t.Errorf("Expected an LCM Payload Size of %x, but decoded %x.\n", 0x0d,
107			lcm.PayloadSize)
108	}
109
110	if lcm.FragmentOffset != 0x2d {
111		t.Errorf("Expected an LCM Fragment Offset of %x, but decoded %x.\n",
112			0x2d, lcm.FragmentOffset)
113	}
114
115	if lcm.FragmentNumber != 0x00 {
116		t.Errorf("Expected the first LCM fragment (%x), but decoded %x.\n",
117			0x00, lcm.FragmentNumber)
118	}
119
120	if lcm.TotalFragments != 0x02 {
121		t.Errorf("Expected two LCM fragments (%x), but decoded %x.\n", 0x02,
122			lcm.TotalFragments)
123	}
124
125	if lcm.ChannelName != expectedChannel {
126		t.Errorf("Expected LCM Channel Name %s but decoded %s\n",
127			expectedChannel, lcm.ChannelName)
128	}
129
130	if !lcm.Fragmented {
131		t.Errorf("Misinterpreted fragmented packet as non-fragmented.")
132	}
133
134	for i, val := range lcm.LayerContents() {
135		if val != fragmentedPacket[i] {
136			t.Errorf("\nLCM Payload: expected\n%sbut received\n%s",
137				hex.Dump(fragmentedPacket[:22]), hex.Dump(lcm.Payload()))
138		}
139	}
140
141	for i, val := range lcm.Payload() {
142		if val != fragmentedPacket[i+34] {
143			t.Errorf("\nLCM Payload: expected\n%sbut received\n%s",
144				hex.Dump(fragmentedPacket[34:]), hex.Dump(lcm.Payload()))
145		}
146	}
147}
148
149func testInvalidLCM(t *testing.T) {
150	lcm := LCM{}
151
152	err := lcm.DecodeFromBytes(invalidPacket, gopacket.NilDecodeFeedback)
153	if err == nil {
154		t.Fatal("Did not detect LCM decode error.")
155	}
156}
157