@@ -27,6 +27,7 @@ class TestBridging : XCTestCase {
27
27
return [
28
28
( " testBridgedDescription " , testBridgedDescription) ,
29
29
( " testDynamicCast " , testDynamicCast) ,
30
+ ( " testConstantsImmortal " , testConstantsImmortal) ,
30
31
]
31
32
}
32
33
@@ -70,4 +71,32 @@ class TestBridging : XCTestCase {
70
71
let anyArray : Any = [ TestClass ( ) ]
71
72
XCTAssertNotNil ( anyArray as? NSObject )
72
73
}
74
+
75
+ func testConstantsImmortal( ) throws {
76
+ func release( _ ptr: UnsafeRawPointer , count: Int ) {
77
+ let object : Unmanaged < NSNumber > = Unmanaged . fromOpaque ( ptr)
78
+ for _ in 0 ..< count {
79
+ object. release ( )
80
+ }
81
+ }
82
+
83
+ let trueConstant = NSNumber ( value: true )
84
+ let falseConstant = NSNumber ( value: false )
85
+
86
+ // To accurately read the whole refcount, we need to read the second
87
+ // word of the pointer.
88
+ let truePtr = unsafeBitCast ( trueConstant, to: UnsafePointer< Int> . self )
89
+ let falsePtr = unsafeBitCast ( falseConstant, to: UnsafePointer< Int> . self )
90
+
91
+ let trueRefCount = truePtr. advanced ( by: 1 ) . pointee
92
+ let falseRefCount = falsePtr. advanced ( by: 1 ) . pointee
93
+
94
+ XCTAssertEqual ( trueRefCount, falseRefCount)
95
+
96
+ release ( truePtr, count: 5 )
97
+ release ( falsePtr, count: 5 )
98
+
99
+ XCTAssertEqual ( trueRefCount, truePtr. advanced ( by: 1 ) . pointee)
100
+ XCTAssertEqual ( falseRefCount, falsePtr. advanced ( by: 1 ) . pointee)
101
+ }
73
102
}
0 commit comments