xref: /xnu-8020.101.4/libkdd/tests/Tests.swift (revision e7776783b89a353188416a9a346c6cdb4928faad)
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 
nsuuid2uuid_tnull23 func nsuuid2uuid_t(_ nsuuid : NSUUID) -> uuid_t {
24     let dat = nsuuid2array(nsuuid)
25     return nsarray2uuid(dat)
26 }
27 
nsarray2uuidnull28 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 
nsuuid2arraynull47 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 
decompressnull60 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 {
valuenull90     func value(forKeyPath s:String) -> Any? {
91         return (self as NSDictionary).value(forKeyPath:s)
92     }
93 }
94 
95 
96 class Tests: XCTestCase {
97 
setUpnull98     override func setUp() {
99         super.setUp()
100         continueAfterFailure = false
101     }
102 
tearDownnull103     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 
parseBuffernull108     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 
testPaddingFlagsnull118     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 
testPaddingFlagsnull155     func testPaddingFlags() {
156         for i in 0..<15 {
157             testPaddingFlags(i)
158         }
159     }
testBootArgsnull160     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 
testBootArgsMissingNulnull188     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 
testLoadInfonull216     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 
testLoadInfoWrongSizenull248     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 
testLoadInfoWayWrongSizenull283     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 
testLoadInfoPreposterousWrongSizenull315     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 
testNewArraynull347     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 
testNewArraysnull386     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 
testArrayLoadInfonull396     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 
testArrayLoadInfonull437     func testArrayLoadInfo() {
438         for n in 0..<20 {
439             testArrayLoadInfo(n: n)
440         }
441     }
442 
testArrayLoadInfoWrongSizenull443     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 
testArrayLoadInfoWayWrongSizenull490     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 
testArrayLoadInfoPreposterouslyWrongSizenull534     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 
testNestednull577     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 
testReadThreadidnull625     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 
testRepeatedKeynull655     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 
testContainernull692     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 
testDispatchQueueLabelnull737     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 
testRepeatedContainernull797     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 
testContainerNoEndnull863     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 
testContainerNoEndNoEndnull897     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 
testNoEndnull928     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 
testCrazySizenull950     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 
testReadRepeatedArraynull976     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 
testReadThreadidArraynull1025     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 
testReadThreadidArraynull1068     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 
testReadThreadidArrayWrongSize1null1078     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 
testReadThreadidArrayWrongSize5null1108     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 
testReadThreadidArrayPaddedSizenull1139     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 
testReadThreadidArrayPaddedSize15null1180     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 
testReadThreadidWrongSizenull1224     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 
testReadThreadidWrongSize0null1253     func testReadThreadidWrongSize0() {
1254         self.testReadThreadidWrongSize(size: 0)
1255     }
1256 
testReadThreadidWrongSize7null1257     func testReadThreadidWrongSize7() {
1258         self.testReadThreadidWrongSize(size: 7)
1259     }
1260 
dataWithResourcenull1261     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 
testSampleStackshotnull1267     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(String(format:"Failed to decode %@", name)); 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         // default python based on #! is python3 in kcdata.py
1311         let kcdatapy = Bundle(for: self.classForCoder).path(forResource: "kcdata.py", ofType: nil)
1312         let pyargs = ["-p", Bundle(for:self.classForCoder).path(forResource: name, ofType: nil)!]
1313         let task = Process()
1314         task.launchPath = kcdatapy
1315         task.arguments = pyargs
1316         let pipe = Pipe()
1317         task.standardOutput = pipe
1318         let cli_invocation = task.arguments!.reduce(task.launchPath!) {$0 + " " + $1}
1319         print(cli_invocation)
1320         task.launch()
1321 
1322         let data = pipe.fileHandleForReading.readDataToEndOfFile()
1323 
1324             guard let dict3 = try? PropertyListSerialization.propertyList(from:data, options:[], format: nil) as? NSDictionary
1325             else { XCTFail(); return }
1326 
1327         XCTAssert(dict == dict3)
1328 
1329         // check for python2 if present
1330         let py2path = "/usr/bin/python2"
1331         if FileManager.default.fileExists(atPath: py2path) {
1332             let task = Process()
1333             task.launchPath = py2path
1334             task.arguments = [kcdatapy!] + pyargs
1335             let pipe = Pipe()
1336             task.standardOutput = pipe
1337             let cli_invocation = task.arguments!.reduce(task.launchPath!) {$0 + " " + $1}
1338             print(cli_invocation)
1339             task.launch()
1340 
1341             let data = pipe.fileHandleForReading.readDataToEndOfFile()
1342 
1343             guard let dict4 = try? PropertyListSerialization.propertyList(from:data, options:[], format: nil) as? NSDictionary
1344             else { XCTFail(); return }
1345 
1346             XCTAssert(dict == dict4)
1347 
1348         }
1349         #endif
1350     }
1351 
testSampleStackshotnull1352     func testSampleStackshot() {
1353         self.testSampleStackshot("stackshot-sample")
1354     }
1355 
testSampleStackshotOldArraysnull1356     func testSampleStackshotOldArrays() {
1357         self.testSampleStackshot("stackshot-sample-old-arrays")
1358     }
1359 
testSampleStackshotNewArraysnull1360     func testSampleStackshotNewArrays() {
1361         self.testSampleStackshot("stackshot-sample-new-arrays")
1362     }
1363 
testSampleDeltaStackshotOldArraysnull1364     func testSampleDeltaStackshotOldArrays() {
1365         self.testSampleStackshot("delta-stackshot-sample-old-arrays")
1366     }
1367 
testSampleDeltaStackshotNewArraysnull1368     func testSampleDeltaStackshotNewArrays() {
1369         self.testSampleStackshot("delta-stackshot-sample-new-arrays")
1370     }
1371 
testSampleCorpsenull1372     func testSampleCorpse() {
1373         self.testSampleStackshot("corpse-sample")
1374     }
1375 
testSampleStackshotTailspinnull1376     func testSampleStackshotTailspin() {
1377         self.testSampleStackshot("stackshot-sample-tailspin")
1378     }
1379 
testSampleStackshotTailspin2null1380     func testSampleStackshotTailspin2() {
1381         self.testSampleStackshot("stackshot-sample-tailspin-2")
1382     }
1383 
testSampleExitReasonnull1384     func testSampleExitReason() {
1385         self.testSampleStackshot("exitreason-sample")
1386     }
1387 
testSampleThreadTnull1388     func testSampleThreadT() {
1389         self.testSampleStackshot("stackshot-sample-ths-thread-t")
1390     }
1391 
testSampleCpuTimesnull1392     func testSampleCpuTimes() {
1393         self.testSampleStackshot("stackshot-sample-cputime")
1394     }
1395 
testSampleDurationnull1396     func testSampleDuration() {
1397         self.testSampleStackshot("stackshot-sample-duration")
1398     }
1399 
testSampleNestednull1400     func testSampleNested() {
1401         self.testSampleStackshot("nested-sample")
1402     }
1403 
testSampleTermWithReasonnull1404     func testSampleTermWithReason() {
1405         self.testSampleStackshot("test-twr-sample")
1406     }
1407 
testSampleCorpseTermWithReasonnull1408     func testSampleCorpseTermWithReason() {
1409         self.testSampleStackshot("corpse-twr-sample")
1410     }
1411 
testSampleCorpseTermWithReasonV2null1412     func testSampleCorpseTermWithReasonV2() {
1413         self.testSampleStackshot("corpse-twr-sample-v2")
1414     }
1415 
testSampleCodesigningExitReasonnull1416     func testSampleCodesigningExitReason() {
1417         self.testSampleStackshot("exitreason-codesigning")
1418     }
1419 
testSampleThreadGroupsnull1420     func testSampleThreadGroups() {
1421         self.testSampleStackshot("stackshot-sample-thread-groups")
1422     }
1423 
testSampleThreadGroupsFlagsnull1424     func testSampleThreadGroupsFlags() {
1425         self.testSampleStackshot("stackshot-sample-thread-groups-flags")
1426     }
1427 
testSampleCoalitionsnull1428     func testSampleCoalitions() {
1429         self.testSampleStackshot("stackshot-sample-coalitions")
1430     }
1431 
testSampleTurnstileInfonull1432     func testSampleTurnstileInfo() {
1433         self.testSampleStackshot("stackshot-sample-turnstileinfo")
1434     }
1435 
testStackshotSharedcacheV2null1436     func testStackshotSharedcacheV2() {
1437         self.testSampleStackshot("stackshot-sample-sharedcachev2")
1438     }
1439 
testStackshotFaultStatsnull1440     func testStackshotFaultStats() {
1441         self.testSampleStackshot("stackshot-fault-stats")
1442     }
1443 
testStackshotwithKCIDnull1444     func testStackshotwithKCID() {
1445         self.testSampleStackshot("stackshot-with-kcid")
1446     }
1447 
testXNUPostTestConfignull1448     func testXNUPostTestConfig() {
1449         self.testSampleStackshot("xnupost_testconfig-sample")
1450     }
1451 
testStackshotWithWaitinfonull1452     func testStackshotWithWaitinfo() {
1453         self.testSampleStackshot("stackshot-with-waitinfo")
1454     }
1455 
testStackshotWithAsyncInfonull1456     func testStackshotWithAsyncInfo() {
1457         self.testSampleStackshot("stackshot-with-asyncinfo")
1458     }
1459 
testStackshotWithThreadPolicynull1460     func testStackshotWithThreadPolicy() {
1461         self.testSampleStackshot("stackshot-sample-thread-policy")
1462     }
1463 
testDeltaStackshotWithThreadPolicynull1464     func testDeltaStackshotWithThreadPolicy() {
1465         self.testSampleStackshot("stackshot-sample-delta-thread-policy")
1466     }
1467 
testStackshotWithInstrsCyclesnull1468     func testStackshotWithInstrsCycles() {
1469         self.testSampleStackshot("stackshot-sample-instrs-cycles")
1470     }
1471 
testStackshotWithPortlabelsnull1472     func testStackshotWithPortlabels() {
1473         self.testSampleStackshot("stackshot-sample-portlabels")
1474     }
1475 
testStackshotWithStacktopnull1476     func testStackshotWithStacktop() {
1477         self.testSampleStackshot("stackshot-sample-stacktop")
1478     }
1479 
testStackshotWithAOTnull1480     func testStackshotWithAOT() {
1481         self.testSampleStackshot("stackshot-sample-aot")
1482     }
1483 
testStackshotWithASIDnull1484     func testStackshotWithASID() {
1485         self.testSampleStackshot("stackshot-sample-asid")
1486     }
1487 
testStackshotWithPageTablesnull1488     func testStackshotWithPageTables() {
1489         self.testSampleStackshot("stackshot-sample-asid-pagetable")
1490     }
1491 
testStackshotCPUTimesnull1492     func testStackshotCPUTimes() {
1493         self.testSampleStackshot("stackshot-sample-cpu-times")
1494     }
1495 
testStackshotWithSharedCacheLayoutnull1496     func testStackshotWithSharedCacheLayout() {
1497         self.testSampleStackshot("stackshot-with-shared-cache-layout")
1498     }
1499 
testStackshotDispatchQueueLabelnull1500     func testStackshotDispatchQueueLabel() {
1501         self.testSampleStackshot("stackshot-sample-dispatch-queue-label")
1502     }
1503 
testTrivialnull1504     func testTrivial() {
1505     }
1506 }
1507