From ce25ee537782fc54dbcf93d69b33ba63e3729769 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Mon, 26 Aug 2019 09:10:19 -0700 Subject: [PATCH] Add HIFI_THUNDER_URL environment variable --- launchers/darwin/CMakeLists.txt | 20 ++++++ launchers/darwin/data/HQDefaults.plist | 14 ++++ launchers/darwin/src/HQDefaults.h | 46 +++++++++++++ launchers/darwin/src/HQDefaults.m | 74 +++++++++++++++++++++ launchers/darwin/src/LatestBuildRequest.m | 9 ++- launchers/darwin/src/Launcher.m | 12 ++++ launchers/darwin/tests/HQDefaultsTests.m | 78 +++++++++++++++++++++++ launchers/darwin/tests/Info.plist | 22 +++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 launchers/darwin/data/HQDefaults.plist create mode 100644 launchers/darwin/src/HQDefaults.h create mode 100644 launchers/darwin/src/HQDefaults.m create mode 100644 launchers/darwin/tests/HQDefaultsTests.m create mode 100644 launchers/darwin/tests/Info.plist diff --git a/launchers/darwin/CMakeLists.txt b/launchers/darwin/CMakeLists.txt index fa4c9d5f45..b495893b97 100644 --- a/launchers/darwin/CMakeLists.txt +++ b/launchers/darwin/CMakeLists.txt @@ -45,6 +45,8 @@ set(src_files src/CustomUI.m src/NSTask+NSTaskExecveAdditions.h src/NSTask+NSTaskExecveAdditions.m + src/HQDefaults.h + src/HQDefaults.m src/main.mm nib/Window.xib nib/SplashScreen.xib @@ -118,6 +120,10 @@ add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/images "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") +add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/data/HQDefaults.plist "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND updater COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/updater" "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${APP_NAME}.app/Contents/Resources/") @@ -146,3 +152,17 @@ set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc" set(CPACK_GENERATOR "DragNDrop") include(CPack) + +include(FindXCTest) + +include_directories(${CMAKE_SOURCE_DIR}/src) + +xctest_add_bundle(HQLauncherTests HQLauncher + ${CMAKE_SOURCE_DIR}/src/HQDefaults.m + ${CMAKE_SOURCE_DIR}/tests/HQDefaultsTests.m + ${CMAKE_SOURCE_DIR}/tests/Info.plist +) + +set_target_properties(HQLauncherTests PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/tests/Info.plist + ) diff --git a/launchers/darwin/data/HQDefaults.plist b/launchers/darwin/data/HQDefaults.plist new file mode 100644 index 0000000000..98a29664c9 --- /dev/null +++ b/launchers/darwin/data/HQDefaults.plist @@ -0,0 +1,14 @@ + + + + + + name + thunderURL + defaultValue + https://thunder.highfidelity.com + environmentVariable + HIFI_THUNDER_URL + + + diff --git a/launchers/darwin/src/HQDefaults.h b/launchers/darwin/src/HQDefaults.h new file mode 100644 index 0000000000..631a672ddf --- /dev/null +++ b/launchers/darwin/src/HQDefaults.h @@ -0,0 +1,46 @@ +// +// Created by Matt Hardcastle +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/* + * `HQDefaults` loads defaults from the `HQDefaults.plist` and allows + * defaults in that plist to be overwritten using an environment variable. + * + * For example, the following `HQDefaults.plist` will set a default "foo" + * with a value "bar". The "bar" value can be overwritten with the value of + * the FOO environment variables, if the FOO environment variable is set. + * + * + * + * + * + * + * name + * foo + * defaultValue + * bar + * environmentVariable + * FOO + * + * + * + */ + +@interface HQDefaults : NSObject + +-(NSString *)defaultNamed:(NSString *)name; ++(HQDefaults *)sharedDefaults; + +@property (strong, readonly) NSDictionary *defaults; + +@end + +NS_ASSUME_NONNULL_END diff --git a/launchers/darwin/src/HQDefaults.m b/launchers/darwin/src/HQDefaults.m new file mode 100644 index 0000000000..5795b05554 --- /dev/null +++ b/launchers/darwin/src/HQDefaults.m @@ -0,0 +1,74 @@ +// +// Created by Matt Hardcastle +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#import "HQDefaults.h" + +@implementation HQDefaults; + +// This initializer is for testing purposes. See `init()` for normal use. +-(id)initWithArray:(NSArray *)array environment:(NSDictionary *)environment +{ + self = [super init]; + if (self) { + NSMutableDictionary *__defaults = [[NSMutableDictionary alloc] init]; + NSString *name, *defaultValue, *environmentVariable; + + for (NSDictionary *obj in array) { + NSMutableArray *missingKeys = [[NSMutableArray alloc] init]; + if ((name = [obj objectForKey:@"name"]) == nil) { + [missingKeys addObject:@"name"]; + } + if ((defaultValue = [obj objectForKey:@"defaultValue"]) == nil) { + [missingKeys addObject:@"defaultValue"]; + } + if ([missingKeys count] > 0) { + @throw [NSException exceptionWithName:@"InvalidHQDefaults" + reason:@"A required key is missing" + userInfo:@{@"missingKeys": missingKeys}]; + } + + environmentVariable = [obj objectForKey:@"environmentVariable"]; + if (environmentVariable == nil) { + __defaults[name] = defaultValue; + continue; + } + + NSString *value = environment[environmentVariable]; + __defaults[name] = value == nil ? defaultValue : value; + } + + // Make the dictionary immutable. + _defaults = __defaults; + } + return self; +} + +// Initialize an `HQLauncher` object using the bundles "HQDefaults.plist" and the current process's environment. +-(id)init { + NSBundle *bundle = [NSBundle mainBundle]; + NSString *defaultsPath = [bundle pathForResource:@"HQDefaults" ofType:@"plist"]; + NSArray *array = [NSArray arrayWithContentsOfFile:defaultsPath]; + return [self initWithArray:array environment:NSProcessInfo.processInfo.environment]; +} + +// Retrieve a default. +-(NSString *)defaultNamed:(NSString *)name { + return _defaults[name]; +} + +// A singleton HQDefaults using the mainBundle's "HQDefaults.plist" and the environment. ++(HQDefaults *)sharedDefaults { + static HQDefaults *defaults = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + defaults = [[HQDefaults alloc] init]; + }); + return defaults; +} + +@end diff --git a/launchers/darwin/src/LatestBuildRequest.m b/launchers/darwin/src/LatestBuildRequest.m index 45ed4418ad..43cd5de213 100644 --- a/launchers/darwin/src/LatestBuildRequest.m +++ b/launchers/darwin/src/LatestBuildRequest.m @@ -1,6 +1,7 @@ #import "LatestBuildRequest.h" #import "Launcher.h" #import "Settings.h" +#import "HQDefaults.h" @implementation LatestBuildRequest @@ -8,7 +9,13 @@ NSString* buildsURL = [[[NSProcessInfo processInfo] environment] objectForKey:@"HQ_LAUNCHER_BUILDS_URL"]; if ([buildsURL length] == 0) { - buildsURL = @"https://thunder.highfidelity.com/builds/api/tags/latest?format=json"; + NSString *thunderURL = [[HQDefaults sharedDefaults] defaultNamed:@"thunderURL"]; + if (thunderURL == nil) { + @throw [NSException exceptionWithName:@"DefaultMissing" + reason:@"The thunderURL default is missing" + userInfo:nil]; + } + buildsURL = [NSString stringWithFormat:@"%@/builds/api/tags/latest?format=json", thunderURL]; } NSLog(@"Making request for builds to: %@", buildsURL); diff --git a/launchers/darwin/src/Launcher.m b/launchers/darwin/src/Launcher.m index 9a70ddf0e7..62242d12ff 100644 --- a/launchers/darwin/src/Launcher.m +++ b/launchers/darwin/src/Launcher.m @@ -9,6 +9,7 @@ #import "Settings.h" #import "NSTask+NSTaskExecveAdditions.h" #import "Interface.h" +#import "HQDefaults.h" @interface Launcher () @@ -483,6 +484,17 @@ static BOOL const DELETE_ZIP_FILES = TRUE; [self.window makeKeyAndOrderFront:self]; } +-(void)applicationDidFinishLaunching:(NSNotification *)notification +{ + // Sanity check the HQDefaults so we fail early if there's an issue. + HQDefaults *defaults = [HQDefaults sharedDefaults]; + if ([defaults defaultNamed:@"thunderURL"] == nil) { + @throw [NSException exceptionWithName:@"DefaultsNotConfigured" + reason:@"thunderURL is not configured" + userInfo:nil]; + } +} + - (void) setDownloadFilename:(NSString *)aFilename { self.filename = aFilename; diff --git a/launchers/darwin/tests/HQDefaultsTests.m b/launchers/darwin/tests/HQDefaultsTests.m new file mode 100644 index 0000000000..483a54e945 --- /dev/null +++ b/launchers/darwin/tests/HQDefaultsTests.m @@ -0,0 +1,78 @@ +// +// Created by Matt Hardcastle +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#import + +#import "HQDefaults.h" + +// Expose the `initWithArray:environment` initializer for testing. +@interface HQDefaults(HQDefaultsTesting) +-(id)initWithArray:(NSArray *)array environment:(NSDictionary *)environment; +@end + +@interface HQDefaultsTests : XCTestCase + +@end + +@implementation HQDefaultsTests + +// If there is not environment the default value should be used. +- (void)testNoEnvironmentReturnsDefaultValue { + NSArray *array = @[@{@"name":@"foo", + @"environmentVariable":@"FOO", + @"defaultValue":@"bar"}]; + + HQDefaults *defaults = [[HQDefaults alloc] initWithArray:array + environment:@{}]; + + XCTAssertEqual([defaults defaultNamed:@"foo"], @"bar"); +} + +// The value from the environment should overwrite the default value. +- (void)testEnvironmentOverWritesDefaultValue { + NSArray *array = @[@{@"name":@"foo", + @"environmentVariable":@"FOO", + @"defaultValue":@"bar"}]; + NSDictionary *environment = @{@"FOO":@"FOO_VALUE_FROM_ENVIRONMENT"}; + + HQDefaults *defaults = [[HQDefaults alloc] initWithArray:array environment:environment]; + + NSString *value = [defaults defaultNamed:@"foo"]; + + XCTAssertEqual(value, @"FOO_VALUE_FROM_ENVIRONMENT"); +} + +// An exception should be thrown if a defaults object is missing `name`. +- (void)testMissingNameThrowsException { + NSArray *array = @[@{@"defaultValue":@"bar"}]; + XCTAssertThrowsSpecificNamed([[HQDefaults alloc] initWithArray:array environment:@{}], + NSException, + @"InvalidHQDefaults"); +} + +// An exception should be thrown if a defaults object is missing `defaultValue`. +- (void)testMissingDefaultValueThrowsException { + NSArray *array = @[@{@"name":@"foo" }]; + XCTAssertThrowsSpecificNamed([[HQDefaults alloc] initWithArray:array environment:@{}], + NSException, + @"InvalidHQDefaults"); +} + +// An exception should **NOT** be thrown if a defaults object is missing `environmentVariable`. +- (void)testMissingEnvironmentVariableDoesNotThrowException { + NSArray *array = @[@{@"name":@"foo", @"defaultValue":@"bar"}]; + XCTAssertNoThrow([[HQDefaults alloc] initWithArray:array environment:@{}]); +} + +// A `nil` should be returned if a default is missing. +- (void)testEmptyDefaultIsNil { + HQDefaults *defaults = [[HQDefaults alloc] initWithArray:@[] environment:@{}]; + XCTAssertNil([defaults defaultNamed:@"foo"]); +} + +@end diff --git a/launchers/darwin/tests/Info.plist b/launchers/darwin/tests/Info.plist new file mode 100644 index 0000000000..6c40a6cd0c --- /dev/null +++ b/launchers/darwin/tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + +