]> git.saurik.com Git - apple/xnu.git/blame - libkdd/tests/Tests.swift
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkdd / tests / Tests.swift
CommitLineData
39037602
A
1//
2// Tests.swift
3//
4// Some of these tests here verify that kdd is able to parse old
5// kcdata files and generate the correct output. To do so, we include
6// compressed versions of the raw kcdata and as well as the expected
7// plist output.
8//
9// NOTE: If you're adding sample data/plist files, you'll need to first
10// add them to the project and then make sure each is part of the
11// tests target.
12//
13// Other tests verify the expected behavior of libkdd for certain
14// situations.
15//
16//
17
18import XCTest
19import Foundation
20
21// Swift's bridging to uuid_t is awkward.
22
5ba3f43e 23func nsuuid2uuid_t(_ nsuuid : NSUUID) -> uuid_t {
39037602
A
24 let dat = nsuuid2array(nsuuid)
25 return nsarray2uuid(dat)
26}
27
5ba3f43e
A
28func nsarray2uuid(_ a : [Int]) -> uuid_t {
29 return uuid_t(UInt8(a[0]),
30 UInt8(a[1]),
31 UInt8(a[2]),
32 UInt8(a[3]),
33 UInt8(a[4]),
34 UInt8(a[5]),
35 UInt8(a[6]),
36 UInt8(a[7]),
37 UInt8(a[8]),
38 UInt8(a[9]),
39 UInt8(a[10]),
40 UInt8(a[11]),
41 UInt8(a[12]),
42 UInt8(a[13]),
43 UInt8(a[14]),
44 UInt8(a[15]))
39037602
A
45}
46
5ba3f43e 47func nsuuid2array(_ uuid: NSUUID) -> [Int] {
39037602 48 var ret = [Int]()
5ba3f43e 49 let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
39037602 50
5ba3f43e 51 defer { ptr.deallocate(capacity:16) }
39037602 52
5ba3f43e 53 uuid.getBytes(ptr)
39037602
A
54 for i in 0..<16 {
55 ret.append(Int(ptr[i]))
56 }
57 return ret
58}
59
5ba3f43e 60func decompress(_ data:NSData) throws -> NSData {
39037602
A
61 var stream = z_stream(next_in: nil, avail_in: 0, total_in: 0, next_out: nil, avail_out: 0, total_out: 0, msg: nil, state: nil, zalloc: nil, zfree: nil, opaque: nil, data_type: 0, adler: 0, reserved: 0)
62
63 let bufsize : Int = 1000
5ba3f43e
A
64 let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufsize)
65 defer { buffer.deallocate(capacity:bufsize) }
39037602
A
66 let output = NSMutableData()
67 stream.next_out = buffer
68 stream.avail_out = UInt32(bufsize)
5ba3f43e 69 stream.next_in = UnsafeMutablePointer(mutating:data.bytes.assumingMemoryBound(to:Bytef.self))
39037602 70 stream.avail_in = UInt32(data.length)
5ba3f43e 71 inflateInit2_(&stream, 16+MAX_WBITS, ZLIB_VERSION, Int32(MemoryLayout<z_stream>.size))
39037602
A
72
73 while (true) {
74 let z = inflate(&stream, Z_NO_FLUSH);
75 if (z == Z_OK || z == Z_STREAM_END) {
5ba3f43e 76 output.append(buffer, length: bufsize - Int(stream.avail_out))
39037602
A
77 stream.avail_out = UInt32(bufsize)
78 stream.next_out = buffer
79 if (z == Z_STREAM_END) {
80 return output;
81 }
82 } else {
83 throw NSError(domain: "zlib", code: Int(z), userInfo: nil)
84 }
85 }
86}
87
88
5ba3f43e
A
89extension Dictionary {
90 func value(forKeyPath s:String) -> Any? {
91 return (self as NSDictionary).value(forKeyPath:s)
92 }
93}
94
39037602
A
95
96class Tests: XCTestCase {
97
98 override func setUp() {
99 super.setUp()
100 continueAfterFailure = false
101 }
102
103 override func tearDown() {
104 // Put teardown code here. This method is called after the invocation of each test method in the class.
105 super.tearDown()
106 }
107
5ba3f43e 108 func parseBuffer(_ buffer:NSData) throws -> [AnyHashable:Any] {
39037602 109 var error : NSError?
5ba3f43e 110 guard let dict = parseKCDataBuffer(UnsafeMutablePointer(mutating:buffer.bytes.assumingMemoryBound(to:UInt8.self)), UInt32(buffer.length), &error)
39037602
A
111 else {
112 XCTAssert(error != nil)
113 throw error!
114 }
115 return dict
116 }
117
5ba3f43e 118 func testPaddingFlags(_ pad : Int) {
39037602
A
119 let buffer = NSMutableData(capacity:1000)!
120
121 var item = kcdata_item()
122
123 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
124 item.flags = 0
125 item.size = 0
5ba3f43e 126 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
127
128 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
129 item.flags = UInt64(pad)
5ba3f43e
A
130 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size)
131 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 132
5ba3f43e 133 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
134
135 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 136 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
39037602
A
137
138 item.type = KCDATA_TYPE_BUFFER_END
139 item.flags = 0
140 item.size = 0
5ba3f43e 141 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
142
143 guard let dict = try? self.parseBuffer(buffer)
144 else { XCTFail(); return; }
145
146 var uuidarray = nsuuid2array(uuid)
147 for _ in 0..<pad {
148 uuidarray.removeLast()
149 }
150
5ba3f43e
A
151 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") as? Int == 42)
152 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") as! [Int] == uuidarray)
39037602
A
153 }
154
155 func testPaddingFlags() {
156 for i in 0..<15 {
157 testPaddingFlags(i)
158 }
159 }
39037602
A
160 func testBootArgs() {
161 let s = "hello, I am some boot args"
162
163 let buffer = NSMutableData(capacity:1000)!
164
165 var item = kcdata_item()
166
167 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
168 item.flags = 0
169 item.size = 0
5ba3f43e 170 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
171
172 item.type = UInt32(STACKSHOT_KCTYPE_BOOTARGS)
173 item.flags = 0
174 item.size = UInt32(s.utf8.count + 1)
5ba3f43e
A
175 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
176 s.utf8CString.withUnsafeBufferPointer({
177 buffer.append($0.baseAddress!, length:s.utf8.count + 1)
39037602 178 })
39037602
A
179 item.type = KCDATA_TYPE_BUFFER_END
180 item.flags = 0
181 item.size = 0
5ba3f43e 182 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
183
184 guard let dict = try? self.parseBuffer(buffer) else { XCTFail(); return; }
5ba3f43e 185 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.boot_args") as? String == s)
39037602
A
186 }
187
188 func testBootArgsMissingNul() {
189 let s = "hello, I am some boot args"
190
191 let buffer = NSMutableData(capacity:1000)!
192
193 var item = kcdata_item()
194
195 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
196 item.flags = 0
197 item.size = 0
5ba3f43e 198 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
199
200 item.type = UInt32(STACKSHOT_KCTYPE_BOOTARGS)
201 item.flags = 0
202 item.size = UInt32(s.utf8.count)
5ba3f43e
A
203 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
204 s.utf8CString.withUnsafeBufferPointer({
205 buffer.append($0.baseAddress!, length:s.utf8.count)
39037602
A
206 })
207
208 item.type = KCDATA_TYPE_BUFFER_END
209 item.flags = 0
210 item.size = 0
5ba3f43e 211 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
212
213 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
214 }
215
216 func testLoadInfo() {
217 let buffer = NSMutableData(capacity:1000)!
218
219 var item = kcdata_item()
220
221 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
222 item.flags = 0
223 item.size = 0
5ba3f43e 224 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
225
226 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
227 item.flags = 0
5ba3f43e
A
228 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size)
229 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 230
5ba3f43e 231 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
232
233 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 234 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
39037602
A
235
236 item.type = KCDATA_TYPE_BUFFER_END
237 item.flags = 0
238 item.size = 0
5ba3f43e 239 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
240
241 guard let dict = try? self.parseBuffer(buffer)
242 else { XCTFail(); return; }
243
5ba3f43e
A
244 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") as? Int == 42)
245 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") as! [Int] == nsuuid2array(uuid))
39037602
A
246 }
247
248 func testLoadInfoWrongSize() {
249 // test what happens when a struct size is short
250
251 let buffer = NSMutableData(capacity:1000)!
252
253 var item = kcdata_item()
254
255 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
256 item.flags = 0
257 item.size = 0
5ba3f43e 258 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
259
260 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
261 item.flags = 0
5ba3f43e
A
262 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size) - 1
263 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 264
5ba3f43e 265 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
266
267 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 268 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size - 1)
39037602
A
269
270 item.type = KCDATA_TYPE_BUFFER_END
271 item.flags = 0
272 item.size = 0
5ba3f43e 273 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
274
275 guard let dict = try? self.parseBuffer(buffer)
276 else { XCTFail(); return; }
5ba3f43e 277 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") as? Int == 42)
39037602
A
278 var uuidarray = nsuuid2array(uuid)
279 uuidarray.removeLast()
5ba3f43e 280 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") as! [Int] == uuidarray)
39037602
A
281 }
282
283 func testLoadInfoWayWrongSize() {
284 // test what happens when a struct size is short
285
286 let buffer = NSMutableData(capacity:1000)!
287
288 var item = kcdata_item()
289
290 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
291 item.flags = 0
292 item.size = 0
5ba3f43e 293 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
294
295 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
296 item.flags = 0
5ba3f43e
A
297 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size) - 16
298 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 299
5ba3f43e 300 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
301
302 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 303 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size - 16)
39037602
A
304
305 item.type = KCDATA_TYPE_BUFFER_END
306 item.flags = 0
307 item.size = 0
5ba3f43e 308 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
309 guard let dict = try? self.parseBuffer(buffer)
310 else { XCTFail(); return; }
5ba3f43e
A
311 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") as? Int == 42)
312 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") == nil)
39037602
A
313 }
314
315 func testLoadInfoPreposterousWrongSize() {
316 // test what happens when a struct size is short
317
318 let buffer = NSMutableData(capacity:1000)!
319
320 var item = kcdata_item()
321
322 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
323 item.flags = 0
324 item.size = 0
5ba3f43e 325 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
326
327 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
328 item.flags = 0
329 item.size = UInt32(1)
5ba3f43e 330 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
331
332 var payload = UInt8(42)
5ba3f43e 333 buffer.append(&payload, length:1)
39037602
A
334
335 item.type = KCDATA_TYPE_BUFFER_END
336 item.flags = 0
337 item.size = 0
5ba3f43e 338 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
339
340 guard let dict = try? self.parseBuffer(buffer)
341 else { XCTFail(); return; }
5ba3f43e
A
342 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") == nil)
343 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") == nil)
39037602
A
344 }
345
346
347 func testNewArray(n : Int, pad : Int) {
348 let buffer = NSMutableData(capacity:1000)!
349 var item = kcdata_item()
350
351 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
352 item.flags = 0
353 item.size = 0
5ba3f43e 354 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
355
356 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0) + UInt32(pad)
357 item.flags = UInt64(STACKSHOT_KCTYPE_DONATING_PIDS) << 32 | UInt64(n)
5ba3f43e
A
358 item.size = UInt32(n * MemoryLayout<UInt32>.size + pad)
359 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
360
361 for i in 0..<n {
362 var payload = UInt32(42 * i)
5ba3f43e 363 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
39037602
A
364 }
365
366 for i in 0..<pad {
367 var payload = UInt8(42-i)
5ba3f43e 368 buffer.append(&payload, length:MemoryLayout<UInt8>.size)
39037602
A
369 }
370
371 item.type = KCDATA_TYPE_BUFFER_END
372 item.flags = 0
373 item.size = 0
5ba3f43e 374 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
375
376 guard let dict = try? self.parseBuffer(buffer)
377 else { XCTFail(); return; }
5ba3f43e 378 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.donating_pids") as! [Any]).count == n)
39037602
A
379 for i in 0..<n {
380 let x = dict["kcdata_crashinfo"] as? NSDictionary
381 let y = x?["donating_pids"] as? NSArray
5ba3f43e 382 XCTAssert((y?[i]) as? Int == 42 * i)
39037602
A
383 }
384 }
385
386 func testNewArrays() {
5ba3f43e 387 self.testNewArray(n:0,pad:0)
39037602
A
388 for i in 1..<20 {
389 for pad in 0..<16 {
5ba3f43e 390 self.testNewArray(n:i, pad:pad)
39037602
A
391 }
392 }
393 }
394
395
396 func testArrayLoadInfo(n : Int) {
397 let buffer = NSMutableData(capacity:1000)!
398 var item = kcdata_item()
399
400 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
401 item.flags = 0
402 item.size = 0
5ba3f43e 403 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
404
405 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
406 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
5ba3f43e
A
407 item.size = UInt32(n * MemoryLayout<dyld_uuid_info_32>.size)
408 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 409
5ba3f43e 410 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
411
412
413 for i in 0..<n {
414 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
415
5ba3f43e 416 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
39037602
A
417 }
418
419 item.type = KCDATA_TYPE_BUFFER_END
420 item.flags = 0
421 item.size = 0
5ba3f43e 422 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
423
424 guard let dict = try? self.parseBuffer(buffer)
425 else { XCTFail(); return; }
5ba3f43e 426 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
39037602 427 for i in 0..<n {
5ba3f43e
A
428 guard let loadinfo = dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as? [Any]
429 else { XCTFail(); return; }
430 guard let loadinfo_i = loadinfo[i] as? [AnyHashable:Any]
431 else { XCTFail(); return; }
432 XCTAssert(loadinfo_i["imageLoadAddress"] as? Int == 42 + i)
433 XCTAssert(loadinfo_i["imageUUID"] as! [Int] == nsuuid2array(uuid))
39037602
A
434 }
435 }
436
437 func testArrayLoadInfo() {
438 for n in 0..<20 {
5ba3f43e 439 testArrayLoadInfo(n: n)
39037602
A
440 }
441 }
442
443 func testArrayLoadInfoWrongSize() {
444 // test what happens when array element sizes are too short
445
446 let n = 7
447 let wrong = 1
448 let buffer = NSMutableData(capacity:1000)!
449 var item = kcdata_item()
450
451 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
452 item.flags = 0
453 item.size = 0
5ba3f43e 454 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
455
456 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
457 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
5ba3f43e
A
458 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
459 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 460
5ba3f43e 461 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
462
463 for i in 0..<n {
464 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 465 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size-wrong)
39037602
A
466 }
467
468 item.type = KCDATA_TYPE_BUFFER_END
469 item.flags = 0
470 item.size = 0
5ba3f43e 471 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
472 var uuidarray = nsuuid2array(uuid)
473 uuidarray.removeLast()
474
475 guard let dict = try? self.parseBuffer(buffer)
5ba3f43e
A
476 else { XCTFail(); return; }
477 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
39037602 478 for i in 0..<n {
5ba3f43e
A
479 guard let loadinfo = dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as? [Any]
480 else { XCTFail(); return; }
481 guard let loadinfo_i = loadinfo[i] as? [AnyHashable:Any]
482 else { XCTFail(); return; }
483 XCTAssert(loadinfo_i["imageLoadAddress"] as? Int == 42 + i)
484 XCTAssert(loadinfo_i["imageUUID"] as! [Int] == uuidarray)
39037602 485 }
5ba3f43e 486
39037602
A
487 }
488
489
490 func testArrayLoadInfoWayWrongSize() {
491 // test what happens when array element sizes are too short
492
493 let n = 7
494 let wrong = 16
495 let buffer = NSMutableData(capacity:1000)!
496 var item = kcdata_item()
497
498 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
499 item.flags = 0
500 item.size = 0
5ba3f43e 501 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
502
503 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
504 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
5ba3f43e
A
505 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
506 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 507
5ba3f43e 508 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
39037602
A
509
510 for i in 0..<n {
511 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
5ba3f43e 512 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size-wrong)
39037602
A
513 }
514
515 item.type = KCDATA_TYPE_BUFFER_END
516 item.flags = 0
517 item.size = 0
5ba3f43e
A
518 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
519
39037602
A
520
521 guard let dict = try? self.parseBuffer(buffer)
5ba3f43e
A
522 else { XCTFail(); return; }
523 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
39037602 524 for i in 0..<n {
5ba3f43e
A
525 guard let loadinfo = dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as? [Any]
526 else { XCTFail(); return; }
527 guard let loadinfo_i = loadinfo[i] as? [AnyHashable:Any]
528 else { XCTFail(); return; }
529 XCTAssert(loadinfo_i["imageLoadAddress"] as? Int == 42 + i)
530 XCTAssert(loadinfo_i["imageUUID"] == nil)
39037602
A
531 }
532 }
533
534 func testArrayLoadInfoPreposterouslyWrongSize() {
535 // test what happens when array element sizes are too short
536
537 let n = 7
538 let wrong = 19
539 let buffer = NSMutableData(capacity:1000)!
540 var item = kcdata_item()
541
542 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
543 item.flags = 0
544 item.size = 0
5ba3f43e 545 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
546
547 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
548 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
5ba3f43e
A
549 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
550 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
551
552 for i in 0..<n {
553 var payload = UInt8(42*i)
5ba3f43e 554 buffer.append(&payload, length:1)
39037602
A
555 }
556
557 item.type = KCDATA_TYPE_BUFFER_END
558 item.flags = 0
559 item.size = 0
5ba3f43e
A
560 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
561
39037602
A
562
563 guard let dict = try? self.parseBuffer(buffer)
5ba3f43e
A
564 else { XCTFail(); return; }
565 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
39037602 566 for i in 0..<n {
5ba3f43e
A
567 guard let loadinfo = dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as? [Any]
568 else { XCTFail(); return; }
569 guard let loadinfo_i = loadinfo[i] as? [AnyHashable:Any]
570 else { XCTFail(); return; }
571 XCTAssert(loadinfo_i["imageLoadAddress"] == nil)
572 XCTAssert(loadinfo_i["imageUUID"] == nil)
39037602
A
573 }
574 }
575
576
577 func testNested() {
578 let buffer = NSMutableData(capacity:1000)!
579
580 var item = kcdata_item()
581
582 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
583 item.flags = 0
584 item.size = 0
5ba3f43e 585 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
586
587 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
588 item.flags = 0
5ba3f43e
A
589 item.size = UInt32(MemoryLayout<UInt64>.size)
590 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
591
592 var payload : UInt64 = 42
5ba3f43e 593 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
594
595 item.type = KCDATA_TYPE_BUFFER_END
596 item.flags = 0
597 item.size = 0
5ba3f43e 598 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
599
600 let buffer2 = NSMutableData(capacity:1000)!
601
602 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
603 item.flags = 0
604 item.size = 0
5ba3f43e 605 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
606
607 item.type = UInt32(KCDATA_TYPE_NESTED_KCDATA)
608 item.flags = 0
609 item.size = UInt32(buffer.length)
5ba3f43e
A
610 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
611 buffer2.append(buffer as Data)
39037602
A
612
613 item.type = KCDATA_TYPE_BUFFER_END
614 item.flags = 0
615 item.size = 0
5ba3f43e 616 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
617
618 guard let dict2 = try? self.parseBuffer(buffer2)
619 else { XCTFail(); return; }
620
5ba3f43e 621 XCTAssert(dict2.value(forKeyPath:"kcdata_crashinfo.kcdata_crashinfo.crashed_threadid") as? Int == 42)
39037602
A
622 }
623
624
625 func testReadThreadid() {
626 let buffer = NSMutableData(capacity:1000)!
627
628 var item = kcdata_item()
629
630 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
631 item.flags = 0
632 item.size = 0
5ba3f43e 633 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
634
635 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
636 item.flags = 0
5ba3f43e
A
637 item.size = UInt32(MemoryLayout<UInt64>.size)
638 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
639
640 var payload : UInt64 = 42
5ba3f43e 641 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
642
643 item.type = KCDATA_TYPE_BUFFER_END
644 item.flags = 0
645 item.size = 0
5ba3f43e 646 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
647
648 guard let dict = try? self.parseBuffer(buffer)
649 else { XCTFail(); return; }
650
5ba3f43e 651 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as? Int == 42)
39037602 652 }
5ba3f43e 653
39037602
A
654
655 func testRepeatedKey() {
656 // test a repeated item of the same key causes error
657
658 let buffer = NSMutableData(capacity:1000)!
659
660 var item = kcdata_item()
661
662 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
663 item.flags = 0
664 item.size = 0
5ba3f43e 665 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
666
667 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
668 item.flags = 0
5ba3f43e
A
669 item.size = UInt32(MemoryLayout<UInt64>.size)
670 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
671
672 var payload : UInt64 = 42
5ba3f43e 673 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
674
675 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
676 item.flags = 0
5ba3f43e
A
677 item.size = UInt32(MemoryLayout<UInt64>.size)
678 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
679
680 payload = 42
5ba3f43e 681 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
682
683 item.type = KCDATA_TYPE_BUFFER_END
684 item.flags = 0
685 item.size = 0
5ba3f43e 686 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
687
688 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
689 }
690
691
692 func testContainer() {
693 let buffer = NSMutableData(capacity:1000)!
694
695 var item = kcdata_item()
696 var payload64 : UInt64
697 var payload32 : UInt32
698
699 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
700 item.flags = 0
701 item.size = 0
5ba3f43e 702 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
703
704 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
705 item.flags = 0
5ba3f43e
A
706 item.size = UInt32(MemoryLayout<UInt32>.size)
707 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 708 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 709 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
710
711 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
712 item.flags = 0
5ba3f43e
A
713 item.size = UInt32(MemoryLayout<UInt64>.size)
714 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 715 payload64 = 42
5ba3f43e 716 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
39037602
A
717
718 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
719 item.flags = 0
5ba3f43e
A
720 item.size = UInt32(MemoryLayout<UInt32>.size)
721 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 722 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 723 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
724
725
726 item.type = KCDATA_TYPE_BUFFER_END
727 item.flags = 0
728 item.size = 0
5ba3f43e 729 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
730
731 guard let dict = try? self.parseBuffer(buffer)
5ba3f43e 732 else { XCTFail(); return; }
39037602 733
5ba3f43e 734 XCTAssert(dict.value(forKeyPath: "kcdata_crashinfo.task_snapshots.0.crashed_threadid") as? Int == 42)
39037602
A
735 }
736
cb323159
A
737 func testDispatchQueueLabel() {
738 let buffer = NSMutableData(capacity:1000)!
739
740 var item = kcdata_item()
741 let dql = "houston.we.had.a.problem"
742 var payload32 : UInt32
743
744 item.type = KCDATA_BUFFER_BEGIN_STACKSHOT
745 item.flags = 0
746 item.size = 0
747 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
748
749 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
750 item.flags = 0
751 item.size = UInt32(MemoryLayout<UInt32>.size)
752 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
753 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
754 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
755
756 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
757 item.flags = 0
758 item.size = UInt32(MemoryLayout<UInt32>.size)
759 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
760 payload32 = UInt32(STACKSHOT_KCCONTAINER_THREAD)
761 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
762
763 item.type = UInt32(STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL)
764 item.flags = 0
765 item.size = UInt32(dql.utf8.count + 1)
766 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
767 dql.utf8CString.withUnsafeBufferPointer({
768 buffer.append($0.baseAddress!, length:dql.utf8.count + 1)
769 })
770
771 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
772 item.flags = 0
773 item.size = UInt32(MemoryLayout<UInt32>.size)
774 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
775 payload32 = UInt32(STACKSHOT_KCCONTAINER_THREAD)
776 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
777
778 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
779 item.flags = 0
780 item.size = UInt32(MemoryLayout<UInt32>.size)
781 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
782 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
783 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
784
785
786 item.type = KCDATA_TYPE_BUFFER_END
787 item.flags = 0
788 item.size = 0
789 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
790
791 guard let dict = try? self.parseBuffer(buffer)
792 else { XCTFail(); return; }
793
794 XCTAssert(dict.value(forKeyPath: "kcdata_stackshot.task_snapshots.0.thread_snapshots.0.dispatch_queue_label") as? String == dql)
795 }
796
39037602
A
797 func testRepeatedContainer() {
798 //repeated container of same name and key shoudl fail
799
800 let buffer = NSMutableData(capacity:1000)!
801
802 var item = kcdata_item()
803 var payload64 : UInt64
804 var payload32 : UInt32
805
806 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
807 item.flags = 0
808 item.size = 0
5ba3f43e 809 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
810
811 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
812 item.flags = 0
5ba3f43e
A
813 item.size = UInt32(MemoryLayout<UInt32>.size)
814 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 815 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 816 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
817
818 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
819 item.flags = 0
5ba3f43e
A
820 item.size = UInt32(MemoryLayout<UInt64>.size)
821 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 822 payload64 = 42
5ba3f43e 823 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
39037602
A
824
825 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
826 item.flags = 0
5ba3f43e
A
827 item.size = UInt32(MemoryLayout<UInt32>.size)
828 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 829 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 830 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
831
832
833 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
834 item.flags = 0
5ba3f43e
A
835 item.size = UInt32(MemoryLayout<UInt32>.size)
836 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 837 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 838 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
839
840 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
841 item.flags = 0
5ba3f43e
A
842 item.size = UInt32(MemoryLayout<UInt64>.size)
843 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 844 payload64 = 42
5ba3f43e 845 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
39037602
A
846
847 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
848 item.flags = 0
5ba3f43e
A
849 item.size = UInt32(MemoryLayout<UInt32>.size)
850 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 851 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 852 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
853
854 item.type = KCDATA_TYPE_BUFFER_END
855 item.flags = 0
856 item.size = 0
5ba3f43e 857 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
858
859 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
860 }
861
862
863 func testContainerNoEnd() {
864 let buffer = NSMutableData(capacity:1000)!
865
866 var item = kcdata_item()
867 var payload64 : UInt64
868 var payload32 : UInt32
869
870 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
871 item.flags = 0
872 item.size = 0
5ba3f43e 873 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
874
875 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
876 item.flags = 0
5ba3f43e
A
877 item.size = UInt32(MemoryLayout<UInt32>.size)
878 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 879 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 880 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
881
882 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
883 item.flags = 0
5ba3f43e
A
884 item.size = UInt32(MemoryLayout<UInt64>.size)
885 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 886 payload64 = 42
5ba3f43e 887 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
39037602
A
888
889 item.type = KCDATA_TYPE_BUFFER_END
890 item.flags = 0
891 item.size = 0
5ba3f43e 892 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
893
894 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
895 }
896
897 func testContainerNoEndNoEnd() {
898 let buffer = NSMutableData(capacity:1000)!
899
900 var item = kcdata_item()
901 var payload64 : UInt64
902 var payload32 : UInt32
903
904 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
905 item.flags = 0
906 item.size = 0
5ba3f43e 907 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
908
909 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
910 item.flags = 0
5ba3f43e
A
911 item.size = UInt32(MemoryLayout<UInt32>.size)
912 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 913 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
5ba3f43e 914 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
39037602
A
915
916 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
917 item.flags = 0
5ba3f43e
A
918 item.size = UInt32(MemoryLayout<UInt64>.size)
919 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602 920 payload64 = 42
5ba3f43e 921 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
39037602
A
922
923 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
924 }
925
926
927
928 func testNoEnd() {
929 let buffer = NSMutableData(capacity:1000)!
930
931 var item = kcdata_item()
932
933 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
934 item.flags = 0
935 item.size = 0
5ba3f43e 936 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
937
938 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
939 item.flags = 0
5ba3f43e
A
940 item.size = UInt32(MemoryLayout<UInt64>.size)
941 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
942
943 var payload : UInt64 = 42
5ba3f43e 944 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
945
946 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
947 }
948
949
950 func testCrazySize() {
951 let buffer = NSMutableData(capacity:1000)!
952
953 var item = kcdata_item()
954
955 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
956 item.flags = 0
957 item.size = 0
5ba3f43e 958 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
959
960 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
961 item.flags = 0
962 item.size = 99999
5ba3f43e 963 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
964
965 var payload : UInt64 = 42
5ba3f43e 966 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
967
968 item.type = KCDATA_TYPE_BUFFER_END
969 item.flags = 0
970 item.size = 0
5ba3f43e 971 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
972
973 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
974 }
975
976 func testReadRepeatedArray() {
977 // repeated arrays should be concatenated
978 let n = 10
979
980 let buffer = NSMutableData(capacity:1000)!
981
982 var item = kcdata_item()
983
984 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
985 item.flags = 0
986 item.size = 0
5ba3f43e 987 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
988
989 item.type = UInt32(KCDATA_TYPE_ARRAY)
990 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
5ba3f43e
A
991 item.size = UInt32(n * MemoryLayout<UInt64>.size)
992 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
993
994 for i in 0..<n {
995 var payload : UInt64 = UInt64(i)
5ba3f43e 996 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
997 }
998
999 item.type = UInt32(KCDATA_TYPE_ARRAY)
1000 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
5ba3f43e
A
1001 item.size = UInt32(n * MemoryLayout<UInt64>.size)
1002 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1003
1004 for i in 0..<n {
1005 var payload : UInt64 = UInt64(i)
5ba3f43e 1006 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
1007 }
1008
1009 item.type = KCDATA_TYPE_BUFFER_END
1010 item.flags = 0
1011 item.size = 0
5ba3f43e 1012 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1013
1014 guard let dict = try? self.parseBuffer(buffer)
1015 else { XCTFail(); return }
1016
5ba3f43e 1017 XCTAssert( 2*n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
39037602
A
1018 for i in 0..<2*n {
1019 let x = dict["kcdata_crashinfo"] as? NSDictionary
1020 let y = x?["crashed_threadid"] as? NSArray
5ba3f43e 1021 XCTAssert((y?[i]) as? Int == i % n)
39037602
A
1022 }
1023 }
1024
1025 func testReadThreadidArray(n : Int, pad : Int) {
1026 let buffer = NSMutableData(capacity:1000)!
1027
1028 var item = kcdata_item()
1029
1030 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1031 item.flags = 0
1032 item.size = 0
5ba3f43e
A
1033 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1034
39037602
A
1035 item.type = UInt32(KCDATA_TYPE_ARRAY)
1036 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
5ba3f43e
A
1037 item.size = UInt32(n * MemoryLayout<UInt64>.size + pad)
1038 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1039
1040 for i in 0..<n {
1041 var payload : UInt64 = UInt64(i)
5ba3f43e 1042 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
1043 }
1044
1045 for _ in 0..<pad {
1046 var payload : UInt8 = 0
5ba3f43e 1047 buffer.append(&payload, length:1)
39037602
A
1048 }
1049
1050 item.type = KCDATA_TYPE_BUFFER_END
1051 item.flags = 0
1052 item.size = 0
5ba3f43e 1053 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1054
1055 guard let dict = try? self.parseBuffer(buffer)
1056 else { XCTFail(); return; }
5ba3f43e
A
1057
1058 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1059
39037602
A
1060 for i in 0..<n {
1061 let x = dict["kcdata_crashinfo"] as? NSDictionary
1062 let y = x?["crashed_threadid"] as? NSArray
5ba3f43e 1063 XCTAssert((y?[i]) as? Int == i)
39037602
A
1064 }
1065
1066 }
5ba3f43e 1067
39037602
A
1068 func testReadThreadidArray() {
1069 // test that we can correctly read old arrays with a variety of sizes and paddings
5ba3f43e 1070 self.testReadThreadidArray(n: 0, pad:0)
39037602
A
1071 for n in 1..<100 {
1072 for pad in 0..<16 {
5ba3f43e 1073 self.testReadThreadidArray(n: n, pad:pad)
39037602
A
1074 }
1075 }
1076 }
1077
1078 func testReadThreadidArrayWrongSize1() {
1079 /// for old style arrays, if the element size is determined by the type. If the array of that size element at the given count doesn't fit, then parsing should fail
1080
1081 let n = 1
5ba3f43e 1082
39037602 1083 let buffer = NSMutableData(capacity:1000)!
5ba3f43e 1084
39037602 1085 var item = kcdata_item()
5ba3f43e 1086
39037602
A
1087 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1088 item.flags = 0
1089 item.size = 0
5ba3f43e
A
1090 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1091
39037602
A
1092 item.type = UInt32(KCDATA_TYPE_ARRAY)
1093 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1094 item.size = UInt32(4)
5ba3f43e
A
1095 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1096
39037602 1097 var payload : UInt32 = UInt32(42)
5ba3f43e
A
1098 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1099
39037602
A
1100 item.type = KCDATA_TYPE_BUFFER_END
1101 item.flags = 0
1102 item.size = 0
5ba3f43e 1103 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1104
1105 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1106 }
5ba3f43e 1107
39037602
A
1108 func testReadThreadidArrayWrongSize5() {
1109 /// if the count is bigger than the buffer, parsing will just fail
5ba3f43e 1110
39037602 1111 let n = 5
5ba3f43e 1112
39037602 1113 let buffer = NSMutableData(capacity:1000)!
5ba3f43e 1114
39037602 1115 var item = kcdata_item()
5ba3f43e 1116
39037602
A
1117 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1118 item.flags = 0
1119 item.size = 0
5ba3f43e
A
1120 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1121
39037602
A
1122 item.type = UInt32(KCDATA_TYPE_ARRAY)
1123 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1124 item.size = UInt32(4)
5ba3f43e
A
1125 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1126
39037602 1127 var payload : UInt32 = UInt32(42)
5ba3f43e
A
1128 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1129
39037602
A
1130 item.type = KCDATA_TYPE_BUFFER_END
1131 item.flags = 0
1132 item.size = 0
5ba3f43e
A
1133 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1134
39037602
A
1135 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1136 }
1137
5ba3f43e 1138
39037602
A
1139 func testReadThreadidArrayPaddedSize() {
1140 // test that we can tolerate a little padding at the end of an array
1141 let n = 5
1142
1143 let buffer = NSMutableData(capacity:1000)!
1144
1145 var item = kcdata_item()
1146
1147 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1148 item.flags = 0
1149 item.size = 0
5ba3f43e 1150 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1151
1152 item.type = UInt32(KCDATA_TYPE_ARRAY)
1153 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
5ba3f43e
A
1154 item.size = UInt32(n * MemoryLayout<UInt64>.size) + 1
1155 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1156
1157 for i in 0..<n {
1158 var payload : UInt64 = UInt64(i)
5ba3f43e 1159 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602
A
1160 }
1161 var payload : UInt8 = 0
5ba3f43e 1162 buffer.append(&payload, length:1)
39037602
A
1163
1164 item.type = KCDATA_TYPE_BUFFER_END
1165 item.flags = 0
1166 item.size = 0
5ba3f43e 1167 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1168
1169 guard let dict = try? self.parseBuffer(buffer)
1170 else { XCTFail(); return; }
1171
5ba3f43e 1172 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
39037602
A
1173 for i in 0..<n {
1174 let x = dict["kcdata_crashinfo"] as? NSDictionary
1175 let y = x?["crashed_threadid"] as? NSArray
5ba3f43e 1176 XCTAssert((y?[i]) as? Int == i)
39037602
A
1177 }
1178 }
1179
1180 func testReadThreadidArrayPaddedSize15() {
1181 // test that we can tolerate a little padding at the end of an array
1182 let n = 5
1183
1184 let buffer = NSMutableData(capacity:1000)!
1185
1186 var item = kcdata_item()
1187
1188 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1189 item.flags = 0
1190 item.size = 0
5ba3f43e 1191 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1192
1193 item.type = UInt32(KCDATA_TYPE_ARRAY)
1194 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
5ba3f43e
A
1195 item.size = UInt32(n * MemoryLayout<UInt64>.size) + 15
1196 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1197
1198 for i in 0..<n {
1199 var payload : UInt64 = UInt64(i)
5ba3f43e 1200 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
39037602 1201 }
5ba3f43e 1202 for _ in 0..<15 {
39037602 1203 var payload : UInt8 = 0
5ba3f43e 1204 buffer.append(&payload, length:1)
39037602
A
1205 }
1206
1207 item.type = KCDATA_TYPE_BUFFER_END
1208 item.flags = 0
1209 item.size = 0
5ba3f43e 1210 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1211
1212 guard let dict = try? self.parseBuffer(buffer)
1213 else { XCTFail(); return; }
1214
5ba3f43e 1215 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
39037602
A
1216 for i in 0..<n {
1217 let x = dict["kcdata_crashinfo"] as? NSDictionary
1218 let y = x?["crashed_threadid"] as? NSArray
5ba3f43e 1219 XCTAssert((y?[i]) as? Int == i)
39037602
A
1220 }
1221 }
1222
1223
1224 func testReadThreadidWrongSize(size : UInt32) {
1225 let buffer = NSMutableData(capacity:1000)!
1226
1227 var item = kcdata_item()
1228
1229 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1230 item.flags = 0
1231 item.size = 0
5ba3f43e 1232 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1233
1234 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
1235 item.flags = 0
1236 item.size = size
5ba3f43e 1237 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1238
1239 var payload : UInt64 = 42
5ba3f43e 1240 buffer.append(&payload, length:Int(size))
39037602
A
1241
1242 item.type = KCDATA_TYPE_BUFFER_END
1243 item.flags = 0
1244 item.size = 0
5ba3f43e 1245 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
39037602
A
1246
1247 guard let dict = try? self.parseBuffer(buffer)
1248 else { XCTFail(); return; }
1249
5ba3f43e 1250 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") == nil)
39037602
A
1251 }
1252
1253 func testReadThreadidWrongSize0() {
5ba3f43e 1254 self.testReadThreadidWrongSize(size: 0)
39037602
A
1255 }
1256
1257 func testReadThreadidWrongSize7() {
5ba3f43e 1258 self.testReadThreadidWrongSize(size: 7)
39037602
A
1259 }
1260
5ba3f43e
A
1261 func dataWithResource(_ name:String) -> NSData? {
1262 guard let filename = Bundle(for: self.classForCoder).path(forResource: name, ofType: nil)
39037602
A
1263 else { return nil }
1264 return NSData(contentsOfFile:filename)!
1265 }
5ba3f43e
A
1266
1267 func testSampleStackshot(_ name : String) {
39037602
A
1268 // check that we agree with sample file
1269
1270 guard let sampledata = self.dataWithResource(name)
d9a64523 1271 else { XCTFail("failed to open bundle resource named " + name); return }
39037602
A
1272 var dict : NSDictionary?
1273
5ba3f43e 1274 dict = try? self.parseBuffer(sampledata) as NSDictionary
39037602
A
1275
1276 if (dict == nil) {
5ba3f43e
A
1277 if let decoded = NSData(base64Encoded: sampledata as Data, options:.ignoreUnknownCharacters) {
1278 dict = try? self.parseBuffer(decoded) as NSDictionary
39037602
A
1279 }
1280 }
1281
1282 if (dict == nil) {
1283 if let decompressed = try? decompress(sampledata) {
5ba3f43e 1284 dict = try? self.parseBuffer(decompressed) as NSDictionary
39037602
A
1285 }
1286 }
1287
1288 if (dict == nil) {
1289 XCTFail(); return;
1290 }
1291
1292 guard let plistdata = self.dataWithResource(name + ".plist.gz") ??
1293 self.dataWithResource(name + ".plist")
1294 else {XCTFail(); return}
1295
d9a64523
A
1296 var opt_dict2 = try? PropertyListSerialization.propertyList(from: plistdata as Data, options: [], format: nil)
1297 if opt_dict2 == nil {
1298 opt_dict2 = try? PropertyListSerialization.propertyList(from:decompress(plistdata) as Data, options:[], format: nil)
39037602 1299 }
d9a64523
A
1300 guard let dict2 = opt_dict2
1301 else { XCTFail(); return}
39037602 1302
d9a64523 1303 XCTAssertEqual(dict, dict2 as! NSDictionary);
39037602 1304
d9a64523 1305 //XCTAssert(dict == dict2 as? NSDictionary)
39037602
A
1306
1307 // check that we agree with python
1308
1309 #if os(OSX)
1310
5ba3f43e 1311 let kcdatapy = Bundle(for: self.classForCoder).path(forResource: "kcdata.py", ofType: nil)
39037602 1312
5ba3f43e 1313 let task = Process()
39037602
A
1314 task.launchPath = kcdatapy
1315 task.arguments = ["-p",
5ba3f43e
A
1316 Bundle(for:self.classForCoder).path(forResource: name, ofType: nil)!]
1317 let pipe = Pipe()
39037602
A
1318 task.standardOutput = pipe
1319 task.launch()
1320
1321 let data = pipe.fileHandleForReading.readDataToEndOfFile()
1322
5ba3f43e 1323 guard let dict3 = try? PropertyListSerialization.propertyList(from:data, options:[], format: nil) as? NSDictionary
39037602
A
1324 else { XCTFail(); return }
1325
1326 XCTAssert(dict == dict3)
1327
1328 #endif
1329 }
1330
1331 func testSampleStackshot() {
1332 self.testSampleStackshot("stackshot-sample")
1333 }
1334
1335 func testSampleStackshotOldArrays() {
1336 self.testSampleStackshot("stackshot-sample-old-arrays")
1337 }
1338
1339 func testSampleStackshotNewArrays() {
1340 self.testSampleStackshot("stackshot-sample-new-arrays")
1341 }
1342
1343 func testSampleDeltaStackshotOldArrays() {
1344 self.testSampleStackshot("delta-stackshot-sample-old-arrays")
1345 }
1346
1347 func testSampleDeltaStackshotNewArrays() {
1348 self.testSampleStackshot("delta-stackshot-sample-new-arrays")
1349 }
1350
1351 func testSampleCorpse() {
1352 self.testSampleStackshot("corpse-sample")
1353 }
1354
1355 func testSampleStackshotTailspin() {
1356 self.testSampleStackshot("stackshot-sample-tailspin")
1357 }
1358
1359 func testSampleStackshotTailspin2() {
1360 self.testSampleStackshot("stackshot-sample-tailspin-2")
1361 }
1362
1363 func testSampleExitReason() {
1364 self.testSampleStackshot("exitreason-sample")
1365 }
5ba3f43e 1366
39037602
A
1367 func testSampleThreadT() {
1368 self.testSampleStackshot("stackshot-sample-ths-thread-t")
1369 }
1370
1371 func testSampleCpuTimes() {
1372 self.testSampleStackshot("stackshot-sample-cputime")
1373 }
1374
1375 func testSampleDuration() {
1376 self.testSampleStackshot("stackshot-sample-duration")
1377 }
1378
1379 func testSampleNested() {
1380 self.testSampleStackshot("nested-sample")
1381 }
1382
1383 func testSampleTermWithReason() {
1384 self.testSampleStackshot("test-twr-sample")
1385 }
1386
1387 func testSampleCorpseTermWithReason() {
1388 self.testSampleStackshot("corpse-twr-sample")
1389 }
1390
1391 func testSampleCorpseTermWithReasonV2() {
1392 self.testSampleStackshot("corpse-twr-sample-v2")
1393 }
1394
1395 func testSampleCodesigningExitReason() {
1396 self.testSampleStackshot("exitreason-codesigning")
1397 }
1398
5ba3f43e
A
1399 func testSampleThreadGroups() {
1400 self.testSampleStackshot("stackshot-sample-thread-groups")
1401 }
1402
5c9f4661
A
1403 func testSampleThreadGroupsFlags() {
1404 self.testSampleStackshot("stackshot-sample-thread-groups-flags")
1405 }
1406
5ba3f43e
A
1407 func testSampleCoalitions() {
1408 self.testSampleStackshot("stackshot-sample-coalitions")
1409 }
1410
cb323159
A
1411 func testSampleTurnstileInfo() {
1412 self.testSampleStackshot("stackshot-sample-turnstileinfo")
1413 }
1414
39037602
A
1415 func testStackshotSharedcacheV2() {
1416 self.testSampleStackshot("stackshot-sample-sharedcachev2")
1417 }
1418
1419 func testStackshotFaultStats() {
1420 self.testSampleStackshot("stackshot-fault-stats")
1421 }
1422
1423 func testStackshotwithKCID() {
1424 self.testSampleStackshot("stackshot-with-kcid")
1425 }
1426
1427 func testXNUPostTestConfig() {
1428 self.testSampleStackshot("xnupost_testconfig-sample")
1429 }
1430
813fb2f6
A
1431 func testStackshotWithWaitinfo() {
1432 self.testSampleStackshot("stackshot-with-waitinfo")
1433 }
1434
5ba3f43e
A
1435 func testStackshotWithThreadPolicy() {
1436 self.testSampleStackshot("stackshot-sample-thread-policy")
1437 }
1438
a39ff7e2
A
1439 func testDeltaStackshotWithThreadPolicy() {
1440 self.testSampleStackshot("stackshot-sample-delta-thread-policy")
1441 }
1442
5ba3f43e
A
1443 func testStackshotWithInstrsCycles() {
1444 self.testSampleStackshot("stackshot-sample-instrs-cycles")
1445 }
1446
d9a64523
A
1447 func testStackshotWithStacktop() {
1448 self.testSampleStackshot("stackshot-sample-stacktop")
1449 }
1450
1451 func testStackshotWithASID() {
1452 self.testSampleStackshot("stackshot-sample-asid")
1453 }
1454
1455 func testStackshotWithPageTables() {
1456 self.testSampleStackshot("stackshot-sample-asid-pagetable")
1457 }
1458
1459 func testStackshotCPUTimes() {
1460 self.testSampleStackshot("stackshot-sample-cpu-times")
1461 }
1462
1463 func testStackshotWithSharedCacheLayout() {
1464 self.testSampleStackshot("stackshot-with-shared-cache-layout")
1465 }
1466
cb323159
A
1467 func testStackshotDispatchQueueLabel() {
1468 self.testSampleStackshot("stackshot-sample-dispatch-queue-label")
1469 }
1470
39037602
A
1471 func testTrivial() {
1472 }
1473}