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 Swift versions of a few more MTRDevice tests. #29914

Merged
merged 1 commit into from
Oct 23, 2023
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
153 changes: 149 additions & 4 deletions src/darwin/Framework/CHIPTests/MTRSwiftDeviceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ struct DeviceConstants {
static let testVendorID = 0xFFF1
static let onboardingPayload = "MT:-24J0AFN00KA0648G00"
static let deviceID = 0x12344321
static let timeoutInSeconds : UInt16 = 3
static let pairingTimeoutInSeconds : UInt16 = 10
static let timeoutInSeconds : Double = 3
static let pairingTimeoutInSeconds : Double = 10
}

var sConnectedDevice: MTRBaseDevice? = nil
Expand Down Expand Up @@ -191,7 +191,7 @@ class MTRSwiftDeviceTests : XCTestCase {
XCTFail("Could not start setting up PASE session: \(error)")
return }

wait(for: [expectation], timeout: TimeInterval(DeviceConstants.pairingTimeoutInSeconds))
wait(for: [expectation], timeout: DeviceConstants.pairingTimeoutInSeconds)
}

static func shutdownStack()
Expand Down Expand Up @@ -396,12 +396,157 @@ class MTRSwiftDeviceTests : XCTestCase {
XCTAssertEqual(eventReportsReceived, 0);
}

func test018_SubscriptionErrorWhenNotResubscribing()
{
let device = sConnectedDevice!
let queue = DispatchQueue.main

let firstSubscribeExpectation = expectation(description: "First subscription complete")
let errorExpectation = expectation(description: "First subscription errored out")

// Subscribe
let params = MTRSubscribeParams(minInterval: 1, maxInterval: 10)
params.shouldResubscribeAutomatically = false
params.shouldReplaceExistingSubscriptions = true // Not strictly needed, but checking that doing this does not
// affect this subscription erroring out correctly.
var subscriptionEstablished = false
device.subscribeToAttributes(withEndpointID: 1,
clusterID: 6,
attributeID: 0,
params: params,
queue: queue,
reportHandler: { values, error in
if (subscriptionEstablished) {
// We should only get an error here.
XCTAssertNil(values)
XCTAssertNotNil(error)
errorExpectation.fulfill()
} else {
XCTAssertNotNil(values)
XCTAssertNil(error)
}
},
subscriptionEstablished: {
NSLog("subscribe attribute: OnOff established")
XCTAssertFalse(subscriptionEstablished)
subscriptionEstablished = true
firstSubscribeExpectation.fulfill()
})

// Wait till establishment
wait(for: [ firstSubscribeExpectation ], timeout: DeviceConstants.timeoutInSeconds)

// Create second subscription which will cancel the first subscription. We
// can use a non-existent path here to cut down on the work that gets done.
params.shouldReplaceExistingSubscriptions = true

device.subscribeToAttributes(withEndpointID: 10000,
clusterID: 6,
attributeID: 0,
params: params,
queue: queue,
reportHandler: { _, _ in
})
wait(for: [ errorExpectation ], timeout: 60)
}

func test019_MTRDeviceMultipleCommands() async
{
let device = MTRDevice(nodeID: DeviceConstants.deviceID as NSNumber, controller:sController!)
let queue = DispatchQueue.main

let opcredsCluster = MTRClusterOperationalCredentials(device: device, endpointID: 0, queue: queue)!
let onOffCluster = MTRClusterOnOff(device: device, endpointID: 1, queue: queue)!
let badOnOffCluster = MTRClusterOnOff(device: device, endpointID: 0, queue: queue)!

// Ensure our existing fabric label is not "Test". This uses a "base"
// cluster to ensure read-through to the other side.
let baseOpCredsCluster = MTRBaseClusterOperationalCredentials(device: sConnectedDevice!, endpointID: 0, queue: queue)!
var fabricList = try! await baseOpCredsCluster.readAttributeFabrics(with: nil)
XCTAssertEqual(fabricList.count, 1)
var entry = fabricList[0] as! MTROperationalCredentialsClusterFabricDescriptorStruct
XCTAssertNotEqual(entry.label, "Test")

let currentFabricIndex = try! await baseOpCredsCluster.readAttributeCurrentFabricIndex()

// NOTE: The command invocations do not use "await", because we actually want
// to do them all sort of in parallel, or at least queue them all on the MTRDevice
// before we get a chance to finish the first one.
let onExpectation = expectation(description: "On command executed")
onOffCluster.on(withExpectedValues: nil, expectedValueInterval: nil) { error in
XCTAssertNil(error)
onExpectation.fulfill()
}

let offFailedExpectation = expectation(description: "Off command failed")
badOnOffCluster.off(withExpectedValues: nil, expectedValueInterval: nil) { error in
XCTAssertNotNil(error)
offFailedExpectation.fulfill()
}

let updateLabelExpectation = expectation(description: "Fabric label updated")
let params = MTROperationalCredentialsClusterUpdateFabricLabelParams()
params.label = "Test"
opcredsCluster.updateFabricLabel(with: params, expectedValues: nil, expectedValueInterval: nil) { data, error in
XCTAssertNil(error)
XCTAssertNotNil(data)
XCTAssertEqual(data?.statusCode, 0)
XCTAssertEqual(data?.fabricIndex, currentFabricIndex)
updateLabelExpectation.fulfill()
}

let offExpectation = expectation(description: "Off command executed")
// Send this one via MTRDevice, to test that codepath
device.invokeCommand(withEndpointID: 1,
clusterID: NSNumber(value: MTRClusterIDType.onOffID.rawValue),
commandID: NSNumber(value: MTRCommandIDType.clusterOnOffCommandOffID.rawValue),
commandFields: nil,
expectedValues: nil,
expectedValueInterval: nil,
queue: queue) { data, error in
XCTAssertNil(error)
offExpectation.fulfill()
}

let onFailedExpectation = expectation(description: "On command failed")
badOnOffCluster.on(withExpectedValues: nil, expectedValueInterval: nil) { error in
XCTAssertNotNil(error)
onFailedExpectation.fulfill()
}

let updateLabelFailedExpectation = expectation(description: "Fabric label update failed")
params.label = "12345678901234567890123445678901234567890" // Too long
opcredsCluster.updateFabricLabel(with: params,
expectedValues: nil,
expectedValueInterval: nil) { data, error in
XCTAssertNotNil(error)
XCTAssertNil(data)
updateLabelFailedExpectation.fulfill()
}

wait(for: [ onExpectation,
offFailedExpectation,
updateLabelExpectation,
offExpectation,
onFailedExpectation,
updateLabelFailedExpectation ],
timeout: 60,
enforceOrder: true)

// Now make sure our fabric label got updated.
fabricList = try! await baseOpCredsCluster.readAttributeFabrics(with: nil)
XCTAssertNotNil(fabricList)
XCTAssertEqual(fabricList.count, 1)
entry = fabricList[0] as! MTROperationalCredentialsClusterFabricDescriptorStruct
XCTAssertEqual(entry.label, "Test")
}

// Note: test027_AttestationChallenge is not implementable in Swift so far,
// because the attestationChallenge property is internal-only

func test999_TearDown()
{
ResetCommissionee(sConnectedDevice, DispatchQueue.main, self, DeviceConstants.timeoutInSeconds)
ResetCommissionee(sConnectedDevice, DispatchQueue.main, self, UInt16(DeviceConstants.timeoutInSeconds))
type(of: self).shutdownStack()
}
}