blob: 1b74c3ee33beee4565743dadd6cab4251d8f5f31 [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 Huang1e5bfaf2023-12-11 00:21:54 +090042 }
43
44 @Test
45 fun testApfInstructionArgumentCheck() {
46 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
47 assertFailsWith<IllegalArgumentException> { gen.addCountAndPass(0) }
48 assertFailsWith<IllegalArgumentException> { gen.addCountAndDrop(0) }
Yuyang Huangce1493a2023-12-07 15:29:40 +090049 }
50
51 @Test
Yuyang Huangae57be02023-10-16 17:49:31 +090052 fun testApfInstructionsEncoding() {
Yuyang Huangdcdb4442023-12-07 14:56:21 +090053 var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION)
54 gen.addPass()
Yuyang Huangae57be02023-10-16 17:49:31 +090055 var program = gen.generate()
Yuyang Huangdcdb4442023-12-07 14:56:21 +090056 // encoding PASS opcode: opcode=0, imm_len=0, R=0
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090057 assertContentEquals(
58 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 0)), program)
Yuyang Huangdcdb4442023-12-07 14:56:21 +090059
60 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangce1493a2023-12-07 15:29:40 +090061 gen.addDrop()
62 program = gen.generate()
63 // encoding DROP opcode: opcode=0, imm_len=0, R=1
Yuyang Huang1e5bfaf2023-12-11 00:21:54 +090064 assertContentEquals(
65 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)), program)
66
67 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
68 gen.addCountAndPass(129)
69 program = gen.generate()
70 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber
71 assertContentEquals(
72 byteArrayOf(encodeInstruction(opcode = 0, immLength = 1, register = 0),
73 0x81.toByte()), program)
74
75 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
76 gen.addCountAndDrop(1000)
77 program = gen.generate()
78 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber
79 assertContentEquals(
80 byteArrayOf(encodeInstruction(opcode = 0, immLength = 2, register = 1),
81 0x03, 0xe8.toByte()), program)
Yuyang Huangce1493a2023-12-07 15:29:40 +090082
83 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangdcdb4442023-12-07 14:56:21 +090084 gen.addAlloc(ApfGenerator.Register.R0)
85 program = gen.generate()
Yuyang Huangae57be02023-10-16 17:49:31 +090086 assertContentEquals(byteArrayOf(encodeInstruction(21, 1, 0), 36), program)
87 assertContentEquals(arrayOf(" 0: alloc r0"), ApfJniUtils.disassembleApf(program))
88
Yuyang Huangdcdb4442023-12-07 14:56:21 +090089 gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
Yuyang Huangfd74ce42023-12-12 20:10:45 +090090 gen.addTransmit()
91 gen.addDiscard()
Yuyang Huangae57be02023-10-16 17:49:31 +090092 program = gen.generate()
Yuyang Huangfd74ce42023-12-12 20:10:45 +090093 // encoding TRANSMIT/DISCARD opcode: opcode=21(EXT opcode number),
94 // imm=37(TRANSMIT/DISCARD opcode number),
95 // R=0 means discard the buffer. R=1 means transmit the buffer.
96 assertContentEquals(byteArrayOf(
97 encodeInstruction(opcode = 21, immLength = 1, register = 0), 37,
98 encodeInstruction(opcode = 21, immLength = 1, register = 1), 37,
99 ), program)
100 // TODO: add back disassembling test check after we update the apf_disassembler
101 // assertContentEquals(arrayOf(" 0: trans"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900102
Yuyang Huange569ecf2023-12-13 19:44:44 +0900103 // TODO: add back when support write opcode
104// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
105// gen.addWrite(0x01, 1)
106// gen.addWrite(0x0102, 2)
107// gen.addWrite(0x01020304, 4)
108// program = gen.generate()
109// assertContentEquals(byteArrayOf(
110// encodeInstruction(24, 1, 0), 0x01,
111// encodeInstruction(24, 2, 0), 0x01, 0x02,
112// encodeInstruction(24, 4, 0), 0x01, 0x02, 0x03, 0x04
113// ), program)
114// assertContentEquals(arrayOf(
115// " 0: write 0x01",
116// " 2: write 0x0102",
117// " 5: write 0x01020304"), ApfJniUtils.disassembleApf(program))
118//
119// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
120// gen.addWrite(ApfGenerator.Register.R0, 1)
121// gen.addWrite(ApfGenerator.Register.R0, 2)
122// gen.addWrite(ApfGenerator.Register.R0, 4)
123// program = gen.generate()
124// assertContentEquals(byteArrayOf(
125// encodeInstruction(21, 1, 0), 38,
126// encodeInstruction(21, 1, 0), 39,
127// encodeInstruction(21, 1, 0), 40
128// ), program)
129// assertContentEquals(arrayOf(
130// " 0: write r0, 1",
131// " 2: write r0, 2",
132// " 4: write r0, 4"), ApfJniUtils.disassembleApf(program))
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900133
Yuyang Huange569ecf2023-12-13 19:44:44 +0900134 // TODO: add back when we properly support copy opcode
135// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
136// gen.addDataCopy(1, 5)
137// gen.addPacketCopy(1000, 255)
138// program = gen.generate()
139// assertContentEquals(byteArrayOf(
140// encodeInstruction(25, 1, 1), 1, 5,
141// encodeInstruction(25, 2, 0),
142// 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(),
143// ), program)
144// assertContentEquals(arrayOf(
145// " 0: dcopy 1, 5",
146// " 3: pcopy 1000, 255"), ApfJniUtils.disassembleApf(program))
147//
148// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV)
149// gen.addDataCopy(ApfGenerator.Register.R1, 0, 5)
150// gen.addPacketCopy(ApfGenerator.Register.R0, 1000, 255)
151// program = gen.generate()
152// assertContentEquals(byteArrayOf(
153// encodeInstruction(21, 1, 1), 42, 0, 5,
154// encodeInstruction(21, 2, 0),
155// 0, 41, 0x03.toByte(), 0xe8.toByte(), 0xff.toByte()
156// ), program)
157// assertContentEquals(arrayOf(
158// " 0: dcopy [r1+0], 5",
159// " 4: pcopy [r0+1000], 255"), ApfJniUtils.disassembleApf(program))
Yuyang Huangae57be02023-10-16 17:49:31 +0900160 }
161
162 private fun encodeInstruction(opcode: Int, immLength: Int, register: Int): Byte {
Yuyang Huang73c6d2d2023-10-19 13:32:37 +0900163 val immLengthEncoding = if (immLength == 4) 3 else immLength
164 return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte()
Yuyang Huangae57be02023-10-16 17:49:31 +0900165 }
Yuyang Huangae57be02023-10-16 17:49:31 +0900166}