blob: 750f97b9736fcac57d79e0410d71f223c16338af [file] [log] [blame]
James Kuszmaul8e62b022022-03-22 09:33:25 -07001/*
2 * Copyright 2021 Google Inc. All rights reserved.
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 */
16
17import XCTest
18@testable import FlatBuffers
19
20final class FlatbuffersVerifierTests: XCTestCase {
21
22 lazy var validStorage: ByteBuffer.Storage = ByteBuffer.Storage(
23 count: Int(FlatBufferMaxSize) - 1,
24 alignment: 1)
25 lazy var errorStorage: ByteBuffer.Storage = ByteBuffer.Storage(
26 count: Int(FlatBufferMaxSize) + 1,
27 alignment: 1)
28
29 var buffer: ByteBuffer!
30
31 var validFlatbuffersObject: ByteBuffer!
32 var invalidFlatbuffersObject: ByteBuffer!
33
34 override func setUp() {
35 // swiftformat:disable all
36 buffer = ByteBuffer(initialSize: 32)
37 add(buffer: &buffer, v: 4, p: 16)
38 add(buffer: &buffer, v: 4, p: 20)
39
40 validFlatbuffersObject = ByteBuffer(bytes: [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
41
42 invalidFlatbuffersObject = ByteBuffer(bytes: [0, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
43
44 // swiftformat:enable all
45 }
46
47 func testVeriferInitPassing() {
48 var buffer = ByteBuffer(initialSize: 0)
49 buffer._storage = validStorage
50 XCTAssertNoThrow(try Verifier(buffer: &buffer))
51 }
52
53 func testVeriferInitFailing() {
54 var buffer = ByteBuffer(initialSize: 0)
55 buffer._storage = errorStorage
56 XCTAssertThrowsError(try Verifier(buffer: &buffer))
57 }
58
59 func testVerifierCheckAlignment() {
60 var verifier = try! Verifier(buffer: &buffer)
61 do {
62 try verifier.isAligned(position: 20, type: Int.self)
63 } catch {
64 XCTAssertEqual(
65 error as? FlatbuffersErrors,
66 .missAlignedPointer(position: 20, type: "Int"))
67 }
68 XCTAssertNoThrow(try verifier.isAligned(position: 16, type: Int.self))
69
70 var newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
71 XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self))
72 }
73
74 func testRangeInBuffer() {
75 var verifier = try! Verifier(buffer: &buffer)
76 let size = MemoryLayout<Int64>.size
77 XCTAssertNoThrow(try verifier.rangeInBuffer(position: 24, size: size))
78 XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
79 XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
80 XCTAssertThrowsError(try verifier.rangeInBuffer(position: 30, size: size))
81 XCTAssertThrowsError(try verifier.rangeInBuffer(position: 32, size: size))
82 XCTAssertThrowsError(try verifier.rangeInBuffer(position: 34, size: size))
83
84 verifier = try! Verifier(
85 buffer: &buffer,
86 options: .init(maxDepth: 0, maxTableCount: 0, maxApparentSize: 4))
87 do {
88 try verifier.rangeInBuffer(position: 24, size: size)
89 } catch {
90 XCTAssertEqual(
91 error as! FlatbuffersErrors,
92 .apparentSizeTooLarge)
93 }
94 }
95
96 func testPositionInBuffer() {
97 var verifier = try! Verifier(buffer: &buffer)
98 XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self))
99 XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self))
100 XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
101 XCTAssertThrowsError(try verifier.inBuffer(position: 25, of: Int64.self))
102 XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int32.self))
103 XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int64.self))
104 XCTAssertThrowsError(try verifier.inBuffer(position: 30, of: Int64.self))
105 XCTAssertThrowsError(try verifier.inBuffer(position: 32, of: Int64.self))
106 XCTAssertThrowsError(try verifier.inBuffer(position: 34, of: Int64.self))
107 }
108
109 func testVisitTable() {
110 var verifier = try! Verifier(buffer: &validFlatbuffersObject)
111 XCTAssertNoThrow(try verifier.visitTable(at: 48))
112 verifier.reset()
113 }
114
115 func testTableVerifier() {
116 var verifier = try! Verifier(buffer: &validFlatbuffersObject)
117
118 var tableVerifer = try! verifier.visitTable(at: 48)
119 XCTAssertNoThrow(try tableVerifer.visit(
120 field: 4,
121 fieldName: "Vec",
122 required: false,
123 type: Vec3.self))
124 XCTAssertNoThrow(try tableVerifer.visit(
125 field: 8,
126 fieldName: "hp",
127 required: false,
128 type: Int16.self))
129
130 XCTAssertNoThrow(try tableVerifer.visit(
131 field: 10,
132 fieldName: "name",
133 required: true,
134 type: ForwardOffset<String>.self))
135
136 XCTAssertNoThrow(try tableVerifer.visit(
137 field: 14,
138 fieldName: "inventory",
139 required: false,
140 type: ForwardOffset<Vector<UInt8, UInt8>>.self))
141
142 XCTAssertNoThrow(try tableVerifer.visit(
143 field: 22,
144 fieldName: "test4",
145 required: false,
146 type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>
147 .self))
148
149 XCTAssertNoThrow(try tableVerifer.visit(
150 field: 24,
151 fieldName: "Vector of strings",
152 required: false,
153 type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self))
154
155 do {
156 try tableVerifer.visit(
157 field: 13,
158 fieldName: "notvalid",
159 required: false,
160 type: Int16.self)
161 } catch {
162 XCTAssertEqual(
163 error as! FlatbuffersErrors,
164 .missAlignedPointer(position: 25, type: "UInt16"))
165 }
166
167 do {
168 try tableVerifer.visit(
169 unionKey: 18,
170 unionField: 20,
171 unionKeyName: "testType",
172 fieldName: "test",
173 required: false,
174 completion: { (verifier, key: MyGame_Example_Any_, pos) in
175 switch key {
176 case .none_:
177 break
178 case .monster:
179 try ForwardOffset<MyGame_Example_Monster>.verify(
180 &verifier,
181 at: pos,
182 of: MyGame_Example_Monster.self)
183
184 case .testsimpletablewithenum:
185 break
186 case .mygameExample2Monster:
187 break
188 }
189 })
190 } catch {
191 XCTAssertEqual(
192 error as! FlatbuffersErrors,
193 .missAlignedPointer(position: 25, type: "UInt16"))
194 }
195 }
196
197 func testVerifyUnionVectors() {
198 // swiftformat:disable all
199 var byteBuffer = ByteBuffer(bytes: [20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 3, 1, 4, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0])
200 // swiftformat:enable all
201 XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie)
202 }
203
204 func testFullVerifier() {
205 XCTAssertNoThrow(
206 try getCheckedRoot(
207 byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster)
208 }
209
210 func testInvalidBuffer() {
211 XCTAssertThrowsError(
212 try getCheckedRoot(
213 byteBuffer: &invalidFlatbuffersObject) as MyGame_Example_Monster)
214 }
215
216 func testValidUnionBuffer() {
217 let string = "Awesome \\\\t\t\nstring!"
218 var fb = FlatBufferBuilder()
219 let stringOffset = fb.create(string: string)
220 let characterType: [Character] = [.bookfan, .other]
221
222 let characters = [
223 fb.create(struct: BookReader(booksRead: 7)),
224 stringOffset,
225 ]
226 let types = fb.createVector(characterType)
227 let characterVector = fb.createVector(ofOffsets: characters)
228
229 let end = Movie.createMovie(
230 &fb,
231 mainCharacterType: .other,
232 mainCharacterOffset: Offset(offset: stringOffset.o),
233 charactersTypeVectorOffset: types,
234 charactersVectorOffset: characterVector)
235 Movie.finish(&fb, end: end)
236 var buf = fb.sizedBuffer
237 XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie)
238 }
239
240 func add(buffer: inout ByteBuffer, v: Int32, p: Int) {
241 buffer.write(value: v, index: p)
242 }
243}