Skip to content

Commit

Permalink
Add propertylist test code and complete some missing part (#16)
Browse files Browse the repository at this point in the history
* Add propertylist test code and complete some missing part

* Update compatibility_tests config file
  • Loading branch information
Kyle-Ye authored Jan 5, 2024
1 parent aefaa95 commit b5b0b77
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 29 deletions.
20 changes: 19 additions & 1 deletion .github/workflows/compatibility_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,27 @@ jobs:
xcode-version: ${{ matrix.xcode-version }}
- name: Swift version
run: swift --version
- name: Run tests against Apple's SwiftUI on macOS
- name: Run compatibility tests on OpenSwiftUI + macOS
run: |
swift test \
--build-path .build-compatibility-test-debug
env:
OPENSWIFTUI_COMPATIBILITY_TEST: 0
- name: Run compatibility tests on SwiftUI + macOS
run: |
swift test \
--build-path .build-compatibility-test-debug
env:
OPENSWIFTUI_COMPATIBILITY_TEST: 1
# - name: Run compatibility tests on OpenSwiftUI + iOS
# run: |
# swift test \
# --build-path .build-compatibility-test-debug
# env:
# OPENSWIFTUI_COMPATIBILITY_TEST: 0
# - name: Run compatibility tests on SwiftUI + iOS
# run: |
# swift test \
# --build-path .build-compatibility-test-debug
# env:
# OPENSWIFTUI_COMPATIBILITY_TEST: 1
2 changes: 2 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
run: |
swift test \
-c debug \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-debug
Expand All @@ -39,6 +40,7 @@ jobs:
run: |
swift test \
-c release \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-release
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
run: |
swift test \
-c debug \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-debug
Expand All @@ -32,6 +33,7 @@ jobs:
run: |
swift test \
-c release \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--build-path .build-test-release
- uses: codecov/codecov-action@v3
Expand Down
5 changes: 4 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ let package = Package(
.target(name: "CoreServices", path: "PrivateFrameworks/CoreServices"),
.target(name: "UIKitCore", path: "PrivateFrameworks/UIKitCore"),
openSwiftUITarget,
openSwiftUICompatibilityTestTarget,
]
)

Expand Down Expand Up @@ -161,6 +160,10 @@ if swiftTestingCondition {
.product(name: "Testing", package: "swift-testing")
)
package.targets.append(openSwiftUITestTarget)
openSwiftUICompatibilityTestTarget.dependencies.append(
.product(name: "Testing", package: "swift-testing")
)
package.targets.append(openSwiftUICompatibilityTestTarget)
}

let compatibilityTestCondition = envEnable("OPENSWIFTUI_COMPATIBILITY_TEST")
Expand Down
6 changes: 6 additions & 0 deletions Sources/OpenSwiftUI/DataAndStorage/Internal/BloomFilter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ struct BloomFilter: Equatable {
let pointer = unsafeBitCast(type, to: OpaquePointer.self)
self.init(hashValue: Int(bitPattern: pointer))
}

