1    @Test
2    public void testFullApfV4ProgramGeneration() throws IllegalInstructionException {
3        ApfV4Generator gen = new ApfV4Generator(APF_VERSION_4);
4        gen.addLoadImmediate(R1, -8);
5        gen.addLoadData(R0, 0);
6        gen.addAdd(1);
7        gen.addStoreData(R0, 0);
8        gen.addLoad16(R0, 12);
9        gen.addLoadImmediate(R1, -120);
10        gen.addJumpIfR0LessThan(0x600, "LABEL_INC_AND_DROP");
11        gen.addLoadImmediate(R1, -124);
12        gen.addJumpIfR0Equals(0x88a2, "LABEL_INC_AND_DROP");
13        gen.addJumpIfR0Equals(0x88a4, "LABEL_INC_AND_DROP");
14        gen.addJumpIfR0Equals(0x88b8, "LABEL_INC_AND_DROP");
15        gen.addJumpIfR0Equals(0x88cd, "LABEL_INC_AND_DROP");
16        gen.addJumpIfR0Equals(0x88e1, "LABEL_INC_AND_DROP");
17        gen.addJumpIfR0Equals(0x88e3, "LABEL_INC_AND_DROP");
18        gen.addJumpIfR0NotEquals(0x806, "LABEL_122");
19        gen.addLoadImmediate(R0, 14);
20        gen.addLoadImmediate(R1, -152);
21        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("000108000604"), "LABEL_INC_AND_DROP");
22        gen.addLoad16(R0, 20);
23        gen.addJumpIfR0Equals(0x1, "LABEL_104");
24        gen.addLoadImmediate(R1, -156);
25        gen.addJumpIfR0NotEquals(0x2, "LABEL_INC_AND_DROP");
26        gen.addLoad32(R0, 28);
27        gen.addLoadImmediate(R1, -128);
28        gen.addJumpIfR0Equals(0x0, "LABEL_INC_AND_DROP");
29        gen.addLoadImmediate(R0, 0);
30        gen.addLoadImmediate(R1, -56);
31        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), "LABEL_INC_AND_PASS");
32
33        gen.defineLabel("LABEL_104");
34        gen.addLoadImmediate(R0, 38);
35        gen.addLoadImmediate(R1, -80);
36        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("c0a801ec"), "LABEL_INC_AND_DROP");
37        gen.addLoadImmediate(R1, -20);
38        gen.addJump("LABEL_INC_AND_PASS");
39
40        gen.defineLabel("LABEL_122");
41        gen.addLoad16(R0, 12);
42        gen.addJumpIfR0NotEquals(0x800, "LABEL_249");
43        gen.addLoad8(R0, 23);
44        gen.addJumpIfR0NotEquals(0x11, "LABEL_165");
45        gen.addLoad16(R0, 20);
46        gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_165");
47        gen.addLoadFromMemory(R1, 13);
48        gen.addLoad16Indexed(R0, 16);
49        gen.addJumpIfR0NotEquals(0x44, "LABEL_165");
50        gen.addLoadImmediate(R0, 50);
51        gen.addAddR1();
52        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc7008"), "LABEL_165");
53        gen.addLoadImmediate(R1, -24);
54        gen.addJump("LABEL_INC_AND_PASS");
55
56        gen.defineLabel("LABEL_165");
57        gen.addLoad8(R0, 30);
58        gen.addAnd(240);
59        gen.addLoadImmediate(R1, -96);
60        gen.addJumpIfR0Equals(0xe0, "LABEL_INC_AND_DROP");
61        gen.addLoadImmediate(R1, -88);
62        gen.addLoad32(R0, 30);
63        gen.addJumpIfR0Equals(0xffffffff, "LABEL_INC_AND_DROP");
64        gen.addLoadImmediate(R1, -92);
65        gen.addJumpIfR0Equals(0xc0a801ff, "LABEL_INC_AND_DROP");
66        gen.addLoad8(R0, 23);
67        gen.addJumpIfR0NotEquals(0x6, "LABEL_225");
68        gen.addLoad16(R0, 20);
69        gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_225");
70        gen.addLoadFromMemory(R1, 13);
71        gen.addLoad16Indexed(R0, 16);
72        gen.addJumpIfR0NotEquals(0x7, "LABEL_225");
73        gen.addLoadImmediate(R1, -148);
74        gen.addJump("LABEL_INC_AND_DROP");
75
76        gen.defineLabel("LABEL_225");
77        gen.addLoadImmediate(R1, -36);
78        gen.addLoadImmediate(R0, 0);
79        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), "LABEL_INC_AND_PASS");
80        gen.addLoadImmediate(R1, -84);
81        gen.addJump("LABEL_INC_AND_DROP");
82        gen.addLoadImmediate(R1, -28);
83        gen.addJump("LABEL_INC_AND_PASS");
84
85        gen.defineLabel("LABEL_249");
86        gen.addJumpIfR0Equals(0x86dd, "LABEL_273");
87        gen.addLoadImmediate(R0, 0);
88        gen.addLoadImmediate(R1, -60);
89        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), "LABEL_INC_AND_PASS");
90        gen.addLoadImmediate(R1, -68);
91        gen.addJump("LABEL_INC_AND_DROP");
92
93        gen.defineLabel("LABEL_273");
94        gen.addLoad8(R0, 20);
95        gen.addJumpIfR0Equals(0x0, "LABEL_INC_AND_PASS");
96        gen.addJumpIfR0Equals(0x3a, "LABEL_297");
97        gen.addLoadImmediate(R1, -116);
98        gen.addLoad8(R0, 38);
99        gen.addJumpIfR0Equals(0xff, "LABEL_INC_AND_DROP");
100        gen.addLoadImmediate(R1, -44);
101        gen.addJump("LABEL_INC_AND_PASS");
102
103        gen.defineLabel("LABEL_297");
104        gen.addLoad8(R0, 54);
105        gen.addLoadImmediate(R1, -100);
106        gen.addJumpIfR0Equals(0x85, "LABEL_INC_AND_DROP");
107        gen.addJumpIfR0NotEquals(0x88, "LABEL_333");
108        gen.addLoadImmediate(R0, 38);
109        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff0200000000000000000000000000"), "LABEL_333");
110        gen.addLoadImmediate(R1, -104);
111        gen.addJump("LABEL_INC_AND_DROP");
112
113        gen.defineLabel("LABEL_333");
114        gen.addLoadFromMemory(R0, 14);
115        gen.addJumpIfR0NotEquals(0x96, "LABEL_UNSOLICITED_MULTICAST_NA");
116        gen.addLoadFromMemory(R0, 15);
117        gen.addJumpIfR0GreaterThan(0x48e, "LABEL_UNSOLICITED_MULTICAST_NA");
118        gen.addLoadImmediate(R0, 0);
119        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc700828c68e23672c86dd60"), "LABEL_UNSOLICITED_MULTICAST_NA");
120        gen.addLoadImmediate(R0, 18);
121        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("00603afffe800000000000002ac68efffe23672c"), "LABEL_UNSOLICITED_MULTICAST_NA");
122        gen.addLoadImmediate(R0, 54);
123        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("8600"), "LABEL_UNSOLICITED_MULTICAST_NA");
124        gen.addLoadImmediate(R0, 58);
125        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("40c0"), "LABEL_UNSOLICITED_MULTICAST_NA");
126        gen.addLoad16(R0, 60);
127        gen.addJumpIfR0LessThan(0x91e, "LABEL_UNSOLICITED_MULTICAST_NA");
128        gen.addJumpIfR0GreaterThan(0x1b58, "LABEL_UNSOLICITED_MULTICAST_NA");
129        gen.addLoadImmediate(R0, 62);
130        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("0000000000000000010128c68e23672c05010000000005dc030440c0"), "LABEL_UNSOLICITED_MULTICAST_NA");
131        gen.addLoad32(R0, 90);
132        gen.addJumpIfR0LessThan(0x55555555, "LABEL_UNSOLICITED_MULTICAST_NA");
133        gen.addJumpIfR0GreaterThan(0xffffffffL, "LABEL_UNSOLICITED_MULTICAST_NA");
134        gen.addLoad32(R0, 94);
135        gen.addJumpIfR0LessThan(0x55555555, "LABEL_UNSOLICITED_MULTICAST_NA");
136        gen.addJumpIfR0GreaterThan(0xffffffffL, "LABEL_UNSOLICITED_MULTICAST_NA");
137        gen.addLoadImmediate(R0, 98);
138        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("000000002401fa000480f000000000000000000019030000"), "LABEL_UNSOLICITED_MULTICAST_NA");
139        gen.addLoad32(R0, 122);
140        gen.addJumpIfR0Equals(0x0, "LABEL_UNSOLICITED_MULTICAST_NA");
141        gen.addJumpIfR0LessThan(0x78, "LABEL_535");
142        gen.addJumpIfR0LessThan(0x91e, "LABEL_UNSOLICITED_MULTICAST_NA");
143        gen.addJumpIfR0GreaterThan(0x1b58, "LABEL_UNSOLICITED_MULTICAST_NA");
144
145        gen.defineLabel("LABEL_535");
146        gen.addLoadImmediate(R0, 126);
147        gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("2401fa000480f00000000000000000010701"), "LABEL_UNSOLICITED_MULTICAST_NA");
148        gen.addLoadImmediate(R1, -72);
149        gen.addJump("LABEL_INC_AND_DROP");
150
151        gen.defineLabel("LABEL_UNSOLICITED_MULTICAST_NA");
152        gen.addLoadImmediate(R1, -40);
153
154        gen.defineLabel("LABEL_INC_AND_PASS");
155        gen.addLoadData(R0, 0);
156        gen.addAdd(1);
157        gen.addStoreData(R0, 0);
158        gen.addJump(PASS_LABEL);
159
160        gen.defineLabel("LABEL_INC_AND_DROP");
161        gen.addLoadData(R0, 0);
162        gen.addAdd(1);
163        gen.addStoreData(R0, 0);
164        gen.addJump(DROP_LABEL);
165
166        byte[] program = gen.generate();
167        final String programString = toHexString(program).toLowerCase();
168        final String referenceProgramHexString = "6bf8b03a01b8120c6b8894022b06006b847c022488a27c021f88a47c021a88b87c021588cd7c021088e17c020b88e384004608066a0e6dff68a401f6000600010800060412147a1f016dff648401e900021a1c6b807c01e00000686bc8a401cc0006ffffffffffff6a266bb0a401c50004c0a801ec6bec7401ba120c84007808000a17821f1112149c00181fffab0d2a108211446a3239a205067e9046bc70086be874018f0a1e52f06ba07c018a00e06ba81a1e7e0000017dffffffff6ba47e00000172c0a801ff0a1782140612149c000d1fffab0d2a108206076dff6c7401596bdc68a401450006ffffffffffff6bac7401466be474013b7c001386dd686bc4a401280006ffffffffffff6bbc7401290a147c011c00007a0e3a6b8c0a267c011600ff6bd474010b0a366b9c7c010800858218886a26a2040fff02000000000000000000000000006b9872edaa0e82e096aa0f8c00d9048e68a2c60f7e9046bc700828c68e23672c86dd606a12a2ad1400603afffe800000000000002ac68efffe23672c6a36a2a60286006a3aa29f0240c0123c940098091e8c00931b586a3ea2721c0000000000000000010128c68e23672c05010000000005dc030440c01a5a9600000067555555558e0000005effffffff1a5e9600000053555555558e0000004affffffff6a62a22d18000000002401fa000480f0000000000000000000190300001a7a7a2800920a78940020091e8c001b1b586a7ea204122401fa000480f000000000000000000107016bb872086bd8b03a01b87206b03a01b87201";
169        assertEquals(referenceProgramHexString, programString);
170    }
171