]> git.saurik.com Git - apple/xnu.git/blob - libkdd/tests/Tests.swift
xnu-6153.11.26.tar.gz
[apple/xnu.git] / libkdd / tests / Tests.swift
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
18 import XCTest
19 import Foundation
20
21 // Swift's bridging to uuid_t is awkward.
22
23 func nsuuid2uuid_t(_ nsuuid : NSUUID) -> uuid_t {
24 let dat = nsuuid2array(nsuuid)
25 return nsarray2uuid(dat)
26 }
27
28 func 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]))
45 }
46
47 func nsuuid2array(_ uuid: NSUUID) -> [Int] {
48 var ret = [Int]()
49 let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
50
51 defer { ptr.deallocate(capacity:16) }
52
53 uuid.getBytes(ptr)
54 for i in 0..<16 {
55 ret.append(Int(ptr[i]))
56 }
57 return ret
58 }
59
60 func decompress(_ data:NSData) throws -> NSData {
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
64 let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufsize)
65 defer { buffer.deallocate(capacity:bufsize) }
66 let output = NSMutableData()
67 stream.next_out = buffer
68 stream.avail_out = UInt32(bufsize)
69 stream.next_in = UnsafeMutablePointer(mutating:data.bytes.assumingMemoryBound(to:Bytef.self))
70 stream.avail_in = UInt32(data.length)
71 inflateInit2_(&stream, 16+MAX_WBITS, ZLIB_VERSION, Int32(MemoryLayout<z_stream>.size))
72
73 while (true) {
74 let z = inflate(&stream, Z_NO_FLUSH);
75 if (z == Z_OK || z == Z_STREAM_END) {
76 output.append(buffer, length: bufsize - Int(stream.avail_out))
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
89 extension Dictionary {
90 func value(forKeyPath s:String) -> Any? {
91 return (self as NSDictionary).value(forKeyPath:s)
92 }
93 }
94
95
96 class 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
108 func parseBuffer(_ buffer:NSData) throws -> [AnyHashable:Any] {
109 var error : NSError?
110 guard let dict = parseKCDataBuffer(UnsafeMutablePointer(mutating:buffer.bytes.assumingMemoryBound(to:UInt8.self)), UInt32(buffer.length), &error)
111 else {
112 XCTAssert(error != nil)
113 throw error!
114 }
115 return dict
116 }
117
118 func testPaddingFlags(_ pad : Int) {
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
126 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
127
128 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
129 item.flags = UInt64(pad)
130 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size)
131 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
132
133 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
134
135 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
136 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
137
138 item.type = KCDATA_TYPE_BUFFER_END
139 item.flags = 0
140 item.size = 0
141 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
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)
153 }
154
155 func testPaddingFlags() {
156 for i in 0..<15 {
157 testPaddingFlags(i)
158 }
159 }
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
170 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
171
172 item.type = UInt32(STACKSHOT_KCTYPE_BOOTARGS)
173 item.flags = 0
174 item.size = UInt32(s.utf8.count + 1)
175 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
176 s.utf8CString.withUnsafeBufferPointer({
177 buffer.append($0.baseAddress!, length:s.utf8.count + 1)
178 })
179 item.type = KCDATA_TYPE_BUFFER_END
180 item.flags = 0
181 item.size = 0
182 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
183
184 guard let dict = try? self.parseBuffer(buffer) else { XCTFail(); return; }
185 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.boot_args") as? String == s)
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
198 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
199
200 item.type = UInt32(STACKSHOT_KCTYPE_BOOTARGS)
201 item.flags = 0
202 item.size = UInt32(s.utf8.count)
203 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
204 s.utf8CString.withUnsafeBufferPointer({
205 buffer.append($0.baseAddress!, length:s.utf8.count)
206 })
207
208 item.type = KCDATA_TYPE_BUFFER_END
209 item.flags = 0
210 item.size = 0
211 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
224 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
225
226 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
227 item.flags = 0
228 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size)
229 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
230
231 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
232
233 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
234 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
235
236 item.type = KCDATA_TYPE_BUFFER_END
237 item.flags = 0
238 item.size = 0
239 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
240
241 guard let dict = try? self.parseBuffer(buffer)
242 else { XCTFail(); return; }
243
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))
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
258 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
259
260 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
261 item.flags = 0
262 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size) - 1
263 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
264
265 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
266
267 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
268 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size - 1)
269
270 item.type = KCDATA_TYPE_BUFFER_END
271 item.flags = 0
272 item.size = 0
273 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
274
275 guard let dict = try? self.parseBuffer(buffer)
276 else { XCTFail(); return; }
277 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") as? Int == 42)
278 var uuidarray = nsuuid2array(uuid)
279 uuidarray.removeLast()
280 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") as! [Int] == uuidarray)
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
293 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
294
295 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
296 item.flags = 0
297 item.size = UInt32(MemoryLayout<dyld_uuid_info_32>.size) - 16
298 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
299
300 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
301
302 var payload = dyld_uuid_info_32(imageLoadAddress: 42, imageUUID: nsuuid2uuid_t(uuid))
303 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size - 16)
304
305 item.type = KCDATA_TYPE_BUFFER_END
306 item.flags = 0
307 item.size = 0
308 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
309 guard let dict = try? self.parseBuffer(buffer)
310 else { XCTFail(); return; }
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)
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
325 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
326
327 item.type = UInt32(KCDATA_TYPE_LIBRARY_LOADINFO)
328 item.flags = 0
329 item.size = UInt32(1)
330 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
331
332 var payload = UInt8(42)
333 buffer.append(&payload, length:1)
334
335 item.type = KCDATA_TYPE_BUFFER_END
336 item.flags = 0
337 item.size = 0
338 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
339
340 guard let dict = try? self.parseBuffer(buffer)
341 else { XCTFail(); return; }
342 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageLoadAddress") == nil)
343 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info.imageUUID") == nil)
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
354 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
355
356 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0) + UInt32(pad)
357 item.flags = UInt64(STACKSHOT_KCTYPE_DONATING_PIDS) << 32 | UInt64(n)
358 item.size = UInt32(n * MemoryLayout<UInt32>.size + pad)
359 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
360
361 for i in 0..<n {
362 var payload = UInt32(42 * i)
363 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
364 }
365
366 for i in 0..<pad {
367 var payload = UInt8(42-i)
368 buffer.append(&payload, length:MemoryLayout<UInt8>.size)
369 }
370
371 item.type = KCDATA_TYPE_BUFFER_END
372 item.flags = 0
373 item.size = 0
374 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
375
376 guard let dict = try? self.parseBuffer(buffer)
377 else { XCTFail(); return; }
378 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.donating_pids") as! [Any]).count == n)
379 for i in 0..<n {
380 let x = dict["kcdata_crashinfo"] as? NSDictionary
381 let y = x?["donating_pids"] as? NSArray
382 XCTAssert((y?[i]) as? Int == 42 * i)
383 }
384 }
385
386 func testNewArrays() {
387 self.testNewArray(n:0,pad:0)
388 for i in 1..<20 {
389 for pad in 0..<16 {
390 self.testNewArray(n:i, pad:pad)
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
403 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
404
405 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
406 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
407 item.size = UInt32(n * MemoryLayout<dyld_uuid_info_32>.size)
408 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
409
410 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
411
412
413 for i in 0..<n {
414 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
415
416 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size)
417 }
418
419 item.type = KCDATA_TYPE_BUFFER_END
420 item.flags = 0
421 item.size = 0
422 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
423
424 guard let dict = try? self.parseBuffer(buffer)
425 else { XCTFail(); return; }
426 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
427 for i in 0..<n {
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))
434 }
435 }
436
437 func testArrayLoadInfo() {
438 for n in 0..<20 {
439 testArrayLoadInfo(n: n)
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
454 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
455
456 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
457 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
458 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
459 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
460
461 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
462
463 for i in 0..<n {
464 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
465 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size-wrong)
466 }
467
468 item.type = KCDATA_TYPE_BUFFER_END
469 item.flags = 0
470 item.size = 0
471 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
472 var uuidarray = nsuuid2array(uuid)
473 uuidarray.removeLast()
474
475 guard let dict = try? self.parseBuffer(buffer)
476 else { XCTFail(); return; }
477 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
478 for i in 0..<n {
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)
485 }
486
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
501 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
502
503 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
504 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
505 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
506 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
507
508 let uuid = NSUUID(uuidString: "de305d54-75b4-431b-adb2-eb6b9e546014")!
509
510 for i in 0..<n {
511 var payload = dyld_uuid_info_32(imageLoadAddress:UInt32(i+42), imageUUID: nsuuid2uuid_t(uuid))
512 buffer.append(&payload, length:MemoryLayout<dyld_uuid_info_32>.size-wrong)
513 }
514
515 item.type = KCDATA_TYPE_BUFFER_END
516 item.flags = 0
517 item.size = 0
518 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
519
520
521 guard let dict = try? self.parseBuffer(buffer)
522 else { XCTFail(); return; }
523 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
524 for i in 0..<n {
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)
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
545 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
546
547 item.type = UInt32(KCDATA_TYPE_ARRAY_PAD0)
548 item.flags = UInt64(KCDATA_TYPE_LIBRARY_LOADINFO) << 32 | UInt64(n)
549 item.size = UInt32(n * (MemoryLayout<dyld_uuid_info_32>.size - wrong))
550 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
551
552 for i in 0..<n {
553 var payload = UInt8(42*i)
554 buffer.append(&payload, length:1)
555 }
556
557 item.type = KCDATA_TYPE_BUFFER_END
558 item.flags = 0
559 item.size = 0
560 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
561
562
563 guard let dict = try? self.parseBuffer(buffer)
564 else { XCTFail(); return; }
565 XCTAssert((dict.value(forKeyPath:"kcdata_crashinfo.dyld_load_info") as! [Any]).count == n)
566 for i in 0..<n {
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)
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
585 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
586
587 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
588 item.flags = 0
589 item.size = UInt32(MemoryLayout<UInt64>.size)
590 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
591
592 var payload : UInt64 = 42
593 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
594
595 item.type = KCDATA_TYPE_BUFFER_END
596 item.flags = 0
597 item.size = 0
598 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
599
600 let buffer2 = NSMutableData(capacity:1000)!
601
602 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
603 item.flags = 0
604 item.size = 0
605 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
606
607 item.type = UInt32(KCDATA_TYPE_NESTED_KCDATA)
608 item.flags = 0
609 item.size = UInt32(buffer.length)
610 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
611 buffer2.append(buffer as Data)
612
613 item.type = KCDATA_TYPE_BUFFER_END
614 item.flags = 0
615 item.size = 0
616 buffer2.append(&item, length: MemoryLayout<kcdata_item>.size)
617
618 guard let dict2 = try? self.parseBuffer(buffer2)
619 else { XCTFail(); return; }
620
621 XCTAssert(dict2.value(forKeyPath:"kcdata_crashinfo.kcdata_crashinfo.crashed_threadid") as? Int == 42)
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
633 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
634
635 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
636 item.flags = 0
637 item.size = UInt32(MemoryLayout<UInt64>.size)
638 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
639
640 var payload : UInt64 = 42
641 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
642
643 item.type = KCDATA_TYPE_BUFFER_END
644 item.flags = 0
645 item.size = 0
646 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
647
648 guard let dict = try? self.parseBuffer(buffer)
649 else { XCTFail(); return; }
650
651 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as? Int == 42)
652 }
653
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
665 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
666
667 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
668 item.flags = 0
669 item.size = UInt32(MemoryLayout<UInt64>.size)
670 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
671
672 var payload : UInt64 = 42
673 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
674
675 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
676 item.flags = 0
677 item.size = UInt32(MemoryLayout<UInt64>.size)
678 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
679
680 payload = 42
681 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
682
683 item.type = KCDATA_TYPE_BUFFER_END
684 item.flags = 0
685 item.size = 0
686 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
702 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
703
704 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
705 item.flags = 0
706 item.size = UInt32(MemoryLayout<UInt32>.size)
707 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
708 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
709 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
710
711 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
712 item.flags = 0
713 item.size = UInt32(MemoryLayout<UInt64>.size)
714 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
715 payload64 = 42
716 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
717
718 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
719 item.flags = 0
720 item.size = UInt32(MemoryLayout<UInt32>.size)
721 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
722 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
723 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
724
725
726 item.type = KCDATA_TYPE_BUFFER_END
727 item.flags = 0
728 item.size = 0
729 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
730
731 guard let dict = try? self.parseBuffer(buffer)
732 else { XCTFail(); return; }
733
734 XCTAssert(dict.value(forKeyPath: "kcdata_crashinfo.task_snapshots.0.crashed_threadid") as? Int == 42)
735 }
736
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
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
809 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
810
811 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
812 item.flags = 0
813 item.size = UInt32(MemoryLayout<UInt32>.size)
814 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
815 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
816 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
817
818 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
819 item.flags = 0
820 item.size = UInt32(MemoryLayout<UInt64>.size)
821 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
822 payload64 = 42
823 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
824
825 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
826 item.flags = 0
827 item.size = UInt32(MemoryLayout<UInt32>.size)
828 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
829 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
830 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
831
832
833 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
834 item.flags = 0
835 item.size = UInt32(MemoryLayout<UInt32>.size)
836 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
837 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
838 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
839
840 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
841 item.flags = 0
842 item.size = UInt32(MemoryLayout<UInt64>.size)
843 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
844 payload64 = 42
845 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
846
847 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
848 item.flags = 0
849 item.size = UInt32(MemoryLayout<UInt32>.size)
850 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
851 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
852 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
853
854 item.type = KCDATA_TYPE_BUFFER_END
855 item.flags = 0
856 item.size = 0
857 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
873 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
874
875 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
876 item.flags = 0
877 item.size = UInt32(MemoryLayout<UInt32>.size)
878 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
879 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
880 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
881
882 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
883 item.flags = 0
884 item.size = UInt32(MemoryLayout<UInt64>.size)
885 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
886 payload64 = 42
887 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
888
889 item.type = KCDATA_TYPE_BUFFER_END
890 item.flags = 0
891 item.size = 0
892 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
907 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
908
909 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
910 item.flags = 0
911 item.size = UInt32(MemoryLayout<UInt32>.size)
912 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
913 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
914 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
915
916 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
917 item.flags = 0
918 item.size = UInt32(MemoryLayout<UInt64>.size)
919 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
920 payload64 = 42
921 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
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
936 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
937
938 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
939 item.flags = 0
940 item.size = UInt32(MemoryLayout<UInt64>.size)
941 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
942
943 var payload : UInt64 = 42
944 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
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
958 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
959
960 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
961 item.flags = 0
962 item.size = 99999
963 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
964
965 var payload : UInt64 = 42
966 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
967
968 item.type = KCDATA_TYPE_BUFFER_END
969 item.flags = 0
970 item.size = 0
971 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
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
987 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
988
989 item.type = UInt32(KCDATA_TYPE_ARRAY)
990 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
991 item.size = UInt32(n * MemoryLayout<UInt64>.size)
992 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
993
994 for i in 0..<n {
995 var payload : UInt64 = UInt64(i)
996 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
997 }
998
999 item.type = UInt32(KCDATA_TYPE_ARRAY)
1000 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1001 item.size = UInt32(n * MemoryLayout<UInt64>.size)
1002 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1003
1004 for i in 0..<n {
1005 var payload : UInt64 = UInt64(i)
1006 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1007 }
1008
1009 item.type = KCDATA_TYPE_BUFFER_END
1010 item.flags = 0
1011 item.size = 0
1012 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1013
1014 guard let dict = try? self.parseBuffer(buffer)
1015 else { XCTFail(); return }
1016
1017 XCTAssert( 2*n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1018 for i in 0..<2*n {
1019 let x = dict["kcdata_crashinfo"] as? NSDictionary
1020 let y = x?["crashed_threadid"] as? NSArray
1021 XCTAssert((y?[i]) as? Int == i % n)
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
1033 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1034
1035 item.type = UInt32(KCDATA_TYPE_ARRAY)
1036 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1037 item.size = UInt32(n * MemoryLayout<UInt64>.size + pad)
1038 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1039
1040 for i in 0..<n {
1041 var payload : UInt64 = UInt64(i)
1042 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1043 }
1044
1045 for _ in 0..<pad {
1046 var payload : UInt8 = 0
1047 buffer.append(&payload, length:1)
1048 }
1049
1050 item.type = KCDATA_TYPE_BUFFER_END
1051 item.flags = 0
1052 item.size = 0
1053 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1054
1055 guard let dict = try? self.parseBuffer(buffer)
1056 else { XCTFail(); return; }
1057
1058 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1059
1060 for i in 0..<n {
1061 let x = dict["kcdata_crashinfo"] as? NSDictionary
1062 let y = x?["crashed_threadid"] as? NSArray
1063 XCTAssert((y?[i]) as? Int == i)
1064 }
1065
1066 }
1067
1068 func testReadThreadidArray() {
1069 // test that we can correctly read old arrays with a variety of sizes and paddings
1070 self.testReadThreadidArray(n: 0, pad:0)
1071 for n in 1..<100 {
1072 for pad in 0..<16 {
1073 self.testReadThreadidArray(n: n, pad:pad)
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
1082
1083 let buffer = NSMutableData(capacity:1000)!
1084
1085 var item = kcdata_item()
1086
1087 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1088 item.flags = 0
1089 item.size = 0
1090 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1091
1092 item.type = UInt32(KCDATA_TYPE_ARRAY)
1093 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1094 item.size = UInt32(4)
1095 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1096
1097 var payload : UInt32 = UInt32(42)
1098 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1099
1100 item.type = KCDATA_TYPE_BUFFER_END
1101 item.flags = 0
1102 item.size = 0
1103 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1104
1105 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1106 }
1107
1108 func testReadThreadidArrayWrongSize5() {
1109 /// if the count is bigger than the buffer, parsing will just fail
1110
1111 let n = 5
1112
1113 let buffer = NSMutableData(capacity:1000)!
1114
1115 var item = kcdata_item()
1116
1117 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1118 item.flags = 0
1119 item.size = 0
1120 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1121
1122 item.type = UInt32(KCDATA_TYPE_ARRAY)
1123 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1124 item.size = UInt32(4)
1125 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1126
1127 var payload : UInt32 = UInt32(42)
1128 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1129
1130 item.type = KCDATA_TYPE_BUFFER_END
1131 item.flags = 0
1132 item.size = 0
1133 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1134
1135 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1136 }
1137
1138
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
1150 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1151
1152 item.type = UInt32(KCDATA_TYPE_ARRAY)
1153 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1154 item.size = UInt32(n * MemoryLayout<UInt64>.size) + 1
1155 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1156
1157 for i in 0..<n {
1158 var payload : UInt64 = UInt64(i)
1159 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1160 }
1161 var payload : UInt8 = 0
1162 buffer.append(&payload, length:1)
1163
1164 item.type = KCDATA_TYPE_BUFFER_END
1165 item.flags = 0
1166 item.size = 0
1167 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1168
1169 guard let dict = try? self.parseBuffer(buffer)
1170 else { XCTFail(); return; }
1171
1172 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1173 for i in 0..<n {
1174 let x = dict["kcdata_crashinfo"] as? NSDictionary
1175 let y = x?["crashed_threadid"] as? NSArray
1176 XCTAssert((y?[i]) as? Int == i)
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
1191 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1192
1193 item.type = UInt32(KCDATA_TYPE_ARRAY)
1194 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1195 item.size = UInt32(n * MemoryLayout<UInt64>.size) + 15
1196 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1197
1198 for i in 0..<n {
1199 var payload : UInt64 = UInt64(i)
1200 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1201 }
1202 for _ in 0..<15 {
1203 var payload : UInt8 = 0
1204 buffer.append(&payload, length:1)
1205 }
1206
1207 item.type = KCDATA_TYPE_BUFFER_END
1208 item.flags = 0
1209 item.size = 0
1210 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1211
1212 guard let dict = try? self.parseBuffer(buffer)
1213 else { XCTFail(); return; }
1214
1215 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1216 for i in 0..<n {
1217 let x = dict["kcdata_crashinfo"] as? NSDictionary
1218 let y = x?["crashed_threadid"] as? NSArray
1219 XCTAssert((y?[i]) as? Int == i)
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
1232 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1233
1234 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
1235 item.flags = 0
1236 item.size = size
1237 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1238
1239 var payload : UInt64 = 42
1240 buffer.append(&payload, length:Int(size))
1241
1242 item.type = KCDATA_TYPE_BUFFER_END
1243 item.flags = 0
1244 item.size = 0
1245 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1246
1247 guard let dict = try? self.parseBuffer(buffer)
1248 else { XCTFail(); return; }
1249
1250 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") == nil)
1251 }
1252
1253 func testReadThreadidWrongSize0() {
1254 self.testReadThreadidWrongSize(size: 0)
1255 }
1256
1257 func testReadThreadidWrongSize7() {
1258 self.testReadThreadidWrongSize(size: 7)
1259 }
1260
1261 func dataWithResource(_ name:String) -> NSData? {
1262 guard let filename = Bundle(for: self.classForCoder).path(forResource: name, ofType: nil)
1263 else { return nil }
1264 return NSData(contentsOfFile:filename)!
1265 }
1266
1267 func testSampleStackshot(_ name : String) {
1268 // check that we agree with sample file
1269
1270 guard let sampledata = self.dataWithResource(name)
1271 else { XCTFail("failed to open bundle resource named " + name); return }
1272 var dict : NSDictionary?
1273
1274 dict = try? self.parseBuffer(sampledata) as NSDictionary
1275
1276 if (dict == nil) {
1277 if let decoded = NSData(base64Encoded: sampledata as Data, options:.ignoreUnknownCharacters) {
1278 dict = try? self.parseBuffer(decoded) as NSDictionary
1279 }
1280 }
1281
1282 if (dict == nil) {
1283 if let decompressed = try? decompress(sampledata) {
1284 dict = try? self.parseBuffer(decompressed) as NSDictionary
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
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)
1299 }
1300 guard let dict2 = opt_dict2
1301 else { XCTFail(); return}
1302
1303 XCTAssertEqual(dict, dict2 as! NSDictionary);
1304
1305 //XCTAssert(dict == dict2 as? NSDictionary)
1306
1307 // check that we agree with python
1308
1309 #if os(OSX)
1310
1311 let kcdatapy = Bundle(for: self.classForCoder).path(forResource: "kcdata.py", ofType: nil)
1312
1313 let task = Process()
1314 task.launchPath = kcdatapy
1315 task.arguments = ["-p",
1316 Bundle(for:self.classForCoder).path(forResource: name, ofType: nil)!]
1317 let pipe = Pipe()
1318 task.standardOutput = pipe
1319 task.launch()
1320
1321 let data = pipe.fileHandleForReading.readDataToEndOfFile()
1322
1323 guard let dict3 = try? PropertyListSerialization.propertyList(from:data, options:[], format: nil) as? NSDictionary
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 }
1366
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
1399 func testSampleThreadGroups() {
1400 self.testSampleStackshot("stackshot-sample-thread-groups")
1401 }
1402
1403 func testSampleThreadGroupsFlags() {
1404 self.testSampleStackshot("stackshot-sample-thread-groups-flags")
1405 }
1406
1407 func testSampleCoalitions() {
1408 self.testSampleStackshot("stackshot-sample-coalitions")
1409 }
1410
1411 func testSampleTurnstileInfo() {
1412 self.testSampleStackshot("stackshot-sample-turnstileinfo")
1413 }
1414
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
1431 func testStackshotWithWaitinfo() {
1432 self.testSampleStackshot("stackshot-with-waitinfo")
1433 }
1434
1435 func testStackshotWithThreadPolicy() {
1436 self.testSampleStackshot("stackshot-sample-thread-policy")
1437 }
1438
1439 func testDeltaStackshotWithThreadPolicy() {
1440 self.testSampleStackshot("stackshot-sample-delta-thread-policy")
1441 }
1442
1443 func testStackshotWithInstrsCycles() {
1444 self.testSampleStackshot("stackshot-sample-instrs-cycles")
1445 }
1446
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
1467 func testStackshotDispatchQueueLabel() {
1468 self.testSampleStackshot("stackshot-sample-dispatch-queue-label")
1469 }
1470
1471 func testTrivial() {
1472 }
1473 }