pointfreeco / swift-custom-dump Goto Github PK
View Code? Open in Web Editor NEWA collection of tools for debugging, diffing, and testing your application's data structures.
License: MIT License
A collection of tools for debugging, diffing, and testing your application's data structures.
License: MIT License
Describe the bug
Compiler assertion when using swift 5.10
To Reproduce
Compile the library using the latest Xcode RC that includes swift 5.10
Currently Xcode 15.3 RC
Expected behavior
The compiler should compile the source.
Environment
Additional context
This API seems to be the culprit
Also tagged @stephencelis in Vapor's discord with the conversation for more context
Describe the bug
Passing a LocalizedStringKey
constructed with basic string interpolation works correctly. For example, the following code works as you would expect:
let name = "Dalton"
let control: LocalizedStringKey = "Static string"
let success: LocalizedStringKey = "Hello, \(name)!"
// This prints:
// - "Static string"
// + "Hello, Dalton!"
print(diff(control, success) ?? "No diff")
However, passing a LocalizedStringKey
that uses any of the other variations of string interpolation supported by LocalizedStringKey
results in a crash:
let control: LocalizedStringKey = "Static string"
let crash1: LocalizedStringKey = "Date: \(Date(), style: .date)"
let crash2: LocalizedStringKey = "Date range: \(Date.distantPast...Date.distantFuture)"
let crash3: LocalizedStringKey = "Time: \(Duration.seconds(10), format: .time(pattern: .minuteSecond))"
print(diff(control, crash1) ?? "No diff") // crash!
print(diff(control, crash2) ?? "No diff") // crash!
print(diff(control, crash3) ?? "No diff") // crash!
The crash (SIGABRT
) occurs on this line:
The console output:
Could not cast value of type 'SwiftUI.LocalizedStringKey.FormatArgument.Token' (0x1fea477e8) to 'NSFormatter' (0x1fd708ed8).
2023-09-02 19:11:54.584602-0500 dump-bug[32884:11397570] Could not cast value of type 'SwiftUI.LocalizedStringKey.FormatArgument.Token' (0x1fea477e8) to 'NSFormatter' (0x1fd708ed8).
Expected behavior
I expect that the above code would not result in a crash and would instead print an appropriate diff between the provided strings.
Environment
Describe the bug
When using customDump(_:to:)
with a plain dictionary eg [String: Int]
the keys are sorted correctly.
When this dictionary is nested, eg in a struct, the keys are no longer sorted.
I noticed this bug when I migrated a project from 0.6.1 to 0.10.2 (seems to occur from 0.10.0 and above).
To Reproduce
import CustomDump
import XCTest
final class DictionarySortedDumpTests: XCTestCase {
// Works as expected
func testDictionaryDump() {
// Given
let dictionary = ["a": 5, "b": 9, "c": 1, "d": -3, "e": 12]
let expectedResult = """
[
"a": 5,
"b": 9,
"c": 1,
"d": -3,
"e": 12
]
"""
// When
var buffer = Buffer()
customDump(dictionary, to: &buffer)
// Then
XCTAssertEqual(buffer.value, expectedResult)
}
// Fails for ~(5! - 1) times
func testNestedDictionaryDump() {
// Given
let dictionary = ["a": 5, "b": 9, "c": 1, "d": -3, "e": 12]
let expectedResult = """
NestedDictionary(
content: [
"a": 5,
"b": 9,
"c": 1,
"d": -1,
"e": 12
]
)
"""
// When
var buffer = Buffer()
customDump(NestedDictionary(content: dictionary), to: &buffer)
// Then
XCTAssertEqual(buffer.value, expectedResult)
}
}
private struct Buffer: TextOutputStream {
private(set) var value: String = ""
mutating func write(_ string: String) {
value += string
}
}
private struct NestedDictionary {
private let content: [String: Int]
init(content: [String: Int]) {
self.content = content
}
}
Expected behavior
I would expect that nested dictionaries are sorted alphabetically like it was in version 0.9.1 and below.
The consistent output is important when for example using snapshot testing. Now every time we record new snapshots the files change. But also the compare fails.
Environment
Describe the bug
Sometimes, you have a big struct full of floating-point numbers, and you want to test them. But the code that produces these structs is susceptible to the foibles of floating-point math, so you want to use the equivalent of the XCTAssertEqual
overload that takes an accuracy
parameter. This would let you assert on a whole struct or nested tree of structs, where any floating-point properties are compared with the given accuracy.
To Reproduce
Proposed syntax:
struct MyThing: Equatable {
var foo: Double
}
let a = MyThing(foo: 1)
let b = MyThing(foo: 1.0001)
XCTAssertNoDifference(a, b, accuracy: 0.01)
Expected behavior
This code compiles, and any floating-point values found in the structs or their children are compared using the given precision.
Additional context
An alternative (that I'm going to use in my app for now) is to write a property wrapper such that you can do:
@CloseEnough var foo: Double
And then have a global/Current
-style precision value that you can set before you write an assertion. The @CloseEnough
property wrapper would use default ==
comparison in production, and use the precision value only when running in tests.
I tried adding my proposed fix to swift-custom-dump, but got bogged down in _openExistential
soup that I didn't understand enough to proceed.
Dumping a struct with an NSNumber crashes CustomDump. Storing the number as Double fixes the issue for me. The NSNumber is coming out of CoreBluetooh's API so pretty old and low-level.
Describe the bug
Dumping a key path crashes CustomDump
. But this only happens in release build that builds on Xcode 14.
Our app uses CustomDump
to do logging and now it always crashes when there's a BindingAction
gets logged.
Tried on Xcode 13.4.1 and there's no problem.
To Reproduce
Just dump any key paths in release build in Xcode 14.
Sample project: https://github.com/jutoart/DumpKeyPath
public struct DumpKeyPath {
public private(set) var text = "Hello, World!"
private let keyPath: WritableKeyPath<DumpKeyPath, String> = \.text
public static func main() {
customDump(testObject.keyPath) // <-- crash here
}
}
Screenshots
Environment
Describe the bug
When trying to dump a generic type, the generic information is not included in the dump
To Reproduce
func testGeneric() {
struct Box<T> {
let value: T
}
let stringBox = Box(value: "test")
var dump = ""
customDump(
stringBox,
to: &dump
)
XCTAssertNoDifference(
dump,
"""
DumpTests.Box(value: \"test\")
"""
)
// Expecting the dump to be DumpTests.Box<String>(value: \"test\") instead
}
Expected behavior
Expecting the generic type information to be included in the dump i.e. DumpTests.Box<String>(value: \"test\")
Environment
I have a project that depends on swift-composable-architecture
which depends on this package. I am using the latest release, v0.30.0.
After updating to Xcode 13.2 and doing a clean build, my project fails to compile.
Please refer to the screenshots for the issue I am seeing.
The Package.swift
for my project declares:
platforms: [
.iOS(.v15)
],
So I do not understand why I am encountering this issue.
Describe the bug
When comparing instances of UIImage
or #imageLiteral
XCTAssertNoDifference
doesn't provide a diff, XCTAssertEqual
does.
To Reproduce
testExample
in ImageResourceComparisonDemoTests
has some assertions which show the difference
ImageResourceComparisonDemo.zip
XCTAssertEqual(
#imageLiteral(
resourceName: "ExampleImage"
),
#imageLiteral(
resourceName: "ExampleImage2"
)
)
// π Produces this diff:
/**
testExample(): XCTAssertEqual failed: ("<UIImage:0x600002d50480 named(main: ExampleImage) {1200, 1200} renderingMode=automatic(original)>") is not equal to ("<UIImage:0x600002d505a0 named(main: ExampleImage2) {1200, 1200} renderingMode=automatic(original)>")
*/
XCTAssertNoDifference(
#imageLiteral(
resourceName: "ExampleImage"
),
#imageLiteral(
resourceName: "ExampleImage2"
)
)
// π Produces this diff:
/**
testExample(): XCTAssertNoDifference failed: β¦
β UIImage()
+ UIImage()
(First: β, Second: +)
*/
Expected behavior
I'd have expected XCTAssertNoDifference
to give me an indication of what the difference between the two images is, similar to what XCTAssertEqual
does.
Environment
Describe the bug
Give a clear and concise description of what the bug is.
Rename failed: /Users/test/Library/Developer/Xcode/DerivedData/Test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Speech-bad90112.o.tmp -> /Users/test/Library/Developer/Xcode/DerivedData/test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Speech.o: No such file or directory
Rename failed: /Users/test/Library/Developer/Xcode/DerivedData/Test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreMotion-07ef2dfa.o.tmp -> /Users/test/Library/Developer/Xcode/DerivedData/test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreMotion.o: No such file or directory
Rename failed: /Users/test/Library/Developer/Xcode/DerivedData/Test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreLocation-aef9f0f0.o.tmp -> /Users/test/Library/Developer/Xcode/DerivedData/test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreLocation.o: No such file or directory
Rename failed: /Users/test/Library/Developer/Xcode/DerivedData/test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Swift-236a70eb.o.tmp -> /Users/test/Library/Developer/Xcode/DerivedData/test-glvqxrieyduwirfnaoouzklnojya/Build/Intermediates.noindex/ArchiveIntermediates/test-staging/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Swift.o: No such file or directory
To Reproduce
Zip up a project that reproduces the behavior and attach it by dragging it here.
I deleted derived data, clean build project, restart PC and did everything I could to try resolving this but it didn't work.
// And/or enter code that reproduces the behavior here.
Expected behavior
Give a clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Environment
Additional context
Add any more context about the problem here.
swift-custom-dump/Package.swift
Line 19 in e1a5818
dependencies: [
.package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "0.2.0")
]
Describe the bug
Some AttributedString
s don't print any diffs although they are not equal
To Reproduce
CustomDumpAttributedString.zip
// If youβll run this test:
func testAttributedString() throws {
var stringOne = AttributedString("One")
stringOne.font = .body
var stringTwo = AttributedString("One")
stringTwo.font = .callout
XCTAssertNoDifference(stringOne, stringTwo)
}
// Itβll fail, but the printed dump will make it look like there are no differences at all:
XCTAssertNoDifference failed: β¦
β "One"
(First: β, Second: +)
// Where if I change the text to be different in addition to the font:
func testAttributedString() throws {
var stringOne = AttributedString("One")
stringOne.font = .body
var stringTwo = AttributedString("Two")
stringTwo.font = .callout
XCTAssertNoDifference(stringOne, stringTwo)
}
// it prints it correctly:
XCTAssertNoDifference failed: β¦
β "One"
+ "Two"
(First: β, Second: +)
// This problem is especially prominent when the AttributedString is a property of a State object inside of a Store, the test could fail and youβll have no idea that the AttributedString is the one which is different:
XCTAssertNoDifference failed: β¦
β State(
β string: "One",
β number: 3
β )
(First: β, Second: +)
Expected behavior
// In my opinion I would expect at least:
- "One"
+ "One"
Environment
Describe the bug
Swift-Custom-Dump fails to build for Archive on Xcode 15.3 RC (latest version on Xcode Cloud though not publically available at time of writing π€, also crashed on beta 3)
To Reproduce
Open the attached project in Xcode 15.3 and build for Archive.
test.zip
Expected behavior
Not crash π
Environment
Additional context
Build log output:
Crash is when building the swift-custom-dump package.
Attribute 'noalias' applied to incompatible type!
%12 = call noalias i64 @swift_allocObject(ptr %9, i64 %11, i64 7) #2, !dbg !2865
Invalid bitcast
%13 = bitcast i64 %12 to ptr, !dbg !2865
Attribute 'noalias' applied to incompatible type!
%12 = call noalias i64 @swift_allocObject(ptr %9, i64 %11, i64 7) #2, !dbg !2921
Invalid bitcast
%13 = bitcast i64 %12 to ptr, !dbg !2921
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
Rename failed: /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreLocation-c0f50386.o.tmp -> /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreLocation.o: No such file or directory
Rename failed: /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Speech-093762a4.o.tmp -> /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Speech.o: No such file or directory
Rename failed: /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Photos-3e8ea971.o.tmp -> /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/Photos.o: No such file or directory
Rename failed: /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/StoreKit-9f8e386a.o.tmp -> /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/StoreKit.o: No such file or directory
Rename failed: /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreMotion-9e96eb64.o.tmp -> /Users/someuser/app/Build/Intermediates.noindex/ArchiveIntermediates/app/IntermediateBuildFilesPath/swift-custom-dump.build/Release-iphoneos/CustomDump.build/Objects-normal/arm64/CoreMotion.o: No such file or directory
0 swift-frontend 0x00000001081b3f3c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x00000001081b30f8 llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x00000001081b4544 SignalHandler(int) + 360
3 libsystem_platform.dylib 0x0000000186381a24 _sigtramp + 56
4 libsystem_pthread.dylib 0x0000000186351cc0 pthread_kill + 288
5 libsystem_c.dylib 0x000000018625da40 abort + 180
6 swift-frontend 0x0000000102abd6d8 PrettyStackTraceFrontend::~PrettyStackTraceFrontend() + 0
7 swift-frontend 0x00000001080fca18 llvm::report_fatal_error(llvm::Twine const&, bool) + 280
8 swift-frontend 0x00000001080fc900 llvm::report_fatal_error(llvm::Twine const&, bool) + 0
9 swift-frontend 0x0000000102f904b8 llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::printPipeline(llvm::raw_ostream&, llvm::function_ref<llvm::StringRef (llvm::StringRef)>) + 0
10 swift-frontend 0x0000000107eb3ce8 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) + 224
11 swift-frontend 0x0000000102f83490 swift::performLLVMOptimizations(swift::IRGenOptions const&, llvm::Module*, llvm::TargetMachine*, llvm::raw_pwrite_stream*) + 3992
12 swift-frontend 0x0000000102f84bec swift::performLLVM(swift::IRGenOptions const&, swift::DiagnosticEngine&, llvm::sys::SmartMutex<false>*, llvm::GlobalVariable*, llvm::Module*, llvm::TargetMachine*, llvm::StringRef, llvm::vfs::OutputBackend&, swift::UnifiedStatsReporter*) + 2364
13 swift-frontend 0x0000000102f8ce70 (anonymous namespace)::LLVMCodeGenThreads::Thread::run() + 156
14 swift-frontend 0x0000000102f8cdc8 (anonymous namespace)::LLVMCodeGenThreads::runThread(void*) + 12
15 libsystem_pthread.dylib 0x0000000186352034 _pthread_start + 136
16 libsystem_pthread.dylib 0x000000018634ce3c thread_start + 8
Command SwiftCompile failed with a nonzero exit code
I really appreciate the pretty printing of customDump()
. However I'm having some challenges with using Mirror
in some cases and would like to suggest a new API that prints like a displayStyle: .struct
but allows me to explicitly override the typeName
.
(Please ignore the protocol naming. I'll trust you guys to come up with something suitable)
extension MyType: CustomDumpValueRespresentable {
var customDumpValue: CustomDumpValue {
.init(
typeName: if isButton ? "Button" : "MyType",
children: [
"child": child,
...
]
}
}
Thanks.
Currently customDump only dumps properties from the main mirror. This is missing all the properties from the superclass e.g
class Human {
let name = "John"
let email = "[email protected]"
let age = 97
}
class Doctor: Human {
let field = "Podiatry"
}
customDump(Doctor())
This prints Doctor(field: "Podiatry")
It would be nice if it could print this instead
Doctor(
field: "Podiatry",
name: "John",
email: "[email protected]"
age: 97
)
CoreImage extensions with availability constraints result in the following error
Protocol 'CustomDumpStringConvertible' requires 'customDumpDescription' to be available in iOS 9.0.0 and newer
Describe the bug
When working with two heterogeneous dictionaries of type [AnyHashable, AnyHasable]
in order to compare them where one dictionary represents a floating point value using a Float
type and the other using Double
leads to a very subtle error where the diff presented shows the two comparing fields as different yet show a identical literal representation.
To Reproduce
func testBug() {
let values: [AnyHashable: AnyHashable] = [
"value": Float(29.99)
]
let expected: [AnyHashable: AnyHashable] = [
"value": 29.99, // Is a Double
]
XCTAssertNoDifference(values, expected)
}
Expected behavior
I assume due to precision that Float vs Double can't be compared like for like but I would expected XCTAssertNoDifference
to maybe show the type information where the two values are literal identical and where the types are different, so something like:
XCTAssertNoDifference failed: β¦
β [
β "value": 29.99 (Float)
+ "value": 29.99 (Double)
β ]
(First: β, Second: +)
I spent hours trying to work out why my two hashable dictionaries that appeared to have identical values were failing and the diff output was confusing things further. It was very subtle that the code under test was using a Float
value and my dictionary I wanted to compare against used a Double literal.
Environment
The library offers a default conformance of CustomDumpRepresentable
for NSAttributedString
that only dumps the string value.
This removes all the attributes from the dump That information might be relevant but there's no way to print any additional information. Curious why this was decided.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.