blob: 2c8d09c9865b54e75bc48293ba954c684c0d53db [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 Huangae57be02023-10-16 17:49:31 +090019import androidx.test.filters.SmallTest
20import androidx.test.runner.AndroidJUnit4
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090021import java.lang.IllegalArgumentException
Yuyang Huangae57be02023-10-16 17:49:31 +090022import kotlin.test.assertContentEquals
Yuyang Huangce1493a2023-12-07 15:29:40 +090023import kotlin.test.assertFailsWith
Yuyang Huangae57be02023-10-16 17:49:31 +090024import org.junit.Test
25import org.junit.runner.RunWith
26
27/**
28 * Tests for APFv6 specific instructions.
29 */
30@RunWith(AndroidJUnit4::class)
31@SmallTest
32class ApfV5Test {
33
34 @Test
Yuyang Huangce1493a2023-12-07 15:29:40 +090035 fun testApfInstructionVersionCheck() {
36 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION)
37 assertFailsWith<IllegalInstructionException> { gen.addDrop() }
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090038 assertFailsWith<IllegalInstructionException> { gen.addCountAndDrop(12) }
39 assertFailsWith<IllegalInstructionException> { gen.addCountAndPass(1000) }
Yuyang Huangfd74ce42023-12-12 20:10:45 +090040 assertFailsWith<IllegalInstructionException> { gen.addTransmit() }
41 assertFailsWith<IllegalInstructionException> { gen.addDiscard() }
Yuyang Huang3ac843c2023-12-13 16:40:15 +090042 assertFailsWith<IllegalInstructionException> { gen.addAllocateR0() }
43 assertFailsWith<IllegalInstructionException> { gen.addAllocate(100) }
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090044 }
45
46 @Test
Yuyang Huang3ac843c2023-12-13 16:40:15 +090047 fun testApfInstructionEncodingSizeCheck() {
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090048 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huang3ac843c2023-12-13 16:40:15 +090049 assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) }
50 assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) }
Yuyang Huangce1493a2023-12-07 15:29:40 +090051 }
52
53 @Test
Yuyang Huangae57be02023-10-16 17:49:31 +090054 fun testApfInstructionsEncoding() {
Yuyang Huangdcdb4442023-12-07 14:56:21 +090055 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION)
56 gen.addPass()
Yuyang Huangae57be02023-10-16 17:49:31 +090057 var program = gen.generate()
Yuyang Huangdcdb4442023-12-07 14:56:21 +090058 // encoding PASS opcode: opcode=0, imm_len=0, R=0
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090059 assertContentEquals(
60 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 0)), program)
Yuyang Huangdcdb4442023-12-07 14:56:21 +090061
62 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangce1493a2023-12-07 15:29:40 +090063 gen.addDrop()
64 program = gen.generate()
65 // encoding DROP opcode: opcode=0, imm_len=0, R=1
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090066 assertContentEquals(
67 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)), program)
68
69 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
70 gen.addCountAndPass(129)
71 program = gen.generate()
72 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber
73 assertContentEquals(
74 byteArrayOf(encodeInstruction(opcode = 0, immLength = 1, register = 0),
75 0x81.toByte()), program)
76
77 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
78 gen.addCountAndDrop(1000)
79 program = gen.generate()
80 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber
81 assertContentEquals(
82 byteArrayOf(encodeInstruction(opcode = 0, immLength = 2, register = 1),
83 0x03, 0xe8.toByte()), program)
Yuyang Huangce1493a2023-12-07 15:29:40 +090084
85 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huang3ac843c2023-12-13 16:40:15 +090086 gen.addAllocateR0()
87 gen.addAllocate(1500)
Yuyang Huangdcdb4442023-12-07 14:56:21 +090088 program = gen.generate()
Yuyang Huang3ac843c2023-12-13 16:40:15 +090089 // encoding ALLOC opcode: opcode=21(EXT opcode number), imm=36(TRANS opcode number).
90 // R=0 means length stored in R0. R=1 means the length stored in imm1.
91 assertContentEquals(byteArrayOf(
92 encodeInstruction(opcode = 21, immLength = 1, register = 0), 36,
93 encodeInstruction(opcode = 21, immLength = 1, register = 1), 36, 0x05,
94 0xDC.toByte()),
95 program)
96 // TODO: add back disassembling test check after we update the apf_disassembler
97 // assertContentEquals(arrayOf(" 0: alloc"), ApfJniUtils.disassembleApf(program))
Yuyang Huangae57be02023-10-16 17:49:31 +090098
Yuyang Huangdcdb4442023-12-07 14:56:21 +090099 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangfd74ce42023-12-12 20:10:45 +0900100 gen.addTransmit()
101 gen.addDiscard()
Yuyang Huangae57be02023-10-16 17:49:31 +0900102 program = gen.generate()
Yuyang Huangfd74ce42023-12-12 20:10:45 +0900103 // encoding TRANSMIT/DISCARD opcode: opcode=21(EXT opcode number),
104 // imm=37(TRANSMIT/DISCARD opcode number),
105 // R=0 means discard the buffer. R=1 means transmit the buffer.
106 assertContentEquals(byteArrayOf(
107 encodeInstruction(opcode = 21, immLength = 1, register = 0), 37,
108 encodeInstruction(opcode = 21, immLength = 1, register = 1), 37,
109 ), program)
110 // TODO: add back disassembling test check after we update the apf_disassembler
111 // assertContentEquals(arrayOf(" 0: trans"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900112
Yuyang Huange569ecf2023-12-13 19:44:44 +0900113 // TODO: add back when support write opcode
114// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
115// gen.addWrite(0x01, 1)
116// gen.addWrite(0x0102, 2)
117// gen.addWrite(0x01020304, 4)
118// program = gen.generate()
119// assertContentEquals(byteArrayOf(
120// encodeInstruction(24, 1, 0), 0x01,
121// encodeInstruction(24, 2, 0), 0x01, 0x02,
122// encodeInstruction(24, 4, 0), 0x01, 0x02, 0x03, 0x04
123// ), program)
124// assertContentEquals(arrayOf(
125// " 0: write 0x01",
126// " 2: write 0x0102",
127// " 5: write 0x01020304"), ApfJniUtils.disassembleApf(program))
128//
129// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
130// gen.addWrite(ApfGenerator.Register.R0, 1)
131// gen.addWrite(ApfGenerator.Register.R0, 2)
132// gen.addWrite(ApfGenerator.Register.R0, 4)
133// program = gen.generate()
134// assertContentEquals(byteArrayOf(
135// encodeInstruction(21, 1, 0), 38,
136// encodeInstruction(21, 1, 0), 39,
137// encodeInstruction(21, 1, 0), 40
138// ), program)
139// assertContentEquals(arrayOf(
140// " 0: write r0, 1",
141// " 2: write r0, 2",
142// " 4: write r0, 4"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900143
Yuyang Huange569ecf2023-12-13 19:44:44 +0900144 // TODO: add back when we properly support copy opcode
145// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
146// gen.addDataCopy(1, 5)
147// gen.addPacketCopy(1000, 255)
148// program = gen.generate()
149// assertContentEquals(byteArrayOf(
150// encodeInstruction(25, 1, 1), 1, 5,
151// encodeInstruction(25, 2, 0),
152// 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(),
153// ), program)
154// assertContentEquals(arrayOf(
155// " 0: dcopy 1, 5",
156// " 3: pcopy 1000, 255"), ApfJniUtils.disassembleApf(program))
157//
158// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
159// gen.addDataCopy(ApfGenerator.Register.R1, 0, 5)
160// gen.addPacketCopy(ApfGenerator.Register.R0, 1000, 255)
161// program = gen.generate()
162// assertContentEquals(byteArrayOf(
163// encodeInstruction(21, 1, 1), 42, 0, 5,
164// encodeInstruction(21, 2, 0),
165// 0, 41, 0x03.toByte(), 0xe8.toByte(), 0xff.toByte()
166// ), program)
167// assertContentEquals(arrayOf(
168// " 0: dcopy [r1+0], 5",
169// " 4: pcopy [r0+1000], 255"), ApfJniUtils.disassembleApf(program))
Yuyang Huangae57be02023-10-16 17:49:31 +0900170 }
171
172 private fun encodeInstruction(opcode: Int, immLength: Int, register: Int): Byte {
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900173 val immLengthEncoding = if (immLength == 4) 3 else immLength
174 return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte()
Yuyang Huangae57be02023-10-16 17:49:31 +0900175 }
Yuyang Huangae57be02023-10-16 17:49:31 +0900176}