]> git.saurik.com Git - apple/xnu.git/blob - libkdd/tests/Tests.swift
xnu-4570.31.3.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 testRepeatedContainer() {
738 //repeated container of same name and key shoudl fail
739
740 let buffer = NSMutableData(capacity:1000)!
741
742 var item = kcdata_item()
743 var payload64 : UInt64
744 var payload32 : UInt32
745
746 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
747 item.flags = 0
748 item.size = 0
749 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
750
751 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
752 item.flags = 0
753 item.size = UInt32(MemoryLayout<UInt32>.size)
754 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
755 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
756 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
757
758 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
759 item.flags = 0
760 item.size = UInt32(MemoryLayout<UInt64>.size)
761 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
762 payload64 = 42
763 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
764
765 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
766 item.flags = 0
767 item.size = UInt32(MemoryLayout<UInt32>.size)
768 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
769 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
770 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
771
772
773 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
774 item.flags = 0
775 item.size = UInt32(MemoryLayout<UInt32>.size)
776 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
777 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
778 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
779
780 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
781 item.flags = 0
782 item.size = UInt32(MemoryLayout<UInt64>.size)
783 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
784 payload64 = 42
785 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
786
787 item.type = UInt32(KCDATA_TYPE_CONTAINER_END)
788 item.flags = 0
789 item.size = UInt32(MemoryLayout<UInt32>.size)
790 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
791 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
792 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
793
794 item.type = KCDATA_TYPE_BUFFER_END
795 item.flags = 0
796 item.size = 0
797 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
798
799 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
800 }
801
802
803 func testContainerNoEnd() {
804 let buffer = NSMutableData(capacity:1000)!
805
806 var item = kcdata_item()
807 var payload64 : UInt64
808 var payload32 : UInt32
809
810 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
811 item.flags = 0
812 item.size = 0
813 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
814
815 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
816 item.flags = 0
817 item.size = UInt32(MemoryLayout<UInt32>.size)
818 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
819 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
820 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
821
822 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
823 item.flags = 0
824 item.size = UInt32(MemoryLayout<UInt64>.size)
825 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
826 payload64 = 42
827 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
828
829 item.type = KCDATA_TYPE_BUFFER_END
830 item.flags = 0
831 item.size = 0
832 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
833
834 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
835 }
836
837 func testContainerNoEndNoEnd() {
838 let buffer = NSMutableData(capacity:1000)!
839
840 var item = kcdata_item()
841 var payload64 : UInt64
842 var payload32 : UInt32
843
844 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
845 item.flags = 0
846 item.size = 0
847 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
848
849 item.type = UInt32(KCDATA_TYPE_CONTAINER_BEGIN)
850 item.flags = 0
851 item.size = UInt32(MemoryLayout<UInt32>.size)
852 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
853 payload32 = UInt32(STACKSHOT_KCCONTAINER_TASK)
854 buffer.append(&payload32, length:MemoryLayout<UInt32>.size)
855
856 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
857 item.flags = 0
858 item.size = UInt32(MemoryLayout<UInt64>.size)
859 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
860 payload64 = 42
861 buffer.append(&payload64, length:MemoryLayout<UInt64>.size)
862
863 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
864 }
865
866
867
868 func testNoEnd() {
869 let buffer = NSMutableData(capacity:1000)!
870
871 var item = kcdata_item()
872
873 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
874 item.flags = 0
875 item.size = 0
876 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
877
878 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
879 item.flags = 0
880 item.size = UInt32(MemoryLayout<UInt64>.size)
881 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
882
883 var payload : UInt64 = 42
884 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
885
886 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
887 }
888
889
890 func testCrazySize() {
891 let buffer = NSMutableData(capacity:1000)!
892
893 var item = kcdata_item()
894
895 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
896 item.flags = 0
897 item.size = 0
898 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
899
900 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
901 item.flags = 0
902 item.size = 99999
903 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
904
905 var payload : UInt64 = 42
906 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
907
908 item.type = KCDATA_TYPE_BUFFER_END
909 item.flags = 0
910 item.size = 0
911 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
912
913 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
914 }
915
916 func testReadRepeatedArray() {
917 // repeated arrays should be concatenated
918 let n = 10
919
920 let buffer = NSMutableData(capacity:1000)!
921
922 var item = kcdata_item()
923
924 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
925 item.flags = 0
926 item.size = 0
927 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
928
929 item.type = UInt32(KCDATA_TYPE_ARRAY)
930 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
931 item.size = UInt32(n * MemoryLayout<UInt64>.size)
932 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
933
934 for i in 0..<n {
935 var payload : UInt64 = UInt64(i)
936 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
937 }
938
939 item.type = UInt32(KCDATA_TYPE_ARRAY)
940 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
941 item.size = UInt32(n * MemoryLayout<UInt64>.size)
942 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
943
944 for i in 0..<n {
945 var payload : UInt64 = UInt64(i)
946 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
947 }
948
949 item.type = KCDATA_TYPE_BUFFER_END
950 item.flags = 0
951 item.size = 0
952 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
953
954 guard let dict = try? self.parseBuffer(buffer)
955 else { XCTFail(); return }
956
957 XCTAssert( 2*n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
958 for i in 0..<2*n {
959 let x = dict["kcdata_crashinfo"] as? NSDictionary
960 let y = x?["crashed_threadid"] as? NSArray
961 XCTAssert((y?[i]) as? Int == i % n)
962 }
963 }
964
965 func testReadThreadidArray(n : Int, pad : Int) {
966 let buffer = NSMutableData(capacity:1000)!
967
968 var item = kcdata_item()
969
970 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
971 item.flags = 0
972 item.size = 0
973 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
974
975 item.type = UInt32(KCDATA_TYPE_ARRAY)
976 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
977 item.size = UInt32(n * MemoryLayout<UInt64>.size + pad)
978 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
979
980 for i in 0..<n {
981 var payload : UInt64 = UInt64(i)
982 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
983 }
984
985 for _ in 0..<pad {
986 var payload : UInt8 = 0
987 buffer.append(&payload, length:1)
988 }
989
990 item.type = KCDATA_TYPE_BUFFER_END
991 item.flags = 0
992 item.size = 0
993 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
994
995 guard let dict = try? self.parseBuffer(buffer)
996 else { XCTFail(); return; }
997
998 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
999
1000 for i in 0..<n {
1001 let x = dict["kcdata_crashinfo"] as? NSDictionary
1002 let y = x?["crashed_threadid"] as? NSArray
1003 XCTAssert((y?[i]) as? Int == i)
1004 }
1005
1006 }
1007
1008 func testReadThreadidArray() {
1009 // test that we can correctly read old arrays with a variety of sizes and paddings
1010 self.testReadThreadidArray(n: 0, pad:0)
1011 for n in 1..<100 {
1012 for pad in 0..<16 {
1013 self.testReadThreadidArray(n: n, pad:pad)
1014 }
1015 }
1016 }
1017
1018 func testReadThreadidArrayWrongSize1() {
1019 /// 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
1020
1021 let n = 1
1022
1023 let buffer = NSMutableData(capacity:1000)!
1024
1025 var item = kcdata_item()
1026
1027 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1028 item.flags = 0
1029 item.size = 0
1030 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1031
1032 item.type = UInt32(KCDATA_TYPE_ARRAY)
1033 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1034 item.size = UInt32(4)
1035 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1036
1037 var payload : UInt32 = UInt32(42)
1038 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1039
1040 item.type = KCDATA_TYPE_BUFFER_END
1041 item.flags = 0
1042 item.size = 0
1043 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1044
1045 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1046 }
1047
1048 func testReadThreadidArrayWrongSize5() {
1049 /// if the count is bigger than the buffer, parsing will just fail
1050
1051 let n = 5
1052
1053 let buffer = NSMutableData(capacity:1000)!
1054
1055 var item = kcdata_item()
1056
1057 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1058 item.flags = 0
1059 item.size = 0
1060 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1061
1062 item.type = UInt32(KCDATA_TYPE_ARRAY)
1063 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1064 item.size = UInt32(4)
1065 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1066
1067 var payload : UInt32 = UInt32(42)
1068 buffer.append(&payload, length:MemoryLayout<UInt32>.size)
1069
1070 item.type = KCDATA_TYPE_BUFFER_END
1071 item.flags = 0
1072 item.size = 0
1073 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1074
1075 XCTAssert( (try? self.parseBuffer(buffer)) == nil )
1076 }
1077
1078
1079 func testReadThreadidArrayPaddedSize() {
1080 // test that we can tolerate a little padding at the end of an array
1081 let n = 5
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(n * MemoryLayout<UInt64>.size) + 1
1095 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1096
1097 for i in 0..<n {
1098 var payload : UInt64 = UInt64(i)
1099 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1100 }
1101 var payload : UInt8 = 0
1102 buffer.append(&payload, length:1)
1103
1104 item.type = KCDATA_TYPE_BUFFER_END
1105 item.flags = 0
1106 item.size = 0
1107 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1108
1109 guard let dict = try? self.parseBuffer(buffer)
1110 else { XCTFail(); return; }
1111
1112 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1113 for i in 0..<n {
1114 let x = dict["kcdata_crashinfo"] as? NSDictionary
1115 let y = x?["crashed_threadid"] as? NSArray
1116 XCTAssert((y?[i]) as? Int == i)
1117 }
1118 }
1119
1120 func testReadThreadidArrayPaddedSize15() {
1121 // test that we can tolerate a little padding at the end of an array
1122 let n = 5
1123
1124 let buffer = NSMutableData(capacity:1000)!
1125
1126 var item = kcdata_item()
1127
1128 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1129 item.flags = 0
1130 item.size = 0
1131 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1132
1133 item.type = UInt32(KCDATA_TYPE_ARRAY)
1134 item.flags = UInt64(TASK_CRASHINFO_CRASHED_THREADID) << 32 | UInt64(n)
1135 item.size = UInt32(n * MemoryLayout<UInt64>.size) + 15
1136 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1137
1138 for i in 0..<n {
1139 var payload : UInt64 = UInt64(i)
1140 buffer.append(&payload, length:MemoryLayout<UInt64>.size)
1141 }
1142 for _ in 0..<15 {
1143 var payload : UInt8 = 0
1144 buffer.append(&payload, length:1)
1145 }
1146
1147 item.type = KCDATA_TYPE_BUFFER_END
1148 item.flags = 0
1149 item.size = 0
1150 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1151
1152 guard let dict = try? self.parseBuffer(buffer)
1153 else { XCTFail(); return; }
1154
1155 XCTAssert( n == (dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") as! [Any]).count)
1156 for i in 0..<n {
1157 let x = dict["kcdata_crashinfo"] as? NSDictionary
1158 let y = x?["crashed_threadid"] as? NSArray
1159 XCTAssert((y?[i]) as? Int == i)
1160 }
1161 }
1162
1163
1164 func testReadThreadidWrongSize(size : UInt32) {
1165 let buffer = NSMutableData(capacity:1000)!
1166
1167 var item = kcdata_item()
1168
1169 item.type = KCDATA_BUFFER_BEGIN_CRASHINFO
1170 item.flags = 0
1171 item.size = 0
1172 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1173
1174 item.type = UInt32(TASK_CRASHINFO_CRASHED_THREADID)
1175 item.flags = 0
1176 item.size = size
1177 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1178
1179 var payload : UInt64 = 42
1180 buffer.append(&payload, length:Int(size))
1181
1182 item.type = KCDATA_TYPE_BUFFER_END
1183 item.flags = 0
1184 item.size = 0
1185 buffer.append(&item, length: MemoryLayout<kcdata_item>.size)
1186
1187 guard let dict = try? self.parseBuffer(buffer)
1188 else { XCTFail(); return; }
1189
1190 XCTAssert(dict.value(forKeyPath:"kcdata_crashinfo.crashed_threadid") == nil)
1191 }
1192
1193 func testReadThreadidWrongSize0() {
1194 self.testReadThreadidWrongSize(size: 0)
1195 }
1196
1197 func testReadThreadidWrongSize7() {
1198 self.testReadThreadidWrongSize(size: 7)
1199 }
1200
1201 func dataWithResource(_ name:String) -> NSData? {
1202 guard let filename = Bundle(for: self.classForCoder).path(forResource: name, ofType: nil)
1203 else { return nil }
1204 return NSData(contentsOfFile:filename)!
1205 }
1206
1207 func testSampleStackshot(_ name : String) {
1208 // check that we agree with sample file
1209
1210 guard let sampledata = self.dataWithResource(name)
1211 else { XCTFail(); return }
1212 var dict : NSDictionary?
1213
1214 dict = try? self.parseBuffer(sampledata) as NSDictionary
1215
1216 if (dict == nil) {
1217 if let decoded = NSData(base64Encoded: sampledata as Data, options:.ignoreUnknownCharacters) {
1218 dict = try? self.parseBuffer(decoded) as NSDictionary
1219 }
1220 }
1221
1222 if (dict == nil) {
1223 if let decompressed = try? decompress(sampledata) {
1224 dict = try? self.parseBuffer(decompressed) as NSDictionary
1225 }
1226 }
1227
1228 if (dict == nil) {
1229 XCTFail(); return;
1230 }
1231
1232 guard let plistdata = self.dataWithResource(name + ".plist.gz") ??
1233 self.dataWithResource(name + ".plist")
1234 else {XCTFail(); return}
1235
1236 var dict2 = try? PropertyListSerialization.propertyList(from: plistdata as Data, options: [], format: nil)
1237 if dict2 == nil {
1238 dict2 = try? PropertyListSerialization.propertyList(from:decompress(plistdata) as Data, options:[], format: nil)
1239 }
1240
1241 XCTAssert(dict2 != nil)
1242
1243 XCTAssert(dict == dict2 as? NSDictionary)
1244
1245 // check that we agree with python
1246
1247 #if os(OSX)
1248
1249 let kcdatapy = Bundle(for: self.classForCoder).path(forResource: "kcdata.py", ofType: nil)
1250
1251 let task = Process()
1252 task.launchPath = kcdatapy
1253 task.arguments = ["-p",
1254 Bundle(for:self.classForCoder).path(forResource: name, ofType: nil)!]
1255 let pipe = Pipe()
1256 task.standardOutput = pipe
1257 task.launch()
1258
1259 let data = pipe.fileHandleForReading.readDataToEndOfFile()
1260
1261 guard let dict3 = try? PropertyListSerialization.propertyList(from:data, options:[], format: nil) as? NSDictionary
1262 else { XCTFail(); return }
1263
1264 XCTAssert(dict == dict3)
1265
1266 #endif
1267 }
1268
1269 func testSampleStackshot() {
1270 self.testSampleStackshot("stackshot-sample")
1271 }
1272
1273 func testSampleStackshotOldArrays() {
1274 self.testSampleStackshot("stackshot-sample-old-arrays")
1275 }
1276
1277 func testSampleStackshotNewArrays() {
1278 self.testSampleStackshot("stackshot-sample-new-arrays")
1279 }
1280
1281 func testSampleDeltaStackshotOldArrays() {
1282 self.testSampleStackshot("delta-stackshot-sample-old-arrays")
1283 }
1284
1285 func testSampleDeltaStackshotNewArrays() {
1286 self.testSampleStackshot("delta-stackshot-sample-new-arrays")
1287 }
1288
1289 func testSampleCorpse() {
1290 self.testSampleStackshot("corpse-sample")
1291 }
1292
1293 func testSampleStackshotTailspin() {
1294 self.testSampleStackshot("stackshot-sample-tailspin")
1295 }
1296
1297 func testSampleStackshotTailspin2() {
1298 self.testSampleStackshot("stackshot-sample-tailspin-2")
1299 }
1300
1301 func testSampleExitReason() {
1302 self.testSampleStackshot("exitreason-sample")
1303 }
1304
1305 func testSampleThreadT() {
1306 self.testSampleStackshot("stackshot-sample-ths-thread-t")
1307 }
1308
1309 func testSampleCpuTimes() {
1310 self.testSampleStackshot("stackshot-sample-cputime")
1311 }
1312
1313 func testSampleDuration() {
1314 self.testSampleStackshot("stackshot-sample-duration")
1315 }
1316
1317 func testSampleNested() {
1318 self.testSampleStackshot("nested-sample")
1319 }
1320
1321 func testSampleTermWithReason() {
1322 self.testSampleStackshot("test-twr-sample")
1323 }
1324
1325 func testSampleCorpseTermWithReason() {
1326 self.testSampleStackshot("corpse-twr-sample")
1327 }
1328
1329 func testSampleCorpseTermWithReasonV2() {
1330 self.testSampleStackshot("corpse-twr-sample-v2")
1331 }
1332
1333 func testSampleCodesigningExitReason() {
1334 self.testSampleStackshot("exitreason-codesigning")
1335 }
1336
1337 func testSampleThreadGroups() {
1338 self.testSampleStackshot("stackshot-sample-thread-groups")
1339 }
1340
1341 func testSampleThreadGroupsFlags() {
1342 self.testSampleStackshot("stackshot-sample-thread-groups-flags")
1343 }
1344
1345 func testSampleCoalitions() {
1346 self.testSampleStackshot("stackshot-sample-coalitions")
1347 }
1348
1349 func testStackshotSharedcacheV2() {
1350 self.testSampleStackshot("stackshot-sample-sharedcachev2")
1351 }
1352
1353 func testStackshotFaultStats() {
1354 self.testSampleStackshot("stackshot-fault-stats")
1355 }
1356
1357 func testStackshotwithKCID() {
1358 self.testSampleStackshot("stackshot-with-kcid")
1359 }
1360
1361 func testXNUPostTestConfig() {
1362 self.testSampleStackshot("xnupost_testconfig-sample")
1363 }
1364
1365 func testStackshotWithWaitinfo() {
1366 self.testSampleStackshot("stackshot-with-waitinfo")
1367 }
1368
1369 func testStackshotWithThreadPolicy() {
1370 self.testSampleStackshot("stackshot-sample-thread-policy")
1371 }
1372
1373 func testStackshotWithInstrsCycles() {
1374 self.testSampleStackshot("stackshot-sample-instrs-cycles")
1375 }
1376
1377 func testTrivial() {
1378 }
1379 }