xref: /DragonOS/kernel/crates/rbpf/tests/assembler.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
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 
12 fn asm(src: &str) -> Result<Vec<ebpf::Insn>, String> {
13     Ok(ebpf::to_insn_vec(&(assemble(src))?))
14 }
15 
16 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]
27 fn test_empty() {
28     assert_eq!(asm(""), Ok(vec![]));
29 }
30 
31 // Example for InstructionType::NoOperand.
32 #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
600 fn test_tcp_sack() {
601     assert_eq!(assemble(TCP_SACK_ASM), Ok(TCP_SACK_BIN.to_vec()));
602 }
603 
604 #[test]
605 fn test_error_invalid_instruction() {
606     assert_eq!(asm("abcd"), Err("Invalid instruction \"abcd\"".to_string()));
607 }
608 
609 #[test]
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]
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]
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