@_transparent
@inline(__always)
func match(_ filter: BloomFilter) -> Bool {
(value & filter.value) == value
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// Created by Kyle on 2023/10/18.
// Lastest Version: iOS 15.5
// Status: WIP
// Status: Blocked by merge
// ID: 2B32D570B0B3D2A55DA9D4BFC1584D20

#if OPENSWIFTUI_ATTRIBUTEGRAPH
Expand All @@ -26,8 +26,19 @@ struct PropertyList: CustomStringConvertible {

@usableFromInline
var description: String {
// TODO
"[]"
var description = "["
var shouldAddSeparator = false
elements?.forEach { element, stop in
let element = element.takeUnretainedValue()
if shouldAddSeparator {
description.append(", ")
} else {
shouldAddSeparator = true
}
description.append(element.description)
}
description.append("]")
return description
}

func forEach<Key: PropertyKey>(keyType: Key.Type, _ body: (Key.Value, inout Swift.Bool) -> Void) {
Expand All @@ -46,14 +57,14 @@ struct PropertyList: CustomStringConvertible {
subscript<Key: PropertyKey>(_ keyType: Key.Type) -> Key.Value {
get {
withExtendedLifetime(keyType) {
guard let result = find(.passUnretained(elements!), key: keyType) else {
guard let result = find(elements.map { .passUnretained($0) }, key: keyType) else {
return Key.defaultValue
}
return result.takeUnretainedValue().value
}
}
set {
if let result = find(.passUnretained(elements!), key: keyType) {
if let result = find(elements.map { .passUnretained($0) }, key: keyType) {
guard !compareValues(
newValue,
result.takeUnretainedValue().value,
Expand Down Expand Up @@ -93,11 +104,30 @@ struct PropertyList: CustomStringConvertible {
// MARK: - PropertyList Help functions

private func find<Key: PropertyKey>(
_: Unmanaged<PropertyList.Element>?,
_ element: Unmanaged<PropertyList.Element>?,
key: Key.Type,
keyFilter: BloomFilter = BloomFilter(type: Key.self)
) -> Unmanaged<TypedElement<Key>>? {
fatalError("TODO")
guard var element else {
return nil
}
repeat {
guard keyFilter.match(element.flatMap(\.keyFilter)) else {
return nil
}
if let before = element.map(\.before),
let result = find(before, key: key, keyFilter: keyFilter) {
return result
}
if element.flatMap(\.keyType) == Key.self {
return element.map { $0 as? TypedElement<Key> }
}
guard let after = element.map(\.after) else {
break
}
element = after
} while(true)
return nil
}

// MARK: - PropertyList.Element
Expand Down Expand Up @@ -393,11 +423,18 @@ private func match(data: TrackerData, from: PropertyList, to: PropertyList) -> U
}

private func move(_ values: inout [ObjectIdentifier: any AnyTrackedValue], to invalidValues: inout [any AnyTrackedValue]) {
fatalError("TODO")
guard !values.isEmpty else { return }
invalidValues.append(contentsOf: values.values)
values.removeAll(keepingCapacity: true)
}

private func compare(_ values: [ObjectIdentifier: any AnyTrackedValue], against plist: PropertyList) -> Bool {
fatalError("TODO")
for (_, value) in values {
guard value.hasMatchingValue(in: plist) else {
return false
}
}
return true
}

// MARK: - TrackerData
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Unmanaged+Extension.swift
// OpenSwiftUI
//
// Created by Kyle on 2024/1/4.
// Lastest Version: iOS 15.5
// Status: Complete

extension Unmanaged {
func map<A: AnyObject>(_ transform: (Instance) throws -> A) rethrows -> Unmanaged<A> {
try _withUnsafeGuaranteedRef { try .passUnretained(transform($0)) }
}

func map<A: AnyObject>(_ transform: (Instance) throws -> A?) rethrows -> Unmanaged<A>? {
try _withUnsafeGuaranteedRef { try transform($0).map { .passUnretained($0) } }
}

func flatMap<A>(_ transform: (Instance) throws -> A) rethrows -> A {
try _withUnsafeGuaranteedRef { try transform($0) }
}

static func == (lhs: Unmanaged, rhs: Unmanaged) -> Bool {
lhs.toOpaque() == rhs.toOpaque()
}
}
17 changes: 0 additions & 17 deletions Tests/OpenSwiftUICompatibilityTests/DummyTests.swift

This file was deleted.

72 changes: 72 additions & 0 deletions Tests/OpenSwiftUICompatibilityTests/EnvironmentValuesTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// EnvironmentValuesTest.swift
//
//
// Created by Kyle on 2023/11/21.
//

#if OPENSWIFTUI_COMPATIBILITY_TEST
import SwiftUI
#else
import OpenSwiftUI
#endif
import Testing

struct EnvironmentValuesTest {
struct BoolKey: EnvironmentKey {
fileprivate static var name: String { "EnvironmentPropertyKey<BoolKey>" }

static let defaultValue = false
}

struct IntKey: EnvironmentKey {
fileprivate static var name: String { "EnvironmentPropertyKey<IntKey>" }

static let defaultValue = 0
}

@Test
func descriptionWithoutTracker() throws {
#if os(macOS) && OPENSWIFTUI_COMPATIBILITY_TEST
// FIXME: The env.description will always be "[]" on macOS 13
if #unavailable(macOS 14) {
var env = EnvironmentValues()
#expect(env.description == "[]")
var bool = env[BoolKey.self]
#expect(bool == BoolKey.defaultValue)
#expect(env.description == "[]")

env[BoolKey.self] = bool
#expect(env.description == "[]")

env[BoolKey.self] = !bool
bool = env[BoolKey.self]
#expect(bool == !BoolKey.defaultValue)
#expect(env.description == "[]")

let value = 1
env[IntKey.self] = value
#expect(env.description == "[]")
return
}
#endif
var env = EnvironmentValues()
#expect(env.description == "[]")

var bool = env[BoolKey.self]
#expect(bool == BoolKey.defaultValue)
#expect(env.description == "[]")

env[BoolKey.self] = bool
#expect(env.description == "[\(BoolKey.name) = \(bool)]")

env[BoolKey.self] = !bool
bool = env[BoolKey.self]
#expect(bool == !BoolKey.defaultValue)
#expect(env.description == "[\(BoolKey.name) = \(bool), \(BoolKey.name) = \(BoolKey.defaultValue)]")

let value = 1
env[IntKey.self] = value
#expect(env.description == "[\(IntKey.name) = \(value), \(BoolKey.name) = \(bool), \(BoolKey.name) = \(BoolKey.defaultValue)]")
}
}
15 changes: 15 additions & 0 deletions Tests/OpenSwiftUICompatibilityTests/Scaffolding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Scaffolding.swift
//
//
// Created by Kyle on 2024/1/4.
//

import Testing
import XCTest

final class AllTests: XCTestCase {
func testAll() async {
await XCTestScaffold.runAllTests(hostedBy: self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,33 @@
import Testing

struct PropertyListTests {
struct BoolKey: PropertyKey {
static let defaultValue = false
}

struct IntKey: PropertyKey {
static let defaultValue = 0
}

@Test
func description() throws {
let plist = PropertyList()
var plist = PropertyList()
#expect(plist.description == "[]")

var bool = plist[BoolKey.self]
#expect(bool == BoolKey.defaultValue)
#expect(plist.description == "[]")

plist[BoolKey.self] = bool
#expect(plist.description == "[\(BoolKey.self) = \(bool)]")

plist[BoolKey.self] = !bool
bool = plist[BoolKey.self]
#expect(bool == !BoolKey.defaultValue)
#expect(plist.description == "[\(BoolKey.self) = \(bool), \(BoolKey.self) = \(BoolKey.defaultValue)]")

let value = 1
plist[IntKey.self] = value
#expect(plist.description == "[\(IntKey.self) = \(value), \(BoolKey.self) = \(bool), \(BoolKey.self) = \(BoolKey.defaultValue)]")
}
}

0 comments on commit b5b0b77

Please sign in to comment.