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