Skip to content

Commit

Permalink
Add NSCopying support to ART*ChannelOptions
Browse files Browse the repository at this point in the history
Will use in an upcoming commit, but it's also handy for users of the SDK
(e.g. I had already found myself wanting it in Chat, when wishing to
create a modified version of an options object recevied as an argument).
  • Loading branch information
lawrence-forooghian committed Jan 28, 2025
1 parent 35805d0 commit a3b3217
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Ably.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@
211A610729DA05D700D169C5 /* ARTAttachRequestParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 211A610629DA05D700D169C5 /* ARTAttachRequestParams.m */; };
211A610829DA05D700D169C5 /* ARTAttachRequestParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 211A610629DA05D700D169C5 /* ARTAttachRequestParams.m */; };
211A610929DA05D700D169C5 /* ARTAttachRequestParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 211A610629DA05D700D169C5 /* ARTAttachRequestParams.m */; };
212374672D41598A005427E0 /* ChannelOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 212374662D415983005427E0 /* ChannelOptionsTests.swift */; };
212374682D41598A005427E0 /* ChannelOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 212374662D415983005427E0 /* ChannelOptionsTests.swift */; };
212374692D41598A005427E0 /* ChannelOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 212374662D415983005427E0 /* ChannelOptionsTests.swift */; };
2124B78729DB127900AD8361 /* MockVersion2Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2124B78629DB127900AD8361 /* MockVersion2Log.swift */; };
2124B78829DB127900AD8361 /* MockVersion2Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2124B78629DB127900AD8361 /* MockVersion2Log.swift */; };
2124B78929DB127900AD8361 /* MockVersion2Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2124B78629DB127900AD8361 /* MockVersion2Log.swift */; };
Expand Down Expand Up @@ -1153,6 +1156,7 @@
211A60FE29D8ABF100D169C5 /* ARTChannelStateChangeParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARTChannelStateChangeParams.m; sourceTree = "<group>"; };
211A610229DA05C700D169C5 /* ARTAttachRequestParams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ARTAttachRequestParams.h; path = PrivateHeaders/Ably/ARTAttachRequestParams.h; sourceTree = "<group>"; };
211A610629DA05D700D169C5 /* ARTAttachRequestParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARTAttachRequestParams.m; sourceTree = "<group>"; };
212374662D415983005427E0 /* ChannelOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelOptionsTests.swift; sourceTree = "<group>"; };
2124B78629DB127900AD8361 /* MockVersion2Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockVersion2Log.swift; sourceTree = "<group>"; };
2124B78A29DB12A900AD8361 /* ARTVersion2Log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARTVersion2Log.h; path = PrivateHeaders/Ably/ARTVersion2Log.h; sourceTree = "<group>"; };
2124B78E29DB13BD00AD8361 /* ARTInternalLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTInternalLog.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1731,6 +1735,7 @@
EB1AE0CD1C5C3A4900D62250 /* UtilitiesTests.swift */,
2110CC392A530D42007310D4 /* AttachRetryStateTests.swift */,
21088DCA2A53560C0033C722 /* ConnectRetryStateTests.swift */,
212374662D415983005427E0 /* ChannelOptionsTests.swift */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -3046,6 +3051,7 @@
D714A63E1C74D4B2002F2CA0 /* NSObject+TestSuite.swift in Sources */,
21276CC229F00BAA00107B5F /* ContinuousClockTests.swift in Sources */,
21881E7C283BD0E100CFD9E2 /* StringifiableTests.swift in Sources */,
212374692D41598A005427E0 /* ChannelOptionsTests.swift in Sources */,
856AAC971B6E30C800B07119 /* TestUtilities.swift in Sources */,
D72768211C9C19040022F8B2 /* RestClientPresenceTests.swift in Sources */,
D5FFA6A829E97EF30082DB4B /* CryptoData.swift in Sources */,
Expand Down Expand Up @@ -3244,6 +3250,7 @@
D7093C1A219E465C00723F17 /* NSObject+TestSuite.m in Sources */,
211A60D829D6D2C400D169C5 /* BackoffRetryDelayCalculatorTests.swift in Sources */,
215F76002922B30F009E0E76 /* ClientInformationTests.swift in Sources */,
212374682D41598A005427E0 /* ChannelOptionsTests.swift in Sources */,
D7093C1E219E466900723F17 /* RestClientTests.swift in Sources */,
21088DCC2A53560C0033C722 /* ConnectRetryStateTests.swift in Sources */,
2124B79829DB144600AD8361 /* DefaultInternalLogCoreTests.swift in Sources */,
Expand Down Expand Up @@ -3302,6 +3309,7 @@
215F76012922B30F009E0E76 /* ClientInformationTests.swift in Sources */,
211A60D929D6D2C500D169C5 /* BackoffRetryDelayCalculatorTests.swift in Sources */,
D7093C78219EE26400723F17 /* RestClientChannelsTests.swift in Sources */,
212374672D41598A005427E0 /* ChannelOptionsTests.swift in Sources */,
D7093C76219EE26400723F17 /* RestClientStatsTests.swift in Sources */,
21088DCD2A53560C0033C722 /* ConnectRetryStateTests.swift in Sources */,
2124B79929DB144600AD8361 /* DefaultInternalLogCoreTests.swift in Sources */,
Expand Down
11 changes: 11 additions & 0 deletions Source/ARTChannelOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ - (instancetype)initWithCipherKey:(id<ARTCipherKeyCompatible>)key {
return [self initWithCipher:@{@"key": key}];
}

