blob: a514457c4833cb47fb3e58a9f3b4a9ed15b1558f [file] [log] [blame]
Yuyang Huangae57be02023-10-16 17:49:31 +09001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.net.apf
17
Yuyang Huangce1493a2023-12-07 15:29:40 +090018import android.net.apf.ApfGenerator.IllegalInstructionException
Yuyang Huange84a9692024-01-01 11:49:49 +090019import android.net.apf.ApfGenerator.Register.R0
20import android.net.apf.ApfGenerator.Register.R1
Yuyang Huangae57be02023-10-16 17:49:31 +090021import androidx.test.filters.SmallTest
22import androidx.test.runner.AndroidJUnit4
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090023import java.lang.IllegalArgumentException
Yuyang Huangae57be02023-10-16 17:49:31 +090024import kotlin.test.assertContentEquals
Yuyang Huangce1493a2023-12-07 15:29:40 +090025import kotlin.test.assertFailsWith
Yuyang Huangae57be02023-10-16 17:49:31 +090026import org.junit.Test
27import org.junit.runner.RunWith
28
29/**
30 * Tests for APFv6 specific instructions.
31 */
32@RunWith(AndroidJUnit4::class)
33@SmallTest
34class ApfV5Test {
35
36 @Test
Yuyang Huangce1493a2023-12-07 15:29:40 +090037 fun testApfInstructionVersionCheck() {
38 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION)
39 assertFailsWith<IllegalInstructionException> { gen.addDrop() }
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090040 assertFailsWith<IllegalInstructionException> { gen.addCountAndDrop(12) }
41 assertFailsWith<IllegalInstructionException> { gen.addCountAndPass(1000) }
Yuyang Huangfd74ce42023-12-12 20:10:45 +090042 assertFailsWith<IllegalInstructionException> { gen.addTransmit() }
43 assertFailsWith<IllegalInstructionException> { gen.addDiscard() }
Yuyang Huang3ac843c2023-12-13 16:40:15 +090044 assertFailsWith<IllegalInstructionException> { gen.addAllocateR0() }
45 assertFailsWith<IllegalInstructionException> { gen.addAllocate(100) }
Yuyang Huanga112cc82023-12-13 17:55:47 +090046 assertFailsWith<IllegalInstructionException> { gen.addData(ByteArray(3) { 0x01 }) }
Yuyang Huang4ac891f2023-12-20 11:49:11 +090047 assertFailsWith<IllegalInstructionException> { gen.addWrite1(100) }
48 assertFailsWith<IllegalInstructionException> { gen.addWrite2(100) }
49 assertFailsWith<IllegalInstructionException> { gen.addWrite4(100) }
Yuyang Huang293f7e72023-12-31 14:24:03 +090050 assertFailsWith<IllegalInstructionException> { gen.addPacketCopy(100, 100) }
51 assertFailsWith<IllegalInstructionException> { gen.addDataCopy(100, 100) }
Yuyang Huange84a9692024-01-01 11:49:49 +090052 assertFailsWith<IllegalInstructionException> { gen.addWriteU8(R0) }
53 assertFailsWith<IllegalInstructionException> { gen.addWriteU16(R0) }
54 assertFailsWith<IllegalInstructionException> { gen.addWriteU32(R0) }
55 assertFailsWith<IllegalInstructionException> { gen.addWriteU8(R1) }
56 assertFailsWith<IllegalInstructionException> { gen.addWriteU16(R1) }
57 assertFailsWith<IllegalInstructionException> { gen.addWriteU32(R1) }
Yuyang Huangd0390612024-01-01 16:21:16 +090058 assertFailsWith<IllegalInstructionException> { gen.addPacketCopyFromR0LenR1() }
59 assertFailsWith<IllegalInstructionException> { gen.addDataCopyFromR0LenR1() }
60 assertFailsWith<IllegalInstructionException> { gen.addPacketCopyFromR0(10) }
61 assertFailsWith<IllegalInstructionException> { gen.addDataCopyFromR0(10) }
Yuyang Huanga112cc82023-12-13 17:55:47 +090062 }
63
64 @Test
65 fun testDataInstructionMustComeFirst() {
66 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
67 gen.addAllocateR0()
68 assertFailsWith<IllegalInstructionException> { gen.addData(ByteArray(3) { 0x01 }) }
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090069 }
70
71 @Test
Yuyang Huang3ac843c2023-12-13 16:40:15 +090072 fun testApfInstructionEncodingSizeCheck() {
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090073 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huang3ac843c2023-12-13 16:40:15 +090074 assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) }
75 assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) }
Yuyang Huang293f7e72023-12-31 14:24:03 +090076 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(-1, 1) }
77 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(-1, 1) }
78 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, 256) }
79 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, 256) }
80 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, -1) }
81 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, -1) }
Yuyang Huangd0390612024-01-01 16:21:16 +090082 assertFailsWith<IllegalArgumentException> { gen.addPacketCopyFromR0(256) }
83 assertFailsWith<IllegalArgumentException> { gen.addDataCopyFromR0(256) }
Yuyang Huangce1493a2023-12-07 15:29:40 +090084 }
85
86 @Test
Yuyang Huangae57be02023-10-16 17:49:31 +090087 fun testApfInstructionsEncoding() {
Yuyang Huangdcdb4442023-12-07 14:56:21 +090088 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION)
89 gen.addPass()
Yuyang Huangae57be02023-10-16 17:49:31 +090090 var program = gen.generate()
Yuyang Huangdcdb4442023-12-07 14:56:21 +090091 // encoding PASS opcode: opcode=0, imm_len=0, R=0
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090092 assertContentEquals(
93 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 0)), program)
Yuyang Huangdcdb4442023-12-07 14:56:21 +090094
95 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangce1493a2023-12-07 15:29:40 +090096 gen.addDrop()
97 program = gen.generate()
98 // encoding DROP opcode: opcode=0, imm_len=0, R=1
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090099 assertContentEquals(
100 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)), program)
101
102 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
103 gen.addCountAndPass(129)
104 program = gen.generate()
105 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber
106 assertContentEquals(
107 byteArrayOf(encodeInstruction(opcode = 0, immLength = 1, register = 0),
108 0x81.toByte()), program)
109
110 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
111 gen.addCountAndDrop(1000)
112 program = gen.generate()
113 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber
114 assertContentEquals(
115 byteArrayOf(encodeInstruction(opcode = 0, immLength = 2, register = 1),
116 0x03, 0xe8.toByte()), program)
Yuyang Huangce1493a2023-12-07 15:29:40 +0900117
118 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huang3ac843c2023-12-13 16:40:15 +0900119 gen.addAllocateR0()
120 gen.addAllocate(1500)
Yuyang Huangdcdb4442023-12-07 14:56:21 +0900121 program = gen.generate()
Yuyang Huang3ac843c2023-12-13 16:40:15 +0900122 // encoding ALLOC opcode: opcode=21(EXT opcode number), imm=36(TRANS opcode number).
123 // R=0 means length stored in R0. R=1 means the length stored in imm1.
124 assertContentEquals(byteArrayOf(
125 encodeInstruction(opcode = 21, immLength = 1, register = 0), 36,
126 encodeInstruction(opcode = 21, immLength = 1, register = 1), 36, 0x05,
127 0xDC.toByte()),
128 program)
129 // TODO: add back disassembling test check after we update the apf_disassembler
130 // assertContentEquals(arrayOf(" 0: alloc"), ApfJniUtils.disassembleApf(program))
Yuyang Huangae57be02023-10-16 17:49:31 +0900131
Yuyang Huangdcdb4442023-12-07 14:56:21 +0900132 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangfd74ce42023-12-12 20:10:45 +0900133 gen.addTransmit()
134 gen.addDiscard()
Yuyang Huangae57be02023-10-16 17:49:31 +0900135 program = gen.generate()
Yuyang Huangfd74ce42023-12-12 20:10:45 +0900136 // encoding TRANSMIT/DISCARD opcode: opcode=21(EXT opcode number),
137 // imm=37(TRANSMIT/DISCARD opcode number),
138 // R=0 means discard the buffer. R=1 means transmit the buffer.
139 assertContentEquals(byteArrayOf(
140 encodeInstruction(opcode = 21, immLength = 1, register = 0), 37,
141 encodeInstruction(opcode = 21, immLength = 1, register = 1), 37,
142 ), program)
143 // TODO: add back disassembling test check after we update the apf_disassembler
144 // assertContentEquals(arrayOf(" 0: trans"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900145
Yuyang Huanga112cc82023-12-13 17:55:47 +0900146 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
147 val largeByteArray = ByteArray(256) { 0x01 }
148 gen.addData(largeByteArray)
149 program = gen.generate()
150 // encoding DATA opcode: opcode=14(JMP), R=1
151 assertContentEquals(byteArrayOf(
152 encodeInstruction(opcode = 14, immLength = 2, register = 1), 0x01, 0x00) +
153 largeByteArray, program)
154
Yuyang Huang4ac891f2023-12-20 11:49:11 +0900155 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
156 gen.addWrite1(0x01)
157 gen.addWrite2(0x0102)
158 gen.addWrite4(0x01020304)
159 gen.addWrite1(0x00)
160 gen.addWrite1(0x80)
161 gen.addWrite2(0x0000)
162 gen.addWrite2(0x8000)
163 gen.addWrite4(0x00000000)
164 gen.addWrite4(0x80000000)
165 program = gen.generate()
166 assertContentEquals(byteArrayOf(
167 encodeInstruction(24, 1, 0), 0x01,
168 encodeInstruction(24, 2, 0), 0x01, 0x02,
169 encodeInstruction(24, 4, 0), 0x01, 0x02, 0x03, 0x04,
170 encodeInstruction(24, 1, 0), 0x00,
171 encodeInstruction(24, 1, 0), 0x80.toByte(),
172 encodeInstruction(24, 2, 0), 0x00, 0x00,
173 encodeInstruction(24, 2, 0), 0x80.toByte(), 0x00,
174 encodeInstruction(24, 4, 0), 0x00, 0x00, 0x00, 0x00,
175 encodeInstruction(24, 4, 0), 0x80.toByte(), 0x00, 0x00,
176 0x00), program)
177 assertContentEquals(arrayOf(
178 " 0: write 0x01",
179 " 2: write 0x0102",
180 " 5: write 0x01020304",
181 " 10: write 0x00",
182 " 12: write 0x80",
183 " 14: write 0x0000",
184 " 17: write 0x8000",
185 " 20: write 0x00000000",
186 " 25: write 0x80000000"),
187 ApfJniUtils.disassembleApf(program))
Yuyang Huange84a9692024-01-01 11:49:49 +0900188
189 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
190 gen.addWriteU8(R0)
191 gen.addWriteU16(R0)
192 gen.addWriteU32(R0)
193 gen.addWriteU8(R1)
194 gen.addWriteU16(R1)
195 gen.addWriteU32(R1)
196 program = gen.generate()
197 assertContentEquals(byteArrayOf(
198 encodeInstruction(21, 1, 0), 38,
199 encodeInstruction(21, 1, 0), 39,
200 encodeInstruction(21, 1, 0), 40,
201 encodeInstruction(21, 1, 1), 38,
202 encodeInstruction(21, 1, 1), 39,
203 encodeInstruction(21, 1, 1), 40
204 ), program)
205 // TODO: add back disassembling test check after we update the apf_disassembler
Yuyang Huange569ecf2023-12-13 19:44:44 +0900206// assertContentEquals(arrayOf(
Yuyang Huange84a9692024-01-01 11:49:49 +0900207// " 0: ewrite1 r0",
208// " 2: ewrite2 r0",
209// " 4: ewrite4 r0",
210// " 6: ewrite1 r1",
211// " 8: ewrite2 r1",
212// " 10: ewrite4 r1"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900213
Yuyang Huang293f7e72023-12-31 14:24:03 +0900214 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
215 gen.addDataCopy(0, 10)
216 gen.addDataCopy(1, 5)
217 gen.addPacketCopy(1000, 255)
218 program = gen.generate()
219 assertContentEquals(byteArrayOf(
220 encodeInstruction(25, 0, 1), 10,
221 encodeInstruction(25, 1, 1), 1, 5,
222 encodeInstruction(25, 2, 0),
223 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(),
224 ), program)
225 // TODO: add back disassembling test check after we update the apf_disassembler
Yuyang Huange569ecf2023-12-13 19:44:44 +0900226// assertContentEquals(arrayOf(
Yuyang Huang293f7e72023-12-31 14:24:03 +0900227// " 0: dcopy 0, 5",
Yuyang Huange569ecf2023-12-13 19:44:44 +0900228// " 3: pcopy 1000, 255"), ApfJniUtils.disassembleApf(program))
Yuyang Huang293f7e72023-12-31 14:24:03 +0900229
Yuyang Huangd0390612024-01-01 16:21:16 +0900230 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
231 gen.addPacketCopyFromR0LenR1()
232 gen.addPacketCopyFromR0(5)
233 gen.addDataCopyFromR0LenR1()
234 gen.addDataCopyFromR0(5)
235 program = gen.generate()
236 assertContentEquals(byteArrayOf(
237 encodeInstruction(21, 1, 1), 41,
238 encodeInstruction(21, 1, 0), 41, 5,
239 encodeInstruction(21, 1, 1), 42,
240 encodeInstruction(21, 1, 0), 42, 5,
241 ), program)
Yuyang Huang293f7e72023-12-31 14:24:03 +0900242 // TODO: add back the following test case when implementing EPKTCOPY, EDATACOPY opcodes.
Yuyang Huange569ecf2023-12-13 19:44:44 +0900243// assertContentEquals(arrayOf(
244// " 0: dcopy [r1+0], 5",
245// " 4: pcopy [r0+1000], 255"), ApfJniUtils.disassembleApf(program))
Yuyang Huangae57be02023-10-16 17:49:31 +0900246 }
247
248 private fun encodeInstruction(opcode: Int, immLength: Int, register: Int): Byte {
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900249 val immLengthEncoding = if (immLength == 4) 3 else immLength
250 return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte()
Yuyang Huangae57be02023-10-16 17:49:31 +0900251 }
Yuyang Huangae57be02023-10-16 17:49:31 +0900252}