1 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
2 // Copyright 2017 Rich Lane <lanerl@gmail.com>
3
4 #![allow(clippy::unreadable_literal)]
5
6 extern crate rbpf;
7 mod common;
8
9 use common::{TCP_SACK_ASM, TCP_SACK_BIN};
10 use rbpf::{assembler::assemble, ebpf};
11
asm(src: &str) -> Result<Vec<ebpf::Insn>, String>12 fn asm(src: &str) -> Result<Vec<ebpf::Insn>, String> {
13 Ok(ebpf::to_insn_vec(&(assemble(src))?))
14 }
15
insn(opc: u8, dst: u8, src: u8, off: i16, imm: i32) -> ebpf::Insn16 fn insn(opc: u8, dst: u8, src: u8, off: i16, imm: i32) -> ebpf::Insn {
17 ebpf::Insn {
18 opc,
19 dst,
20 src,
21 off,
22 imm,
23 }
24 }
25
26 #[test]
test_empty()27 fn test_empty() {
28 assert_eq!(asm(""), Ok(vec![]));
29 }
30
31 // Example for InstructionType::NoOperand.
32 #[test]
test_exit()33 fn test_exit() {
34 assert_eq!(asm("exit"), Ok(vec![insn(ebpf::EXIT, 0, 0, 0, 0)]));
35 }
36
37 // Example for InstructionType::AluBinary.
38 #[test]
test_add64()39 fn test_add64() {
40 assert_eq!(
41 asm("add64 r1, r3"),
42 Ok(vec![insn(ebpf::ADD64_REG, 1, 3, 0, 0)])
43 );
44 assert_eq!(
45 asm("add64 r1, 5"),
46 Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 5)])
47 );
48 }
49
50 // Example for InstructionType::AluUnary.
51 #[test]
test_neg64()52 fn test_neg64() {
53 assert_eq!(asm("neg64 r1"), Ok(vec![insn(ebpf::NEG64, 1, 0, 0, 0)]));
54 }
55
56 // Example for InstructionType::LoadReg.
57 #[test]
test_ldxw()58 fn test_ldxw() {
59 assert_eq!(
60 asm("ldxw r1, [r2+5]"),
61 Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 5, 0)])
62 );
63 }
64
65 // Example for InstructionType::StoreImm.
66 #[test]
test_stw()67 fn test_stw() {
68 assert_eq!(
69 asm("stw [r2+5], 7"),
70 Ok(vec![insn(ebpf::ST_W_IMM, 2, 0, 5, 7)])
71 );
72 }
73
74 // Example for InstructionType::StoreReg.
75 #[test]
test_stxw()76 fn test_stxw() {
77 assert_eq!(
78 asm("stxw [r2+5], r8"),
79 Ok(vec![insn(ebpf::ST_W_REG, 2, 8, 5, 0)])
80 );
81 }
82
83 // Example for InstructionType::JumpUnconditional.
84 #[test]
test_ja()85 fn test_ja() {
86 assert_eq!(asm("ja +8"), Ok(vec![insn(ebpf::JA, 0, 0, 8, 0)]));
87 assert_eq!(asm("ja -3"), Ok(vec![insn(ebpf::JA, 0, 0, -3, 0)]));
88 }
89
90 // Example for InstructionType::JumpConditional.
91 #[test]
test_jeq()92 fn test_jeq() {
93 assert_eq!(
94 asm("jeq r1, 4, +8"),
95 Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 8, 4)])
96 );
97 assert_eq!(
98 asm("jeq r1, r3, +8"),
99 Ok(vec![insn(ebpf::JEQ_REG, 1, 3, 8, 0)])
100 );
101 }
102
103 // Example for InstructionType::Call.
104 #[test]
test_call()105 fn test_call() {
106 assert_eq!(asm("call 300"), Ok(vec![insn(ebpf::CALL, 0, 0, 0, 300)]));
107 }
108
109 // Example for InstructionType::Endian.
110 #[test]
test_be32()111 fn test_be32() {
112 assert_eq!(asm("be32 r1"), Ok(vec![insn(ebpf::BE, 1, 0, 0, 32)]));
113 }
114
115 // Example for InstructionType::LoadImm.
116 #[test]
test_lddw()117 fn test_lddw() {
118 assert_eq!(
119 asm("lddw r1, 0x1234abcd5678eeff"),
120 Ok(vec![
121 insn(ebpf::LD_DW_IMM, 1, 0, 0, 0x5678eeff),
122 insn(0, 0, 0, 0, 0x1234abcd)
123 ])
124 );
125 assert_eq!(
126 asm("lddw r1, 0xff11ee22dd33cc44"),
127 Ok(vec![
128 insn(ebpf::LD_DW_IMM, 1, 0, 0, 0xdd33cc44u32 as i32),
129 insn(0, 0, 0, 0, 0xff11ee22u32 as i32)
130 ])
131 );
132 }
133
134 // Example for InstructionType::LoadAbs.
135 #[test]
test_ldabsw()136 fn test_ldabsw() {
137 assert_eq!(asm("ldabsw 1"), Ok(vec![insn(ebpf::LD_ABS_W, 0, 0, 0, 1)]));
138 }
139
140 // Example for InstructionType::LoadInd.
141 #[test]
test_ldindw()142 fn test_ldindw() {
143 assert_eq!(
144 asm("ldindw r1, 2"),
145 Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2)])
146 );
147 }
148
149 // Example for InstructionType::LoadReg.
150 #[test]
test_ldxdw()151 fn test_ldxdw() {
152 assert_eq!(
153 asm("ldxdw r1, [r2+3]"),
154 Ok(vec![insn(ebpf::LD_DW_REG, 1, 2, 3, 0)])
155 );
156 }
157
158 // Example for InstructionType::StoreImm.
159 #[test]
test_sth()160 fn test_sth() {
161 assert_eq!(
162 asm("sth [r1+2], 3"),
163 Ok(vec![insn(ebpf::ST_H_IMM, 1, 0, 2, 3)])
164 );
165 }
166
167 // Example for InstructionType::StoreReg.
168 #[test]
test_stxh()169 fn test_stxh() {
170 assert_eq!(
171 asm("stxh [r1+2], r3"),
172 Ok(vec![insn(ebpf::ST_H_REG, 1, 3, 2, 0)])
173 );
174 }
175
176 // Test all supported AluBinary mnemonics.
177 #[test]
test_alu_binary()178 fn test_alu_binary() {
179 assert_eq!(
180 asm("add r1, r2
181 sub r1, r2
182 mul r1, r2
183 div r1, r2
184 or r1, r2
185 and r1, r2
186 lsh r1, r2
187 rsh r1, r2
188 mod r1, r2
189 xor r1, r2
190 mov r1, r2
191 arsh r1, r2"),
192 Ok(vec![
193 insn(ebpf::ADD64_REG, 1, 2, 0, 0),
194 insn(ebpf::SUB64_REG, 1, 2, 0, 0),
195 insn(ebpf::MUL64_REG, 1, 2, 0, 0),
196 insn(ebpf::DIV64_REG, 1, 2, 0, 0),
197 insn(ebpf::OR64_REG, 1, 2, 0, 0),
198 insn(ebpf::AND64_REG, 1, 2, 0, 0),
199 insn(ebpf::LSH64_REG, 1, 2, 0, 0),
200 insn(ebpf::RSH64_REG, 1, 2, 0, 0),
201 insn(ebpf::MOD64_REG, 1, 2, 0, 0),
202 insn(ebpf::XOR64_REG, 1, 2, 0, 0),
203 insn(ebpf::MOV64_REG, 1, 2, 0, 0),
204 insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
205 ])
206 );
207
208 assert_eq!(
209 asm("add r1, 2
210 sub r1, 2
211 mul r1, 2
212 div r1, 2
213 or r1, 2
214 and r1, 2
215 lsh r1, 2
216 rsh r1, 2
217 mod r1, 2
218 xor r1, 2
219 mov r1, 2
220 arsh r1, 2"),
221 Ok(vec![
222 insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
223 insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
224 insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
225 insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
226 insn(ebpf::OR64_IMM, 1, 0, 0, 2),
227 insn(ebpf::AND64_IMM, 1, 0, 0, 2),
228 insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
229 insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
230 insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
231 insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
232 insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
233 insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
234 ])
235 );
236
237 assert_eq!(
238 asm("add64 r1, r2
239 sub64 r1, r2
240 mul64 r1, r2
241 div64 r1, r2
242 or64 r1, r2
243 and64 r1, r2
244 lsh64 r1, r2
245 rsh64 r1, r2
246 mod64 r1, r2
247 xor64 r1, r2
248 mov64 r1, r2
249 arsh64 r1, r2"),
250 Ok(vec![
251 insn(ebpf::ADD64_REG, 1, 2, 0, 0),
252 insn(ebpf::SUB64_REG, 1, 2, 0, 0),
253 insn(ebpf::MUL64_REG, 1, 2, 0, 0),
254 insn(ebpf::DIV64_REG, 1, 2, 0, 0),
255 insn(ebpf::OR64_REG, 1, 2, 0, 0),
256 insn(ebpf::AND64_REG, 1, 2, 0, 0),
257 insn(ebpf::LSH64_REG, 1, 2, 0, 0),
258 insn(ebpf::RSH64_REG, 1, 2, 0, 0),
259 insn(ebpf::MOD64_REG, 1, 2, 0, 0),
260 insn(ebpf::XOR64_REG, 1, 2, 0, 0),
261 insn(ebpf::MOV64_REG, 1, 2, 0, 0),
262 insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
263 ])
264 );
265
266 assert_eq!(
267 asm("add64 r1, 2
268 sub64 r1, 2
269 mul64 r1, 2
270 div64 r1, 2
271 or64 r1, 2
272 and64 r1, 2
273 lsh64 r1, 2
274 rsh64 r1, 2
275 mod64 r1, 2
276 xor64 r1, 2
277 mov64 r1, 2
278 arsh64 r1, 2"),
279 Ok(vec![
280 insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
281 insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
282 insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
283 insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
284 insn(ebpf::OR64_IMM, 1, 0, 0, 2),
285 insn(ebpf::AND64_IMM, 1, 0, 0, 2),
286 insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
287 insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
288 insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
289 insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
290 insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
291 insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
292 ])
293 );
294
295 assert_eq!(
296 asm("add32 r1, r2
297 sub32 r1, r2
298 mul32 r1, r2
299 div32 r1, r2
300 or32 r1, r2
301 and32 r1, r2
302 lsh32 r1, r2
303 rsh32 r1, r2
304 mod32 r1, r2
305 xor32 r1, r2
306 mov32 r1, r2
307 arsh32 r1, r2"),
308 Ok(vec![
309 insn(ebpf::ADD32_REG, 1, 2, 0, 0),
310 insn(ebpf::SUB32_REG, 1, 2, 0, 0),
311 insn(ebpf::MUL32_REG, 1, 2, 0, 0),
312 insn(ebpf::DIV32_REG, 1, 2, 0, 0),
313 insn(ebpf::OR32_REG, 1, 2, 0, 0),
314 insn(ebpf::AND32_REG, 1, 2, 0, 0),
315 insn(ebpf::LSH32_REG, 1, 2, 0, 0),
316 insn(ebpf::RSH32_REG, 1, 2, 0, 0),
317 insn(ebpf::MOD32_REG, 1, 2, 0, 0),
318 insn(ebpf::XOR32_REG, 1, 2, 0, 0),
319 insn(ebpf::MOV32_REG, 1, 2, 0, 0),
320 insn(ebpf::ARSH32_REG, 1, 2, 0, 0)
321 ])
322 );
323
324 assert_eq!(
325 asm("add32 r1, 2
326 sub32 r1, 2
327 mul32 r1, 2
328 div32 r1, 2
329 or32 r1, 2
330 and32 r1, 2
331 lsh32 r1, 2
332 rsh32 r1, 2
333 mod32 r1, 2
334 xor32 r1, 2
335 mov32 r1, 2
336 arsh32 r1, 2"),
337 Ok(vec![
338 insn(ebpf::ADD32_IMM, 1, 0, 0, 2),
339 insn(ebpf::SUB32_IMM, 1, 0, 0, 2),
340 insn(ebpf::MUL32_IMM, 1, 0, 0, 2),
341 insn(ebpf::DIV32_IMM, 1, 0, 0, 2),
342 insn(ebpf::OR32_IMM, 1, 0, 0, 2),
343 insn(ebpf::AND32_IMM, 1, 0, 0, 2),
344 insn(ebpf::LSH32_IMM, 1, 0, 0, 2),
345 insn(ebpf::RSH32_IMM, 1, 0, 0, 2),
346 insn(ebpf::MOD32_IMM, 1, 0, 0, 2),
347 insn(ebpf::XOR32_IMM, 1, 0, 0, 2),
348 insn(ebpf::MOV32_IMM, 1, 0, 0, 2),
349 insn(ebpf::ARSH32_IMM, 1, 0, 0, 2)
350 ])
351 );
352 }
353
354 // Test all supported AluUnary mnemonics.
355 #[test]
test_alu_unary()356 fn test_alu_unary() {
357 assert_eq!(
358 asm("neg r1
359 neg64 r1
360 neg32 r1"),
361 Ok(vec![
362 insn(ebpf::NEG64, 1, 0, 0, 0),
363 insn(ebpf::NEG64, 1, 0, 0, 0),
364 insn(ebpf::NEG32, 1, 0, 0, 0)
365 ])
366 );
367 }
368
369 // Test all supported LoadAbs mnemonics.
370 #[test]
test_load_abs()371 fn test_load_abs() {
372 assert_eq!(
373 asm("ldabsw 1
374 ldabsh 1
375 ldabsb 1
376 ldabsdw 1"),
377 Ok(vec![
378 insn(ebpf::LD_ABS_W, 0, 0, 0, 1),
379 insn(ebpf::LD_ABS_H, 0, 0, 0, 1),
380 insn(ebpf::LD_ABS_B, 0, 0, 0, 1),
381 insn(ebpf::LD_ABS_DW, 0, 0, 0, 1)
382 ])
383 );
384 }
385
386 // Test all supported LoadInd mnemonics.
387 #[test]
test_load_ind()388 fn test_load_ind() {
389 assert_eq!(
390 asm("ldindw r1, 2
391 ldindh r1, 2
392 ldindb r1, 2
393 ldinddw r1, 2"),
394 Ok(vec![
395 insn(ebpf::LD_IND_W, 0, 1, 0, 2),
396 insn(ebpf::LD_IND_H, 0, 1, 0, 2),
397 insn(ebpf::LD_IND_B, 0, 1, 0, 2),
398 insn(ebpf::LD_IND_DW, 0, 1, 0, 2)
399 ])
400 );
401 }
402
403 // Test all supported LoadReg mnemonics.
404 #[test]
test_load_reg()405 fn test_load_reg() {
406 assert_eq!(
407 asm("ldxw r1, [r2+3]
408 ldxh r1, [r2+3]
409 ldxb r1, [r2+3]
410 ldxdw r1, [r2+3]"),
411 Ok(vec![
412 insn(ebpf::LD_W_REG, 1, 2, 3, 0),
413 insn(ebpf::LD_H_REG, 1, 2, 3, 0),
414 insn(ebpf::LD_B_REG, 1, 2, 3, 0),
415 insn(ebpf::LD_DW_REG, 1, 2, 3, 0)
416 ])
417 );
418 }
419
420 // Test all supported StoreImm mnemonics.
421 #[test]
test_store_imm()422 fn test_store_imm() {
423 assert_eq!(
424 asm("stw [r1+2], 3
425 sth [r1+2], 3
426 stb [r1+2], 3
427 stdw [r1+2], 3"),
428 Ok(vec![
429 insn(ebpf::ST_W_IMM, 1, 0, 2, 3),
430 insn(ebpf::ST_H_IMM, 1, 0, 2, 3),
431 insn(ebpf::ST_B_IMM, 1, 0, 2, 3),
432 insn(ebpf::ST_DW_IMM, 1, 0, 2, 3)
433 ])
434 );
435 }
436
437 // Test all supported StoreReg mnemonics.
438 #[test]
test_store_reg()439 fn test_store_reg() {
440 assert_eq!(
441 asm("stxw [r1+2], r3
442 stxh [r1+2], r3
443 stxb [r1+2], r3
444 stxdw [r1+2], r3"),
445 Ok(vec![
446 insn(ebpf::ST_W_REG, 1, 3, 2, 0),
447 insn(ebpf::ST_H_REG, 1, 3, 2, 0),
448 insn(ebpf::ST_B_REG, 1, 3, 2, 0),
449 insn(ebpf::ST_DW_REG, 1, 3, 2, 0)
450 ])
451 );
452 }
453
454 // Test all supported JumpConditional mnemonics.
455 #[test]
test_jump_conditional()456 fn test_jump_conditional() {
457 assert_eq!(
458 asm("jeq r1, r2, +3
459 jgt r1, r2, +3
460 jge r1, r2, +3
461 jlt r1, r2, +3
462 jle r1, r2, +3
463 jset r1, r2, +3
464 jne r1, r2, +3
465 jsgt r1, r2, +3
466 jsge r1, r2, +3
467 jslt r1, r2, +3
468 jsle r1, r2, +3"),
469 Ok(vec![
470 insn(ebpf::JEQ_REG, 1, 2, 3, 0),
471 insn(ebpf::JGT_REG, 1, 2, 3, 0),
472 insn(ebpf::JGE_REG, 1, 2, 3, 0),
473 insn(ebpf::JLT_REG, 1, 2, 3, 0),
474 insn(ebpf::JLE_REG, 1, 2, 3, 0),
475 insn(ebpf::JSET_REG, 1, 2, 3, 0),
476 insn(ebpf::JNE_REG, 1, 2, 3, 0),
477 insn(ebpf::JSGT_REG, 1, 2, 3, 0),
478 insn(ebpf::JSGE_REG, 1, 2, 3, 0),
479 insn(ebpf::JSLT_REG, 1, 2, 3, 0),
480 insn(ebpf::JSLE_REG, 1, 2, 3, 0)
481 ])
482 );
483
484 assert_eq!(
485 asm("jeq r1, 2, +3
486 jgt r1, 2, +3
487 jge r1, 2, +3
488 jlt r1, 2, +3
489 jle r1, 2, +3
490 jset r1, 2, +3
491 jne r1, 2, +3
492 jsgt r1, 2, +3
493 jsge r1, 2, +3
494 jslt r1, 2, +3
495 jsle r1, 2, +3"),
496 Ok(vec![
497 insn(ebpf::JEQ_IMM, 1, 0, 3, 2),
498 insn(ebpf::JGT_IMM, 1, 0, 3, 2),
499 insn(ebpf::JGE_IMM, 1, 0, 3, 2),
500 insn(ebpf::JLT_IMM, 1, 0, 3, 2),
501 insn(ebpf::JLE_IMM, 1, 0, 3, 2),
502 insn(ebpf::JSET_IMM, 1, 0, 3, 2),
503 insn(ebpf::JNE_IMM, 1, 0, 3, 2),
504 insn(ebpf::JSGT_IMM, 1, 0, 3, 2),
505 insn(ebpf::JSGE_IMM, 1, 0, 3, 2),
506 insn(ebpf::JSLT_IMM, 1, 0, 3, 2),
507 insn(ebpf::JSLE_IMM, 1, 0, 3, 2)
508 ])
509 );
510
511 assert_eq!(
512 asm("jeq32 r1, r2, +3
513 jgt32 r1, r2, +3
514 jge32 r1, r2, +3
515 jlt32 r1, r2, +3
516 jle32 r1, r2, +3
517 jset32 r1, r2, +3
518 jne32 r1, r2, +3
519 jsgt32 r1, r2, +3
520 jsge32 r1, r2, +3
521 jslt32 r1, r2, +3
522 jsle32 r1, r2, +3"),
523 Ok(vec![
524 insn(ebpf::JEQ_REG32, 1, 2, 3, 0),
525 insn(ebpf::JGT_REG32, 1, 2, 3, 0),
526 insn(ebpf::JGE_REG32, 1, 2, 3, 0),
527 insn(ebpf::JLT_REG32, 1, 2, 3, 0),
528 insn(ebpf::JLE_REG32, 1, 2, 3, 0),
529 insn(ebpf::JSET_REG32, 1, 2, 3, 0),
530 insn(ebpf::JNE_REG32, 1, 2, 3, 0),
531 insn(ebpf::JSGT_REG32, 1, 2, 3, 0),
532 insn(ebpf::JSGE_REG32, 1, 2, 3, 0),
533 insn(ebpf::JSLT_REG32, 1, 2, 3, 0),
534 insn(ebpf::JSLE_REG32, 1, 2, 3, 0)
535 ])
536 );
537
538 assert_eq!(
539 asm("jeq32 r1, 2, +3
540 jgt32 r1, 2, +3
541 jge32 r1, 2, +3
542 jlt32 r1, 2, +3
543 jle32 r1, 2, +3
544 jset32 r1, 2, +3
545 jne32 r1, 2, +3
546 jsgt32 r1, 2, +3
547 jsge32 r1, 2, +3
548 jslt32 r1, 2, +3
549 jsle32 r1, 2, +3"),
550 Ok(vec![
551 insn(ebpf::JEQ_IMM32, 1, 0, 3, 2),
552 insn(ebpf::JGT_IMM32, 1, 0, 3, 2),
553 insn(ebpf::JGE_IMM32, 1, 0, 3, 2),
554 insn(ebpf::JLT_IMM32, 1, 0, 3, 2),
555 insn(ebpf::JLE_IMM32, 1, 0, 3, 2),
556 insn(ebpf::JSET_IMM32, 1, 0, 3, 2),
557 insn(ebpf::JNE_IMM32, 1, 0, 3, 2),
558 insn(ebpf::JSGT_IMM32, 1, 0, 3, 2),
559 insn(ebpf::JSGE_IMM32, 1, 0, 3, 2),
560 insn(ebpf::JSLT_IMM32, 1, 0, 3, 2),
561 insn(ebpf::JSLE_IMM32, 1, 0, 3, 2)
562 ])
563 );
564 }
565
566 // Test all supported Endian mnemonics.
567 #[test]
test_endian()568 fn test_endian() {
569 assert_eq!(
570 asm("be16 r1
571 be32 r1
572 be64 r1
573 le16 r1
574 le32 r1
575 le64 r1"),
576 Ok(vec![
577 insn(ebpf::BE, 1, 0, 0, 16),
578 insn(ebpf::BE, 1, 0, 0, 32),
579 insn(ebpf::BE, 1, 0, 0, 64),
580 insn(ebpf::LE, 1, 0, 0, 16),
581 insn(ebpf::LE, 1, 0, 0, 32),
582 insn(ebpf::LE, 1, 0, 0, 64)
583 ])
584 );
585 }
586
587 #[test]
test_large_immediate()588 fn test_large_immediate() {
589 assert_eq!(
590 asm("add64 r1, 2147483647"),
591 Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2147483647)])
592 );
593 assert_eq!(
594 asm("add64 r1, -2147483648"),
595 Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, -2147483648)])
596 );
597 }
598
599 #[test]
test_tcp_sack()600 fn test_tcp_sack() {
601 assert_eq!(assemble(TCP_SACK_ASM), Ok(TCP_SACK_BIN.to_vec()));
602 }
603
604 #[test]
test_error_invalid_instruction()605 fn test_error_invalid_instruction() {
606 assert_eq!(asm("abcd"), Err("Invalid instruction \"abcd\"".to_string()));
607 }
608
609 #[test]
test_error_unexpected_operands()610 fn test_error_unexpected_operands() {
611 assert_eq!(
612 asm("add 1, 2"),
613 Err("Failed to encode add: Unexpected operands: [Integer(1), Integer(2)]".to_string())
614 );
615 }
616
617 #[test]
test_error_too_many_operands()618 fn test_error_too_many_operands() {
619 assert_eq!(
620 asm("add 1, 2, 3, 4"),
621 Err("Failed to encode add: Too many operands".to_string())
622 );
623 }
624
625 #[test]
test_error_operands_out_of_range()626 fn test_error_operands_out_of_range() {
627 assert_eq!(
628 asm("add r16, r2"),
629 Err("Failed to encode add: Invalid destination register 16".to_string())
630 );
631 assert_eq!(
632 asm("add r1, r16"),
633 Err("Failed to encode add: Invalid source register 16".to_string())
634 );
635 assert_eq!(
636 asm("ja -32769"),
637 Err("Failed to encode ja: Invalid offset -32769".to_string())
638 );
639 assert_eq!(
640 asm("ja 32768"),
641 Err("Failed to encode ja: Invalid offset 32768".to_string())
642 );
643 assert_eq!(
644 asm("add r1, 4294967296"),
645 Err("Failed to encode add: Invalid immediate 4294967296".to_string())
646 );
647 assert_eq!(
648 asm("add r1, 2147483648"),
649 Err("Failed to encode add: Invalid immediate 2147483648".to_string())
650 );
651 assert_eq!(
652 asm("add r1, -2147483649"),
653 Err("Failed to encode add: Invalid immediate -2147483649".to_string())
654 );
655 }
656