Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add propertylist test code and complete some missing part #16

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion .github/workflows/compatibility_tests.yml
Original file line number Diff line number Diff line change
@@ -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
@@ -28,6 +28,7 @@ jobs:
run: |
swift test \
-c debug \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-debug
@@ -39,6 +40,7 @@ jobs:
run: |
swift test \
-c release \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-release
2 changes: 2 additions & 0 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ jobs:
run: |
swift test \
-c debug \
--filter OpenSwiftUITests \
-Xswiftc -warnings-as-errors \
--enable-code-coverage \
--build-path .build-test-debug
@@ -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
5 changes: 4 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -78,7 +78,6 @@ let package = Package(
.target(name: "CoreServices", path: "PrivateFrameworks/CoreServices"),
.target(name: "UIKitCore", path: "PrivateFrameworks/UIKitCore"),
openSwiftUITarget,
openSwiftUICompatibilityTestTarget,
]
)

@@ -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")
6 changes: 6 additions & 0 deletions Sources/OpenSwiftUI/DataAndStorage/Internal/BloomFilter.swift
Original file line number Diff line number Diff line change
@@ -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
@@ -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
@@ -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) {
@@ -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,
@@ -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
@@ -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
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
@@ -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)]")
}
}