blob: e600e3c282db417d4fbfb455f990eab7416d3531 [file] [log] [blame]
Matt Layher1961d9d2016-06-15 16:37:29 -04001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package bpf_test
6
7import (
8 "testing"
9
10 "golang.org/x/net/bpf"
11)
12
13func TestVMStoreScratchInvalidScratchRegisterTooSmall(t *testing.T) {
14 _, _, err := testVM(t, []bpf.Instruction{
15 bpf.StoreScratch{
16 Src: bpf.RegA,
17 N: -1,
18 },
19 bpf.RetA{},
20 })
21 if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
22 t.Fatalf("unexpected error: %v", err)
23 }
24}
25
26func TestVMStoreScratchInvalidScratchRegisterTooLarge(t *testing.T) {
27 _, _, err := testVM(t, []bpf.Instruction{
28 bpf.StoreScratch{
29 Src: bpf.RegA,
30 N: 16,
31 },
32 bpf.RetA{},
33 })
34 if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
35 t.Fatalf("unexpected error: %v", err)
36 }
37}
38
39func TestVMStoreScratchUnknownSourceRegister(t *testing.T) {
40 _, _, err := testVM(t, []bpf.Instruction{
41 bpf.StoreScratch{
42 Src: 100,
43 N: 0,
44 },
45 bpf.RetA{},
46 })
47 if errStr(err) != "assembling instruction 1: invalid source register 100" {
48 t.Fatalf("unexpected error: %v", err)
49 }
50}
51
52func TestVMLoadScratchInvalidScratchRegisterTooSmall(t *testing.T) {
53 _, _, err := testVM(t, []bpf.Instruction{
54 bpf.LoadScratch{
55 Dst: bpf.RegX,
56 N: -1,
57 },
58 bpf.RetA{},
59 })
60 if errStr(err) != "assembling instruction 1: invalid scratch slot -1" {
61 t.Fatalf("unexpected error: %v", err)
62 }
63}
64
65func TestVMLoadScratchInvalidScratchRegisterTooLarge(t *testing.T) {
66 _, _, err := testVM(t, []bpf.Instruction{
67 bpf.LoadScratch{
68 Dst: bpf.RegX,
69 N: 16,
70 },
71 bpf.RetA{},
72 })
73 if errStr(err) != "assembling instruction 1: invalid scratch slot 16" {
74 t.Fatalf("unexpected error: %v", err)
75 }
76}
77
78func TestVMLoadScratchUnknownDestinationRegister(t *testing.T) {
79 _, _, err := testVM(t, []bpf.Instruction{
80 bpf.LoadScratch{
81 Dst: 100,
82 N: 0,
83 },
84 bpf.RetA{},
85 })
86 if errStr(err) != "assembling instruction 1: invalid target register 100" {
87 t.Fatalf("unexpected error: %v", err)
88 }
89}
90
91func TestVMStoreScratchLoadScratchOneValue(t *testing.T) {
92 vm, done, err := testVM(t, []bpf.Instruction{
93 // Load byte 255
94 bpf.LoadAbsolute{
95 Off: 8,
96 Size: 1,
97 },
98 // Copy to X and store in scratch[0]
99 bpf.TAX{},
100 bpf.StoreScratch{
101 Src: bpf.RegX,
102 N: 0,
103 },
104 // Load byte 1
105 bpf.LoadAbsolute{
106 Off: 9,
107 Size: 1,
108 },
109 // Overwrite 1 with 255 from scratch[0]
110 bpf.LoadScratch{
111 Dst: bpf.RegA,
112 N: 0,
113 },
114 // Return 255
115 bpf.RetA{},
116 })
117 if err != nil {
118 t.Fatalf("failed to load BPF program: %v", err)
119 }
120 defer done()
121
122 out, err := vm.Run([]byte{
123 0xff, 0xff, 0xff, 0xff,
124 0xff, 0xff, 0xff, 0xff,
125 255, 1, 2,
126 })
127 if err != nil {
128 t.Fatalf("unexpected error while running program: %v", err)
129 }
130 if want, got := 3, out; want != got {
131 t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
132 want, got)
133 }
134}
135
136func TestVMStoreScratchLoadScratchMultipleValues(t *testing.T) {
137 vm, done, err := testVM(t, []bpf.Instruction{
138 // Load byte 10
139 bpf.LoadAbsolute{
140 Off: 8,
141 Size: 1,
142 },
143 // Store in scratch[0]
144 bpf.StoreScratch{
145 Src: bpf.RegA,
146 N: 0,
147 },
148 // Load byte 20
149 bpf.LoadAbsolute{
150 Off: 9,
151 Size: 1,
152 },
153 // Store in scratch[1]
154 bpf.StoreScratch{
155 Src: bpf.RegA,
156 N: 1,
157 },
158 // Load byte 30
159 bpf.LoadAbsolute{
160 Off: 10,
161 Size: 1,
162 },
163 // Store in scratch[2]
164 bpf.StoreScratch{
165 Src: bpf.RegA,
166 N: 2,
167 },
168 // Load byte 1
169 bpf.LoadAbsolute{
170 Off: 11,
171 Size: 1,
172 },
173 // Store in scratch[3]
174 bpf.StoreScratch{
175 Src: bpf.RegA,
176 N: 3,
177 },
178 // Load in byte 10 to X
179 bpf.LoadScratch{
180 Dst: bpf.RegX,
181 N: 0,
182 },
183 // Copy X -> A
184 bpf.TXA{},
185 // Verify value is 10
186 bpf.JumpIf{
187 Cond: bpf.JumpEqual,
188 Val: 10,
189 SkipTrue: 1,
190 },
191 // Fail test if incorrect
192 bpf.RetConstant{
193 Val: 0,
194 },
195 // Load in byte 20 to A
196 bpf.LoadScratch{
197 Dst: bpf.RegA,
198 N: 1,
199 },
200 // Verify value is 20
201 bpf.JumpIf{
202 Cond: bpf.JumpEqual,
203 Val: 20,
204 SkipTrue: 1,
205 },
206 // Fail test if incorrect
207 bpf.RetConstant{
208 Val: 0,
209 },
210 // Load in byte 30 to A
211 bpf.LoadScratch{
212 Dst: bpf.RegA,
213 N: 2,
214 },
215 // Verify value is 30
216 bpf.JumpIf{
217 Cond: bpf.JumpEqual,
218 Val: 30,
219 SkipTrue: 1,
220 },
221 // Fail test if incorrect
222 bpf.RetConstant{
223 Val: 0,
224 },
225 // Return first two bytes on success
226 bpf.RetConstant{
227 Val: 10,
228 },
229 })
230 if err != nil {
231 t.Fatalf("failed to load BPF program: %v", err)
232 }
233 defer done()
234
235 out, err := vm.Run([]byte{
236 0xff, 0xff, 0xff, 0xff,
237 0xff, 0xff, 0xff, 0xff,
238 10, 20, 30, 1,
239 })
240 if err != nil {
241 t.Fatalf("unexpected error while running program: %v", err)
242 }
243 if want, got := 2, out; want != got {
244 t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d",
245 want, got)
246 }
247}