-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP implement ClientLibraryInfo class
ably/specification#113 TODO test TODO mention spec points TODO we need docstrings, what's the process for that? Asked Srushtika here: https://ably-real-time.slack.com/archives/C030C5YLY/p1668457571004079 Closes #1530.
- Loading branch information
1 parent
c36947c
commit 5802fb9
Showing
18 changed files
with
226 additions
and
107 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#import <Ably/ARTClientLibraryInfo.h> | ||
|
||
extern NSString *const ARTClientLibraryInfo_libraryVersion; | ||
|
||
@interface ARTClientLibraryInfo (Private) | ||
|
||
+ (NSString *)libraryAgentIdentifier; | ||
+ (NSString *)platformAgentIdentifier; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#import <Foundation/Foundation.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface ARTClientLibraryInfo : NSObject | ||
|
||
// TODO mention the no version sentinel | ||
@property (class, readonly) NSDictionary<NSString *, NSString *> *agents; | ||
+ (NSString *)agentIdentifierWithAdditionalAgents:(nullable NSDictionary<NSString *, NSString *> *)additionalAgents; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#import "ARTClientLibraryInfo.h" | ||
#import "ARTClientLibraryInfo+Private.h" | ||
#import "ARTDefault.h" | ||
#import "ARTDefault+Private.h" | ||
#import "ARTClientOptions.h" | ||
#import <sys/utsname.h> | ||
|
||
NSString *const ARTClientLibraryInfo_libraryVersion = @"1.2.16"; | ||
static NSString *const _libraryName = @"ably-cocoa"; | ||
|
||
// NSOperatingSystemVersion has NSInteger as version components for some reason, so mitigate it here. | ||
static inline UInt32 conformVersionComponent(const NSInteger component) { | ||
return (component < 0) ? 0 : (UInt32)component; | ||
} | ||
|
||
@implementation ARTClientLibraryInfo | ||
|
||
+ (NSDictionary<NSString *, NSString *> *)agents { | ||
NSMutableDictionary<NSString *, NSString *> *result = [NSMutableDictionary dictionary]; | ||
|
||
[result addEntriesFromDictionary:[self platformAgent]]; | ||
[result addEntriesFromDictionary:[self libraryAgent]]; | ||
|
||
return result; | ||
} | ||
|
||
+ (NSString *)agentIdentifierWithAdditionalAgents:(nullable NSDictionary<NSString *, NSString *> *)additionalAgents { | ||
NSMutableDictionary<NSString *, NSString *> *agents = [self.agents mutableCopy]; | ||
|
||
for (NSString *const additionalAgentName in additionalAgents) { | ||
agents[additionalAgentName] = additionalAgents[additionalAgentName]; | ||
} | ||
|
||
return [self agentIdentifierForAgents:agents]; | ||
} | ||
|
||
+ (NSString *)agentIdentifierForAgents:(NSDictionary<NSString *, NSString*> *)agents { | ||
NSMutableString *agentIdentifier = [NSMutableString string]; | ||
|
||
// We sort the agent names so that we have a predictable order when testing. | ||
NSArray<NSString *> *sortedAgentNames = [agents.allKeys sortedArrayUsingSelector:@selector(compare:)]; | ||
for (NSString *name in sortedAgentNames) { | ||
NSString *const version = agents[name]; | ||
if (version == ARTClientOptionsAgentNotVersioned) { | ||
[agentIdentifier appendFormat:@"%@ ", name]; | ||
} else { | ||
[agentIdentifier appendFormat:@"%@/%@ ", name, version]; | ||
} | ||
} | ||
|
||
return agentIdentifier; | ||
} | ||
|
||
+ (NSDictionary<NSString *, NSString *> *)libraryAgent { | ||
return @{ _libraryName: ARTClientLibraryInfo_libraryVersion }; | ||
} | ||
|
||
+ (NSString *)libraryAgentIdentifier { | ||
return [self agentIdentifierForAgents:[self libraryAgent]]; | ||
} | ||
|
||
+ (NSDictionary<NSString *, NSString *> *)platformAgent { | ||
NSString *const osName = [self osName]; | ||
|
||
if (osName == nil) { | ||
return @{}; | ||
} | ||
|
||
return @{ osName: [self osVersionString] }; | ||
} | ||
|
||
+ (NSString *)platformAgentIdentifier { | ||
return [self agentIdentifierForAgents:[self platformAgent]]; | ||
} | ||
|
||
+ (NSString *)osName { | ||
return | ||
#if TARGET_OS_IOS | ||
@"iOS" | ||
#elif TARGET_OS_TV | ||
@"tvOS" | ||
#elif TARGET_OS_WATCH | ||
@"watchOS" | ||
#elif TARGET_OS_OSX | ||
@"macOS" | ||
#else | ||
nil | ||
#endif | ||
; | ||
} | ||
|
||
+ (NSString *)osVersionString { | ||
static NSString *versionString; | ||
static dispatch_once_t onceToken; | ||
dispatch_once(&onceToken, ^{ | ||
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; | ||
versionString = [NSString stringWithFormat:@"%lu.%lu.%lu", | ||
(unsigned long)conformVersionComponent(version.majorVersion), | ||
(unsigned long)conformVersionComponent(version.minorVersion), | ||
(unsigned long)conformVersionComponent(version.patchVersion)]; | ||
}); | ||
return versionString; | ||
} | ||
|
||
+ (NSString *)deviceModel { | ||
struct utsname systemInfo; | ||
if (uname(&systemInfo) < 0) { | ||
return nil; | ||
} | ||
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../Source/ARTClientLibraryInfo+Private.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../Source/ARTClientLibraryInfo.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import XCTest | ||
import Ably | ||
|
||
final class ClientLibraryInfoTests: XCTestCase { | ||
|
||
func testAgents() { | ||
let agents = ARTClientLibraryInfo.agents | ||
|
||
XCTAssertEqual(agents.keys.count, 2) | ||
|
||
XCTAssertEqual(agents["ably-cocoa"], "1.2.16") | ||
|
||
#if os(iOS) | ||
XCTAssertTrue(agents.keys.contains("iOS")) | ||
#elseif os(tvOS) | ||
XCTAssertTrue(agents.keys.contains("tvOS")) | ||
#elseif os(watchOS) | ||
XCTAssertTrue(agents.keys.contains("watchOS")) | ||
#elseif os(macOS) | ||
XCTAssertTrue(agents.keys.contains("macOS")) | ||
#else | ||
#error("Building for unknown OS") | ||
#endif | ||
} | ||
|
||
func testAgentIdentifierWithAdditionalAgents_withNilAdditionalAgents() { | ||
let expectedIdentifier = "\(ARTDefault.libraryAgent()) \(ARTDefault.platformAgent())" | ||
|
||
XCTAssertEqual(ARTClientLibraryInfo.agentIdentifier(withAdditionalAgents: nil), expectedIdentifier) | ||
} | ||
|
||
func testAgentIdentifierWithAdditionalAgents_withNonNilAdditionalAgents() { | ||
let additionalAgents = [ | ||
"demolib": "0.0.1", | ||
"morelib": ARTClientOptionsAgentNotVersioned | ||
] | ||
|
||
let expectedIdentifier = "\(ARTDefault.libraryAgent()) demolib/0.0.1 morelib \(ARTDefault.platformAgent())" | ||
|
||
XCTAssertEqual(ARTClientLibraryInfo.agentIdentifier(withAdditionalAgents: additionalAgents), expectedIdentifier) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.