- (id)copyWithZone:(NSZone *)zone {
ARTChannelOptions *copied = [[[self class] alloc] init];

// The _frozen flag prevents the instance we were copying from being mutated, but we don't yet want to prevent the new instance from being mutated
copied->_frozen = NO;

copied->_cipher = _cipher;

return copied;
}

- (ARTCipherParams *)cipher {
return _cipher;
}
Expand Down
10 changes: 10 additions & 0 deletions Source/ARTRealtimeChannelOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ - (instancetype)initWithCipher:(id<ARTCipherParamsCompatible>)cipherParams {
return self;
}

- (id)copyWithZone:(NSZone *)zone {
ARTRealtimeChannelOptions *copied = [super copyWithZone:zone];

copied->_params = _params;
copied->_modes = _modes;
copied->_attachOnSubscribe = _attachOnSubscribe;

return copied;
}

- (NSStringDictionary *)params {
return _params;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/include/Ably/ARTChannelOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Passes additional properties to an `ARTRestChannel` object, such as encryption.
*/
@interface ARTChannelOptions : NSObject
@interface ARTChannelOptions : NSObject <NSCopying>

/**
* Requests encryption for this channel when not `nil`, and specifies encryption-related parameters (such as algorithm, chaining mode, key length and key). See [an example](https://ably.com/docs/realtime/encryption#getting-started).
Expand Down
56 changes: 56 additions & 0 deletions Test/Tests/ChannelOptionsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Ably
import XCTest

class ChannelOptionsTests: XCTestCase {
// MARK: - ARTChannelOptions

func test_copyChannelOptions() throws {
let options = ARTChannelOptions()
options.cipher = ARTCrypto.getDefaultParams(["key": ARTCrypto.generateRandomKey()])

let copied = try XCTUnwrap(options.copy() as? ARTChannelOptions)

// Check it creates a new object
XCTAssertFalse(options === copied)

// Check properties
XCTAssertIdentical(options.cipher, copied.cipher)
}

func test_copyingFrozenChannelOptions_createsUnfrozenCopy() throws {
let options = ARTChannelOptions()
options.isFrozen = true

let copied = try XCTUnwrap(options.copy() as? ARTChannelOptions)
XCTAssertFalse(copied.isFrozen)
}

// MARK: - ARTRealtimeChannelOptions

func test_copyRealtimeChannelOptions() throws {
let options = ARTRealtimeChannelOptions()
options.cipher = ARTCrypto.getDefaultParams(["key": ARTCrypto.generateRandomKey()])
options.params = ["foo": "bar"]
options.modes = [.subscribe]
options.attachOnSubscribe = false

let copied = try XCTUnwrap(options.copy() as? ARTRealtimeChannelOptions)

// Check it creates a new object
XCTAssertFalse(options === copied)

// Check properties
XCTAssertIdentical(options.cipher, copied.cipher)
XCTAssertIdentical(options.params as NSDictionary?, copied.params as NSDictionary?)
XCTAssertEqual(options.modes, copied.modes)
XCTAssertEqual(options.attachOnSubscribe, copied.attachOnSubscribe)
}

func test_copyingFrozenRealtimeChannelOptions_createsUnfrozenCopy() throws {
let options = ARTRealtimeChannelOptions()
options.isFrozen = true

let copied = try XCTUnwrap(options.copy() as? ARTRealtimeChannelOptions)
XCTAssertFalse(copied.isFrozen)
}
}

0 comments on commit a3b3217

Please sign in to comment.