diff --git a/Cartfile b/Cartfile index 3b108e5d..ac5488b3 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "launchdarkly/ios-eventsource" \ No newline at end of file +github "launchdarkly/ios-eventsource" >= 3.2 diff --git a/Cartfile.resolved b/Cartfile.resolved index 4c855c9f..318791ce 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "launchdarkly/ios-eventsource" "3.1.2" +github "launchdarkly/ios-eventsource" "3.2.0" diff --git a/Darkly.xcodeproj/project.pbxproj b/Darkly.xcodeproj/project.pbxproj index ce06ce51..5d34dc0a 100644 --- a/Darkly.xcodeproj/project.pbxproj +++ b/Darkly.xcodeproj/project.pbxproj @@ -43,7 +43,7 @@ 6903472C1E689B9F00E45133 /* LDClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6903471A1E689B9F00E45133 /* LDClientTest.m */; }; 6903472D1E689B9F00E45133 /* LDUtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6903471B1E689B9F00E45133 /* LDUtilTest.m */; }; 6903472E1E689B9F00E45133 /* LDClientManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6903471C1E689B9F00E45133 /* LDClientManagerTest.m */; }; - 6903472F1E689B9F00E45133 /* feature_flags.json in Resources */ = {isa = PBXBuildFile; fileRef = 6903471E1E689B9F00E45133 /* feature_flags.json */; }; + 6903472F1E689B9F00E45133 /* featureFlags-withVersions.json in Resources */ = {isa = PBXBuildFile; fileRef = 6903471E1E689B9F00E45133 /* featureFlags-withVersions.json */; }; 690347301E689B9F00E45133 /* LDConfigTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6903471F1E689B9F00E45133 /* LDConfigTest.m */; }; 690347311E689B9F00E45133 /* LDFlagConfigModelTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 690347211E689B9F00E45133 /* LDFlagConfigModelTest.m */; }; 690347321E689B9F00E45133 /* DarklyXCTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 690347221E689B9F00E45133 /* DarklyXCTestCase.m */; }; @@ -135,11 +135,37 @@ 69F3F6AB1E6BF82C00079A09 /* NSDictionary+JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = 690346F21E68990000E45133 /* NSDictionary+JSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; 69F3F6AC1E6BF82C00079A09 /* NSDictionary+JSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 690346F31E68990000E45133 /* NSDictionary+JSON.m */; }; 69F3F6AE1E6BF84B00079A09 /* Darkly-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 690346D81E68990000E45133 /* Darkly-Prefix.pch */; settings = {ATTRIBUTES = (Public, ); }; }; - 830BF931202A8855006DF9B1 /* NSJSONSerialization+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 830BF930202A8855006DF9B1 /* NSJSONSerialization+Testable.m */; }; + 8305EC6720221973002F20DB /* LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6520221973002F20DB /* LDFlagConfigValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8305EC6820221973002F20DB /* LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6520221973002F20DB /* LDFlagConfigValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8305EC6920221973002F20DB /* LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6520221973002F20DB /* LDFlagConfigValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8305EC6A20221973002F20DB /* LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6520221973002F20DB /* LDFlagConfigValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8305EC6B20221973002F20DB /* LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC6620221973002F20DB /* LDFlagConfigValue.m */; }; + 8305EC6C20221973002F20DB /* LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC6620221973002F20DB /* LDFlagConfigValue.m */; }; + 8305EC6D20221973002F20DB /* LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC6620221973002F20DB /* LDFlagConfigValue.m */; }; + 8305EC6E20221973002F20DB /* LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC6620221973002F20DB /* LDFlagConfigValue.m */; }; + 8305EC7120222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */; }; + 8305EC7220222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */; }; + 8305EC7320222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */; }; + 8305EC7420222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */; }; + 8305EC7520222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */; }; + 8305EC7620222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */; }; + 8305EC7720222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */; }; + 8305EC7820222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */; }; + 8305EC7A20222B5E002F20DB /* NSObject+LDFlagConfigValueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7920222B5E002F20DB /* NSObject+LDFlagConfigValueTest.m */; }; + 8305EC7C2022336C002F20DB /* LDFlagConfigValueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8305EC7B2022336C002F20DB /* LDFlagConfigValueTest.m */; }; + 8305EC7E202238FC002F20DB /* boolConfigIsABool-true-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC7D202238FC002F20DB /* boolConfigIsABool-true-withoutVersion.json */; }; + 8305EC8020223A2E002F20DB /* numberConfigIsANumber-2-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC7F20223A2E002F20DB /* numberConfigIsANumber-2-withoutVersion.json */; }; + 8305EC8220223BC3002F20DB /* doubleConfigIsADouble-Pi-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8120223BC2002F20DB /* doubleConfigIsADouble-Pi-withoutVersion.json */; }; + 8305EC8420223D65002F20DB /* stringConfigIsAString-someString-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8320223D65002F20DB /* stringConfigIsAString-someString-withoutVersion.json */; }; + 8305EC8620223EBA002F20DB /* arrayConfigIsAnArray-123-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8520223EBA002F20DB /* arrayConfigIsAnArray-123-withoutVersion.json */; }; + 8305EC8820224156002F20DB /* dictionaryConfigIsADictionary-3Key-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8720224156002F20DB /* dictionaryConfigIsADictionary-3Key-withoutVersion.json */; }; + 8305EC8A202243D6002F20DB /* nullConfigIsANull-null-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC89202243D6002F20DB /* nullConfigIsANull-null-withVersion.json */; }; + 8305EC8C2022440D002F20DB /* nullConfigIsANull-null-withoutVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8B2022440D002F20DB /* nullConfigIsANull-null-withoutVersion.json */; }; + 8305EC8E20227365002F20DB /* featureFlags-withoutVersions.json in Resources */ = {isa = PBXBuildFile; fileRef = 8305EC8D20227365002F20DB /* featureFlags-withoutVersions.json */; }; 83258A3D1F323049008C2133 /* LDClientManager+EventSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 83258A3C1F323049008C2133 /* LDClientManager+EventSource.m */; }; 83258A401F3244D0008C2133 /* LDUserBuilder+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 83258A3F1F3244D0008C2133 /* LDUserBuilder+Testable.m */; }; 83258A421F32721A008C2133 /* emptyConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = 83258A411F32721A008C2133 /* emptyConfig.json */; }; - 83258A441F329EFB008C2133 /* doubleConfigIsADouble-Pi.json in Resources */ = {isa = PBXBuildFile; fileRef = 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi.json */; }; + 83258A441F329EFB008C2133 /* doubleConfigIsADouble-Pi-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi-withVersion.json */; }; 832C78831F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */ = {isa = PBXBuildFile; fileRef = 832C78811F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h */; }; 832C78841F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */ = {isa = PBXBuildFile; fileRef = 832C78811F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h */; }; 832C78851F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */ = {isa = PBXBuildFile; fileRef = 832C78811F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h */; }; @@ -162,20 +188,28 @@ 8349F5211F195BCF00B1F3DB /* LDUserModel+Equatable.m in Sources */ = {isa = PBXBuildFile; fileRef = 8349F5201F195BCF00B1F3DB /* LDUserModel+Equatable.m */; }; 8358F25A1F4202A300ECE1AF /* LDConfig+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 8358F2591F4202A300ECE1AF /* LDConfig+Testable.m */; }; 835B421B1FD5AF7300709384 /* DarklyEventSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 835B421A1FD5AF7300709384 /* DarklyEventSource.framework */; }; + 8365E5082028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */; }; + 8365E5092028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */; }; + 8365E50A2028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */; }; + 8365E50B2028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */; }; + 8365E50C2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */; }; + 8365E50D2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */; }; + 8365E50E2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */; }; + 8365E50F2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */; }; 8369475C1F1FED400047697C /* boolConfigIsABool-false.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947591F1FED400047697C /* boolConfigIsABool-false.json */; }; - 8369475D1F1FED400047697C /* boolConfigIsABool-true.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369475A1F1FED400047697C /* boolConfigIsABool-true.json */; }; + 8369475D1F1FED400047697C /* boolConfigIsABool-true-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369475A1F1FED400047697C /* boolConfigIsABool-true-withVersion.json */; }; 8369475E1F1FED400047697C /* boolConfigIsABool2-true.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369475B1F1FED400047697C /* boolConfigIsABool2-true.json */; }; 836947621F1FEEB40047697C /* numberConfigIsANumber-1.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369475F1F1FEEB40047697C /* numberConfigIsANumber-1.json */; }; - 836947631F1FEEB40047697C /* numberConfigIsANumber-2.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947601F1FEEB40047697C /* numberConfigIsANumber-2.json */; }; + 836947631F1FEEB40047697C /* numberConfigIsANumber-2-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947601F1FEEB40047697C /* numberConfigIsANumber-2-withVersion.json */; }; 836947641F1FEEB40047697C /* numberConfigIsANumber2-1.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947611F1FEEB40047697C /* numberConfigIsANumber2-1.json */; }; - 836947681F1FF0A00047697C /* stringConfigIsAString-someString.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947651F1FF0A00047697C /* stringConfigIsAString-someString.json */; }; + 836947681F1FF0A00047697C /* stringConfigIsAString-someString-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947651F1FF0A00047697C /* stringConfigIsAString-someString-withVersion.json */; }; 836947691F1FF0A00047697C /* stringConfigIsAString-someStringA.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947661F1FF0A00047697C /* stringConfigIsAString-someStringA.json */; }; 8369476A1F1FF0A00047697C /* stringConfigIsAStringA-someString.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947671F1FF0A00047697C /* stringConfigIsAStringA-someString.json */; }; 8369476F1F1FF45B0047697C /* arrayConfigIsAnArray-1.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369476B1F1FF45B0047697C /* arrayConfigIsAnArray-1.json */; }; - 836947701F1FF45B0047697C /* arrayConfigIsAnArray-123.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123.json */; }; + 836947701F1FF45B0047697C /* arrayConfigIsAnArray-123-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123-withVersion.json */; }; 836947711F1FF45B0047697C /* arrayConfigIsAnArray-Empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369476D1F1FF45B0047697C /* arrayConfigIsAnArray-Empty.json */; }; 836947721F1FF45B0047697C /* arrayConfigIsAnArrayA-123.json in Resources */ = {isa = PBXBuildFile; fileRef = 8369476E1F1FF45B0047697C /* arrayConfigIsAnArrayA-123.json */; }; - 8369477A1F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key.json */; }; + 8369477A1F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key-withVersion.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key-withVersion.json */; }; 8369477B1F1FF80A0047697C /* dictionaryConfigIsADictionary-Empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947741F1FF80A0047697C /* dictionaryConfigIsADictionary-Empty.json */; }; 8369477C1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyA.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947751F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyA.json */; }; 8369477D1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB-124.json in Resources */ = {isa = PBXBuildFile; fileRef = 836947761F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB-124.json */; }; @@ -196,6 +230,8 @@ 839956E820053081009707D1 /* LDUserModel+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 839956E720053081009707D1 /* LDUserModel+Testable.m */; }; 839D6D271FD1B57B000BE6BD /* DarklyEventSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 839D6D261FD1B57B000BE6BD /* DarklyEventSource.framework */; }; 839D6D291FD1B58E000BE6BD /* DarklyEventSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 839D6D281FD1B58E000BE6BD /* DarklyEventSource.framework */; }; + 839E0A16201F97E900DB8CD1 /* ldClientManagerTestPatchIsANumber.json in Resources */ = {isa = PBXBuildFile; fileRef = 839E0A15201F97E800DB8CD1 /* ldClientManagerTestPatchIsANumber.json */; }; + 839E0A18201FB8D900DB8CD1 /* ldClientManagerTestDeleteIsANumber.json in Resources */ = {isa = PBXBuildFile; fileRef = 839E0A17201FB8D900DB8CD1 /* ldClientManagerTestDeleteIsANumber.json */; }; 83B8C24C1FEB1CD20082B8A9 /* LDUserModel+Stub.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B8C24B1FEB1CD20082B8A9 /* LDUserModel+Stub.m */; }; 83B8C24F1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B8C24D1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h */; }; 83B8C2501FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B8C24D1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h */; }; @@ -205,8 +241,20 @@ 83B8C2541FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B8C24E1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m */; }; 83B8C2551FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B8C24E1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m */; }; 83B8C2561FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B8C24E1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m */; }; - 83B8C2581FEC4C3B0082B8A9 /* userStubFlags.json in Resources */ = {isa = PBXBuildFile; fileRef = 83B8C2571FEC4C3B0082B8A9 /* userStubFlags.json */; }; + 83B8C2581FEC4C3B0082B8A9 /* featureFlags-excludeNulls-withVersions.json in Resources */ = {isa = PBXBuildFile; fileRef = 83B8C2571FEC4C3B0082B8A9 /* featureFlags-excludeNulls-withVersions.json */; }; 83B975D31FD1CA6000A4EF4E /* DarklyEventSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B975D21FD1CA6000A4EF4E /* DarklyEventSource.framework */; }; + 83BE9385201A63B400DD1ED9 /* ldDataManagerTestConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9384201A63B400DD1ED9 /* ldDataManagerTestConfig.json */; }; + 83BE9387201A6AA400DD1ED9 /* ldFlagConfigModelTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9386201A6AA400DD1ED9 /* ldFlagConfigModelTest.json */; }; + 83BE9389201A781200DD1ED9 /* ldFlagConfigModelPatchVersion1Flag.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9388201A781200DD1ED9 /* ldFlagConfigModelPatchVersion1Flag.json */; }; + 83BE938C201A797B00DD1ED9 /* NSJSONSerialization+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BE938B201A797B00DD1ED9 /* NSJSONSerialization+Testable.m */; }; + 83BE938E201A863D00DD1ED9 /* ldFlagConfigModelPatchNewFlag.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE938D201A863C00DD1ED9 /* ldFlagConfigModelPatchNewFlag.json */; }; + 83BE9391201A8AD100DD1ED9 /* NSDictionary+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BE9390201A8AD100DD1ED9 /* NSDictionary+Testable.m */; }; + 83BE9394201A8DEE00DD1ED9 /* NSObject+Testable.m in Sources */ = {isa = PBXBuildFile; fileRef = 83BE9393201A8DEE00DD1ED9 /* NSObject+Testable.m */; }; + 83BE9396201A93AC00DD1ED9 /* ldFlagConfigModelPatchVersion2Flag.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9395201A93AC00DD1ED9 /* ldFlagConfigModelPatchVersion2Flag.json */; }; + 83BE9398201AA53100DD1ED9 /* ldFlagConfigModelPatchVersion2FlagWithNull.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9397201AA53100DD1ED9 /* ldFlagConfigModelPatchVersion2FlagWithNull.json */; }; + 83BE939A201B6EBA00DD1ED9 /* ldFlagConfigModelDeleteVersion2Flag.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE9399201B6EBA00DD1ED9 /* ldFlagConfigModelDeleteVersion2Flag.json */; }; + 83BE939C201B80F800DD1ED9 /* ldFlagConfigModelDeleteNewFlag.json in Resources */ = {isa = PBXBuildFile; fileRef = 83BE939B201B80F800DD1ED9 /* ldFlagConfigModelDeleteNewFlag.json */; }; + 83C28CF92023872C00394693 /* featureFlags-excludeNulls-withoutVersions.json in Resources */ = {isa = PBXBuildFile; fileRef = 83C28CF82023872B00394693 /* featureFlags-excludeNulls-withoutVersions.json */; }; 83EF67811F979B4100403126 /* LDEvent+Unauthorized.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EF677F1F979B4100403126 /* LDEvent+Unauthorized.h */; }; 83EF67821F979B4100403126 /* LDEvent+Unauthorized.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EF677F1F979B4100403126 /* LDEvent+Unauthorized.h */; }; 83EF67831F979B4100403126 /* LDEvent+Unauthorized.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EF677F1F979B4100403126 /* LDEvent+Unauthorized.h */; }; @@ -290,7 +338,7 @@ 6903471A1E689B9F00E45133 /* LDClientTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LDClientTest.m; sourceTree = ""; }; 6903471B1E689B9F00E45133 /* LDUtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LDUtilTest.m; sourceTree = ""; }; 6903471C1E689B9F00E45133 /* LDClientManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LDClientManagerTest.m; sourceTree = ""; }; - 6903471E1E689B9F00E45133 /* feature_flags.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = feature_flags.json; sourceTree = ""; }; + 6903471E1E689B9F00E45133 /* featureFlags-withVersions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "featureFlags-withVersions.json"; sourceTree = ""; }; 6903471F1E689B9F00E45133 /* LDConfigTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LDConfigTest.m; sourceTree = ""; }; 690347201E689B9F00E45133 /* DarklyXCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DarklyXCTestCase.h; sourceTree = ""; }; 690347211E689B9F00E45133 /* LDFlagConfigModelTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LDFlagConfigModelTest.m; sourceTree = ""; }; @@ -303,6 +351,21 @@ 69BD7E101E6C79550056D70F /* Darkly.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Darkly.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69F3F67B1E6BF7C000079A09 /* Darkly.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Darkly.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7587BE78E11BC6EC851CA413 /* Pods-Darkly_osx.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Darkly_osx.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.debug.xcconfig"; sourceTree = ""; }; + 8305EC6520221973002F20DB /* LDFlagConfigValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LDFlagConfigValue.h; sourceTree = ""; }; + 8305EC6620221973002F20DB /* LDFlagConfigValue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LDFlagConfigValue.m; sourceTree = ""; }; + 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+LDFlagConfigValue.h"; sourceTree = ""; }; + 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+LDFlagConfigValue.m"; sourceTree = ""; }; + 8305EC7920222B5E002F20DB /* NSObject+LDFlagConfigValueTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+LDFlagConfigValueTest.m"; sourceTree = ""; }; + 8305EC7B2022336C002F20DB /* LDFlagConfigValueTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LDFlagConfigValueTest.m; sourceTree = ""; }; + 8305EC7D202238FC002F20DB /* boolConfigIsABool-true-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "boolConfigIsABool-true-withoutVersion.json"; sourceTree = ""; }; + 8305EC7F20223A2E002F20DB /* numberConfigIsANumber-2-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "numberConfigIsANumber-2-withoutVersion.json"; sourceTree = ""; }; + 8305EC8120223BC2002F20DB /* doubleConfigIsADouble-Pi-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "doubleConfigIsADouble-Pi-withoutVersion.json"; sourceTree = ""; }; + 8305EC8320223D65002F20DB /* stringConfigIsAString-someString-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "stringConfigIsAString-someString-withoutVersion.json"; sourceTree = ""; }; + 8305EC8520223EBA002F20DB /* arrayConfigIsAnArray-123-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArray-123-withoutVersion.json"; sourceTree = ""; }; + 8305EC8720224156002F20DB /* dictionaryConfigIsADictionary-3Key-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-3Key-withoutVersion.json"; sourceTree = ""; }; + 8305EC89202243D6002F20DB /* nullConfigIsANull-null-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "nullConfigIsANull-null-withVersion.json"; sourceTree = ""; }; + 8305EC8B2022440D002F20DB /* nullConfigIsANull-null-withoutVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "nullConfigIsANull-null-withoutVersion.json"; sourceTree = ""; }; + 8305EC8D20227365002F20DB /* featureFlags-withoutVersions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "featureFlags-withoutVersions.json"; sourceTree = ""; }; 830BF92F202A8854006DF9B1 /* NSJSONSerialization+Testable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSJSONSerialization+Testable.h"; sourceTree = ""; }; 830BF930202A8855006DF9B1 /* NSJSONSerialization+Testable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSJSONSerialization+Testable.m"; sourceTree = ""; }; 83258A3B1F323049008C2133 /* LDClientManager+EventSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LDClientManager+EventSource.h"; sourceTree = ""; }; @@ -310,7 +373,7 @@ 83258A3E1F3244D0008C2133 /* LDUserBuilder+Testable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LDUserBuilder+Testable.h"; sourceTree = ""; }; 83258A3F1F3244D0008C2133 /* LDUserBuilder+Testable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "LDUserBuilder+Testable.m"; sourceTree = ""; }; 83258A411F32721A008C2133 /* emptyConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = emptyConfig.json; sourceTree = ""; }; - 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "doubleConfigIsADouble-Pi.json"; sourceTree = ""; }; + 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "doubleConfigIsADouble-Pi-withVersion.json"; sourceTree = ""; }; 832C78811F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+NullRemovable.h"; sourceTree = ""; }; 832C78821F296F3400E334A2 /* NSMutableDictionary+NullRemovable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+NullRemovable.m"; sourceTree = ""; }; 832C788B1F2977B800E334A2 /* NSString+RemoveWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+RemoveWhitespace.h"; path = "../../Darkly/NSString+RemoveWhitespace.h"; sourceTree = ""; }; @@ -326,20 +389,22 @@ 8358F2581F4202A300ECE1AF /* LDConfig+Testable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LDConfig+Testable.h"; sourceTree = ""; }; 8358F2591F4202A300ECE1AF /* LDConfig+Testable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "LDConfig+Testable.m"; sourceTree = ""; }; 835B421A1FD5AF7300709384 /* DarklyEventSource.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarklyEventSource.framework; path = Carthage/Build/iOS/DarklyEventSource.framework; sourceTree = ""; }; + 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LDEvent+EventTypes.h"; sourceTree = ""; }; + 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "LDEvent+EventTypes.m"; sourceTree = ""; }; 836947591F1FED400047697C /* boolConfigIsABool-false.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "boolConfigIsABool-false.json"; sourceTree = ""; }; - 8369475A1F1FED400047697C /* boolConfigIsABool-true.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "boolConfigIsABool-true.json"; sourceTree = ""; }; + 8369475A1F1FED400047697C /* boolConfigIsABool-true-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "boolConfigIsABool-true-withVersion.json"; sourceTree = ""; }; 8369475B1F1FED400047697C /* boolConfigIsABool2-true.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "boolConfigIsABool2-true.json"; sourceTree = ""; }; 8369475F1F1FEEB40047697C /* numberConfigIsANumber-1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "numberConfigIsANumber-1.json"; sourceTree = ""; }; - 836947601F1FEEB40047697C /* numberConfigIsANumber-2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "numberConfigIsANumber-2.json"; sourceTree = ""; }; + 836947601F1FEEB40047697C /* numberConfigIsANumber-2-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "numberConfigIsANumber-2-withVersion.json"; sourceTree = ""; }; 836947611F1FEEB40047697C /* numberConfigIsANumber2-1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "numberConfigIsANumber2-1.json"; sourceTree = ""; }; - 836947651F1FF0A00047697C /* stringConfigIsAString-someString.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "stringConfigIsAString-someString.json"; sourceTree = ""; }; + 836947651F1FF0A00047697C /* stringConfigIsAString-someString-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "stringConfigIsAString-someString-withVersion.json"; sourceTree = ""; }; 836947661F1FF0A00047697C /* stringConfigIsAString-someStringA.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "stringConfigIsAString-someStringA.json"; sourceTree = ""; }; 836947671F1FF0A00047697C /* stringConfigIsAStringA-someString.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "stringConfigIsAStringA-someString.json"; sourceTree = ""; }; 8369476B1F1FF45B0047697C /* arrayConfigIsAnArray-1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArray-1.json"; sourceTree = ""; }; - 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArray-123.json"; sourceTree = ""; }; + 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArray-123-withVersion.json"; sourceTree = ""; }; 8369476D1F1FF45B0047697C /* arrayConfigIsAnArray-Empty.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArray-Empty.json"; sourceTree = ""; }; 8369476E1F1FF45B0047697C /* arrayConfigIsAnArrayA-123.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "arrayConfigIsAnArrayA-123.json"; sourceTree = ""; }; - 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-3Key.json"; sourceTree = ""; }; + 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key-withVersion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-3Key-withVersion.json"; sourceTree = ""; }; 836947741F1FF80A0047697C /* dictionaryConfigIsADictionary-Empty.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-Empty.json"; sourceTree = ""; }; 836947751F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyA.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-KeyA.json"; sourceTree = ""; }; 836947761F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB-124.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "dictionaryConfigIsADictionary-KeyB-124.json"; sourceTree = ""; }; @@ -356,12 +421,29 @@ 839956E720053081009707D1 /* LDUserModel+Testable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "LDUserModel+Testable.m"; sourceTree = ""; }; 839D6D261FD1B57B000BE6BD /* DarklyEventSource.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarklyEventSource.framework; path = Carthage/Build/watchOS/DarklyEventSource.framework; sourceTree = ""; }; 839D6D281FD1B58E000BE6BD /* DarklyEventSource.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarklyEventSource.framework; path = Carthage/Build/tvOS/DarklyEventSource.framework; sourceTree = ""; }; + 839E0A15201F97E800DB8CD1 /* ldClientManagerTestPatchIsANumber.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldClientManagerTestPatchIsANumber.json; sourceTree = ""; }; + 839E0A17201FB8D900DB8CD1 /* ldClientManagerTestDeleteIsANumber.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldClientManagerTestDeleteIsANumber.json; sourceTree = ""; }; 83B8C24A1FEB1CD20082B8A9 /* LDUserModel+Stub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LDUserModel+Stub.h"; sourceTree = ""; }; 83B8C24B1FEB1CD20082B8A9 /* LDUserModel+Stub.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "LDUserModel+Stub.m"; sourceTree = ""; }; 83B8C24D1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDateFormatter+LDUserModel.h"; sourceTree = ""; }; 83B8C24E1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+LDUserModel.m"; sourceTree = ""; }; - 83B8C2571FEC4C3B0082B8A9 /* userStubFlags.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = userStubFlags.json; sourceTree = ""; }; + 83B8C2571FEC4C3B0082B8A9 /* featureFlags-excludeNulls-withVersions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "featureFlags-excludeNulls-withVersions.json"; sourceTree = ""; }; 83B975D21FD1CA6000A4EF4E /* DarklyEventSource.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DarklyEventSource.framework; path = Carthage/Build/Mac/DarklyEventSource.framework; sourceTree = ""; }; + 83BE9384201A63B400DD1ED9 /* ldDataManagerTestConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldDataManagerTestConfig.json; sourceTree = ""; }; + 83BE9386201A6AA400DD1ED9 /* ldFlagConfigModelTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelTest.json; sourceTree = ""; }; + 83BE9388201A781200DD1ED9 /* ldFlagConfigModelPatchVersion1Flag.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelPatchVersion1Flag.json; sourceTree = ""; }; + 83BE938A201A797B00DD1ED9 /* NSJSONSerialization+Testable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSJSONSerialization+Testable.h"; sourceTree = ""; }; + 83BE938B201A797B00DD1ED9 /* NSJSONSerialization+Testable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSJSONSerialization+Testable.m"; sourceTree = ""; }; + 83BE938D201A863C00DD1ED9 /* ldFlagConfigModelPatchNewFlag.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelPatchNewFlag.json; sourceTree = ""; }; + 83BE938F201A8AD100DD1ED9 /* NSDictionary+Testable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Testable.h"; sourceTree = ""; }; + 83BE9390201A8AD100DD1ED9 /* NSDictionary+Testable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Testable.m"; sourceTree = ""; }; + 83BE9392201A8DEE00DD1ED9 /* NSObject+Testable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+Testable.h"; sourceTree = ""; }; + 83BE9393201A8DEE00DD1ED9 /* NSObject+Testable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Testable.m"; sourceTree = ""; }; + 83BE9395201A93AC00DD1ED9 /* ldFlagConfigModelPatchVersion2Flag.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelPatchVersion2Flag.json; sourceTree = ""; }; + 83BE9397201AA53100DD1ED9 /* ldFlagConfigModelPatchVersion2FlagWithNull.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelPatchVersion2FlagWithNull.json; sourceTree = ""; }; + 83BE9399201B6EBA00DD1ED9 /* ldFlagConfigModelDeleteVersion2Flag.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelDeleteVersion2Flag.json; sourceTree = ""; }; + 83BE939B201B80F800DD1ED9 /* ldFlagConfigModelDeleteNewFlag.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ldFlagConfigModelDeleteNewFlag.json; sourceTree = ""; }; + 83C28CF82023872B00394693 /* featureFlags-excludeNulls-withoutVersions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "featureFlags-excludeNulls-withoutVersions.json"; sourceTree = ""; }; 83EF677F1F979B4100403126 /* LDEvent+Unauthorized.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LDEvent+Unauthorized.h"; sourceTree = ""; }; 83EF67801F979B4100403126 /* LDEvent+Unauthorized.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "LDEvent+Unauthorized.m"; sourceTree = ""; }; 83EF678B1F98FC9200403126 /* LDFlagConfigModel+Testable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LDFlagConfigModel+Testable.h"; sourceTree = ""; }; @@ -501,6 +583,8 @@ 690346E21E68990000E45133 /* LDEventModel.m */, 690346E31E68990000E45133 /* LDFlagConfigModel.h */, 690346E41E68990000E45133 /* LDFlagConfigModel.m */, + 8305EC6520221973002F20DB /* LDFlagConfigValue.h */, + 8305EC6620221973002F20DB /* LDFlagConfigValue.m */, 690346E51E68990000E45133 /* LDPollingManager.h */, 690346E61E68990000E45133 /* LDPollingManager.m */, 690346E71E68990000E45133 /* LDRequestManager.h */, @@ -530,7 +614,6 @@ 6903471B1E689B9F00E45133 /* LDUtilTest.m */, 6903471C1E689B9F00E45133 /* LDClientManagerTest.m */, 6903471F1E689B9F00E45133 /* LDConfigTest.m */, - 690347211E689B9F00E45133 /* LDFlagConfigModelTest.m */, 690347201E689B9F00E45133 /* DarklyXCTestCase.h */, 690347221E689B9F00E45133 /* DarklyXCTestCase.m */, 690346CE1E6872EA00E45133 /* Info.plist */, @@ -544,6 +627,9 @@ 690347161E689B9F00E45133 /* LDDataManagerTest.m */, 690347171E689B9F00E45133 /* LDEventModelTest.m */, 690347181E689B9F00E45133 /* LDUserModelTest.m */, + 690347211E689B9F00E45133 /* LDFlagConfigModelTest.m */, + 8305EC7920222B5E002F20DB /* NSObject+LDFlagConfigValueTest.m */, + 8305EC7B2022336C002F20DB /* LDFlagConfigValueTest.m */, ); path = Models; sourceTree = ""; @@ -551,32 +637,52 @@ 6903471D1E689B9F00E45133 /* Fixtures */ = { isa = PBXGroup; children = ( - 6903471E1E689B9F00E45133 /* feature_flags.json */, + 6903471E1E689B9F00E45133 /* featureFlags-withVersions.json */, + 8305EC8D20227365002F20DB /* featureFlags-withoutVersions.json */, + 83B8C2571FEC4C3B0082B8A9 /* featureFlags-excludeNulls-withVersions.json */, + 83C28CF82023872B00394693 /* featureFlags-excludeNulls-withoutVersions.json */, 83258A411F32721A008C2133 /* emptyConfig.json */, 836947591F1FED400047697C /* boolConfigIsABool-false.json */, - 8369475A1F1FED400047697C /* boolConfigIsABool-true.json */, + 8369475A1F1FED400047697C /* boolConfigIsABool-true-withVersion.json */, + 8305EC7D202238FC002F20DB /* boolConfigIsABool-true-withoutVersion.json */, 8369475B1F1FED400047697C /* boolConfigIsABool2-true.json */, - 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi.json */, + 83258A431F329EFB008C2133 /* doubleConfigIsADouble-Pi-withVersion.json */, + 8305EC8120223BC2002F20DB /* doubleConfigIsADouble-Pi-withoutVersion.json */, 8369475F1F1FEEB40047697C /* numberConfigIsANumber-1.json */, - 836947601F1FEEB40047697C /* numberConfigIsANumber-2.json */, + 836947601F1FEEB40047697C /* numberConfigIsANumber-2-withVersion.json */, + 8305EC7F20223A2E002F20DB /* numberConfigIsANumber-2-withoutVersion.json */, 836947611F1FEEB40047697C /* numberConfigIsANumber2-1.json */, - 836947651F1FF0A00047697C /* stringConfigIsAString-someString.json */, + 836947651F1FF0A00047697C /* stringConfigIsAString-someString-withVersion.json */, + 8305EC8320223D65002F20DB /* stringConfigIsAString-someString-withoutVersion.json */, 836947661F1FF0A00047697C /* stringConfigIsAString-someStringA.json */, 836947671F1FF0A00047697C /* stringConfigIsAStringA-someString.json */, 8369476B1F1FF45B0047697C /* arrayConfigIsAnArray-1.json */, - 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123.json */, + 8369476C1F1FF45B0047697C /* arrayConfigIsAnArray-123-withVersion.json */, + 8305EC8520223EBA002F20DB /* arrayConfigIsAnArray-123-withoutVersion.json */, 8369476D1F1FF45B0047697C /* arrayConfigIsAnArray-Empty.json */, 8369476E1F1FF45B0047697C /* arrayConfigIsAnArrayA-123.json */, - 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key.json */, + 836947731F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key-withVersion.json */, + 8305EC8720224156002F20DB /* dictionaryConfigIsADictionary-3Key-withoutVersion.json */, 836947741F1FF80A0047697C /* dictionaryConfigIsADictionary-Empty.json */, 836947751F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyA.json */, 836947761F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB-124.json */, 836947771F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB.json */, 836947781F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json */, 836947791F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyC.json */, + 8305EC89202243D6002F20DB /* nullConfigIsANull-null-withVersion.json */, + 8305EC8B2022440D002F20DB /* nullConfigIsANull-null-withoutVersion.json */, 836947811F20125F0047697C /* ldClientManagerTestConfigA.json */, 836947821F20125F0047697C /* ldClientManagerTestConfigB.json */, - 83B8C2571FEC4C3B0082B8A9 /* userStubFlags.json */, + 83BE9384201A63B400DD1ED9 /* ldDataManagerTestConfig.json */, + 83BE9386201A6AA400DD1ED9 /* ldFlagConfigModelTest.json */, + 83BE9388201A781200DD1ED9 /* ldFlagConfigModelPatchVersion1Flag.json */, + 83BE9395201A93AC00DD1ED9 /* ldFlagConfigModelPatchVersion2Flag.json */, + 83BE9397201AA53100DD1ED9 /* ldFlagConfigModelPatchVersion2FlagWithNull.json */, + 83BE938D201A863C00DD1ED9 /* ldFlagConfigModelPatchNewFlag.json */, + 83BE9399201B6EBA00DD1ED9 /* ldFlagConfigModelDeleteVersion2Flag.json */, + 83BE939B201B80F800DD1ED9 /* ldFlagConfigModelDeleteNewFlag.json */, + 839E0A15201F97E800DB8CD1 /* ldClientManagerTestPatchIsANumber.json */, + 839E0A17201FB8D900DB8CD1 /* ldClientManagerTestDeleteIsANumber.json */, ); path = Fixtures; sourceTree = ""; @@ -584,12 +690,18 @@ 690347231E689B9F00E45133 /* Categories */ = { isa = PBXGroup; children = ( + 83BE9392201A8DEE00DD1ED9 /* NSObject+Testable.h */, + 83BE9393201A8DEE00DD1ED9 /* NSObject+Testable.m */, 690347241E689B9F00E45133 /* NSArray+UnitTests.h */, 690347251E689B9F00E45133 /* NSArray+UnitTests.m */, 8349F51B1F1934A000B1F3DB /* NSDictionary+StringKey_Matchable.h */, 8349F51D1F19352300B1F3DB /* NSDictionary+StringKey_Matchable.m */, + 83BE938F201A8AD100DD1ED9 /* NSDictionary+Testable.h */, + 83BE9390201A8AD100DD1ED9 /* NSDictionary+Testable.m */, 832C788B1F2977B800E334A2 /* NSString+RemoveWhitespace.h */, 832C788C1F2977B800E334A2 /* NSString+RemoveWhitespace.m */, + 83BE938A201A797B00DD1ED9 /* NSJSONSerialization+Testable.h */, + 83BE938B201A797B00DD1ED9 /* NSJSONSerialization+Testable.m */, 83B8C24A1FEB1CD20082B8A9 /* LDUserModel+Stub.h */, 83B8C24B1FEB1CD20082B8A9 /* LDUserModel+Stub.m */, 839956E620053081009707D1 /* LDUserModel+Testable.h */, @@ -633,8 +745,12 @@ 83F5B4771F95096A00174DF7 /* NSHTTPURLResponse+Unauthorized.m */, 83EF677F1F979B4100403126 /* LDEvent+Unauthorized.h */, 83EF67801F979B4100403126 /* LDEvent+Unauthorized.m */, + 8365E5062028F39E00DE8E2B /* LDEvent+EventTypes.h */, + 8365E5072028F39E00DE8E2B /* LDEvent+EventTypes.m */, 83B8C24D1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h */, 83B8C24E1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m */, + 8305EC6F20222078002F20DB /* NSObject+LDFlagConfigValue.h */, + 8305EC7020222078002F20DB /* NSObject+LDFlagConfigValue.m */, ); name = Categories; sourceTree = ""; @@ -659,6 +775,7 @@ files = ( 690346FD1E68990000E45133 /* LDEventModel.h in Headers */, 690346F91E68990000E45133 /* LDClientManager.h in Headers */, + 8305EC7120222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */, 690346FF1E68990000E45133 /* LDFlagConfigModel.h in Headers */, 83EF67811F979B4100403126 /* LDEvent+Unauthorized.h in Headers */, 83B8C24F1FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */, @@ -669,6 +786,7 @@ 690347111E68994500E45133 /* LDDataManager.h in Headers */, 690347031E68990000E45133 /* LDRequestManager.h in Headers */, 690347051E68990000E45133 /* LDUserBuilder.h in Headers */, + 8305EC6720221973002F20DB /* LDFlagConfigValue.h in Headers */, 83F5B4781F95096A00174DF7 /* NSHTTPURLResponse+Unauthorized.h in Headers */, 6903470D1E68990000E45133 /* NSDictionary+JSON.h in Headers */, 690347091E68990000E45133 /* LDUtil.h in Headers */, @@ -677,6 +795,7 @@ 833D08CB1F3B97EB00BEED83 /* NSThread+MainExecutable.h in Headers */, 83889B171F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.h in Headers */, 690347071E68990000E45133 /* LDUserModel.h in Headers */, + 8365E5082028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */, 832C78831F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -687,6 +806,7 @@ files = ( 69A87EA21E74712800B88B23 /* LDEventModel.h in Headers */, 69A87E9E1E74712800B88B23 /* LDClientManager.h in Headers */, + 8305EC7420222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */, 69A87EA41E74712800B88B23 /* LDFlagConfigModel.h in Headers */, 83EF67841F979B4100403126 /* LDEvent+Unauthorized.h in Headers */, 83B8C2521FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */, @@ -697,6 +817,7 @@ 69A87E971E74712800B88B23 /* LDDataManager.h in Headers */, 69A87EA81E74712800B88B23 /* LDRequestManager.h in Headers */, 69A87EB01E74712800B88B23 /* NSDictionary+JSON.h in Headers */, + 8305EC6A20221973002F20DB /* LDFlagConfigValue.h in Headers */, 83F5B47B1F95096A00174DF7 /* NSHTTPURLResponse+Unauthorized.h in Headers */, 69A87EAA1E74712800B88B23 /* LDUserBuilder.h in Headers */, 69A87EAE1E74712800B88B23 /* LDUtil.h in Headers */, @@ -705,6 +826,7 @@ 833D08CE1F3B97EB00BEED83 /* NSThread+MainExecutable.h in Headers */, 83889B1A1F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.h in Headers */, 69A87EAC1E74712800B88B23 /* LDUserModel.h in Headers */, + 8365E50B2028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */, 832C78861F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -715,6 +837,7 @@ files = ( 69BD7E231E6C79910056D70F /* LDEventModel.h in Headers */, 69BD7E1F1E6C79910056D70F /* LDClientManager.h in Headers */, + 8305EC7320222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */, 69BD7E251E6C79910056D70F /* LDFlagConfigModel.h in Headers */, 83EF67831F979B4100403126 /* LDEvent+Unauthorized.h in Headers */, 83B8C2511FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */, @@ -725,6 +848,7 @@ 69BD7E181E6C79910056D70F /* LDDataManager.h in Headers */, 69BD7E291E6C79910056D70F /* LDRequestManager.h in Headers */, 69BD7E311E6C79910056D70F /* NSDictionary+JSON.h in Headers */, + 8305EC6920221973002F20DB /* LDFlagConfigValue.h in Headers */, 83F5B47A1F95096A00174DF7 /* NSHTTPURLResponse+Unauthorized.h in Headers */, 69BD7E2B1E6C79910056D70F /* LDUserBuilder.h in Headers */, 69BD7E2F1E6C79910056D70F /* LDUtil.h in Headers */, @@ -733,6 +857,7 @@ 833D08CD1F3B97EB00BEED83 /* NSThread+MainExecutable.h in Headers */, 83889B191F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.h in Headers */, 69BD7E2D1E6C79910056D70F /* LDUserModel.h in Headers */, + 8365E50A2028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */, 832C78851F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -743,6 +868,7 @@ files = ( 69F3F6AE1E6BF84B00079A09 /* Darkly-Prefix.pch in Headers */, 69F3F6A11E6BF82C00079A09 /* LDPollingManager.h in Headers */, + 8305EC7220222078002F20DB /* NSObject+LDFlagConfigValue.h in Headers */, 69F3F6941E6BF80800079A09 /* LDDataManager.h in Headers */, 83EF67821F979B4100403126 /* LDEvent+Unauthorized.h in Headers */, 83B8C2501FEC19500082B8A9 /* NSDateFormatter+LDUserModel.h in Headers */, @@ -753,6 +879,7 @@ 69F3F69F1E6BF82C00079A09 /* LDFlagConfigModel.h in Headers */, 69F3F6A71E6BF82C00079A09 /* LDUserModel.h in Headers */, 69F3F6951E6BF82100079A09 /* DarklyConstants.h in Headers */, + 8305EC6820221973002F20DB /* LDFlagConfigValue.h in Headers */, 83F5B4791F95096A00174DF7 /* NSHTTPURLResponse+Unauthorized.h in Headers */, 69F3F6971E6BF82C00079A09 /* LDClient.h in Headers */, 69F3F6AB1E6BF82C00079A09 /* NSDictionary+JSON.h in Headers */, @@ -761,6 +888,7 @@ 833D08CC1F3B97EB00BEED83 /* NSThread+MainExecutable.h in Headers */, 83889B181F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.h in Headers */, 69F3F69D1E6BF82C00079A09 /* LDEventModel.h in Headers */, + 8365E5092028F39E00DE8E2B /* LDEvent+EventTypes.h in Headers */, 832C78841F296F3400E334A2 /* NSMutableDictionary+NullRemovable.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -875,7 +1003,7 @@ 690346B51E6872EA00E45133 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = LaunchDarkly; TargetAttributes = { 690346BD1E6872EA00E45133 = { @@ -934,31 +1062,51 @@ buildActionMask = 2147483647; files = ( 8369477D1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB-124.json in Resources */, + 8305EC8820224156002F20DB /* dictionaryConfigIsADictionary-3Key-withoutVersion.json in Resources */, + 8305EC8C2022440D002F20DB /* nullConfigIsANull-null-withoutVersion.json in Resources */, + 8305EC8220223BC3002F20DB /* doubleConfigIsADouble-Pi-withoutVersion.json in Resources */, + 83BE9398201AA53100DD1ED9 /* ldFlagConfigModelPatchVersion2FlagWithNull.json in Resources */, + 8305EC8A202243D6002F20DB /* nullConfigIsANull-null-withVersion.json in Resources */, + 83BE9387201A6AA400DD1ED9 /* ldFlagConfigModelTest.json in Resources */, 836947801F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyC.json in Resources */, 836947841F20125F0047697C /* ldClientManagerTestConfigB.json in Resources */, + 83BE939C201B80F800DD1ED9 /* ldFlagConfigModelDeleteNewFlag.json in Resources */, + 83C28CF92023872C00394693 /* featureFlags-excludeNulls-withoutVersions.json in Resources */, 836947711F1FF45B0047697C /* arrayConfigIsAnArray-Empty.json in Resources */, 8369476A1F1FF0A00047697C /* stringConfigIsAStringA-someString.json in Resources */, 83258A421F32721A008C2133 /* emptyConfig.json in Resources */, 836947691F1FF0A00047697C /* stringConfigIsAString-someStringA.json in Resources */, - 8369477A1F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key.json in Resources */, + 8369477A1F1FF80A0047697C /* dictionaryConfigIsADictionary-3Key-withVersion.json in Resources */, + 8305EC8420223D65002F20DB /* stringConfigIsAString-someString-withoutVersion.json in Resources */, 836947621F1FEEB40047697C /* numberConfigIsANumber-1.json in Resources */, - 6903472F1E689B9F00E45133 /* feature_flags.json in Resources */, - 836947631F1FEEB40047697C /* numberConfigIsANumber-2.json in Resources */, + 6903472F1E689B9F00E45133 /* featureFlags-withVersions.json in Resources */, + 83BE9389201A781200DD1ED9 /* ldFlagConfigModelPatchVersion1Flag.json in Resources */, + 836947631F1FEEB40047697C /* numberConfigIsANumber-2-withVersion.json in Resources */, 8369475C1F1FED400047697C /* boolConfigIsABool-false.json in Resources */, - 83B8C2581FEC4C3B0082B8A9 /* userStubFlags.json in Resources */, + 8305EC8020223A2E002F20DB /* numberConfigIsANumber-2-withoutVersion.json in Resources */, + 83B8C2581FEC4C3B0082B8A9 /* featureFlags-excludeNulls-withVersions.json in Resources */, + 8305EC7E202238FC002F20DB /* boolConfigIsABool-true-withoutVersion.json in Resources */, + 83BE9396201A93AC00DD1ED9 /* ldFlagConfigModelPatchVersion2Flag.json in Resources */, 836947831F20125F0047697C /* ldClientManagerTestConfigA.json in Resources */, + 839E0A16201F97E900DB8CD1 /* ldClientManagerTestPatchIsANumber.json in Resources */, 836947721F1FF45B0047697C /* arrayConfigIsAnArrayA-123.json in Resources */, 8369477C1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyA.json in Resources */, 8369475E1F1FED400047697C /* boolConfigIsABool2-true.json in Resources */, - 83258A441F329EFB008C2133 /* doubleConfigIsADouble-Pi.json in Resources */, + 83258A441F329EFB008C2133 /* doubleConfigIsADouble-Pi-withVersion.json in Resources */, + 83BE9385201A63B400DD1ED9 /* ldDataManagerTestConfig.json in Resources */, 836947641F1FEEB40047697C /* numberConfigIsANumber2-1.json in Resources */, + 839E0A18201FB8D900DB8CD1 /* ldClientManagerTestDeleteIsANumber.json in Resources */, + 8305EC8E20227365002F20DB /* featureFlags-withoutVersions.json in Resources */, 8369477B1F1FF80A0047697C /* dictionaryConfigIsADictionary-Empty.json in Resources */, - 836947681F1FF0A00047697C /* stringConfigIsAString-someString.json in Resources */, + 836947681F1FF0A00047697C /* stringConfigIsAString-someString-withVersion.json in Resources */, 8369477E1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyB.json in Resources */, 8369476F1F1FF45B0047697C /* arrayConfigIsAnArray-1.json in Resources */, - 8369475D1F1FED400047697C /* boolConfigIsABool-true.json in Resources */, + 8369475D1F1FED400047697C /* boolConfigIsABool-true-withVersion.json in Resources */, 8369477F1F1FF80A0047697C /* dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json in Resources */, - 836947701F1FF45B0047697C /* arrayConfigIsAnArray-123.json in Resources */, + 836947701F1FF45B0047697C /* arrayConfigIsAnArray-123-withVersion.json in Resources */, + 83BE939A201B6EBA00DD1ED9 /* ldFlagConfigModelDeleteVersion2Flag.json in Resources */, + 83BE938E201A863D00DD1ED9 /* ldFlagConfigModelPatchNewFlag.json in Resources */, + 8305EC8620223EBA002F20DB /* arrayConfigIsAnArray-123-withoutVersion.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1181,6 +1329,7 @@ buildActionMask = 2147483647; files = ( 83889B1B1F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.m in Sources */, + 8365E50C2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */, 690346FE1E68990000E45133 /* LDEventModel.m in Sources */, 690347121E68994500E45133 /* LDDataManager.m in Sources */, 832C78871F296F3400E334A2 /* NSMutableDictionary+NullRemovable.m in Sources */, @@ -1191,11 +1340,13 @@ 690346F81E68990000E45133 /* LDClient.m in Sources */, 690346F61E68990000E45133 /* DarklyConstants.m in Sources */, 83B8C2531FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */, + 8305EC6B20221973002F20DB /* LDFlagConfigValue.m in Sources */, 83EF67851F979B4100403126 /* LDEvent+Unauthorized.m in Sources */, 6903470E1E68990000E45133 /* NSDictionary+JSON.m in Sources */, 690347021E68990000E45133 /* LDPollingManager.m in Sources */, 690346FC1E68990000E45133 /* LDConfig.m in Sources */, 690347061E68990000E45133 /* LDUserBuilder.m in Sources */, + 8305EC7520222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */, 690347081E68990000E45133 /* LDUserModel.m in Sources */, 6903470A1E68990000E45133 /* LDUtil.m in Sources */, 690347001E68990000E45133 /* LDFlagConfigModel.m in Sources */, @@ -1218,20 +1369,24 @@ 6903472B1E689B9F00E45133 /* LDPollingManagerTest.m in Sources */, 83EF67901F99365600403126 /* LDClient+Testable.m in Sources */, 83258A3D1F323049008C2133 /* LDClientManager+EventSource.m in Sources */, + 8305EC7A20222B5E002F20DB /* NSObject+LDFlagConfigValueTest.m in Sources */, + 83BE938C201A797B00DD1ED9 /* NSJSONSerialization+Testable.m in Sources */, 6903472E1E689B9F00E45133 /* LDClientManagerTest.m in Sources */, 69E5275E1E6E948F00E4B63B /* LDDataManagerTest.m in Sources */, + 83BE9394201A8DEE00DD1ED9 /* NSObject+Testable.m in Sources */, 690347321E689B9F00E45133 /* DarklyXCTestCase.m in Sources */, 83889B141F8E93A100A4EF69 /* LDEvent+Testable.m in Sources */, 69B205D31EA92ECD00487CA3 /* LDRequestManagerTest.m in Sources */, 6903472D1E689B9F00E45133 /* LDUtilTest.m in Sources */, 690347311E689B9F00E45133 /* LDFlagConfigModelTest.m in Sources */, + 8305EC7C2022336C002F20DB /* LDFlagConfigValueTest.m in Sources */, + 83BE9391201A8AD100DD1ED9 /* NSDictionary+Testable.m in Sources */, 83258A401F3244D0008C2133 /* LDUserBuilder+Testable.m in Sources */, 690347331E689B9F00E45133 /* NSArray+UnitTests.m in Sources */, 6903472C1E689B9F00E45133 /* LDClientTest.m in Sources */, 83B8C24C1FEB1CD20082B8A9 /* LDUserModel+Stub.m in Sources */, 832C78901F2A8DF600E334A2 /* LDUserModel+JsonDecodeable.m in Sources */, 8358F25A1F4202A300ECE1AF /* LDConfig+Testable.m in Sources */, - 830BF931202A8855006DF9B1 /* NSJSONSerialization+Testable.m in Sources */, 83F5B4751F91560300174DF7 /* LDDataManager+Testable.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1241,6 +1396,7 @@ buildActionMask = 2147483647; files = ( 83889B1E1F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.m in Sources */, + 8365E50F2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */, 69A87EA31E74712800B88B23 /* LDEventModel.m in Sources */, 69A87E9D1E74712800B88B23 /* LDClient.m in Sources */, 832C788A1F296F3400E334A2 /* NSMutableDictionary+NullRemovable.m in Sources */, @@ -1251,11 +1407,13 @@ 69A87EA51E74712800B88B23 /* LDFlagConfigModel.m in Sources */, 69A87EB11E74712800B88B23 /* NSDictionary+JSON.m in Sources */, 83B8C2561FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */, + 8305EC6E20221973002F20DB /* LDFlagConfigValue.m in Sources */, 83EF67881F979B4100403126 /* LDEvent+Unauthorized.m in Sources */, 69A87EAF1E74712800B88B23 /* LDUtil.m in Sources */, 69A87EA71E74712800B88B23 /* LDPollingManager.m in Sources */, 69A87E9F1E74712800B88B23 /* LDClientManager.m in Sources */, 69A87EAD1E74712800B88B23 /* LDUserModel.m in Sources */, + 8305EC7820222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */, 69A87E981E74712800B88B23 /* LDDataManager.m in Sources */, 69A87EAB1E74712800B88B23 /* LDUserBuilder.m in Sources */, 69A87EA91E74712800B88B23 /* LDRequestManager.m in Sources */, @@ -1267,6 +1425,7 @@ buildActionMask = 2147483647; files = ( 83889B1D1F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.m in Sources */, + 8365E50E2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */, 69BD7E241E6C79910056D70F /* LDEventModel.m in Sources */, 69BD7E1E1E6C79910056D70F /* LDClient.m in Sources */, 832C78891F296F3400E334A2 /* NSMutableDictionary+NullRemovable.m in Sources */, @@ -1277,11 +1436,13 @@ 69BD7E261E6C79910056D70F /* LDFlagConfigModel.m in Sources */, 69BD7E321E6C79910056D70F /* NSDictionary+JSON.m in Sources */, 83B8C2551FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */, + 8305EC6D20221973002F20DB /* LDFlagConfigValue.m in Sources */, 83EF67871F979B4100403126 /* LDEvent+Unauthorized.m in Sources */, 69BD7E301E6C79910056D70F /* LDUtil.m in Sources */, 69BD7E281E6C79910056D70F /* LDPollingManager.m in Sources */, 69BD7E201E6C79910056D70F /* LDClientManager.m in Sources */, 69BD7E2E1E6C79910056D70F /* LDUserModel.m in Sources */, + 8305EC7720222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */, 69BD7E191E6C79910056D70F /* LDDataManager.m in Sources */, 69BD7E2C1E6C79910056D70F /* LDUserBuilder.m in Sources */, 69BD7E2A1E6C79910056D70F /* LDRequestManager.m in Sources */, @@ -1293,6 +1454,7 @@ buildActionMask = 2147483647; files = ( 83889B1C1F8F28AB00A4EF69 /* NSURLResponse+Unauthorized.m in Sources */, + 8365E50D2028F39E00DE8E2B /* LDEvent+EventTypes.m in Sources */, 69F3F69E1E6BF82C00079A09 /* LDEventModel.m in Sources */, 69F3F6981E6BF82C00079A09 /* LDClient.m in Sources */, 832C78881F296F3400E334A2 /* NSMutableDictionary+NullRemovable.m in Sources */, @@ -1303,11 +1465,13 @@ 69F3F6A01E6BF82C00079A09 /* LDFlagConfigModel.m in Sources */, 69F3F6AC1E6BF82C00079A09 /* NSDictionary+JSON.m in Sources */, 83B8C2541FEC19500082B8A9 /* NSDateFormatter+LDUserModel.m in Sources */, + 8305EC6C20221973002F20DB /* LDFlagConfigValue.m in Sources */, 83EF67861F979B4100403126 /* LDEvent+Unauthorized.m in Sources */, 69F3F6AA1E6BF82C00079A09 /* LDUtil.m in Sources */, 69F3F6A21E6BF82C00079A09 /* LDPollingManager.m in Sources */, 69F3F69A1E6BF82C00079A09 /* LDClientManager.m in Sources */, 69F3F6A81E6BF82C00079A09 /* LDUserModel.m in Sources */, + 8305EC7620222078002F20DB /* NSObject+LDFlagConfigValue.m in Sources */, 69F3F6921E6BF7F600079A09 /* LDDataManager.m in Sources */, 69F3F6A61E6BF82C00079A09 /* LDUserBuilder.m in Sources */, 69F3F6A41E6BF82C00079A09 /* LDRequestManager.m in Sources */, diff --git a/Darkly.xcodeproj/xcshareddata/xcschemes/Darkly_iOS.xcscheme b/Darkly.xcodeproj/xcshareddata/xcschemes/Darkly_iOS.xcscheme index 48b630f0..05f7c406 100644 --- a/Darkly.xcodeproj/xcshareddata/xcschemes/Darkly_iOS.xcscheme +++ b/Darkly.xcodeproj/xcshareddata/xcschemes/Darkly_iOS.xcscheme @@ -1,6 +1,6 @@ #import "LDEvent+Unauthorized.h" +#import "LDEvent+EventTypes.h" + +NSString * const kLDClientManagerStreamMethod = @"meval"; @interface LDClientManager() @@ -135,11 +138,14 @@ - (void)configureEventSource { DEBUG_LOGX(@"ClientManager aborting event source creation - event source running"); return; } - eventSource = [LDEventSource eventSourceWithURL:[NSURL URLWithString:[LDClient sharedInstance].ldConfig.streamUrl] httpHeaders:[self httpHeadersForEventSource]]; - + + eventSource = [self eventSourceForUser:[LDClient sharedInstance].ldUser config:[LDClient sharedInstance].ldConfig httpHeaders:[self httpHeadersForEventSource]]; + [eventSource onMessage:^(LDEvent *event) { - if (![event.event isEqualToString:@"ping"]) { return; } - [self syncWithServerForConfig]; + [self handlePingEvent:event]; + [self handlePutEvent:event]; + [self handlePatchEvent:event]; + [self handleDeleteEvent:event]; }]; [eventSource onError:^(LDEvent *event) { @@ -150,6 +156,126 @@ - (void)configureEventSource { } } +- (LDEventSource*)eventSourceForUser:(LDUserModel*)user config:(LDConfig*)config httpHeaders:(NSDictionary*)httpHeaders { + LDEventSource *eventSource; + if (config.useReport) { + eventSource = [LDEventSource eventSourceWithURL:[self eventSourceUrlForUser:user config:config] + httpHeaders:httpHeaders + connectMethod:kHTTPMethodReport + connectBody:[[[user dictionaryValueWithPrivateAttributesAndFlagConfig:NO] jsonString] dataUsingEncoding:NSUTF8StringEncoding]]; + } else { + eventSource = [LDEventSource eventSourceWithURL:[self eventSourceUrlForUser:user config:config] httpHeaders:httpHeaders connectMethod:nil connectBody:nil]; + } + return eventSource; +} + +- (NSURL*)eventSourceUrlForUser:(LDUserModel *)user config:(LDConfig*)config { + NSString *eventStreamUrl = [config.streamUrl stringByAppendingPathComponent:kLDClientManagerStreamMethod]; + if (!config.useReport) { + NSString *encodedUser = [LDUtil base64UrlEncodeString:[[user dictionaryValueWithPrivateAttributesAndFlagConfig:NO] jsonString]]; + eventStreamUrl = [eventStreamUrl stringByAppendingPathComponent:encodedUser]; + } + return [NSURL URLWithString:eventStreamUrl]; +} + +- (void)handlePingEvent:(LDEvent*)event { + if (![event.event isEqualToString:kLDEventTypePing]) { return; } + [self syncWithServerForConfig]; +} + +- (void)handlePutEvent:(LDEvent*)event { + if (![event.event isEqualToString:kLDEventTypePut]) { return; } + if (event.data.length == 0) { + DEBUG_LOGX(@"ClientManager aborted handlePutEvent - event contains no data"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + NSDictionary *newConfigDictionary = [NSJSONSerialization JSONObjectWithData:[event.data dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; + if (!newConfigDictionary) { + DEBUG_LOGX(@"ClientManager aborted handlePutEvent - event contains json data could not be read"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + LDFlagConfigModel *newConfig = [[LDFlagConfigModel alloc] initWithDictionary:newConfigDictionary]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + + if ([user.config isEqualToConfig:newConfig]) { + DEBUG_LOGX(@"ClientManager handlePutEvent resulted in no change to the flag config"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + user.config = newConfig; + [[LDDataManager sharedManager] saveUser:user]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserUpdatedNotification object:nil]; + DEBUG_LOGX(@"ClientManager posted Darkly.UserUpdatedNotification following user config update from SSE put event"); +} + +- (void)handlePatchEvent:(LDEvent*)event { + if (![event.event isEqualToString:kLDEventTypePatch]) { return; } + if (event.data.length == 0) { + DEBUG_LOGX(@"ClientManager aborted handlePatchEvent - event contains no data"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + NSDictionary *patchDictionary = [NSJSONSerialization JSONObjectWithData:[event.data dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; + if (!patchDictionary) { + DEBUG_LOGX(@"ClientManager aborted handlePatchEvent - event json data could not be read"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + NSDictionary *originalFlagConfig = user.config.featuresJsonDictionary; + + [user.config addOrReplaceFromDictionary:patchDictionary]; + + if ([user.config hasFeaturesEqualToDictionary:originalFlagConfig]) { + DEBUG_LOGX(@"ClientManager handlePatchEvent resulted in no change to the flag config"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + [[LDDataManager sharedManager] saveUser:user]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserUpdatedNotification object:nil]; + DEBUG_LOGX(@"ClientManager posted Darkly.UserUpdatedNotification following user config update from SSE patch event"); +} + +- (void)handleDeleteEvent:(LDEvent*)event { + if (![event.event isEqualToString:kLDEventTypeDelete]) { return; } + if (event.data.length == 0) { + DEBUG_LOGX(@"ClientManager aborted handleDeleteEvent - event contains no data"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + NSDictionary *deleteDictionary = [NSJSONSerialization JSONObjectWithData:[event.data dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; + if (!deleteDictionary) { + DEBUG_LOGX(@"ClientManager aborted handleDeleteEvent - event json data could not be read"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + NSDictionary *originalFlagConfig = user.config.featuresJsonDictionary; + + [user.config deleteFromDictionary:deleteDictionary]; + + if ([user.config hasFeaturesEqualToDictionary:originalFlagConfig]) { + DEBUG_LOGX(@"ClientManager handleDeleteEvent resulted in no change to the flag config"); + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserNoChangeNotification object:nil]; + return; + } + + [[LDDataManager sharedManager] saveUser:user]; + [[NSNotificationCenter defaultCenter] postNotificationName:kLDUserUpdatedNotification object:nil]; + DEBUG_LOGX(@"ClientManager posted Darkly.UserUpdatedNotification following user config update from SSE delete event"); +} + +- (void)postClientUnauthorizedNotification { + [[NSNotificationCenter defaultCenter] postNotificationName:kLDClientUnauthorizedNotification object:nil]; +} + - (void)stopEventSource { @synchronized (self) { [eventSource close]; diff --git a/Darkly/LDConfig.m b/Darkly/LDConfig.m index 7fb4c1c6..c915a5f4 100644 --- a/Darkly/LDConfig.m +++ b/Darkly/LDConfig.m @@ -63,7 +63,7 @@ - (void)setEventsUrl:(NSString *)eventsUrl { } - (void)setCapacity:(NSNumber *)capacity { - if (capacity) { + if (capacity != nil) { DEBUG_LOG(@"Set LDConfig capacity: %@", capacity); _capacity = capacity; } else { @@ -73,7 +73,7 @@ - (void)setCapacity:(NSNumber *)capacity { } - (void)setConnectionTimeout:(NSNumber *)connectionTimeout { - if (connectionTimeout) { + if (connectionTimeout != nil) { DEBUG_LOG(@"Set LDConfig timeout: %@", connectionTimeout); _connectionTimeout = connectionTimeout; } else { @@ -83,7 +83,7 @@ - (void)setConnectionTimeout:(NSNumber *)connectionTimeout { } - (void)setFlushInterval:(NSNumber *)flushInterval { - if (flushInterval) { + if (flushInterval != nil) { DEBUG_LOG(@"Set LDConfig flush interval: %@", flushInterval); _flushInterval = flushInterval; } else { @@ -93,7 +93,7 @@ - (void)setFlushInterval:(NSNumber *)flushInterval { } - (void)setPollingInterval:(NSNumber *)pollingInterval { - if (pollingInterval) { + if (pollingInterval != nil) { DEBUG_LOG(@"Set LDConfig polling interval: %@", pollingInterval); _pollingInterval = [NSNumber numberWithInt:MAX(pollingInterval.intValue, kMinimumPollingInterval)]; } else { @@ -103,7 +103,7 @@ - (void)setPollingInterval:(NSNumber *)pollingInterval { } - (void)setBackgroundFetchInterval:(NSNumber *)backgroundFetchInterval { - if (backgroundFetchInterval) { + if (backgroundFetchInterval != nil) { DEBUG_LOG(@"Set LDConfig background fetch interval: %@", backgroundFetchInterval); _backgroundFetchInterval = backgroundFetchInterval; } else { diff --git a/Darkly/LDDataManager.m b/Darkly/LDDataManager.m index b831f1dc..39849aa4 100644 --- a/Darkly/LDDataManager.m +++ b/Darkly/LDDataManager.m @@ -98,7 +98,7 @@ -(LDUserModel *)findUserWithkey: (NSString *)key { } - (void)compareConfigForUser:(LDUserModel *)user withNewUser:(LDUserModel *)newUser { - for (NSString *key in [[newUser.config dictionaryValue] objectForKey:kFeaturesJsonDictionaryKey]) { + for (NSString *key in [newUser.config dictionaryValueIncludeNulls:NO]) { if(user == nil || ![[newUser.config configFlagValue:key] isEqual:[user.config configFlagValue:key]]) { [[NSNotificationCenter defaultCenter] postNotificationName:kLDFlagConfigChangedNotification object:nil userInfo:[NSDictionary dictionaryWithObject:key forKey:kFlagKey]]; } diff --git a/Darkly/LDEvent+EventTypes.h b/Darkly/LDEvent+EventTypes.h new file mode 100644 index 00000000..4b87b5e0 --- /dev/null +++ b/Darkly/LDEvent+EventTypes.h @@ -0,0 +1,18 @@ +// +// LDEvent+EventTypes.h +// Darkly +// +// Created by Mark Pokorny on 2/5/18. +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import + +extern NSString * const kLDEventTypePing; +extern NSString * const kLDEventTypePut; +extern NSString * const kLDEventTypePatch; +extern NSString * const kLDEventTypeDelete; + +@interface LDEvent (EventTypes) + +@end diff --git a/Darkly/LDEvent+EventTypes.m b/Darkly/LDEvent+EventTypes.m new file mode 100644 index 00000000..fac8b5fe --- /dev/null +++ b/Darkly/LDEvent+EventTypes.m @@ -0,0 +1,18 @@ +// +// LDEvent+EventTypes.m +// Darkly +// +// Created by Mark Pokorny on 2/5/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import "LDEvent+EventTypes.h" + +NSString * const kLDEventTypePing = @"ping"; +NSString * const kLDEventTypePut = @"put"; +NSString * const kLDEventTypePatch = @"patch"; +NSString * const kLDEventTypeDelete = @"delete"; + +@implementation LDEvent (EventTypes) + +@end diff --git a/Darkly/LDFlagConfigModel.h b/Darkly/LDFlagConfigModel.h index 44668d60..2a37f5b1 100644 --- a/Darkly/LDFlagConfigModel.h +++ b/Darkly/LDFlagConfigModel.h @@ -7,18 +7,23 @@ // #import +#import "LDFlagConfigValue.h" @interface LDFlagConfigModel : NSObject -extern NSString * _Nullable const kFeaturesJsonDictionaryKey; +@property (nullable, nonatomic, strong) NSDictionary *featuresJsonDictionary; -@property (nullable, nonatomic, strong) NSDictionary *featuresJsonDictionary; +-(nullable id)initWithDictionary:(nullable NSDictionary*)dictionary; +-(nullable NSDictionary*)dictionaryValue; +-(nullable NSDictionary*)dictionaryValueIncludeNulls:(BOOL)includeNulls; -- (nonnull id)initWithDictionary:(nonnull NSDictionary *)dictionary; --(nonnull NSDictionary *)dictionaryValue; +-(BOOL)doesConfigFlagExist:(nonnull NSString*)keyName; +-(nullable id)configFlagValue:(nonnull NSString*)keyName; +-(NSInteger)configFlagVersion:(nonnull NSString*)keyName; --(nonnull NSObject*) configFlagValue: ( NSString * __nonnull )keyName; --(BOOL) doesConfigFlagExist: ( NSString * __nonnull )keyName; +-(void)addOrReplaceFromDictionary:(nullable NSDictionary*)patch; +-(void)deleteFromDictionary:(nullable NSDictionary*)delete; --(BOOL)isEqualToConfig:(nullable LDFlagConfigModel *)otherConfig; +-(BOOL)isEqualToConfig:(nullable LDFlagConfigModel*)otherConfig; +-(BOOL)hasFeaturesEqualToDictionary:(nullable NSDictionary*)otherDictionary; @end diff --git a/Darkly/LDFlagConfigModel.m b/Darkly/LDFlagConfigModel.m index ce52ddf8..0d476cf9 100644 --- a/Darkly/LDFlagConfigModel.m +++ b/Darkly/LDFlagConfigModel.m @@ -11,70 +11,115 @@ #import "NSMutableDictionary+NullRemovable.h" NSString * const kFeaturesJsonDictionaryKey = @"featuresJsonDictionary"; +NSString * const kLDFlagConfigJsonDictionaryKeyKey = @"key"; -static NSString * const kFeaturesJsonDictionaryServerKey = @"items"; - -static NSString * const kFeatureJsonValueName = @"value"; +extern NSString * const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString * const kLDFlagConfigJsonDictionaryKeyVersion; +extern const NSInteger kLDFlagConfigVersionDoesNotExist; @implementation LDFlagConfigModel - (void)encodeWithCoder:(NSCoder *)encoder { - //Encode properties, other class variables, etc [encoder encodeObject:self.featuresJsonDictionary forKey:kFeaturesJsonDictionaryKey]; } - (id)initWithCoder:(NSCoder *)decoder { - if((self = [super init])) { - //Decode properties, other class vars - self.featuresJsonDictionary = [decoder decodeObjectForKey:kFeaturesJsonDictionaryKey]; - } + if (!(self = [super init])) { return nil; } + _featuresJsonDictionary = [decoder decodeObjectForKey:kFeaturesJsonDictionaryKey]; return self; } - (id)initWithDictionary:(NSDictionary *)dictionary { - if((self = [super init])) { - //Process json that comes down from server - self.featuresJsonDictionary = dictionary; + if (!(self = [super init])) { return nil; } + + NSMutableDictionary *flagConfigValues = [NSMutableDictionary dictionaryWithCapacity:dictionary.count]; + + for (NSString *key in [dictionary.allKeys copy]) { + flagConfigValues[key] = [LDFlagConfigValue flagConfigValueWithObject:dictionary[key]]; } + + _featuresJsonDictionary = [NSDictionary dictionaryWithDictionary:[flagConfigValues copy]]; + return self; } --(NSDictionary *)dictionaryValue{ - NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; - - self.featuresJsonDictionary ? [dictionary setObject:[self.featuresJsonDictionary mutableCopy] forKey: kFeaturesJsonDictionaryKey] : nil; - return [[dictionary removeNullValues] copy]; +-(NSDictionary *)dictionaryValue { + return [self dictionaryValueIncludeNulls:YES]; } --(NSObject*) configFlagValue: ( NSString * __nonnull )keyName { - NSObject *result = nil; - - NSDictionary *featureValue = [self.featuresJsonDictionary objectForKey: keyName]; - - if (featureValue) { - id aValue = featureValue; - if (![aValue isKindOfClass:[NSNull class]]) { - @try { - result = aValue; - } - @catch (NSException *exception) { - DEBUG_LOG(@"Error parsing value for key: %@", keyName); - } - } +-(NSDictionary*)dictionaryValueIncludeNulls:(BOOL)includeNulls { + if (!self.featuresJsonDictionary) return nil; + + NSMutableDictionary *flagConfigDictionaryValues = [NSMutableDictionary dictionaryWithCapacity:self.featuresJsonDictionary.count]; + for (NSString *key in [self.featuresJsonDictionary.allKeys copy]) { + if (!includeNulls && [self.featuresJsonDictionary[key].value isKindOfClass:[NSNull class]]) { continue; } + flagConfigDictionaryValues[key] = [self.featuresJsonDictionary[key] dictionaryValue]; } - return result; + if (!includeNulls) { + [flagConfigDictionaryValues removeNullValues]; //Redact nulls out of values that are dictionaries + } + + return [NSDictionary dictionaryWithDictionary:[flagConfigDictionaryValues copy]]; } --(BOOL) doesConfigFlagExist: ( NSString * __nonnull )keyName { - if (self.featuresJsonDictionary != nil) { - BOOL value = [[self.featuresJsonDictionary allKeys] containsObject: keyName]; - return value; - } - return false; +-(id)configFlagValue:(NSString*)keyName { + LDFlagConfigValue *featureValue = self.featuresJsonDictionary[keyName]; + if (!featureValue || [featureValue.value isKindOfClass:[NSNull class]]) { return nil; } + + return featureValue.value; +} + +-(NSInteger)configFlagVersion:(NSString*)keyName { + LDFlagConfigValue *featureValue = self.featuresJsonDictionary[keyName]; + if (!featureValue) { return kLDFlagConfigVersionDoesNotExist; } + + return featureValue.version; +} + +-(BOOL)doesConfigFlagExist:(NSString*)keyName { + if (!self.featuresJsonDictionary) { return NO; } + + return [[self.featuresJsonDictionary allKeys] containsObject: keyName]; +} + +-(void)addOrReplaceFromDictionary:(NSDictionary*)patch { + NSString *flagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + if (flagKey.length == 0) { return; } + + id flagValue = patch[kLDFlagConfigJsonDictionaryKeyValue]; + if (!flagValue) { return; } + + id flagVersionObject = patch[kLDFlagConfigJsonDictionaryKeyVersion]; + if (!flagVersionObject || ![flagVersionObject isKindOfClass:[NSNumber class]]) { return; } + NSInteger flagVersion = [(NSNumber*)flagVersionObject integerValue]; + if ([self doesConfigFlagExist:flagKey] && flagVersion <= [self configFlagVersion:flagKey]) { return; } + + NSMutableDictionary *updatedFlagConfig = [NSMutableDictionary dictionaryWithDictionary:self.featuresJsonDictionary]; + updatedFlagConfig[flagKey] = [LDFlagConfigValue flagConfigValueWithObject:@{kLDFlagConfigJsonDictionaryKeyValue:flagValue, kLDFlagConfigJsonDictionaryKeyVersion:@(flagVersion)}]; + self.featuresJsonDictionary = [updatedFlagConfig copy]; +} + +-(void)deleteFromDictionary:(nullable NSDictionary*)delete { + NSString *flagKey = delete[kLDFlagConfigJsonDictionaryKeyKey]; + if (flagKey.length == 0) { return; } + + id flagVersionObject = delete[kLDFlagConfigJsonDictionaryKeyVersion]; + if (!flagVersionObject || ![flagVersionObject isKindOfClass:[NSNumber class]]) { return; } + NSInteger flagVersion = [(NSNumber*)flagVersionObject integerValue]; + if ([self doesConfigFlagExist:flagKey] && flagVersion <= [self configFlagVersion:flagKey]) { return; } + + NSMutableDictionary *updatedFlagConfig = [NSMutableDictionary dictionaryWithDictionary:self.featuresJsonDictionary]; + updatedFlagConfig[flagKey] = nil; + + self.featuresJsonDictionary = [updatedFlagConfig copy]; } --(BOOL)isEqualToConfig:(nullable LDFlagConfigModel *)otherConfig { +-(BOOL)isEqualToConfig:(LDFlagConfigModel *)otherConfig { return [self.featuresJsonDictionary isEqualToDictionary:otherConfig.featuresJsonDictionary]; } +-(BOOL)hasFeaturesEqualToDictionary:(NSDictionary*)otherDictionary { + return [[self dictionaryValue] isEqualToDictionary:otherDictionary]; +} + @end diff --git a/Darkly/LDFlagConfigValue.h b/Darkly/LDFlagConfigValue.h new file mode 100644 index 00000000..3f5ca4ef --- /dev/null +++ b/Darkly/LDFlagConfigValue.h @@ -0,0 +1,25 @@ +// +// LDFlagConfigValue.h +// Darkly +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import + +extern NSInteger const kLDFlagConfigVersionDoesNotExist; + +@interface LDFlagConfigValue: NSObject +@property (nonatomic, strong) id _Nullable value; +@property (nonatomic, assign) NSInteger version; + ++(nullable instancetype)flagConfigValueWithObject:(nullable id)object; +-(nullable instancetype)initWithObject:(nullable id)object; + +-(void)encodeWithCoder:(nonnull NSCoder*)encoder; +-(nullable id)initWithCoder:(nonnull NSCoder*)decoder; +-(nonnull NSDictionary*)dictionaryValue; + +-(BOOL)isEqual:(nullable id)object; +@end diff --git a/Darkly/LDFlagConfigValue.m b/Darkly/LDFlagConfigValue.m new file mode 100644 index 00000000..07f7d8b6 --- /dev/null +++ b/Darkly/LDFlagConfigValue.m @@ -0,0 +1,62 @@ +// +// LDFlagValue.m +// Darkly +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import "LDFlagConfigValue.h" +#import "NSObject+LDFlagConfigValue.h" + +NSString * const kLDFlagConfigJsonDictionaryKeyValue = @"value"; +NSString * const kLDFlagConfigJsonDictionaryKeyVersion = @"version"; + +NSInteger const kLDFlagConfigVersionDoesNotExist = -1; + +@implementation LDFlagConfigValue + ++(instancetype)flagConfigValueWithObject:(id)object { + return [[LDFlagConfigValue alloc] initWithObject:object]; +} + +-(instancetype)initWithObject:(id)object { + if (!object) { return nil; } + if (!(self = [super init])) { return nil; } + if ([object isValueAndVersionDictionary]) { + NSDictionary *valueAndVersionDictionary = object; + _value = valueAndVersionDictionary[kLDFlagConfigJsonDictionaryKeyValue]; + _version = [(NSNumber*)valueAndVersionDictionary[kLDFlagConfigJsonDictionaryKeyVersion] integerValue]; + } else { + _value = object; + _version = kLDFlagConfigVersionDoesNotExist; + } + + return self; +} + +-(void)encodeWithCoder:(NSCoder *)encoder { + [encoder encodeObject:self.value forKey:kLDFlagConfigJsonDictionaryKeyValue]; + [encoder encodeInteger:self.version forKey:kLDFlagConfigJsonDictionaryKeyVersion]; +} + +-(id)initWithCoder:(NSCoder *)decoder { + if (!(self = [super init])) { return nil; } + + _value = [decoder decodeObjectForKey:kLDFlagConfigJsonDictionaryKeyValue]; + _version = [decoder decodeIntegerForKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + return self; +} + +-(NSDictionary*)dictionaryValue { + return @{kLDFlagConfigJsonDictionaryKeyValue: self.value, kLDFlagConfigJsonDictionaryKeyVersion: @(self.version)}; +} + +-(BOOL)isEqual:(id)object { + if (!object || ![object isKindOfClass:[LDFlagConfigValue class]]) { return NO; } + LDFlagConfigValue *other = object; + + return [self.value isEqual:other.value] && self.version == other.version; +} +@end diff --git a/Darkly/LDRequestManager.m b/Darkly/LDRequestManager.m index 3fbf4293..929ecee7 100644 --- a/Darkly/LDRequestManager.m +++ b/Darkly/LDRequestManager.m @@ -205,7 +205,7 @@ -(NSURLRequest*)flagRequestUsingReportMethodForUser:(LDUserModel*)user { NSString *requestUrl = [baseUrl stringByAppendingString:kFeatureFlagReportUrl]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestUrl]]; - request.HTTPMethod = @"REPORT"; + request.HTTPMethod = kHTTPMethodReport; request.HTTPBody = [userJson dataUsingEncoding:NSUTF8StringEncoding]; [request setTimeoutInterval:self.connectionTimeout]; [self addFeatureRequestHeaders:request]; diff --git a/Darkly/LDUserModel.m b/Darkly/LDUserModel.m index 74885831..64593b54 100644 --- a/Darkly/LDUserModel.m +++ b/Darkly/LDUserModel.m @@ -36,7 +36,9 @@ -(NSDictionary *)dictionaryValueWithPrivateAttributesAndFlagConfig:(BOOL)include -(NSDictionary *)dictionaryValueWithFlagConfig:(BOOL)includeFlags includePrivateAttributes:(BOOL)includePrivate config:(LDConfig*)config { NSMutableArray *combinedPrivateAttributes = [NSMutableArray arrayWithArray:self.privateAttributes]; - [combinedPrivateAttributes addObjectsFromArray:config.privateUserAttributes]; + if (config.privateUserAttributes.count) { + [combinedPrivateAttributes addObjectsFromArray:config.privateUserAttributes]; + } if (config.allUserAttributesPrivate) { combinedPrivateAttributes = [[LDUserModel allUserAttributes] mutableCopy]; } NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; @@ -63,7 +65,7 @@ -(NSDictionary *)dictionaryValueWithFlagConfig:(BOOL)includeFlags includePrivate } if (includeFlags && self.config.featuresJsonDictionary) { - dictionary[kUserAttributeConfig] = [[self.config dictionaryValue] objectForKey:kFeaturesJsonDictionaryKey]; + dictionary[kUserAttributeConfig] = [self.config dictionaryValueIncludeNulls:NO]; } return [dictionary copy]; diff --git a/Darkly/NSObject+LDFlagConfigValue.h b/Darkly/NSObject+LDFlagConfigValue.h new file mode 100644 index 00000000..f9baa755 --- /dev/null +++ b/Darkly/NSObject+LDFlagConfigValue.h @@ -0,0 +1,15 @@ +// +// NSObject+LDFlagConfigValue.h +// Darkly +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import + +@interface NSObject(LDFlagConfigValue) + +-(BOOL)isValueAndVersionDictionary; + +@end diff --git a/Darkly/NSObject+LDFlagConfigValue.m b/Darkly/NSObject+LDFlagConfigValue.m new file mode 100644 index 00000000..1fe0f674 --- /dev/null +++ b/Darkly/NSObject+LDFlagConfigValue.m @@ -0,0 +1,26 @@ +// +// NSObject+LDFlagConfigValue.m +// Darkly +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import "NSObject+LDFlagConfigValue.h" + +extern NSString * const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString * const kLDFlagConfigJsonDictionaryKeyVersion; + +@implementation NSObject(LDFlagConfigValue) + +-(BOOL)isValueAndVersionDictionary { + if (![self isKindOfClass:[NSDictionary class]]) { return NO; } + NSDictionary *dictionaryObject = (NSDictionary*)self; + if (![dictionaryObject.allKeys containsObject:kLDFlagConfigJsonDictionaryKeyValue]) { return NO; } + if (![dictionaryObject.allKeys containsObject:kLDFlagConfigJsonDictionaryKeyVersion]) { return NO; } + if (![dictionaryObject[kLDFlagConfigJsonDictionaryKeyVersion] isKindOfClass:[NSNumber class]]) { return NO; } + + return YES; +} + +@end diff --git a/DarklyTests/Categories/LDEvent+Testable.h b/DarklyTests/Categories/LDEvent+Testable.h index 74c93810..39c8ad11 100644 --- a/DarklyTests/Categories/LDEvent+Testable.h +++ b/DarklyTests/Categories/LDEvent+Testable.h @@ -6,9 +6,12 @@ // Copyright © 2017 LaunchDarkly. All rights reserved. // -#import "LDEventSource.h" +#import @interface LDEvent(Testable) -+(instancetype)stubUnauthorizedEvent; -+(instancetype)stubErrorEvent; ++(nonnull instancetype)stubPingEvent; ++(nonnull instancetype)stubEvent:(nonnull NSString*)eventType fromJsonFileNamed:(nonnull NSString*)fileName; ++(nonnull instancetype)stubEvent:(nonnull NSString*)eventType withDataDictionary:(nonnull NSDictionary*)dataDictionary; ++(nonnull instancetype)stubUnauthorizedEvent; ++(nonnull instancetype)stubErrorEvent; @end diff --git a/DarklyTests/Categories/LDEvent+Testable.m b/DarklyTests/Categories/LDEvent+Testable.m index 9e3ebe07..0a22a0ca 100644 --- a/DarklyTests/Categories/LDEvent+Testable.m +++ b/DarklyTests/Categories/LDEvent+Testable.m @@ -7,9 +7,35 @@ // #import "LDEvent+Testable.h" +#import "LDEvent+EventTypes.h" #import "DarklyConstants.h" +#import "NSJSONSerialization+Testable.h" +#import "NSDictionary+JSON.h" @implementation LDEvent(Testable) ++(instancetype)stubPingEvent{ + LDEvent *event = [LDEvent new]; + event.event = kLDEventTypePing; + event.readyState = kEventStateOpen; + return event; +} + ++(instancetype)stubEvent:(NSString*)eventType fromJsonFileNamed:(NSString*)fileName { + LDEvent *event = [LDEvent new]; + event.event = eventType; + event.readyState = kEventStateOpen; + event.data = [NSJSONSerialization jsonStringFromFileNamed:fileName]; + return event; +} + ++(instancetype)stubEvent:(NSString*)eventType withDataDictionary:(NSDictionary*)dataDictionary { + LDEvent *event = [LDEvent new]; + event.event = eventType; + event.readyState = kEventStateOpen; + event.data = [dataDictionary jsonString]; + return event; +} + +(instancetype)stubUnauthorizedEvent { NSError *error = [NSError errorWithDomain:LDEventSourceErrorDomain code:kErrorCodeUnauthorized userInfo:nil]; LDEvent *event = [LDEvent new]; diff --git a/DarklyTests/Categories/LDFlagConfigModel+Testable.h b/DarklyTests/Categories/LDFlagConfigModel+Testable.h index 12c573d8..c161d74b 100644 --- a/DarklyTests/Categories/LDFlagConfigModel+Testable.h +++ b/DarklyTests/Categories/LDFlagConfigModel+Testable.h @@ -10,4 +10,8 @@ @interface LDFlagConfigModel(Testable) +(instancetype)flagConfigFromJsonFileNamed:(NSString *)fileName; ++(NSDictionary*)patchFromJsonFileNamed:(NSString *)fileName useVersion:(NSInteger)version; ++(NSDictionary*)patchFromJsonFileNamed:(NSString *)fileName omitKey:(NSString*)key; ++(NSDictionary*)deleteFromJsonFileNamed:(NSString *)fileName useVersion:(NSInteger)version; ++(NSDictionary*)deleteFromJsonFileNamed:(NSString *)fileName omitKey:(NSString*)key; @end diff --git a/DarklyTests/Categories/LDFlagConfigModel+Testable.m b/DarklyTests/Categories/LDFlagConfigModel+Testable.m index 6713364d..d38e1982 100644 --- a/DarklyTests/Categories/LDFlagConfigModel+Testable.m +++ b/DarklyTests/Categories/LDFlagConfigModel+Testable.m @@ -8,18 +8,32 @@ #import "LDFlagConfigModel.h" #import "LDFlagConfigModel+Testable.h" +#import "NSJSONSerialization+Testable.h" + +extern NSString * _Nonnull const kLDFlagConfigJsonDictionaryKeyVersion; @implementation LDFlagConfigModel(Testable) +(instancetype)flagConfigFromJsonFileNamed:(NSString *)fileName { - NSString *filepath; - for (NSBundle *bundle in [[NSBundle allBundles] copy]) { - filepath = [bundle pathForResource:fileName ofType:@"json"]; - if (filepath) { break; } - } - if (!filepath) { return nil; } - NSData *data = [NSData dataWithContentsOfFile:filepath]; - if (!data) { return nil; } - NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; - return [[LDFlagConfigModel alloc] initWithDictionary:jsonDictionary]; + return [[LDFlagConfigModel alloc] initWithDictionary:[NSJSONSerialization jsonObjectFromFileNamed:fileName]]; +} + ++(NSDictionary*)patchFromJsonFileNamed:(NSString *)fileName useVersion:(NSInteger)version { + NSMutableDictionary *patch = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization jsonObjectFromFileNamed:fileName]]; + patch[kLDFlagConfigJsonDictionaryKeyVersion] = @(version); + return patch; +} + ++(NSDictionary*)patchFromJsonFileNamed:(NSString *)fileName omitKey:(NSString*)key { + NSMutableDictionary *patch = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization jsonObjectFromFileNamed:fileName]]; + patch[key] = nil; + return patch; +} + ++(NSDictionary*)deleteFromJsonFileNamed:(NSString *)fileName useVersion:(NSInteger)version { + return [LDFlagConfigModel patchFromJsonFileNamed:fileName useVersion:version]; +} + ++(NSDictionary*)deleteFromJsonFileNamed:(NSString *)fileName omitKey:(NSString*)key { + return [LDFlagConfigModel patchFromJsonFileNamed:fileName omitKey:key]; } @end diff --git a/DarklyTests/Categories/LDUserModel+Equatable.m b/DarklyTests/Categories/LDUserModel+Equatable.m index 7cfedaae..a530284a 100644 --- a/DarklyTests/Categories/LDUserModel+Equatable.m +++ b/DarklyTests/Categories/LDUserModel+Equatable.m @@ -120,7 +120,7 @@ -(BOOL)matchesDictionary:(NSDictionary *)dictionary includeFlags:(BOOL)includeCo NSDictionary *dictionaryConfig = dictionary[kUserAttributeConfig]; if (includeConfig) { - NSDictionary *config = self.config.featuresJsonDictionary; + NSDictionary *config = [self.config dictionaryValueIncludeNulls:NO]; if ( (config && ![config isEqual:dictionaryConfig]) || (!config && dictionaryConfig) ) { NSLog(matchingFailureReason, kUserAttributeConfig); return NO; diff --git a/DarklyTests/Categories/LDUserModel+Stub.m b/DarklyTests/Categories/LDUserModel+Stub.m index 02fc42eb..c7c98016 100644 --- a/DarklyTests/Categories/LDUserModel+Stub.m +++ b/DarklyTests/Categories/LDUserModel+Stub.m @@ -35,7 +35,7 @@ +(instancetype)stubWithKey:(NSString*)key { stub.email = userModelStubEmail; stub.avatar = userModelStubAvatar; stub.custom = [LDUserModel customStub]; - stub.config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"userStubFlags"]; + stub.config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-excludeNulls-withVersions"]; return stub; } diff --git a/DarklyTests/Categories/NSDictionary+Testable.h b/DarklyTests/Categories/NSDictionary+Testable.h new file mode 100644 index 00000000..a4a5a3a3 --- /dev/null +++ b/DarklyTests/Categories/NSDictionary+Testable.h @@ -0,0 +1,15 @@ +// +// NSDictionary+Testable.h +// DarklyTests +// +// Created by Mark Pokorny on 1/25/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import +#import "NSObject+Testable.h" + +@interface NSDictionary(Testable) +-(BOOL)boolValueForKey:(nullable NSString*)key; +-(NSInteger)integerValueForKey:(nullable NSString*)key; +@end diff --git a/DarklyTests/Categories/NSDictionary+Testable.m b/DarklyTests/Categories/NSDictionary+Testable.m new file mode 100644 index 00000000..674c83e2 --- /dev/null +++ b/DarklyTests/Categories/NSDictionary+Testable.m @@ -0,0 +1,19 @@ +// +// NSDictionary+Testable.m +// DarklyTests +// +// Created by Mark Pokorny on 1/25/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import "NSDictionary+Testable.h" + +@implementation NSDictionary(Testable) +-(BOOL)boolValueForKey:(NSString*)key { + return [self[key] boolValue]; +} + +-(NSInteger)integerValueForKey:(nullable NSString*)key { + return [self[key] integerValue]; +} +@end diff --git a/DarklyTests/Categories/NSObject+Testable.h b/DarklyTests/Categories/NSObject+Testable.h new file mode 100644 index 00000000..489ee34e --- /dev/null +++ b/DarklyTests/Categories/NSObject+Testable.h @@ -0,0 +1,14 @@ +// +// NSObject+Testable.h +// DarklyTests +// +// Created by Mark Pokorny on 1/25/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import + +@interface NSObject(Testable) +-(BOOL)boolValue; +-(NSInteger)integerValue; +@end diff --git a/DarklyTests/Categories/NSObject+Testable.m b/DarklyTests/Categories/NSObject+Testable.m new file mode 100644 index 00000000..83e922f4 --- /dev/null +++ b/DarklyTests/Categories/NSObject+Testable.m @@ -0,0 +1,23 @@ +// +// NSObject+Testable.m +// DarklyTests +// +// Created by Mark Pokorny on 1/25/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import "NSObject+Testable.h" + +@implementation NSObject(Testable) +-(BOOL)boolValue { + NSNumber *numberValue = (NSNumber*)self; + if (!numberValue) { return false; } + return [numberValue boolValue]; +} + +-(NSInteger)integerValue { + NSNumber *numberValue = (NSNumber*)self; + if (!numberValue) { return INT_MIN; } + return [numberValue integerValue]; +} +@end diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArray-1.json b/DarklyTests/Fixtures/arrayConfigIsAnArray-1.json index 2c0bea0f..77a91ea8 100644 --- a/DarklyTests/Fixtures/arrayConfigIsAnArray-1.json +++ b/DarklyTests/Fixtures/arrayConfigIsAnArray-1.json @@ -1,3 +1,6 @@ { - "isAnArray":[1] + "isAnArray": { + "value": [1], + "version": 4 + } } diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withVersion.json b/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withVersion.json new file mode 100644 index 00000000..37c8a19d --- /dev/null +++ b/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withVersion.json @@ -0,0 +1,6 @@ +{ + "isAnArray": { + "value": [1,2,3], + "version": 5 + } +} diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withoutVersion.json b/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withoutVersion.json new file mode 100644 index 00000000..348ca26e --- /dev/null +++ b/DarklyTests/Fixtures/arrayConfigIsAnArray-123-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isAnArray": [1,2,3] +} diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArray-123.json b/DarklyTests/Fixtures/arrayConfigIsAnArray-123.json deleted file mode 100644 index 9284ecdd..00000000 --- a/DarklyTests/Fixtures/arrayConfigIsAnArray-123.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isAnArray":[1,2,3] -} diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArray-Empty.json b/DarklyTests/Fixtures/arrayConfigIsAnArray-Empty.json index 26f53691..6d38a093 100644 --- a/DarklyTests/Fixtures/arrayConfigIsAnArray-Empty.json +++ b/DarklyTests/Fixtures/arrayConfigIsAnArray-Empty.json @@ -1,3 +1,6 @@ { - "isAnArray":[] + "isAnArray": { + "value": [], + "version": 3 + } } diff --git a/DarklyTests/Fixtures/arrayConfigIsAnArrayA-123.json b/DarklyTests/Fixtures/arrayConfigIsAnArrayA-123.json index eeb8bf2d..fc4545b3 100644 --- a/DarklyTests/Fixtures/arrayConfigIsAnArrayA-123.json +++ b/DarklyTests/Fixtures/arrayConfigIsAnArrayA-123.json @@ -1,3 +1,6 @@ { - "isAnArrayA":[1,2,3] + "isAnArrayA": { + "value": [1,2,3], + "version": 3 + } } diff --git a/DarklyTests/Fixtures/boolConfigIsABool-false.json b/DarklyTests/Fixtures/boolConfigIsABool-false.json index 3b157c32..8b8e371d 100644 --- a/DarklyTests/Fixtures/boolConfigIsABool-false.json +++ b/DarklyTests/Fixtures/boolConfigIsABool-false.json @@ -1,3 +1,6 @@ { - "isABool":false + "isABool": { + "value": false, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/boolConfigIsABool-true-withVersion.json b/DarklyTests/Fixtures/boolConfigIsABool-true-withVersion.json new file mode 100644 index 00000000..1c416808 --- /dev/null +++ b/DarklyTests/Fixtures/boolConfigIsABool-true-withVersion.json @@ -0,0 +1,6 @@ +{ + "isABool": { + "value": true, + "version": 4 + } +} diff --git a/DarklyTests/Fixtures/boolConfigIsABool-true-withoutVersion.json b/DarklyTests/Fixtures/boolConfigIsABool-true-withoutVersion.json new file mode 100644 index 00000000..2d851959 --- /dev/null +++ b/DarklyTests/Fixtures/boolConfigIsABool-true-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isABool": true +} diff --git a/DarklyTests/Fixtures/boolConfigIsABool-true.json b/DarklyTests/Fixtures/boolConfigIsABool-true.json deleted file mode 100644 index c40ccdd0..00000000 --- a/DarklyTests/Fixtures/boolConfigIsABool-true.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isABool":true -} diff --git a/DarklyTests/Fixtures/boolConfigIsABool2-true.json b/DarklyTests/Fixtures/boolConfigIsABool2-true.json index cc2cf58b..374c5769 100644 --- a/DarklyTests/Fixtures/boolConfigIsABool2-true.json +++ b/DarklyTests/Fixtures/boolConfigIsABool2-true.json @@ -1,3 +1,6 @@ { - "isABool2":true + "isABool2": { + "value": true, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withVersion.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withVersion.json new file mode 100644 index 00000000..ee53482d --- /dev/null +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withVersion.json @@ -0,0 +1,12 @@ +{ + "isADictionary": { + "value": { + "keyA": true, + "keyB": [1, 2, 3], + "keyC": { + "keyD": "someStringValue" + } + }, + "version": 4 + } +} diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withoutVersion.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withoutVersion.json new file mode 100644 index 00000000..ea01a201 --- /dev/null +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key-withoutVersion.json @@ -0,0 +1,9 @@ +{ + "isADictionary": { + "keyA": true, + "keyB": [1, 2, 3], + "keyC": { + "keyD": "someStringValue" + } + } +} diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key.json deleted file mode 100644 index 7b1c66c6..00000000 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-3Key.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isADictionary":{"keyA":true,"keyB":[1,2,3],"keyC":{"keyD":"someStringValue"}} -} diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-Empty.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-Empty.json index 13d107dc..a0104819 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-Empty.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-Empty.json @@ -1,3 +1,10 @@ { "isADictionary":{} } +{ + "isADictionary": { + "value": {} + }, + "version": 3 + } +} diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyA.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyA.json index 03f2974c..49987b7f 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyA.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyA.json @@ -1,3 +1,8 @@ { - "isADictionary":{"keyA":true} + "isADictionary": { + "value": { + "keyA": true + }, + "version": 5 + } } diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB-124.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB-124.json index f9ba663f..d13c2033 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB-124.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB-124.json @@ -1,3 +1,8 @@ { - "isADictionary":{"keyB”:[1,2,4]} + "isADictionary": { + "value": { + "keyB": [1, 2, 4] + }, + "version": 5 + } } diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB.json index db88fd38..5cc60a10 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyB.json @@ -1,3 +1,8 @@ { - "isADictionary":{"keyB":[1,2,3]} + "isADictionary": { + "value": { + "keyB": [1, 2, 3] + }, + "version": 5 + } } diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json index a9634a3a..c97ede1f 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC-keyDValueDiffers.json @@ -1,3 +1,10 @@ { - "isADictionary":{"keyC":{"keyD":"someStringValueA"}} + "isADictionary": { + "value": { + "keyC": { + "keyD": "someStringValueA" + } + }, + "version": 5 + } } diff --git a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC.json b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC.json index 6f7448bb..a17be9c7 100644 --- a/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC.json +++ b/DarklyTests/Fixtures/dictionaryConfigIsADictionary-KeyC.json @@ -1,3 +1,10 @@ { - "isADictionary":{"keyC":{"keyD":"someStringValue"}} + "isADictionary": { + "value": { + "keyC": { + "keyD": "someStringValue" + } + }, + "version": 5 + } } diff --git a/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withVersion.json b/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withVersion.json new file mode 100644 index 00000000..72b10aa0 --- /dev/null +++ b/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withVersion.json @@ -0,0 +1,6 @@ +{ + "isADouble": { + "value": 3.141592653589793238462643383279502884197169399375105820974944592307816406286, + "version": 3 + } +} diff --git a/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withoutVersion.json b/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withoutVersion.json new file mode 100644 index 00000000..eabc5428 --- /dev/null +++ b/DarklyTests/Fixtures/doubleConfigIsADouble-Pi-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isADouble": 3.141592653589793238462643383279502884197169399375105820974944592307816406286 +} diff --git a/DarklyTests/Fixtures/doubleConfigIsADouble-Pi.json b/DarklyTests/Fixtures/doubleConfigIsADouble-Pi.json deleted file mode 100644 index 421128fc..00000000 --- a/DarklyTests/Fixtures/doubleConfigIsADouble-Pi.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isADouble":3.141592653589793238462643383279502884197169399375105820974944592307816406286 -} diff --git a/DarklyTests/Fixtures/featureFlags-excludeNulls-withVersions.json b/DarklyTests/Fixtures/featureFlags-excludeNulls-withVersions.json new file mode 100644 index 00000000..a3be7742 --- /dev/null +++ b/DarklyTests/Fixtures/featureFlags-excludeNulls-withVersions.json @@ -0,0 +1,35 @@ +{ + "_links": { + "value": { + "href": "/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", + "type": "application/json" + }, + "version": 2 + }, + "devices.hasipad": { + "value": false, + "version": 2 + }, + "isAString": { + "value": "test", + "version": 2 + }, + "isAArray": { + "value": [0, 1, 2], + "version": 2 + }, + "isAObject": { + "value": { + "key": 0 + }, + "version": 2 + }, + "isANumber": { + "value": 0, + "version": 2 + }, + "isABawler": { + "value": true, + "version": 2 + } +} diff --git a/DarklyTests/Fixtures/featureFlags-excludeNulls-withoutVersions.json b/DarklyTests/Fixtures/featureFlags-excludeNulls-withoutVersions.json new file mode 100644 index 00000000..acaafef7 --- /dev/null +++ b/DarklyTests/Fixtures/featureFlags-excludeNulls-withoutVersions.json @@ -0,0 +1,14 @@ +{ + "_links": { + "href": "/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", + "type": "application/json" + }, + "devices.hasipad": false, + "isAString": "test", + "isAArray": [0, 1, 2], + "isAObject": { + "key": 0 + }, + "isANumber": 0, + "isABawler": true +} diff --git a/DarklyTests/Fixtures/featureFlags-withVersions.json b/DarklyTests/Fixtures/featureFlags-withVersions.json new file mode 100644 index 00000000..7f540606 --- /dev/null +++ b/DarklyTests/Fixtures/featureFlags-withVersions.json @@ -0,0 +1,39 @@ +{ + "_links": { + "value": { + "href": "/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", + "type": "application/json" + }, + "version": 2 + }, + "devices.hasipad": { + "value": false, + "version": 2 + }, + "isConnected": { + "value": null, + "version": 2 + }, + "isAString": { + "value": "test", + "version": 2 + }, + "isAArray": { + "value": [0, 1, 2], + "version": 2 + }, + "isAObject": { + "value": { + "key": 0 + }, + "version": 2 + }, + "isANumber": { + "value": 0, + "version": 2 + }, + "isABawler": { + "value": true, + "version": 2 + } +} diff --git a/DarklyTests/Fixtures/featureFlags-withoutVersions.json b/DarklyTests/Fixtures/featureFlags-withoutVersions.json new file mode 100644 index 00000000..3c15489e --- /dev/null +++ b/DarklyTests/Fixtures/featureFlags-withoutVersions.json @@ -0,0 +1,15 @@ +{ + "_links": { + "href": "/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", + "type": "application/json" + }, + "devices.hasipad": false, + "isConnected": null, + "isAString": "test", + "isAArray": [0, 1, 2], + "isAObject": { + "key": 0 + }, + "isANumber": 0, + "isABawler": true +} diff --git a/DarklyTests/Fixtures/feature_flags.json b/DarklyTests/Fixtures/feature_flags.json deleted file mode 100644 index f499189c..00000000 --- a/DarklyTests/Fixtures/feature_flags.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "_links": - { - "href":"/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", - "type":"application/json" - }, - "devices.hasipad":false, - "isConnected":null, - "isAString":"test", - "isAArray":[0,1,2], - "isAObject": - { - "key": 0 - }, - "isANumber":0, - "isABawler":true -} diff --git a/DarklyTests/Fixtures/ldClientManagerTestConfigA.json b/DarklyTests/Fixtures/ldClientManagerTestConfigA.json index 503d97fd..0b501661 100644 --- a/DarklyTests/Fixtures/ldClientManagerTestConfigA.json +++ b/DarklyTests/Fixtures/ldClientManagerTestConfigA.json @@ -1,11 +1,32 @@ { - "ddeefe": false, - "main-slider": false, - "new-feature": false, - "new-gallery": { - "foo": 2 - }, - "one-click-checkout": false, - "shopping-cart": 20, - "social-icon-toggle": false + "ddeefe": { + "value": false, + "version": 3 + }, + "main-slider": { + "value": false, + "version": 3 + }, + "new-feature": { + "value": false, + "version": 3 + }, + "new-gallery": { + "value": { + "foo": 2 + }, + "version": 3 + }, + "one-click-checkout": { + "value": false, + "version": 3 + }, + "shopping-cart": { + "value": 20, + "version": 3 + }, + "social-icon-toggle": { + "value": false, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/ldClientManagerTestConfigB.json b/DarklyTests/Fixtures/ldClientManagerTestConfigB.json index e5e44b6f..98281a99 100644 --- a/DarklyTests/Fixtures/ldClientManagerTestConfigB.json +++ b/DarklyTests/Fixtures/ldClientManagerTestConfigB.json @@ -1,11 +1,32 @@ { - "ddeefe": false, - "main-slider": false, - "new-feature": true, - "new-gallery": { - "foo": 2 - }, - "one-click-checkout": false, - "shopping-cart": 20, - "social-icon-toggle": false + "ddeefe": { + "value": false, + "version": 3 + }, + "main-slider": { + "value": false, + "version": 3 + }, + "new-feature": { + "value": true, + "version": 4 + }, + "new-gallery": { + "value": { + "foo": 2 + }, + "version": 3 + }, + "one-click-checkout": { + "value": false, + "version": 3 + }, + "shopping-cart": { + "value": 20, + "version": 3 + }, + "social-icon-toggle": { + "value": false, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/ldClientManagerTestDeleteIsANumber.json b/DarklyTests/Fixtures/ldClientManagerTestDeleteIsANumber.json new file mode 100644 index 00000000..8998caef --- /dev/null +++ b/DarklyTests/Fixtures/ldClientManagerTestDeleteIsANumber.json @@ -0,0 +1,5 @@ +{ + "key": "isANumber", + "value": 8675309, + "version": 3 +} diff --git a/DarklyTests/Fixtures/ldClientManagerTestPatchIsANumber.json b/DarklyTests/Fixtures/ldClientManagerTestPatchIsANumber.json new file mode 100644 index 00000000..31cae209 --- /dev/null +++ b/DarklyTests/Fixtures/ldClientManagerTestPatchIsANumber.json @@ -0,0 +1,4 @@ +{ + "key": "isANumber", + "version": 3 +} diff --git a/DarklyTests/Fixtures/ldDataManagerTestConfig.json b/DarklyTests/Fixtures/ldDataManagerTestConfig.json new file mode 100644 index 00000000..dbe81959 --- /dev/null +++ b/DarklyTests/Fixtures/ldDataManagerTestConfig.json @@ -0,0 +1,10 @@ +{ + "iosuser": { + "value": false, + "version": 2 + }, + "ipaduser": { + "value": true, + "version": 2 + } +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelDeleteNewFlag.json b/DarklyTests/Fixtures/ldFlagConfigModelDeleteNewFlag.json new file mode 100644 index 00000000..c02cfcaf --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelDeleteNewFlag.json @@ -0,0 +1,4 @@ +{ + "key": "someNewFlag", + "version": 1 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelDeleteVersion2Flag.json b/DarklyTests/Fixtures/ldFlagConfigModelDeleteVersion2Flag.json new file mode 100644 index 00000000..7f268ee4 --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelDeleteVersion2Flag.json @@ -0,0 +1,4 @@ +{ + "key": "version2Flag", + "version": 3 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelPatchNewFlag.json b/DarklyTests/Fixtures/ldFlagConfigModelPatchNewFlag.json new file mode 100644 index 00000000..0b0bcfca --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelPatchNewFlag.json @@ -0,0 +1,5 @@ +{ + "key": "someNewFlag", + "value": true, + "version": 1 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion1Flag.json b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion1Flag.json new file mode 100644 index 00000000..32f05e3e --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion1Flag.json @@ -0,0 +1,5 @@ +{ + "key": "version1Flag", + "value": true, + "version": 2 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2Flag.json b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2Flag.json new file mode 100644 index 00000000..83a1f2a2 --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2Flag.json @@ -0,0 +1,5 @@ +{ + "key": "version2Flag", + "value": "version2patched", + "version": 3 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2FlagWithNull.json b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2FlagWithNull.json new file mode 100644 index 00000000..7d27f409 --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelPatchVersion2FlagWithNull.json @@ -0,0 +1,5 @@ +{ + "key": "version2Flag", + "value": null, + "version": 3 +} diff --git a/DarklyTests/Fixtures/ldFlagConfigModelTest.json b/DarklyTests/Fixtures/ldFlagConfigModelTest.json new file mode 100644 index 00000000..0419c53f --- /dev/null +++ b/DarklyTests/Fixtures/ldFlagConfigModelTest.json @@ -0,0 +1,14 @@ +{ + "version1Flag": { + "value": false, + "version": 1 + }, + "version2Flag": { + "value": "version2", + "version": 2 + }, + "version3Flag": { + "value": 3, + "version": 3 + } +} diff --git a/DarklyTests/Fixtures/nullConfigIsANull-null-withVersion.json b/DarklyTests/Fixtures/nullConfigIsANull-null-withVersion.json new file mode 100644 index 00000000..55730335 --- /dev/null +++ b/DarklyTests/Fixtures/nullConfigIsANull-null-withVersion.json @@ -0,0 +1,6 @@ +{ + "isANull": { + "value": null, + "version": 2 + } +} diff --git a/DarklyTests/Fixtures/nullConfigIsANull-null-withoutVersion.json b/DarklyTests/Fixtures/nullConfigIsANull-null-withoutVersion.json new file mode 100644 index 00000000..ade66043 --- /dev/null +++ b/DarklyTests/Fixtures/nullConfigIsANull-null-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isANull": null +} diff --git a/DarklyTests/Fixtures/numberConfigIsANumber-1.json b/DarklyTests/Fixtures/numberConfigIsANumber-1.json index 9c850282..1056c3bd 100644 --- a/DarklyTests/Fixtures/numberConfigIsANumber-1.json +++ b/DarklyTests/Fixtures/numberConfigIsANumber-1.json @@ -1,3 +1,6 @@ { - "isANumber":1 + "isANumber": { + "value": 1, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/numberConfigIsANumber-2-withVersion.json b/DarklyTests/Fixtures/numberConfigIsANumber-2-withVersion.json new file mode 100644 index 00000000..43064bfb --- /dev/null +++ b/DarklyTests/Fixtures/numberConfigIsANumber-2-withVersion.json @@ -0,0 +1,6 @@ +{ + "isANumber": { + "value": 2, + "version": 4 + } +} diff --git a/DarklyTests/Fixtures/numberConfigIsANumber-2-withoutVersion.json b/DarklyTests/Fixtures/numberConfigIsANumber-2-withoutVersion.json new file mode 100644 index 00000000..a16d79b4 --- /dev/null +++ b/DarklyTests/Fixtures/numberConfigIsANumber-2-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isANumber": 2 +} diff --git a/DarklyTests/Fixtures/numberConfigIsANumber-2.json b/DarklyTests/Fixtures/numberConfigIsANumber-2.json deleted file mode 100644 index bcd44f2f..00000000 --- a/DarklyTests/Fixtures/numberConfigIsANumber-2.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isANumber":2 -} diff --git a/DarklyTests/Fixtures/numberConfigIsANumber2-1.json b/DarklyTests/Fixtures/numberConfigIsANumber2-1.json index 33accdbe..21964519 100644 --- a/DarklyTests/Fixtures/numberConfigIsANumber2-1.json +++ b/DarklyTests/Fixtures/numberConfigIsANumber2-1.json @@ -1,3 +1,6 @@ { - "isANumber2”:1 + "isANumber2": { + "value": 1, + "version": 3 + } } diff --git a/DarklyTests/Fixtures/stringConfigIsAString-someString-withVersion.json b/DarklyTests/Fixtures/stringConfigIsAString-someString-withVersion.json new file mode 100644 index 00000000..20aff5bf --- /dev/null +++ b/DarklyTests/Fixtures/stringConfigIsAString-someString-withVersion.json @@ -0,0 +1,6 @@ +{ + "isAString": { + "value": "someString", + "version": 3 + } +} diff --git a/DarklyTests/Fixtures/stringConfigIsAString-someString-withoutVersion.json b/DarklyTests/Fixtures/stringConfigIsAString-someString-withoutVersion.json new file mode 100644 index 00000000..36d0761d --- /dev/null +++ b/DarklyTests/Fixtures/stringConfigIsAString-someString-withoutVersion.json @@ -0,0 +1,3 @@ +{ + "isAString": "someString" +} diff --git a/DarklyTests/Fixtures/stringConfigIsAString-someString.json b/DarklyTests/Fixtures/stringConfigIsAString-someString.json deleted file mode 100644 index 9460a280..00000000 --- a/DarklyTests/Fixtures/stringConfigIsAString-someString.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "isAString":"someString" -} diff --git a/DarklyTests/Fixtures/stringConfigIsAString-someStringA.json b/DarklyTests/Fixtures/stringConfigIsAString-someStringA.json index 2a28b30f..2b7fb193 100644 --- a/DarklyTests/Fixtures/stringConfigIsAString-someStringA.json +++ b/DarklyTests/Fixtures/stringConfigIsAString-someStringA.json @@ -1,3 +1,6 @@ { - "isAString":"someStringA" + "isAString": { + "value": "someStringA", + "version": 4 + } } diff --git a/DarklyTests/Fixtures/stringConfigIsAStringA-someString.json b/DarklyTests/Fixtures/stringConfigIsAStringA-someString.json index 64203312..68dd2359 100644 --- a/DarklyTests/Fixtures/stringConfigIsAStringA-someString.json +++ b/DarklyTests/Fixtures/stringConfigIsAStringA-someString.json @@ -1,3 +1,6 @@ { - "isAStringA":"someString" + "isAStringA": { + "value": "someString", + "version": 3 + } } diff --git a/DarklyTests/Fixtures/userStubFlags.json b/DarklyTests/Fixtures/userStubFlags.json deleted file mode 100644 index 7a6576d2..00000000 --- a/DarklyTests/Fixtures/userStubFlags.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "_links": - { - "href":"/api/eval/users/eyJrZXkiOiAiamVmZkB0ZXN0LmNvbSJ9", - "type":"application/json" - }, - "devices.hasipad":false, - "isAString":"test", - "isAArray":[0,1,2], - "isAObject": - { - "key": 0 - }, - "isANumber":0, - "isABawler":true -} diff --git a/DarklyTests/LDClientManagerTest.m b/DarklyTests/LDClientManagerTest.m index 7362507a..fcc6cb81 100644 --- a/DarklyTests/LDClientManagerTest.m +++ b/DarklyTests/LDClientManagerTest.m @@ -13,10 +13,17 @@ #import "LDEventModel.h" #import "LDClientManager+EventSource.h" #import "LDEvent+Testable.h" +#import "LDEvent+EventTypes.h" #import "LDFlagConfigModel+Testable.h" +#import "LDUserModel+Stub.h" #import "NSJSONSerialization+Testable.h" #import "LDUserModel+Equatable.h" +extern NSString * _Nonnull const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString * _Nonnull const kLDFlagConfigJsonDictionaryKeyVersion; +extern NSString * _Nonnull const kLDClientManagerStreamMethod; + + NSString *const mockMobileKey = @"mockMobileKey"; NSString *const kFeaturesJsonDictionary = @"featuresJsonDictionary"; NSString *const kBoolFlagKey = @"isABawler"; @@ -27,6 +34,7 @@ @interface LDClientManagerTest : DarklyXCTestCase @property (nonatomic) id dataManagerMock; @property (nonatomic) id pollingManagerMock; @property (nonatomic) id eventSourceMock; +@property (nonatomic, strong) void (^cleanup)(void); @end @implementation LDClientManagerTest @@ -39,9 +47,7 @@ @implementation LDClientManagerTest - (void)setUp { [super setUp]; - LDUserModel *user = [[LDUserModel alloc] init]; - user.key = [[NSUUID UUID] UUIDString]; - user.email = @"jeff@test.com"; + LDUserModel *user = [LDUserModel stubWithKey:[[NSUUID UUID] UUIDString]]; LDConfig *config = [[LDConfig alloc] initWithMobileKey:mockMobileKey]; @@ -60,16 +66,18 @@ - (void)setUp { OCMStub(ClassMethod([pollingManagerMock sharedInstance])).andReturn(pollingManagerMock); eventSourceMock = OCMClassMock([LDEventSource class]); - OCMStub(ClassMethod([eventSourceMock eventSourceWithURL:[OCMArg any] httpHeaders:[OCMArg any]])).andReturn(eventSourceMock); + OCMStub(ClassMethod([eventSourceMock eventSourceWithURL:[OCMArg any] httpHeaders:[OCMArg any] connectMethod:[OCMArg any] connectBody:[OCMArg any]])).andReturn(eventSourceMock); } - (void)tearDown { + if (self.cleanup) { self.cleanup(); } [LDClientManager sharedInstance].online = NO; [ldClientMock stopMocking]; [requestManagerMock stopMocking]; [dataManagerMock stopMocking]; [pollingManagerMock stopMocking]; [eventSourceMock stopMocking]; + self.cleanup = nil; ldClientMock = nil; requestManagerMock = nil; dataManagerMock = nil; @@ -78,6 +86,74 @@ - (void)tearDown { [super tearDown]; } +- (void)testEventSourceConfiguredToConnectUsingGetMethod { + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + LDUserModel *user = [LDClient sharedInstance].ldUser; + NSString *encodedUser = [LDUtil base64UrlEncodeString:[[user dictionaryValueWithPrivateAttributesAndFlagConfig:NO] jsonString]]; + + __block NSURL *streamUrl; + __block NSString *streamConnectMethod; + __block NSData *streamConnectData; + OCMVerify([eventSourceMock eventSourceWithURL:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSURL class]]) { return NO; } + streamUrl = obj; + return YES; + }] httpHeaders:[OCMArg any] connectMethod:[OCMArg checkWithBlock:^BOOL(id obj) { + if (obj && ![obj isKindOfClass:[NSString class]]) { return NO; } + streamConnectMethod = obj; + return YES; + }] connectBody:[OCMArg checkWithBlock:^BOOL(id obj) { + if (obj && ![obj isKindOfClass:[NSData class]]) { return NO; } + streamConnectData = obj; + return YES; + }]]); + XCTAssertTrue([[streamUrl pathComponents] containsObject:kLDClientManagerStreamMethod]); + XCTAssertFalse([[streamUrl pathComponents] containsObject:@"mping"]); + XCTAssertTrue([[streamUrl lastPathComponent] isEqualToString:encodedUser]); + XCTAssertTrue(streamConnectMethod == nil || [streamConnectMethod isEqualToString:@"GET"]); + XCTAssertNil(streamConnectData); +} + +- (void)testEventSourceConfiguredToConnectUsingReportMethod { + LDConfig *config = [LDClient sharedInstance].ldConfig; + config.useReport = YES; + LDUserModel *user = [LDClient sharedInstance].ldUser; + + [ldClientMock stopMocking]; + ldClientMock = OCMClassMock([LDClient class]); + OCMStub(ClassMethod([ldClientMock sharedInstance])).andReturn(ldClientMock); + OCMStub([ldClientMock ldUser]).andReturn(user); + OCMStub([ldClientMock ldConfig]).andReturn(config); + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + NSData *encodedUserData = [[[user dictionaryValueWithPrivateAttributesAndFlagConfig:NO] jsonString] dataUsingEncoding:NSUTF8StringEncoding]; + + __block NSURL *streamUrl; + __block NSString *streamConnectMethod; + __block NSData *streamConnectData; + OCMVerify([eventSourceMock eventSourceWithURL:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSURL class]]) { return NO; } + streamUrl = obj; + return YES; + }] httpHeaders:[OCMArg any] connectMethod:[OCMArg checkWithBlock:^BOOL(id obj) { + if (obj && ![obj isKindOfClass:[NSString class]]) { return NO; } + streamConnectMethod = obj; + return YES; + }] connectBody:[OCMArg checkWithBlock:^BOOL(id obj) { + if (obj && ![obj isKindOfClass:[NSData class]]) { return NO; } + streamConnectData = obj; + return YES; + }]]); + XCTAssertTrue([[streamUrl lastPathComponent] isEqualToString:kLDClientManagerStreamMethod]); + XCTAssertFalse([[streamUrl pathComponents] containsObject:@"mping"]); + XCTAssertTrue([streamConnectMethod isEqualToString:kHTTPMethodReport]); + XCTAssertTrue([streamConnectData isEqualToData:encodedUserData]); +} + - (void)testEventSourceCreatedOnStartPollingWhileOnline { LDClientManager *clientManager = [LDClientManager sharedInstance]; clientManager.online = YES; @@ -154,9 +230,8 @@ - (void)testSyncWithServerForConfigWhenUserExistsAndOnline { } - (void)testSyncWithServerForConfigWhenUserDoesNotExist { - [self mockClientWithUser:nil]; - XCTAssertNil([LDClient sharedInstance].ldUser); - + ldClientMock = [self mockClientWithUser:nil]; + [[requestManagerMock reject] performFeatureFlagRequest:[OCMArg any]]; LDClientManager *clientManager = [LDClientManager sharedInstance]; @@ -294,21 +369,26 @@ - (void)testProcessedConfigSuccessWithUserConfigChanged { id mockUserNoChangeObserver = OCMObserverMock(); //expect this NOT to be posted [[NSNotificationCenter defaultCenter] addMockObserver:mockUserNoChangeObserver name:kLDUserNoChangeNotification object:nil]; - LDFlagConfigModel *flagConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"feature_flags"]; + LDFlagConfigModel *flagConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; LDUserModel *user = [ldClientMock ldUser]; user.config = flagConfig; [[[ldClientMock expect] andReturn:user] ldUser]; - NSMutableDictionary *updatedFlags = [NSMutableDictionary dictionaryWithDictionary:flagConfig.featuresJsonDictionary]; - XCTAssertNotNil(updatedFlags[kBoolFlagKey]); - updatedFlags[kBoolFlagKey] = @(![updatedFlags[kBoolFlagKey] boolValue]); + NSMutableDictionary *updatedFlags = [NSMutableDictionary dictionaryWithDictionary:[flagConfig dictionaryValue]]; + NSMutableDictionary *updatedBoolFlag = [NSMutableDictionary dictionaryWithDictionary:updatedFlags[kBoolFlagKey]]; + updatedBoolFlag[kLDFlagConfigJsonDictionaryKeyValue] = @(![updatedBoolFlag[kLDFlagConfigJsonDictionaryKeyValue] boolValue]); + updatedBoolFlag[kLDFlagConfigJsonDictionaryKeyVersion] = @([updatedBoolFlag[kLDFlagConfigJsonDictionaryKeyVersion] integerValue] + 1); + updatedFlags[kBoolFlagKey] = updatedBoolFlag; [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:[updatedFlags copy]]; OCMVerify([dataManagerMock saveUser:[OCMArg any]]); OCMVerifyAll(mockUserUpdatedObserver); OCMVerifyAll(mockUserNoChangeObserver); + + [[NSNotificationCenter defaultCenter] removeObserver:mockUserUpdatedObserver]; + [[NSNotificationCenter defaultCenter] removeObserver:mockUserNoChangeObserver]; } - (void)testProcessedConfigSuccessWithUserConfigUnchanged { @@ -321,17 +401,20 @@ - (void)testProcessedConfigSuccessWithUserConfigUnchanged { [[dataManagerMock reject] saveUser:[OCMArg any]]; - LDFlagConfigModel *flagConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"feature_flags"]; + LDFlagConfigModel *flagConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; LDUserModel *user = [ldClientMock ldUser]; user.config = flagConfig; [[[ldClientMock expect] andReturn:user] ldUser]; - [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:[flagConfig.featuresJsonDictionary copy]]; + [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:[flagConfig dictionaryValue]]; OCMVerifyAll(dataManagerMock); OCMVerifyAll(mockUserUpdatedObserver); OCMVerifyAll(mockUserNoChangeObserver); + + [[NSNotificationCenter defaultCenter] removeObserver:mockUserUpdatedObserver]; + [[NSNotificationCenter defaultCenter] removeObserver:mockUserNoChangeObserver]; } - (void)testProcessedConfigSuccessWithoutUserConfig { @@ -359,7 +442,7 @@ - (void)testProcessedConfigSuccessWithUserSameUserConfig { LDUserModel *clientUser = [[LDClient sharedInstance] ldUser]; clientUser.config = startingConfig; - [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:startingConfig.featuresJsonDictionary]; + [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:[startingConfig dictionaryValue]]; XCTAssertTrue(clientUser.config == startingConfig); //Should be the same object, unchanged } @@ -373,7 +456,7 @@ - (void)testProcessedConfigSuccessWithUserDifferentUserConfig { LDFlagConfigModel *endingConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldClientManagerTestConfigB"]; XCTAssertNotNil(endingConfig); - [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:endingConfig.featuresJsonDictionary]; + [[LDClientManager sharedInstance] processedConfig:YES jsonConfigDictionary:[endingConfig dictionaryValue]]; XCTAssertFalse(clientUser.config == startingConfig); //Should not be the same object XCTAssertTrue([clientUser.config isEqualToConfig:endingConfig]); } @@ -438,6 +521,11 @@ - (void)testClientUnauthorizedPosted { return YES; }]]); + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:clientUnauthorizedObserver]; + [[NSNotificationCenter defaultCenter] removeObserver:serverUnavailableObserver]; + }; + LDClientManager *clientManager = [LDClientManager sharedInstance]; clientManager.online = YES; @@ -445,12 +533,8 @@ - (void)testClientUnauthorizedPosted { if (!errorHandler) { return; } errorHandler([LDEvent stubUnauthorizedEvent]); - [[NSNotificationCenter defaultCenter] removeObserver:clientUnauthorizedObserver]; [clientUnauthorizedObserver verify]; - [[NSNotificationCenter defaultCenter] removeObserver:serverUnavailableObserver]; [serverUnavailableObserver verify]; - - clientManager.online = NO; //Although LDClientManager.online = NO is in tearDown, setting it here allows following tests to not fail on errorHandler != nil } - (void)testClientUnauthorizedNotPosted { @@ -468,6 +552,11 @@ - (void)testClientUnauthorizedNotPosted { return YES; }]]); + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:clientUnauthorizedObserver]; + [[NSNotificationCenter defaultCenter] removeObserver:serverUnavailableObserver]; + }; + LDClientManager *clientManager = [LDClientManager sharedInstance]; clientManager.online = YES; @@ -475,104 +564,675 @@ - (void)testClientUnauthorizedNotPosted { if (!errorHandler) { return; } errorHandler([LDEvent stubErrorEvent]); - [[NSNotificationCenter defaultCenter] removeObserver:clientUnauthorizedObserver]; [clientUnauthorizedObserver verify]; - [[NSNotificationCenter defaultCenter] removeObserver:serverUnavailableObserver]; [serverUnavailableObserver verify]; +} + +- (void)testSSEPingEvent { + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; - clientManager.online = NO; //Although LDClientManager.online = NO is in tearDown, setting it here allows following tests to not fail on errorHandler != nil + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + messageHandler([LDEvent stubPingEvent]); + + OCMVerify([requestManagerMock performFeatureFlagRequest:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[LDUserModel class]]) { return NO; } + LDUserModel *userFromRequest = (LDUserModel*)obj; + return [user isEqual:userFromRequest]; + }]]); } --(void)testProcessedConfig_success_flagsChanged { - NSDictionary *flagConfigDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"feature_flags"]; - LDFlagConfigModel *targetFlagConfig = [[LDFlagConfigModel alloc] initWithDictionary:flagConfigDictionary]; +- (void)testSSEPutEventSuccess { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserUpdatedNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserUpdatedNotification object:[OCMArg any]]; - id userUpdatedObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userUpdatedObserver name:kLDUserUpdatedNotification object:nil]; - [[userUpdatedObserver expect] notificationWithName:kLDUserUpdatedNotification object:[OCMArg any]]; + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); - id userNoChangeObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userNoChangeObserver name:kLDUserNoChangeNotification object:nil]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + LDFlagConfigModel *targetFlagConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; - id connectionUnavailableObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:connectionUnavailableObserver name:kLDServerConnectionUnavailableNotification object:nil]; + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; - LDUserModel *user = [LDClient sharedInstance].ldUser; + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *put = [LDEvent stubEvent:kLDEventTypePut fromJsonFileNamed:@"featureFlags-withVersions"]; + + messageHandler(put); + XCTAssertTrue([user.config isEqualToConfig: targetFlagConfig]); __block LDUserModel *savedUser; - [[self.dataManagerMock expect] saveUser:[OCMArg checkWithBlock:^BOOL(id obj) { + OCMVerify([dataManagerMock saveUser:[OCMArg checkWithBlock:^BOOL(id obj) { if (![obj isKindOfClass:[LDUserModel class]]) { return NO; } savedUser = obj; return YES; + }]]); + XCTAssertTrue([savedUser.config isEqualToConfig:targetFlagConfig]); + OCMVerifyAll(notificationObserver); +} + +- (void)testSSEPutResultedInNoChange { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + __block NSDictionary *putDictionary; + [[flagConfigMock expect] addOrReplaceFromDictionary:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { return NO; } + putDictionary = obj; + return YES; }]]; + OCMStub([flagConfigMock isEqualToConfig:[OCMArg any]]).andReturn(YES); + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedConfig:YES jsonConfigDictionary:flagConfigDictionary]; + clientManager.online = YES; - XCTAssertTrue([user.config isEqualToConfig:targetFlagConfig]); - XCTAssertNotNil(savedUser); - XCTAssertTrue([savedUser isEqual:user ignoringAttributes:@[kUserAttributeConfig]]); - XCTAssertTrue([savedUser.config isEqualToConfig:targetFlagConfig]); + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + //NOTE: Because the flag config mock will return YES on a config comparison, the put here doesn't matter + LDEvent *put = [LDEvent stubEvent:kLDEventTypePut fromJsonFileNamed:@"featureFlags-withVersions"]; + + messageHandler(put); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPutEventFailedNilData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); - [userUpdatedObserver verify]; - [userNoChangeObserver verify]; - [connectionUnavailableObserver verify]; + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + LDFlagConfigModel *targetFlagConfig = user.config; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *put = [LDEvent stubEvent:kLDEventTypePut fromJsonFileNamed:@"featureFlags-withVersions"]; + put.data = nil; + + messageHandler(put); + + XCTAssertTrue([user.config isEqualToConfig: targetFlagConfig]); + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); } --(void)testProcessedConfig_success_flagsUnchanged { - NSDictionary *flagConfigDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"feature_flags"]; - LDFlagConfigModel *targetFlagConfig = [[LDFlagConfigModel alloc] initWithDictionary:flagConfigDictionary]; +- (void)testSSEPutEventFailedEmptyData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; - id userUpdatedObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userUpdatedObserver name:kLDUserUpdatedNotification object:nil]; + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); - id userNoChangeObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userNoChangeObserver name:kLDUserNoChangeNotification object:nil]; - [[userNoChangeObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + [[dataManagerMock reject] saveUser:[OCMArg any]]; - id connectionUnavailableObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:connectionUnavailableObserver name:kLDServerConnectionUnavailableNotification object:nil]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + LDFlagConfigModel *targetFlagConfig = user.config; - LDUserModel *user = [LDClient sharedInstance].ldUser; - user.config = targetFlagConfig; + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; - [[self.dataManagerMock reject] saveUser:[OCMArg any]]; + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *put = [LDEvent stubEvent:kLDEventTypePut fromJsonFileNamed:@"featureFlags-withVersions"]; + put.data = @""; + + messageHandler(put); + + XCTAssertTrue([user.config isEqualToConfig: targetFlagConfig]); + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPutEventFailedInvalidData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + LDFlagConfigModel *targetFlagConfig = user.config; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedConfig:YES jsonConfigDictionary:flagConfigDictionary]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *put = [LDEvent stubEvent:kLDEventTypePut fromJsonFileNamed:@"featureFlags-withVersions"]; + put.data = @"{\"someInvalidData\":}"; - XCTAssertTrue([user.config isEqualToConfig:targetFlagConfig]); + messageHandler(put); - [userUpdatedObserver verify]; - [userNoChangeObserver verify]; - [connectionUnavailableObserver verify]; + XCTAssertTrue([user.config isEqualToConfig: targetFlagConfig]); + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); } --(void)testProcessedConfig_failure { - NSDictionary *flagConfigDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"feature_flags"]; +- (void)testSSEUnrecognizedEvent { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserUpdatedNotification object:nil]; + //it's not obvious, but by not setting expect on the mock observer, the observer will fail when verify is called IF it has received the notification - id userUpdatedObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userUpdatedObserver name:kLDUserUpdatedNotification object:nil]; + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); - id userNoChangeObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:userNoChangeObserver name:kLDUserNoChangeNotification object:nil]; + [[dataManagerMock reject] saveUser:[OCMArg any]]; - id connectionUnavailableObserver = OCMObserverMock(); - [[NSNotificationCenter defaultCenter] addMockObserver:connectionUnavailableObserver name:kLDServerConnectionUnavailableNotification object:nil]; - [[connectionUnavailableObserver expect] notificationWithName:kLDServerConnectionUnavailableNotification object:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + LDFlagConfigModel *targetFlagConfig = user.config; - LDUserModel *user = [LDClient sharedInstance].ldUser; + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *put = [LDEvent stubEvent:@"someUnrecognizedEvent" fromJsonFileNamed:@"featureFlags-withVersions"]; + + messageHandler(put); + + XCTAssertTrue([user.config isEqualToConfig: targetFlagConfig]); + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPatchEventSuccess { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserUpdatedNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserUpdatedNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + OCMStub([flagConfigMock hasFeaturesEqualToDictionary:[OCMArg any]]).andReturn(NO); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; - [[self.dataManagerMock reject] saveUser:[OCMArg any]]; + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; LDClientManager *clientManager = [LDClientManager sharedInstance]; - [clientManager processedConfig:NO jsonConfigDictionary:flagConfigDictionary]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *patch = [LDEvent stubEvent:kLDEventTypePatch fromJsonFileNamed:@"ldClientManagerTestPatchIsANumber"]; + NSDictionary *targetPatchDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"ldClientManagerTestPatchIsANumber"]; + + messageHandler(patch); + + __block NSDictionary *patchDictionary; + OCMVerify([flagConfigMock addOrReplaceFromDictionary:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { return NO; } + patchDictionary = obj; + return YES; + }]]); + XCTAssertTrue([patchDictionary isEqualToDictionary:targetPatchDictionary]); + __block LDUserModel *savedUser; + OCMVerify([dataManagerMock saveUser:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[LDUserModel class]]) { return NO; } + savedUser = obj; + return YES; + }]]); + XCTAssertTrue([savedUser isEqual:user]); + OCMVerifyAll(notificationObserver); +} + +- (void)testSSEPatchResultedInNoChange { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + __block NSDictionary *patchDictionary; + [[flagConfigMock expect] addOrReplaceFromDictionary:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { return NO; } + patchDictionary = obj; + return YES; + }]]; + OCMStub([flagConfigMock hasFeaturesEqualToDictionary:[OCMArg any]]).andReturn(YES); + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + //NOTE: Because the flag config mock will return YES on a dictionary comparison, the patch here doesn't matter + LDEvent *patch = [LDEvent stubEvent:kLDEventTypePatch fromJsonFileNamed:@"ldClientManagerTestPatchIsANumber"]; + + messageHandler(patch); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPatchFailedNilData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] addOrReplaceFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *patch = [LDEvent stubEvent:kLDEventTypePatch fromJsonFileNamed:@"ldClientManagerTestPatchIsANumber"]; + patch.data = nil; + + messageHandler(patch); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPatchFailedEmptyData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] addOrReplaceFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *patch = [LDEvent stubEvent:kLDEventTypePatch fromJsonFileNamed:@"ldClientManagerTestPatchIsANumber"]; + patch.data = @""; + + messageHandler(patch); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEPatchFailedInvalidData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] addOrReplaceFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *patch = [LDEvent stubEvent:kLDEventTypePatch fromJsonFileNamed:@"ldClientManagerTestPatchIsANumber"]; + patch.data = @"{\"someInvalidData\":}"; + + messageHandler(patch); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEDeleteEventSuccess { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserUpdatedNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserUpdatedNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + OCMStub([flagConfigMock hasFeaturesEqualToDictionary:[OCMArg any]]).andReturn(NO); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + self.cleanup = ^{ + [flagConfigMock stopMocking]; + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *delete = [LDEvent stubEvent:kLDEventTypeDelete fromJsonFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + NSDictionary *targetDeleteDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + + messageHandler(delete); + + __block NSDictionary *deleteDictionary; + OCMVerify([flagConfigMock deleteFromDictionary:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { return NO; } + deleteDictionary = obj; + return YES; + }]]); + XCTAssertTrue([deleteDictionary isEqualToDictionary:targetDeleteDictionary]); + __block LDUserModel *savedUser; + OCMVerify([dataManagerMock saveUser:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[LDUserModel class]]) { return NO; } + savedUser = obj; + return YES; + }]]); + XCTAssertNotNil(savedUser); + XCTAssertTrue([savedUser isEqual:user]); + OCMVerifyAll(notificationObserver); +} + +- (void)testSSEDeleteResultedInNoChange { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + __block NSDictionary *deleteDictionary; + [[flagConfigMock expect] deleteFromDictionary:[OCMArg checkWithBlock:^BOOL(id obj) { + if (![obj isKindOfClass:[NSDictionary class]]) { return NO; } + deleteDictionary = obj; + return YES; + }]]; + OCMStub([flagConfigMock hasFeaturesEqualToDictionary:[OCMArg any]]).andReturn(YES); + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + //NOTE: Because the flag config mock will return YES on a dictionary comparison, the delete here doesn't matter + LDEvent *delete = [LDEvent stubEvent:kLDEventTypeDelete fromJsonFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + + messageHandler(delete); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEDeleteFailedNilData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] deleteFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *delete = [LDEvent stubEvent:kLDEventTypeDelete fromJsonFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + delete.data = nil; + + messageHandler(delete); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEDeleteFailedEmptyData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] deleteFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *delete = [LDEvent stubEvent:kLDEventTypeDelete fromJsonFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + delete.data = @""; + + messageHandler(delete); + + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); +} + +- (void)testSSEDeleteFailedInvalidData { + id notificationObserver = OCMObserverMock(); + [[NSNotificationCenter defaultCenter] addMockObserver:notificationObserver name:kLDUserNoChangeNotification object:nil]; + [[notificationObserver expect] notificationWithName:kLDUserNoChangeNotification object:[OCMArg any]]; + + __block LDEventSourceEventHandler messageHandler; + OCMStub([eventSourceMock onMessage:[OCMArg checkWithBlock:^BOOL(id obj) { + messageHandler = (LDEventSourceEventHandler)obj; + return YES; + }]]); + + id flagConfigMock = OCMClassMock([LDFlagConfigModel class]); + [[flagConfigMock reject] deleteFromDictionary:[OCMArg any]]; + LDUserModel *user = [[LDClient sharedInstance] ldUser]; + user.config = flagConfigMock; + + [[dataManagerMock reject] saveUser:[OCMArg any]]; + + self.cleanup = ^{ + [[NSNotificationCenter defaultCenter] removeObserver:notificationObserver]; + [flagConfigMock stopMocking]; + }; + + LDClientManager *clientManager = [LDClientManager sharedInstance]; + clientManager.online = YES; + + XCTAssertNotNil(messageHandler); + if (!messageHandler) { return; } + + LDEvent *delete = [LDEvent stubEvent:kLDEventTypeDelete fromJsonFileNamed:@"ldClientManagerTestDeleteIsANumber"]; + delete.data = @"{\"someInvalidData\":}"; - XCTAssertNil(user.config); + messageHandler(delete); - [userUpdatedObserver verify]; - [userNoChangeObserver verify]; - [connectionUnavailableObserver verify]; + OCMVerifyAll(notificationObserver); + OCMVerify(dataManagerMock); } #pragma mark - Helpers diff --git a/DarklyTests/LDClientTest.m b/DarklyTests/LDClientTest.m index f29ceb0a..24342ed8 100644 --- a/DarklyTests/LDClientTest.m +++ b/DarklyTests/LDClientTest.m @@ -12,12 +12,15 @@ #import "LDPollingManager.h" #import "LDUserBuilder+Testable.h" #import "LDClient+Testable.h" +#import "NSJSONSerialization+Testable.h" #import "OCMock.h" #import typedef void(^MockLDClientDelegateCallbackBlock)(void); +extern NSString * _Nonnull const kLDFlagConfigJsonDictionaryKeyValue; + @interface MockLDClientDelegate : NSObject @property (nonatomic, assign) NSInteger userDidUpdateCallCount; @property (nonatomic, assign) NSInteger userUnchangedCallCount; @@ -147,7 +150,7 @@ - (void)testBoolVariationWithConfig { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -190,7 +193,7 @@ - (void)testStringVariationWithConfig { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -205,7 +208,7 @@ - (void)testStringVariationFallback { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -230,7 +233,7 @@ - (void)testNumberVariationWithConfig { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -245,7 +248,7 @@ - (void)testNumberVariationFallback { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -268,8 +271,8 @@ - (void)testDoubleVariationWithoutConfig { - (void)testDoubleVariationWithConfig { NSString *targetKey = @"isADouble"; - NSString *jsonFileName = @"doubleConfigIsADouble-Pi"; - double target = [[self objectFromJsonFileNamed:jsonFileName key:targetKey] doubleValue]; + NSString *jsonFileName = @"doubleConfigIsADouble-Pi-withVersion"; + double target = [[self valueFromJsonFileNamed:jsonFileName key:targetKey] doubleValue]; LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; @@ -290,7 +293,7 @@ - (void)testDoubleVariationFallback { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"doubleConfigIsADouble-Pi"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"doubleConfigIsADouble-Pi-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -315,10 +318,10 @@ - (void)testArrayVariationWithoutConfig { - (void)testArrayVariationWithConfig { NSString *targetKey = @"isAnArray"; - NSString *jsonFileName = @"arrayConfigIsAnArray-123"; + NSString *jsonFileName = @"arrayConfigIsAnArray-123-withVersion"; NSArray *fallbackArray = @[@1, @2]; - NSArray *targetArray = [self objectFromJsonFileNamed:jsonFileName key:targetKey]; + NSArray *targetArray = [self valueFromJsonFileNamed:jsonFileName key:targetKey]; XCTAssertFalse([targetArray isEqualToArray:fallbackArray]); LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; @@ -342,7 +345,7 @@ - (void)testArrayVariationFallback { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -368,10 +371,10 @@ - (void)testDictionaryVariationWithoutConfig { - (void)testDictionaryVariationWithConfig { NSString *targetKey = @"isADictionary"; - NSString *jsonFileName = @"dictionaryConfigIsADictionary-3Key"; + NSString *jsonFileName = @"dictionaryConfigIsADictionary-3Key-withVersion"; NSDictionary *fallback = @{@"key1": @"value1", @"key2": @[@1, @2]}; - NSDictionary *target = [self objectFromJsonFileNamed:jsonFileName key:targetKey]; + NSDictionary *target = [self valueFromJsonFileNamed:jsonFileName key:targetKey]; XCTAssertFalse([target isEqualToDictionary:fallback]); LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; @@ -394,7 +397,7 @@ - (void)testDictionaryVariationFallback { LDConfig *clientConfig = [[LDConfig alloc] initWithMobileKey:kTestMobileKey]; LDUserBuilder *userBuilder = [LDUserBuilder userBuilderWithKey:[[NSUUID UUID] UUIDString]]; - LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key"]; + LDFlagConfigModel *flags = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key-withVersion"]; BOOL clientStarted = [[LDClient sharedInstance] start:clientConfig withUserBuilder:userBuilder]; XCTAssertTrue(clientStarted); @@ -630,11 +633,11 @@ - (void)testUserUnchangedCalled { #pragma mark - Helpers - (id)objectFromJsonFileNamed:(NSString*)jsonFileName key:(NSString*)key { - NSString *filepath = [[NSBundle bundleForClass:[LDClientTest class]] pathForResource: jsonFileName - ofType:@"json"]; - NSData *configData = [NSData dataWithContentsOfFile:filepath]; - NSError *error; - NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:configData options:0 error:&error]; + NSDictionary *jsonDictionary = [NSJSONSerialization jsonObjectFromFileNamed:jsonFileName]; return jsonDictionary[key]; } + +- (id)valueFromJsonFileNamed:(NSString*)jsonFileName key:(NSString*)key { + return [self objectFromJsonFileNamed:jsonFileName key:key][kLDFlagConfigJsonDictionaryKeyValue]; +} @end diff --git a/DarklyTests/LDFlagConfigModelTest.m b/DarklyTests/LDFlagConfigModelTest.m deleted file mode 100644 index 4195e521..00000000 --- a/DarklyTests/LDFlagConfigModelTest.m +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright © 2015 Catamorphic Co. All rights reserved. -// - -#import -#import "LDFlagConfigModel.h" -#import "LDFlagConfigModel+Testable.h" - - -@interface LDFlagConfigModelTest : XCTestCase - -@end - -@implementation LDFlagConfigModelTest - -- (void)setUp { - [super setUp]; -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - --(void)testIsFlagOnForKey { - LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"feature_flags"]; - - XCTAssertTrue([config configFlagValue: @"isABawler"]); - XCTAssertFalse([config configFlagValue: @"isConnected"]); - XCTAssertFalse([(NSNumber *)[config configFlagValue: @"devices.hasipad"] boolValue]); -} - -- (void)testDoesFlagExist { - LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"feature_flags"]; - - XCTAssertTrue([config doesConfigFlagExist: @"isABawler"]); - XCTAssertTrue([config doesConfigFlagExist: @"isConnected"]); - XCTAssertTrue([config doesConfigFlagExist: @"devices.hasipad"]); - XCTAssertFalse([config doesConfigFlagExist: @"caramel"]); -} - -- (void)testIsEqualToConfigBoolValues { - LDFlagConfigModel *boolConfigIsABool_true = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true"]; - LDFlagConfigModel *boolConfigIsABool_trueCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true"]; - LDFlagConfigModel *boolConfigIsABool_false = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-false"]; - LDFlagConfigModel *boolConfigIsABool2_true = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool2-true"]; - - XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:nil]); - XCTAssertTrue([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_true]); - XCTAssertTrue([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_trueCopy]); - XCTAssertNotNil(boolConfigIsABool_false); - XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_false]); - XCTAssertNotNil(boolConfigIsABool2_true); - XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool2_true]); - -} - -- (void)testIsEqualToConfigNumberValues { - LDFlagConfigModel *numberConfigIsANumber_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-1"]; - LDFlagConfigModel *numberConfigIsANumber_1Copy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-1"]; - LDFlagConfigModel *numberConfigIsANumber_2 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2"]; - LDFlagConfigModel *numberConfigIsANumber2_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber2-1"]; - - XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:nil]); - XCTAssertTrue([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_1]); - XCTAssertTrue([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_1Copy]); - XCTAssertNotNil(numberConfigIsANumber_2); - XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_2]); - XCTAssertNotNil(numberConfigIsANumber2_1); - XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber2_1]); -} - -- (void)testIsEqualToConfigStringValues { - LDFlagConfigModel *stringConfigIsAString_someString = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString"]; - LDFlagConfigModel *stringConfigIsAString_someStringCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString"]; - LDFlagConfigModel *stringConfigIsAString_someStringA = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someStringA"]; - LDFlagConfigModel *stringConfigIsAStringA_someString = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAStringA-someString"]; - - XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:nil]); - XCTAssertTrue([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someString]); - XCTAssertTrue([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someStringCopy]); - XCTAssertNotNil(stringConfigIsAString_someStringA); - XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someStringA]); - XCTAssertNotNil(stringConfigIsAStringA_someString); - XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAStringA_someString]); -} - -- (void)testIsEqualToConfigArrayValues { - LDFlagConfigModel *arrayConfigIsAnArray_123 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123"]; - LDFlagConfigModel *arrayConfigIsAnArray_123Copy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123"]; - LDFlagConfigModel *arrayConfigIsAnArray_Empty = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-Empty"]; - LDFlagConfigModel *arrayConfigIsAnArray_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-1"]; - LDFlagConfigModel *arrayConfigIsAnArrayA_123 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArrayA-123"]; - - XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:nil]); - XCTAssertTrue([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_123]); - XCTAssertTrue([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_123Copy]); - XCTAssertNotNil(arrayConfigIsAnArray_Empty); - XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_Empty]); - XCTAssertNotNil(arrayConfigIsAnArray_1); - XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_1]); - XCTAssertNotNil(arrayConfigIsAnArrayA_123); - XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArrayA_123]); -} - -- (void)testIsEqualToConfigDictionaryValues { - LDFlagConfigModel *dictionaryConfigIsADictionary_3Key = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_3KeyCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_Empty = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-Empty"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_KeyA = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyA"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_KeyB = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyB"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_KeyB_124 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyB-124"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_KeyC = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyC"]; - LDFlagConfigModel *dictionaryConfigIsADictionary_KeyC_keyDValueDiffers = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyC-keyDValueDiffers"]; - - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:nil]); - XCTAssertTrue([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_3Key]); - XCTAssertTrue([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_3KeyCopy]); - XCTAssertNotNil(dictionaryConfigIsADictionary_Empty); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_Empty]); - XCTAssertNotNil(dictionaryConfigIsADictionary_KeyA); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyA]); - XCTAssertNotNil(dictionaryConfigIsADictionary_KeyB); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyB]); - XCTAssertNotNil(dictionaryConfigIsADictionary_KeyB_124); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyB_124]); - XCTAssertNotNil(dictionaryConfigIsADictionary_KeyC); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyC]); - XCTAssertNotNil(dictionaryConfigIsADictionary_KeyC_keyDValueDiffers); - XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyC_keyDValueDiffers]); -} -@end diff --git a/DarklyTests/LDRequestManagerTest.m b/DarklyTests/LDRequestManagerTest.m index 995b3ae7..05a3c063 100644 --- a/DarklyTests/LDRequestManagerTest.m +++ b/DarklyTests/LDRequestManagerTest.m @@ -14,7 +14,6 @@ #import "LDConfig+Testable.h" #import "LDClient.h" -static NSString *const httpMethodReport = @"REPORT"; static NSString *const httpMethodGet = @"GET"; static NSString *const testMobileKey = @"testMobileKey"; static NSString *const emptyJson = @"{ }"; @@ -144,7 +143,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_Success { LDConfig *config = [[LDConfig alloc] initWithMobileKey:testMobileKey]; config.useReport = YES; - [self mockClientWithUser:[self mockUser] config:config]; + self.ldClientMock = [self mockClientWithUser:[self mockUser] config:config]; __block id requestManagerDelegateMock = [OCMockObject niceMockForProtocol:@protocol(RequestManagerDelegate)]; [[requestManagerDelegateMock expect] processedConfig:YES jsonConfigDictionary:[OCMArg isKindOfClass:[NSDictionary class]]]; @@ -154,14 +153,14 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_Success { __weak XCTestExpectation *responseArrived = [self expectationWithDescription:@"feature flag response arrived"]; [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { - return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:httpMethodReport]; + return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:kHTTPMethodReport]; } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { [reportRequestMade fulfill]; return [OHHTTPStubsResponse responseWithData: [self successJsonData] statusCode:httpStatusCodeOk headers:[self headerForStatusCode:httpStatusCodeOk]]; }]; [OHHTTPStubs onStubActivation:^(NSURLRequest * _Nonnull request, id _Nonnull stub) { - XCTAssertTrue([request.HTTPMethod isEqualToString:httpMethodReport]); + XCTAssertTrue([request.HTTPMethod isEqualToString:kHTTPMethodReport]); [responseArrived fulfill]; }]; @@ -185,7 +184,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_Success_invalidData { [LDRequestManager sharedInstance].delegate = requestManagerDelegateMock; [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { - return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:httpMethodReport]; + return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:kHTTPMethodReport]; } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { [reportRequestMade fulfill]; return [OHHTTPStubsResponse responseWithData: [self invalidJsonData] statusCode:httpStatusCodeOk headers:[self headerForStatusCode:httpStatusCodeOk]]; @@ -202,7 +201,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_MakesFallbackGetRequest { LDConfig *config = [[LDConfig alloc] initWithMobileKey:testMobileKey]; config.useReport = YES; - [self mockClientWithUser:[self mockUser] config:config]; + self.ldClientMock = [self mockClientWithUser:[self mockUser] config:config]; NSArray *fallbackStatusCodes = [config flagRetryStatusCodes]; XCTAssertNotNil(fallbackStatusCodes); @@ -221,7 +220,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_MakesFallbackGetRequest { [LDRequestManager sharedInstance].delegate = requestManagerDelegateMock; [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { - return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:httpMethodReport]; + return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:kHTTPMethodReport]; } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { [reportRequestMade fulfill]; return [OHHTTPStubsResponse responseWithData: [NSData data] statusCode:[fallbackStatusCode intValue] headers:[self headerForStatusCode:[fallbackStatusCode intValue]]]; @@ -268,7 +267,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_DoesNotMakeFallbackGetReques LDConfig *config = [[LDConfig alloc] initWithMobileKey:testMobileKey]; config.useReport = YES; - [self mockClientWithUser:[self mockUser] config:config]; + self.ldClientMock = [self mockClientWithUser:[self mockUser] config:config]; NSString *reportStubName = @"report stub"; NSString *getStubName = @"get stub"; @@ -281,7 +280,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_DoesNotMakeFallbackGetReques [LDRequestManager sharedInstance].delegate = requestManagerDelegateMock; [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { - return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:httpMethodReport]; + return [request.URL.host isEqualToString:flagRequestHost] && [request.HTTPMethod isEqualToString:kHTTPMethodReport]; } withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) { [reportRequestMade fulfill]; return [OHHTTPStubsResponse responseWithData: [NSData data] statusCode:[fallbackStatusCode intValue] headers:[self headerForStatusCode:[fallbackStatusCode intValue]]]; @@ -317,7 +316,7 @@ - (void)testPerformFeatureFlagRequest_ReportRequest_DoesNotMakeFallbackGetReques } - (void)testPerformFeatureFlagRequestWithoutUser { - [self mockClientWithUser:nil config:[self testConfig]]; + self.ldClientMock = [self mockClientWithUser:nil config:[self testConfig]]; [self mockFlagResponse]; diff --git a/DarklyTests/Models/LDDataManagerTest.m b/DarklyTests/Models/LDDataManagerTest.m index 193023c4..9818f074 100644 --- a/DarklyTests/Models/LDDataManagerTest.m +++ b/DarklyTests/Models/LDDataManagerTest.m @@ -7,6 +7,7 @@ #import "LDDataManager.h" #import "LDUserModel.h" #import "LDFlagConfigModel.h" +#import "LDFlagConfigModel+Testable.h" #import "LDEventModel.h" #import "LDClient.h" #import "OCMock.h" @@ -31,9 +32,7 @@ - (void)setUp { user.email = @"bob@gmail.com"; user.updatedAt = [NSDate date]; - LDFlagConfigModel *config = [[LDFlagConfigModel alloc] init]; - config.featuresJsonDictionary = [NSDictionary dictionaryWithObjects:@[@YES, @NO] - forKeys: @[@"ipaduser", @"iosuser"]]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldDataManagerTestConfig"]; user.config = config; clientMock = OCMClassMock([LDClient class]); diff --git a/DarklyTests/Models/LDFlagConfigModelTest.m b/DarklyTests/Models/LDFlagConfigModelTest.m new file mode 100644 index 00000000..d746fcca --- /dev/null +++ b/DarklyTests/Models/LDFlagConfigModelTest.m @@ -0,0 +1,473 @@ +// +// Copyright © 2015 Catamorphic Co. All rights reserved. +// + +#import +#import "LDFlagConfigModel.h" +#import "LDFlagConfigModel+Testable.h" +#import "NSJSONSerialization+Testable.h" +#import "NSDictionary+Testable.h" + +extern NSString *const kLDFlagConfigJsonDictionaryKeyKey; +extern NSString *const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString *const kLDFlagConfigJsonDictionaryKeyVersion; +extern const NSInteger kLDFlagConfigVersionDoesNotExist; + +@interface LDFlagConfigModelTest : XCTestCase + +@end + +@implementation LDFlagConfigModelTest + +-(void)testEncodeAndDecode { + LDFlagConfigModel *originalConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:originalConfig]; + LDFlagConfigModel *restoredConfig = [NSKeyedUnarchiver unarchiveObjectWithData:archive]; + + XCTAssertTrue([restoredConfig isEqualToConfig:originalConfig]); +} + +-(void)testInitWithDictionary_withVersions { + NSDictionary *flagConfigDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + LDFlagConfigModel *subject = [[LDFlagConfigModel alloc] initWithDictionary:flagConfigDictionary]; + + for (NSString *key in [flagConfigDictionary.allKeys copy]) { + LDFlagConfigValue *flagConfigValueFromDictionary = [[LDFlagConfigValue alloc] initWithObject:flagConfigDictionary[key]]; + + XCTAssertTrue([subject.featuresJsonDictionary[key] isEqual:flagConfigValueFromDictionary]); + } +} + +-(void)testInitWithDictionary_withoutVersions { + NSDictionary *flagConfigDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withoutVersions"]; + LDFlagConfigModel *subject = [[LDFlagConfigModel alloc] initWithDictionary:flagConfigDictionary]; + + for (NSString *key in [flagConfigDictionary.allKeys copy]) { + LDFlagConfigValue *flagConfigValueFromDictionary = [[LDFlagConfigValue alloc] initWithObject:flagConfigDictionary[key]]; + + XCTAssertTrue([subject.featuresJsonDictionary[key] isEqual:flagConfigValueFromDictionary]); + } +} + +-(void)testDictionaryValue_includeNullValues_withVersions { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + + NSDictionary *flagConfigDictionary = [subject dictionaryValueIncludeNulls:YES]; + XCTAssertTrue([subject hasFeaturesEqualToDictionary:flagConfigDictionary]); + + NSDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-excludeNulls-withVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +-(void)testDictionaryValue_excludeNullValues_withVersions { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-excludeNulls-withVersions"]; + + NSDictionary *flagConfigDictionary = [subject dictionaryValueIncludeNulls:NO]; + XCTAssertTrue([subject hasFeaturesEqualToDictionary:flagConfigDictionary]); + + NSDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +-(void)testDictionaryValue_includeNullValues_withoutVersions { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withoutVersions"]; + + NSDictionary *flagConfigDictionary = [subject dictionaryValueIncludeNulls:YES]; + XCTAssertTrue([subject hasFeaturesEqualToDictionary:flagConfigDictionary]); + + NSDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-excludeNulls-withoutVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +-(void)testDictionaryValue_excludeNullValues_withoutVersions { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-excludeNulls-withoutVersions"]; + + NSDictionary *flagConfigDictionary = [subject dictionaryValueIncludeNulls:NO]; + XCTAssertTrue([subject hasFeaturesEqualToDictionary:flagConfigDictionary]); + + NSDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withoutVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +-(void)testFlagConfigValue_withVersions { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + NSDictionary *flagValues = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + + for (NSString *key in [flagValues.allKeys copy]) { + id targetValue = flagValues[key][kLDFlagConfigJsonDictionaryKeyValue]; + if ([targetValue isKindOfClass:[NSNull class]]) { + XCTAssertNil([config configFlagValue:key]); + continue; + } + XCTAssertTrue([[config configFlagValue:key] isEqual:targetValue]); + } + + XCTAssertNil([config configFlagValue:@"someMissingKey"]); +} + +-(void)testFlagConfigValue_withoutVersions { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withoutVersions"]; + NSDictionary *flagValues = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withoutVersions"]; + + for (NSString *key in [flagValues.allKeys copy]) { + id targetValue = flagValues[key]; + if ([targetValue isKindOfClass:[NSNull class]]) { + XCTAssertNil([config configFlagValue:key]); + continue; + } + XCTAssertTrue([[config configFlagValue:key] isEqual:targetValue]); + } + + XCTAssertNil([config configFlagValue:@"someMissingKey"]); +} + +-(void)testFlagConfigVersion_withVersions { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + NSDictionary *flagValues = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + + for (NSString *key in [flagValues.allKeys copy]) { + NSInteger targetVersion = [(NSNumber*)(flagValues[key])[kLDFlagConfigJsonDictionaryKeyVersion] integerValue]; + XCTAssertTrue([config configFlagVersion:key] == targetVersion); + } + + XCTAssertTrue([config configFlagVersion:@"someMissingKey"] == kLDFlagConfigVersionDoesNotExist); +} + +-(void)testFlagConfigVersion_withoutVersions { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withoutVersions"]; + NSDictionary *flagValues = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withoutVersions"]; + + for (NSString *key in [flagValues.allKeys copy]) { + XCTAssertTrue([config configFlagVersion:key] == kLDFlagConfigVersionDoesNotExist); + } + + XCTAssertTrue([config configFlagVersion:@"someMissingKey"] == kLDFlagConfigVersionDoesNotExist); +} + +- (void)testDoesFlagExist { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + NSDictionary *flagValues = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + + for (NSString *key in [flagValues.allKeys copy]) { + XCTAssertTrue([config doesConfigFlagExist:key]); + } + + XCTAssertFalse([config doesConfigFlagExist:@"someMissingKey"]); +} + +- (void)testAddOrReplaceFromDictionaryWhenKeyDoesntExist { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [NSJSONSerialization jsonObjectFromFileNamed:@"ldFlagConfigModelPatchNewFlag"]; + NSString *patchedFlagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + BOOL patchedFlagValue = [patch boolValueForKey:kLDFlagConfigJsonDictionaryKeyValue]; + NSInteger patchedFlagVersion = [patch integerValueForKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config doesConfigFlagExist:patchedFlagKey]); + XCTAssertEqual([[config configFlagValue:patchedFlagKey] boolValue], patchedFlagValue); + XCTAssertEqual([config configFlagVersion:patchedFlagKey], patchedFlagVersion); +} + +- (void)testAddOrReplaceFromDictionaryWhenKeyExistsWithPreviousVersion { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [NSJSONSerialization jsonObjectFromFileNamed:@"ldFlagConfigModelPatchVersion1Flag"]; + NSString *patchedFlagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + BOOL patchedFlagValue = [patch boolValueForKey:kLDFlagConfigJsonDictionaryKeyValue]; + NSInteger patchedFlagVersion = [patch integerValueForKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config doesConfigFlagExist:patchedFlagKey]); + XCTAssertEqual([[config configFlagValue:patchedFlagKey] boolValue], patchedFlagValue); + XCTAssertEqual([config configFlagVersion:patchedFlagKey], patchedFlagVersion); +} + +- (void)testAddOrReplaceFromDictionaryWhenPatchValueIsNull { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [NSJSONSerialization jsonObjectFromFileNamed:@"ldFlagConfigModelPatchVersion2FlagWithNull"]; + NSString *patchedFlagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + NSInteger patchedFlagVersion = [patch integerValueForKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config doesConfigFlagExist:patchedFlagKey]); + XCTAssertNil([config configFlagValue:patchedFlagKey]); + XCTAssertEqual([config configFlagVersion:patchedFlagKey], patchedFlagVersion); +} + +- (void)testAddOrReplaceFromDictionaryWhenKeyExistsWithSameVersion { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [LDFlagConfigModel patchFromJsonFileNamed:@"ldFlagConfigModelPatchVersion2Flag" useVersion:2]; + NSString *patchedFlagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + NSString *originalFlagValue = (NSString*)[config configFlagValue:patchedFlagKey]; + NSInteger originalFlagVersion = [config configFlagVersion:patchedFlagKey]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config doesConfigFlagExist:patchedFlagKey]); + XCTAssertEqual([config configFlagValue:patchedFlagKey], originalFlagValue); + XCTAssertEqual([config configFlagVersion:patchedFlagKey], originalFlagVersion); +} + +- (void)testAddOrReplaceFromDictionaryWhenKeyExistsWithLaterVersion { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [LDFlagConfigModel patchFromJsonFileNamed:@"ldFlagConfigModelPatchVersion2Flag" useVersion:1]; + NSString *patchedFlagKey = patch[kLDFlagConfigJsonDictionaryKeyKey]; + NSString *originalFlagValue = (NSString*)[config configFlagValue:patchedFlagKey]; + NSInteger originalFlagVersion = [config configFlagVersion:patchedFlagKey]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config doesConfigFlagExist:patchedFlagKey]); + XCTAssertEqual([config configFlagValue:patchedFlagKey], originalFlagValue); + XCTAssertEqual([config configFlagVersion:patchedFlagKey], originalFlagVersion); +} + +- (void)testAddOrReplaceFromDictionaryWhenDictionaryIsNil { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = nil; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testAddOrReplaceFromDictionaryWhenDictionaryIsEmpty { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = @{}; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testAddOrReplaceFromDictionaryWhenDictionaryIsMissingValue { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [LDFlagConfigModel patchFromJsonFileNamed:@"ldFlagConfigModelPatchVersion2Flag" omitKey:kLDFlagConfigJsonDictionaryKeyValue]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testAddOrReplaceFromDictionaryWhenDictionaryIsMissingVersion { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [LDFlagConfigModel patchFromJsonFileNamed:@"ldFlagConfigModelPatchVersion2Flag" omitKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testAddOrReplaceFromDictionaryWhenDictionaryIsUnexpectedFormat { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *patch = [LDFlagConfigModel patchFromJsonFileNamed:@"ldFlagConfigModelPatchVersion2Flag" omitKey:kLDFlagConfigJsonDictionaryKeyKey]; + + [config addOrReplaceFromDictionary:patch]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenKeyExistsWithPreviousVersion { + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [NSJSONSerialization jsonObjectFromFileNamed:@"ldFlagConfigModelDeleteVersion2Flag"]; + NSString *deletedFlagKey = delete[kLDFlagConfigJsonDictionaryKeyKey]; + + [config deleteFromDictionary:delete]; + + XCTAssertFalse([config doesConfigFlagExist:deletedFlagKey]); +} + +- (void)testDeleteFromDictionaryWhenKeyDoesntExist { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [NSJSONSerialization jsonObjectFromFileNamed:@"ldFlagConfigModelDeleteNewFlag"]; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenKeyExistsWithSameVersion { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [LDFlagConfigModel deleteFromJsonFileNamed:@"ldFlagConfigModelDeleteVersion2Flag" useVersion:2]; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenKeyExistsWithLaterVersion { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [LDFlagConfigModel deleteFromJsonFileNamed:@"ldFlagConfigModelDeleteVersion2Flag" useVersion:1]; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenDictionaryIsNil { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = nil; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenDictionaryIsEmpty { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = @{}; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenDictionaryIsMissingVersion { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [LDFlagConfigModel deleteFromJsonFileNamed:@"ldFlagConfigModelDeleteVersion2Flag" omitKey:kLDFlagConfigJsonDictionaryKeyVersion]; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testDeleteFromDictionaryWhenDictionaryIsUnexpectedFormat { + LDFlagConfigModel *targetConfig = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + LDFlagConfigModel *config = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"ldFlagConfigModelTest"]; + NSDictionary *delete = [LDFlagConfigModel deleteFromJsonFileNamed:@"ldFlagConfigModelDeleteVersion2Flag" omitKey:kLDFlagConfigJsonDictionaryKeyKey]; + + [config deleteFromDictionary:delete]; + + XCTAssertTrue([config isEqualToConfig:targetConfig]); +} + +- (void)testIsEqualToConfigBoolValues { + LDFlagConfigModel *boolConfigIsABool_true = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigModel *boolConfigIsABool_trueCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigModel *boolConfigIsABool_false = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool-false"]; + LDFlagConfigModel *boolConfigIsABool2_true = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"boolConfigIsABool2-true"]; + + XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:nil]); + XCTAssertTrue([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_true]); + XCTAssertTrue([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_trueCopy]); + XCTAssertNotNil(boolConfigIsABool_false); + XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool_false]); + XCTAssertNotNil(boolConfigIsABool2_true); + XCTAssertFalse([boolConfigIsABool_true isEqualToConfig:boolConfigIsABool2_true]); + +} + +- (void)testIsEqualToConfigNumberValues { + LDFlagConfigModel *numberConfigIsANumber_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-1"]; + LDFlagConfigModel *numberConfigIsANumber_1Copy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-1"]; + LDFlagConfigModel *numberConfigIsANumber_2 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber-2-withVersion"]; + LDFlagConfigModel *numberConfigIsANumber2_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"numberConfigIsANumber2-1"]; + + XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:nil]); + XCTAssertTrue([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_1]); + XCTAssertTrue([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_1Copy]); + XCTAssertNotNil(numberConfigIsANumber_2); + XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber_2]); + XCTAssertNotNil(numberConfigIsANumber2_1); + XCTAssertFalse([numberConfigIsANumber_1 isEqualToConfig:numberConfigIsANumber2_1]); +} + +- (void)testIsEqualToConfigStringValues { + LDFlagConfigModel *stringConfigIsAString_someString = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString-withVersion"]; + LDFlagConfigModel *stringConfigIsAString_someStringCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString-withVersion"]; + LDFlagConfigModel *stringConfigIsAString_someStringA = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAString-someString-withVersionA"]; + LDFlagConfigModel *stringConfigIsAStringA_someString = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"stringConfigIsAStringA-someString"]; + + XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:nil]); + XCTAssertTrue([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someString]); + XCTAssertTrue([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someStringCopy]); + XCTAssertNotNil(stringConfigIsAString_someStringA); + XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAString_someStringA]); + XCTAssertNotNil(stringConfigIsAStringA_someString); + XCTAssertFalse([stringConfigIsAString_someString isEqualToConfig:stringConfigIsAStringA_someString]); +} + +- (void)testIsEqualToConfigArrayValues { + LDFlagConfigModel *arrayConfigIsAnArray_123 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123-withVersion"]; + LDFlagConfigModel *arrayConfigIsAnArray_123Copy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-123-withVersion"]; + LDFlagConfigModel *arrayConfigIsAnArray_Empty = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-Empty"]; + LDFlagConfigModel *arrayConfigIsAnArray_1 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArray-1"]; + LDFlagConfigModel *arrayConfigIsAnArrayA_123 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"arrayConfigIsAnArrayA-123"]; + + XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:nil]); + XCTAssertTrue([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_123]); + XCTAssertTrue([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_123Copy]); + XCTAssertNotNil(arrayConfigIsAnArray_Empty); + XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_Empty]); + XCTAssertNotNil(arrayConfigIsAnArray_1); + XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArray_1]); + XCTAssertNotNil(arrayConfigIsAnArrayA_123); + XCTAssertFalse([arrayConfigIsAnArray_123 isEqualToConfig:arrayConfigIsAnArrayA_123]); +} + +- (void)testIsEqualToConfigDictionaryValues { + LDFlagConfigModel *dictionaryConfigIsADictionary_3Key = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key-withVersion"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_3KeyCopy = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-3Key-withVersion"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_Empty = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-Empty"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_KeyA = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyA"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_KeyB = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyB"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_KeyB_124 = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyB-124"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_KeyC = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyC"]; + LDFlagConfigModel *dictionaryConfigIsADictionary_KeyC_keyDValueDiffers = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"dictionaryConfigIsADictionary-KeyC-keyDValueDiffers"]; + + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:nil]); + XCTAssertTrue([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_3Key]); + XCTAssertTrue([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_3KeyCopy]); + XCTAssertNotNil(dictionaryConfigIsADictionary_Empty); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_Empty]); + XCTAssertNotNil(dictionaryConfigIsADictionary_KeyA); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyA]); + XCTAssertNotNil(dictionaryConfigIsADictionary_KeyB); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyB]); + XCTAssertNotNil(dictionaryConfigIsADictionary_KeyB_124); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyB_124]); + XCTAssertNotNil(dictionaryConfigIsADictionary_KeyC); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyC]); + XCTAssertNotNil(dictionaryConfigIsADictionary_KeyC_keyDValueDiffers); + XCTAssertFalse([dictionaryConfigIsADictionary_3Key isEqualToConfig:dictionaryConfigIsADictionary_KeyC_keyDValueDiffers]); +} + +- (void)testHasFeaturesEqualToDictionary_withVersion { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withVersions"]; + NSDictionary *sameDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; + + XCTAssertTrue([subject hasFeaturesEqualToDictionary:sameDictionary]); + + NSDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-excludeNulls-withVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +- (void)testHasFeaturesEqualToDictionary_withoutVersion { + LDFlagConfigModel *subject = [LDFlagConfigModel flagConfigFromJsonFileNamed:@"featureFlags-withoutVersions"]; + NSMutableDictionary *sameDictionary = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]]; + for (NSString* key in [sameDictionary.allKeys copy]) { + NSMutableDictionary *flagConfigValueDictionary = [NSMutableDictionary dictionaryWithDictionary:sameDictionary[key]]; + flagConfigValueDictionary[kLDFlagConfigJsonDictionaryKeyVersion] = @(kLDFlagConfigVersionDoesNotExist); + sameDictionary[key] = flagConfigValueDictionary; + } + + XCTAssertTrue([subject hasFeaturesEqualToDictionary:sameDictionary]); + + NSMutableDictionary *differentDictionary = [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-excludeNulls-withoutVersions"]; + XCTAssertFalse([subject hasFeaturesEqualToDictionary:differentDictionary]); +} + +@end diff --git a/DarklyTests/Models/LDFlagConfigValueTest.m b/DarklyTests/Models/LDFlagConfigValueTest.m new file mode 100644 index 00000000..5c6c1694 --- /dev/null +++ b/DarklyTests/Models/LDFlagConfigValueTest.m @@ -0,0 +1,257 @@ +// +// LDFlagConfigValueTest.m +// DarklyTests +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import +#import "NSJSONSerialization+Testable.h" +#import "LDFlagConfigValue.h" + +extern NSString * const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString * const kLDFlagConfigJsonDictionaryKeyVersion; + +@interface LDFlagConfigValueTest : XCTestCase + +@end + +@implementation LDFlagConfigValueTest + +-(void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +-(void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +-(void)testInitializer_boolValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + XCTAssertTrue([(NSNumber*)subject.value boolValue]); + XCTAssertEqual(subject.version, 4); +} + +-(void)testInitializer_boolValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + XCTAssertTrue([(NSNumber*)subject.value boolValue]); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_numberValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"numberConfigIsANumber-2-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isANumber"]]; + + XCTAssertEqual([(NSNumber*)subject.value integerValue], 2); + XCTAssertEqual(subject.version, 4); +} + +-(void)testInitializer_numberValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"numberConfigIsANumber-2-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isANumber"]]; + + XCTAssertEqual([(NSNumber*)subject.value integerValue], 2); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_doubleValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"doubleConfigIsADouble-Pi-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isADouble"]]; + + XCTAssertEqual([(NSNumber*)subject.value doubleValue], M_PI); + XCTAssertEqual(subject.version, 3); +} + +-(void)testInitializer_doubleValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"doubleConfigIsADouble-Pi-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isADouble"]]; + + XCTAssertEqual([(NSNumber*)subject.value doubleValue], M_PI); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_stringValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"stringConfigIsAString-someString-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isAString"]]; + + XCTAssertTrue([subject.value isEqualToString:@"someString"]); + XCTAssertEqual(subject.version, 3); +} + +-(void)testInitializer_stringValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"stringConfigIsAString-someString-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isAString"]]; + + XCTAssertTrue([subject.value isEqualToString:@"someString"]); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_arrayValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"arrayConfigIsAnArray-123-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isAnArray"]]; + + NSArray *targetArray = @[@(1), @(2), @(3)]; + XCTAssertTrue([subject.value isEqualToArray:targetArray]); + XCTAssertEqual(subject.version, 5); +} + +-(void)testInitializer_arrayValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"arrayConfigIsAnArray-123-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isAnArray"]]; + + NSArray *targetArray = @[@(1), @(2), @(3)]; + XCTAssertTrue([subject.value isEqualToArray:targetArray]); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_dictionaryValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"dictionaryConfigIsADictionary-3Key-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isADictionary"]]; + + NSDictionary *targetDictionary = @{@"keyA": @(true), @"keyB": @[@(1), @(2), @(3)], @"keyC": @{@"keyD": @"someStringValue"}}; + XCTAssertTrue([subject.value isEqualToDictionary:targetDictionary]); + XCTAssertEqual(subject.version, 4); +} + +-(void)testInitializer_dictionaryValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"dictionaryConfigIsADictionary-3Key-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isADictionary"]]; + + NSDictionary *targetDictionary = @{@"keyA": @(true), @"keyB": @[@(1), @(2), @(3)], @"keyC": @{@"keyD": @"someStringValue"}}; + XCTAssertTrue([subject.value isEqualToDictionary:targetDictionary]); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testInitializer_ObjectIsNil { + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:nil]; + + XCTAssertNil(subject); +} + +-(void)testInitializer_nullValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"nullConfigIsANull-null-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isANull"]]; + + XCTAssertTrue([subject.value isEqual:[NSNull null]]); + XCTAssertEqual(subject.version, 2); +} + +-(void)testInitializer_nullValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"nullConfigIsANull-null-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isANull"]]; + + XCTAssertTrue([subject.value isEqual:[NSNull null]]); + XCTAssertEqual(subject.version, kLDFlagConfigVersionDoesNotExist); +} + +-(void)testEncodeAndDecode_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:subject]; + LDFlagConfigValue *restored = [NSKeyedUnarchiver unarchiveObjectWithData:archive]; + + XCTAssertTrue([subject isEqual:restored]); +} + +-(void)testEncodeAndDecode_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:subject]; + LDFlagConfigValue *restored = [NSKeyedUnarchiver unarchiveObjectWithData:archive]; + + XCTAssertTrue([subject isEqual:restored]); +} + +-(void)testDictionaryValue_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *flagConfigValue = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + NSDictionary *flagDictionary = [flagConfigValue dictionaryValue]; + + XCTAssertEqual(flagConfigValue.value, flagDictionary[kLDFlagConfigJsonDictionaryKeyValue]); + XCTAssertTrue([flagDictionary[kLDFlagConfigJsonDictionaryKeyVersion] isKindOfClass:[NSNumber class]]); + XCTAssertTrue(flagConfigValue.version == [(NSNumber*)flagDictionary[kLDFlagConfigJsonDictionaryKeyVersion] integerValue]); +} + +-(void)testDictionaryValue_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withoutVersion"]; + LDFlagConfigValue *flagConfigValue = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + NSDictionary *flagDictionary = [flagConfigValue dictionaryValue]; + + XCTAssertEqual(flagConfigValue.value, flagDictionary[kLDFlagConfigJsonDictionaryKeyValue]); + XCTAssertTrue([flagDictionary[kLDFlagConfigJsonDictionaryKeyVersion] isKindOfClass:[NSNumber class]]); + XCTAssertTrue(flagConfigValue.version == [(NSNumber*)flagDictionary[kLDFlagConfigJsonDictionaryKeyVersion] integerValue]); +} + +-(void)testEqual_valuesAreTheSame_withVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + LDFlagConfigValue *other = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + XCTAssertTrue([subject isEqual:other]); +} + +-(void)testEqual_valuesAreTheSame_withoutVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + LDFlagConfigValue *other = [LDFlagConfigValue flagConfigValueWithObject:flagConfigStub[@"isABool"]]; + + XCTAssertTrue([subject isEqual:other]); +} + +-(void)testEqual_valuesDiffer_differentValues_withVersion { + id subjectFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:subjectFlagConfigStub[@"isABool"]]; + + id otherFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-false-withVersion"]; + LDFlagConfigValue *other = [LDFlagConfigValue flagConfigValueWithObject:otherFlagConfigStub[@"isABool"]]; + + XCTAssertFalse([subject isEqual:other]); +} + +-(void)testEqual_valuesDiffer_differentValues_withoutVersion { + id subjectFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withoutVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:subjectFlagConfigStub[@"isABool"]]; + + id otherFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-false-withoutVersion"]; + LDFlagConfigValue *other = [LDFlagConfigValue flagConfigValueWithObject:otherFlagConfigStub[@"isABool"]]; + + XCTAssertFalse([subject isEqual:other]); +} + +-(void)testEqual_valuesDiffer_differentVersions { + id subjectFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:subjectFlagConfigStub[@"isABool"]]; + + id otherFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *other = [LDFlagConfigValue flagConfigValueWithObject:otherFlagConfigStub[@"isABool"]]; + other.version += 1; + + XCTAssertFalse([subject isEqual:other]); +} + +-(void)testEqual_valuesDiffer_differentObjects { + id subjectFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:subjectFlagConfigStub[@"isABool"]]; + + XCTAssertFalse([subject isEqual:@"someString"]); +} + +-(void)testEqual_valuesDiffer_otherIsNil { + id subjectFlagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + LDFlagConfigValue *subject = [LDFlagConfigValue flagConfigValueWithObject:subjectFlagConfigStub[@"isABool"]]; + + XCTAssertFalse([subject isEqual:nil]); +} + +@end diff --git a/DarklyTests/Models/LDUserModelTest.m b/DarklyTests/Models/LDUserModelTest.m index 61df0b24..b65f94da 100644 --- a/DarklyTests/Models/LDUserModelTest.m +++ b/DarklyTests/Models/LDUserModelTest.m @@ -12,6 +12,7 @@ #import "LDUserModel+JsonDecodeable.h" #import "NSMutableDictionary+NullRemovable.h" #import "NSString+RemoveWhitespace.h" +#import "NSJSONSerialization+Testable.h" @interface LDUserModelTest : XCTestCase @end @@ -490,14 +491,7 @@ -(void)validateUserModelIsEqualBehaviorUsingUserDictionary:(NSMutableDictionary* } -(NSDictionary*)serverJson { - NSString *filepath = [[NSBundle bundleForClass:[LDUserModelTest class]] pathForResource:@"feature_flags" - ofType:@"json"]; - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfFile:filepath]; - NSDictionary *serverJson = [NSJSONSerialization JSONObjectWithData:data - options:kNilOptions - error:&error]; - return serverJson; + return [NSJSONSerialization jsonObjectFromFileNamed:@"featureFlags-withVersions"]; } -(NSMutableDictionary*)customDictionary { diff --git a/DarklyTests/Models/NSObject+LDFlagConfigValueTest.m b/DarklyTests/Models/NSObject+LDFlagConfigValueTest.m new file mode 100644 index 00000000..c4e778d0 --- /dev/null +++ b/DarklyTests/Models/NSObject+LDFlagConfigValueTest.m @@ -0,0 +1,64 @@ +// +// NSObject+LDFlagConfigValueTest.m +// DarklyTests +// +// Created by Mark Pokorny on 1/31/18. +JMJ +// Copyright © 2018 LaunchDarkly. All rights reserved. +// + +#import +#import "NSObject+LDFlagConfigValue.h" +#import "NSJSONSerialization+Testable.h" + +extern NSString * const kLDFlagConfigJsonDictionaryKeyValue; +extern NSString * const kLDFlagConfigJsonDictionaryKeyVersion; + +@interface NSObject_LDFlagConfigValueTest : XCTestCase +@end + +@implementation NSObject_LDFlagConfigValueTest + +-(void)testIsValueAndVersionDictionary_Yes { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + id subject = (NSDictionary*)flagConfigStub[@"isABool"]; + + XCTAssertTrue([subject isValueAndVersionDictionary]); +} + +-(void)testIsValueAndVersionDictionary_No_MissingValue { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + id subject = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)flagConfigStub[@"isABool"]]; + subject[kLDFlagConfigJsonDictionaryKeyValue] = nil; + + XCTAssertFalse([subject isValueAndVersionDictionary]); +} + +-(void)testIsValueAndVersionDictionary_No_MissingVersion { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + id subject = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)flagConfigStub[@"isABool"]]; + subject[kLDFlagConfigJsonDictionaryKeyVersion] = nil; + + XCTAssertFalse([subject isValueAndVersionDictionary]); +} + +-(void)testIsValueAndVersionDictionary_No_VersionIsNotANumber { + id flagConfigStub = [NSJSONSerialization jsonObjectFromFileNamed:@"boolConfigIsABool-true-withVersion"]; + id subject = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)flagConfigStub[@"isABool"]]; + subject[kLDFlagConfigJsonDictionaryKeyVersion] = @"not a number"; + + XCTAssertFalse([subject isValueAndVersionDictionary]); +} + +-(void)testIsValueAndVersionDictionary_No_EmptyDictionary { + id subject = [NSJSONSerialization jsonObjectFromFileNamed:@"emptyConfig"]; + + XCTAssertFalse([subject isValueAndVersionDictionary]); +} + +-(void)testIsValueAndVersionDictionary_No_NotADictionary { + id subject = @"not a dictionary"; + + XCTAssertFalse([subject isValueAndVersionDictionary]); +} + +@end diff --git a/LaunchDarkly.podspec b/LaunchDarkly.podspec index 5975b017..180b24f5 100644 --- a/LaunchDarkly.podspec +++ b/LaunchDarkly.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "LaunchDarkly" - s.version = "2.10.1" + s.version = "2.11.0" s.summary = "iOS SDK for LaunchDarkly" s.description = <<-DESC @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.tvos.deployment_target = "9.0" s.osx.deployment_target = '10.10' - s.source = { :git => "https://github.com/launchdarkly/ios-client.git", :tag => "2.10.1" } + s.source = { :git => "https://github.com/launchdarkly/ios-client.git", :tag => "2.11.0" } s.source_files = "Darkly/*.{h,m}" diff --git a/Podfile b/Podfile index d2948473..bf786e3d 100644 --- a/Podfile +++ b/Podfile @@ -1,22 +1,22 @@ use_frameworks! target 'Darkly_iOS' do platform :ios, '8.0' - pod 'DarklyEventSource' + pod 'DarklyEventSource', '~> 3.2' end target 'Darkly_tvOS' do platform :tvos, '9.0' - pod 'DarklyEventSource' + pod 'DarklyEventSource', '~> 3.2' end target 'Darkly_watchOS' do platform :watchos, '2.0' - pod 'DarklyEventSource' + pod 'DarklyEventSource', '~> 3.2' end target 'Darkly_osx' do platform :osx, '10.10' - pod 'DarklyEventSource' + pod 'DarklyEventSource', '~> 3.2' end target 'DarklyTests' do diff --git a/Podfile.lock b/Podfile.lock index 6f79e282..13f4cb19 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - DarklyEventSource (3.1.2) + - DarklyEventSource (3.2.0) - OCMock (3.4.1) - OHHTTPStubs (4.8.0): - OHHTTPStubs/Default (= 4.8.0) @@ -16,15 +16,15 @@ PODS: - OHHTTPStubs/OHPathHelpers (4.8.0) DEPENDENCIES: - - DarklyEventSource + - DarklyEventSource (~> 3.2) - OCMock (~> 3.1) - OHHTTPStubs (~> 4.2) SPEC CHECKSUMS: - DarklyEventSource: 701c8e651e792ad2d74b98aae6a85234d810b73f + DarklyEventSource: ad6a75c82b22bea91c75fc980a563f6d2902ce90 OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 OHHTTPStubs: b393565822317305b87a1440d4c7aff131679f66 -PODFILE CHECKSUM: 067a3f5c83c580423c3f8ae10d4ab6f2b7025306 +PODFILE CHECKSUM: f3f36ff2533f4e1230e409cec137989205971a1f -COCOAPODS: 1.3.1 +COCOAPODS: 1.4.0 diff --git a/Pods/DarklyEventSource/LDEventSource/LDEventSource.h b/Pods/DarklyEventSource/LDEventSource/LDEventSource.h index 0c17b1a1..c24645b6 100644 --- a/Pods/DarklyEventSource/LDEventSource/LDEventSource.h +++ b/Pods/DarklyEventSource/LDEventSource/LDEventSource.h @@ -50,12 +50,22 @@ typedef void (^LDEventSourceEventHandler)(LDEvent *event); /// @param headers The http headers to be included + (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers; +/// Returns a new instance of EventSource with the specified URL. +/// +/// @param URL The URL of the EventSource. +/// @param headers The http headers to be included +/// @param connectMethod The http method to use to connect to the EventSource. Default: GET +/// @param connectBody The http body to use to connect to the EventSource. Default: nil ++ (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*)headers connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody; + /// Returns a new instance of EventSource with the specified URL. /// /// @param URL The URL of the EventSource. /// @param headers The http headers to be included /// @param timeoutInterval The request timeout interval in seconds. See NSURLRequest for more details. Default: 5 minutes. -+ (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval; +/// @param connectMethod The http method to use to connect to the EventSource. Default: GET +/// @param connectBody The http body to use to connect to the EventSource. Default: nil ++ (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*)headers timeoutInterval:(NSTimeInterval)timeoutInterval connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody; /// Creates a new instance of EventSource with the specified URL. /// @@ -63,12 +73,22 @@ typedef void (^LDEventSourceEventHandler)(LDEvent *event); /// @param headers The http headers to be included - (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers; +/// Creates a new instance of EventSource with the specified URL. +/// +/// @param URL The URL of the EventSource. +/// @param headers The http headers to be included +/// @param connectMethod The http method to use to connect to the EventSource. Default: GET +/// @param connectBody The http body to use to connect to the EventSource. Default: nil +- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody; + /// Creates a new instance of EventSource with the specified URL. /// /// @param URL The URL of the EventSource. /// @param headers The http headers to be included /// @param timeoutInterval The request timeout interval in seconds. See NSURLRequest for more details. Default: 5 minutes. -- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval; +/// @param connectMethod The http method to use to connect to the EventSource. Default: GET +/// @param connectBody The http body to use to connect to the EventSource. Default: nil +- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody; /// Registers an event handler for the Message event. /// diff --git a/Pods/DarklyEventSource/LDEventSource/LDEventSource.m b/Pods/DarklyEventSource/LDEventSource/LDEventSource.m index 5c93c85d..f1f55000 100644 --- a/Pods/DarklyEventSource/LDEventSource/LDEventSource.m +++ b/Pods/DarklyEventSource/LDEventSource/LDEventSource.m @@ -41,6 +41,8 @@ @interface LDEventSource () { @property (nonatomic, assign) NSTimeInterval retryInterval; @property (nonatomic, assign) NSInteger retryAttempt; @property (readonly, nonatomic, strong) NSDictionary *httpRequestHeaders; +@property (nonatomic, strong) NSString *connectMethod; +@property (nonatomic, strong) NSData *connectBody; @property (nonatomic, strong) id lastEventID; - (void)_open; @@ -55,17 +57,27 @@ + (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval ++ (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*)headers connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody { - return [[LDEventSource alloc] initWithURL:URL httpHeaders:headers timeoutInterval:timeoutInterval]; + return [[LDEventSource alloc] initWithURL:URL httpHeaders:headers timeoutInterval:ES_DEFAULT_TIMEOUT connectMethod:connectMethod connectBody:connectBody]; +} + ++ (instancetype)eventSourceWithURL:(NSURL *)URL httpHeaders:(NSDictionary*)headers timeoutInterval:(NSTimeInterval)timeoutInterval connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody +{ + return [[LDEventSource alloc] initWithURL:URL httpHeaders:headers timeoutInterval:timeoutInterval connectMethod:connectMethod connectBody:connectBody]; } - (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers { - return [self initWithURL:URL httpHeaders:headers timeoutInterval:ES_DEFAULT_TIMEOUT]; + return [self initWithURL:URL httpHeaders:headers timeoutInterval:ES_DEFAULT_TIMEOUT connectMethod:@"GET" connectBody:nil]; +} + +- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody +{ + return [self initWithURL:URL httpHeaders:headers timeoutInterval:ES_DEFAULT_TIMEOUT connectMethod:connectMethod connectBody:connectBody]; } -- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval +- (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary*) headers timeoutInterval:(NSTimeInterval)timeoutInterval connectMethod:(NSString*)connectMethod connectBody:(NSData*)connectBody { self = [super init]; if (self) { @@ -75,6 +87,8 @@ - (instancetype)initWithURL:(NSURL *)URL httpHeaders:(NSDictionary 0) { + request.HTTPMethod = self.connectMethod; + } + + if (self.connectBody.length > 0) { + request.HTTPBody = self.connectBody; + } if (self.session) { [self.session invalidateAndCancel]; diff --git a/Pods/DarklyEventSource/README.md b/Pods/DarklyEventSource/README.md index bc15e767..1213c61a 100644 --- a/Pods/DarklyEventSource/README.md +++ b/Pods/DarklyEventSource/README.md @@ -38,7 +38,7 @@ EventSource *source = [EventSource eventSourceWithURL:serverURL]; #### Listening for Connection State Changes -Additionally, there are `onOpen:`, `onError:`, and `onReadyStateChanged:` methods to receive connection state events. +Additionally, there are `onOpen:`, `onMessage`, `onError:`, and `onReadyStateChanged:` methods to receive connection state events. ```objc NSURL *serverURL = [NSURL URLWithString:@"http://127.0.0.1:8000/"]; diff --git a/Pods/Local Podspecs/DarklyEventSource.podspec.json b/Pods/Local Podspecs/DarklyEventSource.podspec.json index ad357dc4..dad2fe66 100644 --- a/Pods/Local Podspecs/DarklyEventSource.podspec.json +++ b/Pods/Local Podspecs/DarklyEventSource.podspec.json @@ -1,6 +1,6 @@ { "name": "DarklyEventSource", - "version": "3.1.1", + "version": "3.2.0", "summary": "HTML5 Server-Sent Events in your Cocoa app.", "homepage": "https://github.com/launchdarkly/ios-eventsource", "license": "MIT (see LICENSE.txt)", @@ -9,7 +9,7 @@ }, "source": { "git": "https://github.com/launchdarkly/ios-eventsource.git", - "tag": "v3.1.1" + "tag": "3.2.0" }, "source_files": [ "LDEventSource", diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index 6f79e282..13f4cb19 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - DarklyEventSource (3.1.2) + - DarklyEventSource (3.2.0) - OCMock (3.4.1) - OHHTTPStubs (4.8.0): - OHHTTPStubs/Default (= 4.8.0) @@ -16,15 +16,15 @@ PODS: - OHHTTPStubs/OHPathHelpers (4.8.0) DEPENDENCIES: - - DarklyEventSource + - DarklyEventSource (~> 3.2) - OCMock (~> 3.1) - OHHTTPStubs (~> 4.2) SPEC CHECKSUMS: - DarklyEventSource: 701c8e651e792ad2d74b98aae6a85234d810b73f + DarklyEventSource: ad6a75c82b22bea91c75fc980a563f6d2902ce90 OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3 OHHTTPStubs: b393565822317305b87a1440d4c7aff131679f66 -PODFILE CHECKSUM: 067a3f5c83c580423c3f8ae10d4ab6f2b7025306 +PODFILE CHECKSUM: f3f36ff2533f4e1230e409cec137989205971a1f -COCOAPODS: 1.3.1 +COCOAPODS: 1.4.0 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index ff78009a..ae1d87aa 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 01F7D55919C59833456188558FE8D7FA /* OCMExpectationRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 1541B7DBA1AD0A7B65F8FFC607CBD5B5 /* OCMExpectationRecorder.h */; settings = {ATTRIBUTES = (Project, ); }; }; 0310B1523123778B0E3FB78BE3A14095 /* OCMBlockCaller.h in Headers */ = {isa = PBXBuildFile; fileRef = D530BD02AFFFAC8355740377AFEE3DA7 /* OCMBlockCaller.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 076CC6AEFAE06B5E31AE2CA3860FD54A /* DarklyEventSource-macOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 34979088B08D830B9639A87F473A6103 /* DarklyEventSource-macOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 076CC6AEFAE06B5E31AE2CA3860FD54A /* DarklyEventSource-macOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E33CB6687CDAB4DA1AD2E228C84B160 /* DarklyEventSource-macOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 08B95EC0E9E8E488C1F210D31873A678 /* OHHTTPStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = EF760A95F22C50A6B60AECA5D320903C /* OHHTTPStubs.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0AEAD2BEB61CCA26BB0798F2E527BF84 /* OCMRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 65C0919CA083CA15AE160F0D4A37025B /* OCMRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 0D183650A2D88CB6DAD886030A3A2B62 /* OCMBoxedReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = A99F324709D15E97D9B7E7EFD390B810 /* OCMBoxedReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -38,7 +38,7 @@ 353759005B92EEC29E4B15765C4D3EEB /* OCPartialMockObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FA926717A94389A01F7FE7C87C4FDC8 /* OCPartialMockObject.h */; settings = {ATTRIBUTES = (Project, ); }; }; 35675FF5ABBB5D07872C3F48DA96ED6D /* LDEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA49AFC7E73CAB7B63A97FC6963BD84B /* LDEventSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35D4B99EC89BD8895C82FA64695C0125 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ACDF0E08285415092448B937524BBFBC /* Foundation.framework */; }; - 368CB50FFBFF7DB7F817A4F36572BBCB /* DarklyEventSource-tvOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FF9347142BEA1E84D127A54BCCC5DB4 /* DarklyEventSource-tvOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 368CB50FFBFF7DB7F817A4F36572BBCB /* DarklyEventSource-tvOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C40E3FFD873C7D48C730A5838826A87 /* DarklyEventSource-tvOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 38D5085895B3757AF0DCED078EF8B145 /* OCMRealObjectForwarder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FBF42418B3DBA6C8DFFF85F037DBDFF /* OCMRealObjectForwarder.h */; settings = {ATTRIBUTES = (Project, ); }; }; 397B254D629C8F6DCDEB6982B52EE1B6 /* Pods-Darkly_watchOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F50D3F52D7CB7847A47C5F75170511F6 /* Pods-Darkly_watchOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3AC7DF75455976534659CC5ED2436C27 /* OHHTTPStubs-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BE2D23B2F7585B9AA19F3761C6D116D /* OHHTTPStubs-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -70,7 +70,7 @@ 71213523998EC4038EEF2881118A57A1 /* NSInvocation+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F90968080A13E2B5A51548EB12B78716 /* NSInvocation+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 72C8CC2855787B9DC1A37DDEB5E24155 /* OCMFunctionsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CF4197454D6EDFC7E82D1585BA642113 /* OCMFunctionsPrivate.h */; settings = {ATTRIBUTES = (Project, ); }; }; 74BC62D6FEB722F4976016FD4DCA870B /* OCMObserverRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F51EF986FA63F62D8ABE46B5A0EF12E /* OCMObserverRecorder.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - 7AD8CDC8F994F9A30A70576930F1EF95 /* DarklyEventSource-iOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A8C4897465F74B77310822641F36F080 /* DarklyEventSource-iOS-dummy.m */; }; + 7AD8CDC8F994F9A30A70576930F1EF95 /* DarklyEventSource-iOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C38A025BC21157F653CA5A21398FE0 /* DarklyEventSource-iOS-dummy.m */; }; 7B006E74668E41702B8881E724728DE9 /* OCMBlockCaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E025880705C042E53B065C6BF916CB5 /* OCMBlockCaller.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 7B3D75F6DB24A43FB02D2818D4864958 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 528B66A2BC53927BB64C91DB055F0D5D /* Foundation.framework */; }; 7D94DE66B8B5E3B4A0B5E53A88C3FAEE /* OCMIndirectReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = F0ECB43B373A36914B537E7B9B076175 /* OCMIndirectReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -81,7 +81,7 @@ 905A8D955AE02C6B8D2DBBFD1FF33427 /* LDEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = AA49AFC7E73CAB7B63A97FC6963BD84B /* LDEventSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 915751C97068AF644D3FE4498633DAB1 /* OCMExceptionReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DDCE1AC39485BC4C5E1642371CBC5BD /* OCMExceptionReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 92F61FA0ACB1B709FFEBE1D9DC2C68E5 /* OCMPassByRefSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = A28DA38325D7E02D324E31F1806EF191 /* OCMPassByRefSetter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 95687EEBD9E7FCE1BFDBAF31A3397B1F /* DarklyEventSource-watchOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F919E593698DCC1B8650577A96EB8CD /* DarklyEventSource-watchOS-dummy.m */; }; + 95687EEBD9E7FCE1BFDBAF31A3397B1F /* DarklyEventSource-watchOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E1C1F9D7DAF1E94D08AF3CD6C446409B /* DarklyEventSource-watchOS-dummy.m */; }; 974362D040AC870A5D72E365B21A8CE4 /* OCMExceptionReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 60700428BE87830C6BA702CCD3998F89 /* OCMExceptionReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; 9A92686CF21CC8ECAB69A3CFB621FA4B /* OCMock-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B8283FF686308B6F58A4104348BA29B /* OCMock-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9AD757E4C5E491AD307CF40DAAA81645 /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = B73316F0AB2ADA478403780E72C212FD /* OHHTTPStubs+NSURLSessionConfiguration.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; @@ -93,7 +93,7 @@ A58AB2AAA4C1B2BEFEE21DC0EF2194C4 /* OHHTTPStubsResponse+JSON.h in Headers */ = {isa = PBXBuildFile; fileRef = DC67523FE012358DE75EE4A668A5A664 /* OHHTTPStubsResponse+JSON.h */; settings = {ATTRIBUTES = (Public, ); }; }; A59AE6011C58D3D2F009DEF7F5AA259B /* OCMInvocationExpectation.m in Sources */ = {isa = PBXBuildFile; fileRef = 20086391A8D8523A58D226AAEA76DA06 /* OCMInvocationExpectation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; A9571E56544CD912F0DA62E545DB2419 /* OCMReturnValueProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F043D9D4D153EF80F85834A3D728DE /* OCMReturnValueProvider.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A992DC3E5A593C9641D59707DBF9CF0E /* DarklyEventSource-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E1DF06BEE2041494877E39ECBA02D84F /* DarklyEventSource-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A992DC3E5A593C9641D59707DBF9CF0E /* DarklyEventSource-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 887C6CAEC0919C7D49C33ED75924DF6E /* DarklyEventSource-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; ABC47FD397187DA12E4CB4C46F125957 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 528B66A2BC53927BB64C91DB055F0D5D /* Foundation.framework */; }; AF8EFDAD5DAF96A49EE0BC9A948280F3 /* DarklyEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D5DD619EF039D6A394E253938F85A12 /* DarklyEventSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; B1960493BE31653F99CCAE64D1AAC7E0 /* OHPathHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A9CF35EF466BC4B915F48EF27C1846AB /* OHPathHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -106,7 +106,7 @@ B677137A7B135394B0C7185E9D3D91A9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FBFEAC80AB2E00CFC60743201EA79E8E /* Foundation.framework */; }; B852DBE3593443215A94EEFD59786402 /* NSObject+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 02335183C4ABC789319BEC9F361F888E /* NSObject+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; BD181F7E8C0BB325B051DA9F2FBD71BC /* NSMethodSignature+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DFF803BFA99780D0C3AFFBD95CBA6BF /* NSMethodSignature+OCMAdditions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - BE82F80E7D6D501CF46925D6E25B15E1 /* DarklyEventSource-watchOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 95D9AA0F43AAAEF45D791A80EB1F746F /* DarklyEventSource-watchOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE82F80E7D6D501CF46925D6E25B15E1 /* DarklyEventSource-watchOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E03662098C79CCBA047D87E60E9CD8DA /* DarklyEventSource-watchOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; C12846B090288AFA42CEA099276F8437 /* DarklyEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D5DD619EF039D6A394E253938F85A12 /* DarklyEventSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; C390FE838362EBE94E5A5052CBF6196F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D922F2D72779A1967524BBBAECEF3120 /* CFNetwork.framework */; }; C65A28088F0668711386816290C3880E /* OCMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F1B9C604582097FDE56BFE0E5DBD7D8 /* OCMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -115,7 +115,7 @@ CFFD80CB651FDC49953FB5D8672038AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ACDF0E08285415092448B937524BBFBC /* Foundation.framework */; }; D9C7A57A574090442C8631BA856B1599 /* OCMMacroState.m in Sources */ = {isa = PBXBuildFile; fileRef = 69AC1833240D28BD3D8461ED1935EDB1 /* OCMMacroState.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; E14A5FC189CD75054825E45DA6D9F293 /* OCMBoxedReturnValueProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C7FB0444707E5FEEB30DACDFD164A0 /* OCMBoxedReturnValueProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E17BB96FF8264DADDCAE9B5932C94BF3 /* DarklyEventSource-macOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F45B985D33C4A6B647FEDEC72A2B20FC /* DarklyEventSource-macOS-dummy.m */; }; + E17BB96FF8264DADDCAE9B5932C94BF3 /* DarklyEventSource-macOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CEF0E82282A5BA582E0C41D28BBBE57 /* DarklyEventSource-macOS-dummy.m */; }; E3D64C1E36A44947D6B7B2A63224C5AC /* Pods-DarklyTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6214AED575698BFB1B7374E4F72F399F /* Pods-DarklyTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; E4070427AD7F08E573CAA22DCEB79FB1 /* OCProtocolMockObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312591EA5F95D2A26205C563B9FC872 /* OCProtocolMockObject.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; E4A87D8BA9BA24EE81DEC41C8BE98F2B /* OCMVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = E736DD7FFDD3BE1C73A56D0CCAE7AD54 /* OCMVerifier.h */; settings = {ATTRIBUTES = (Project, ); }; }; @@ -125,7 +125,7 @@ EFC1318446EB79DC091867000F45D61C /* OCMLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 786D1550089C847D816C575010098672 /* OCMLocation.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; F02C2CD0A94965FFA8928B316D5825CB /* OCMArg.h in Headers */ = {isa = PBXBuildFile; fileRef = ECCFC10038A1B1EDC39E7F558EBF050B /* OCMArg.h */; settings = {ATTRIBUTES = (Public, ); }; }; F03D3AA4304C5670F89855FFBEC8B652 /* Pods-DarklyTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EDFC43501CD7FC2E1A1E3CA1470A04B9 /* Pods-DarklyTests-dummy.m */; }; - F22E6173EA55588F0007F80E936A13F5 /* DarklyEventSource-tvOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 77C1F0ADE1DF2380F6FCEEA6252A8E10 /* DarklyEventSource-tvOS-dummy.m */; }; + F22E6173EA55588F0007F80E936A13F5 /* DarklyEventSource-tvOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1320E1AB0AB0D789A16983AA70F3867B /* DarklyEventSource-tvOS-dummy.m */; }; F90421F35E91B0A952234BEF474030B6 /* DarklyEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D5DD619EF039D6A394E253938F85A12 /* DarklyEventSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; F98852F58D5FDF0191647087678ABE70 /* OCMArg.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C457218CF6FB6FB940AF05DA169610 /* OCMArg.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; FAB7A1E7E1414DC657BA79D07135E15B /* OCMock.h in Headers */ = {isa = PBXBuildFile; fileRef = E7EEA70FD196A9350783D5F26267EA36 /* OCMock.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -189,22 +189,21 @@ 01FCE6E495553E209A455B8F5412E9D1 /* DarklyEventSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DarklyEventSource.framework; path = "DarklyEventSource-watchOS.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 02335183C4ABC789319BEC9F361F888E /* NSObject+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+OCMAdditions.m"; path = "Source/OCMock/NSObject+OCMAdditions.m"; sourceTree = ""; }; 03BE6D0006314A4C9C17031BC9EDEC50 /* Pods-Darkly_osx-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Darkly_osx-dummy.m"; sourceTree = ""; }; - 0A0C3541D5B2550F453161199C3523B7 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-watchOS/Info.plist"; sourceTree = ""; }; + 08AAF989C5B8490560379149F700BE18 /* DarklyEventSource-tvOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-tvOS.xcconfig"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig"; sourceTree = ""; }; 0A670828140FDCF35A8A3D3D28A34561 /* OHHTTPStubs.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OHHTTPStubs.xcconfig; sourceTree = ""; }; - 0AB9818BBCAAD6EDFC9CB2C6106D8705 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0B8283FF686308B6F58A4104348BA29B /* OCMock-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OCMock-umbrella.h"; sourceTree = ""; }; 0CDDBBF20B9E8B60CCF52A35F23C2768 /* OCMArgAction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMArgAction.h; path = Source/OCMock/OCMArgAction.h; sourceTree = ""; }; 0DDCE1AC39485BC4C5E1642371CBC5BD /* OCMExceptionReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMExceptionReturnValueProvider.m; path = Source/OCMock/OCMExceptionReturnValueProvider.m; sourceTree = ""; }; 0E025880705C042E53B065C6BF916CB5 /* OCMBlockCaller.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMBlockCaller.m; path = Source/OCMock/OCMBlockCaller.m; sourceTree = ""; }; + 0E33CB6687CDAB4DA1AD2E228C84B160 /* DarklyEventSource-macOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-macOS-umbrella.h"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-umbrella.h"; sourceTree = ""; }; 0FA9BAC5F5AA8C7555A63F5E968C150C /* NSMethodSignature+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMethodSignature+OCMAdditions.h"; path = "Source/OCMock/NSMethodSignature+OCMAdditions.h"; sourceTree = ""; }; 117B584DCF407651FC99BDB681682B55 /* Pods-Darkly_iOS-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Darkly_iOS-resources.sh"; sourceTree = ""; }; - 11E5214A5E825730F5D6B9804EFA6E4A /* DarklyEventSource-tvOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-tvOS-prefix.pch"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-prefix.pch"; sourceTree = ""; }; - 1233506F8B9067704EE12EB44DAAD3CC /* DarklyEventSource-iOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "DarklyEventSource-iOS.modulemap"; sourceTree = ""; }; 128B8A1056ECFB29107F015AC4DD4250 /* Pods-Darkly_osx-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Darkly_osx-acknowledgements.markdown"; sourceTree = ""; }; + 1320E1AB0AB0D789A16983AA70F3867B /* DarklyEventSource-tvOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-tvOS-dummy.m"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-dummy.m"; sourceTree = ""; }; 1541B7DBA1AD0A7B65F8FFC607CBD5B5 /* OCMExpectationRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMExpectationRecorder.h; path = Source/OCMock/OCMExpectationRecorder.h; sourceTree = ""; }; 159BA483E378F5A628582FF68CE1783E /* OCMInvocationMatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMInvocationMatcher.h; path = Source/OCMock/OCMInvocationMatcher.h; sourceTree = ""; }; - 187D2BDA10C0B70EC2472E77A35173E0 /* DarklyEventSource-iOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "DarklyEventSource-iOS.xcconfig"; sourceTree = ""; }; 187F88505BDAA6C7F183ED50F09CE8B6 /* Pods-DarklyTests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DarklyTests-resources.sh"; sourceTree = ""; }; + 18C38A025BC21157F653CA5A21398FE0 /* DarklyEventSource-iOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DarklyEventSource-iOS-dummy.m"; sourceTree = ""; }; 18C457218CF6FB6FB940AF05DA169610 /* OCMArg.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMArg.m; path = Source/OCMock/OCMArg.m; sourceTree = ""; }; 1AFC0F519CA2ABEEF80E7347EF34382C /* OCObserverMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCObserverMockObject.h; path = Source/OCMock/OCObserverMockObject.h; sourceTree = ""; }; 1DD72F9E4A9CF0C4E710F30B8C337243 /* OCMArgAction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMArgAction.m; path = Source/OCMock/OCMArgAction.m; sourceTree = ""; }; @@ -218,9 +217,8 @@ 27467853512D2003F1639D1425ABA364 /* LDEventSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = LDEventSource.m; path = LDEventSource/LDEventSource.m; sourceTree = ""; }; 2AC64AA2A942523B078445719823594D /* OCMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMockObject.h; path = Source/OCMock/OCMockObject.h; sourceTree = ""; }; 2B49D1E3B3F51E47356F0D5D024369D2 /* Pods-DarklyTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DarklyTests-frameworks.sh"; sourceTree = ""; }; - 2D0C3231CA29C867AEFF3CC147611931 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-macOS/Info.plist"; sourceTree = ""; }; + 2BEAB801B1A9EF20CFD64E9805105EA4 /* DarklyEventSource-iOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DarklyEventSource-iOS-prefix.pch"; sourceTree = ""; }; 3054A0C1BA1392D2CFA6E4540AF0C3CF /* OCMBlockArgCaller.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMBlockArgCaller.h; path = Source/OCMock/OCMBlockArgCaller.h; sourceTree = ""; }; - 34979088B08D830B9639A87F473A6103 /* DarklyEventSource-macOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-macOS-umbrella.h"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-umbrella.h"; sourceTree = ""; }; 35EE13696C7E2F0B2A823F0323A40E2C /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36EF2A58593920A528EB346E42F18C19 /* Compatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Compatibility.h; path = OHHTTPStubs/Sources/Compatibility.h; sourceTree = ""; }; 38046D70E8B2DCD80FE24AC71CE3C528 /* Pods-Darkly_tvOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Darkly_tvOS-umbrella.h"; sourceTree = ""; }; @@ -228,9 +226,8 @@ 3AED0E22AA228BA1D18CC0641DAE659C /* Pods-Darkly_iOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Darkly_iOS-umbrella.h"; sourceTree = ""; }; 3B6647FF28FFA097E8F2269CFD4713C8 /* OHPathHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHPathHelpers.m; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.m; sourceTree = ""; }; 3BE2D23B2F7585B9AA19F3761C6D116D /* OHHTTPStubs-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubs-umbrella.h"; sourceTree = ""; }; - 3CD4B50B136405244BAAF97DD7ABCC83 /* DarklyEventSource-tvOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-tvOS.xcconfig"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig"; sourceTree = ""; }; - 3FF9347142BEA1E84D127A54BCCC5DB4 /* DarklyEventSource-tvOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-tvOS-umbrella.h"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-umbrella.h"; sourceTree = ""; }; 411D0C20238413BDAE6873846A933D0A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + 4375CA90EBC88CD1948269572E93EDE5 /* DarklyEventSource-macOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-macOS.xcconfig"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig"; sourceTree = ""; }; 43B336800A0A8D1CDE33E78FB261B2A4 /* Pods-Darkly_watchOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Darkly_watchOS.modulemap"; sourceTree = ""; }; 44E13D1AB2457923E89EDABB9FE7D5C5 /* NSValue+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSValue+OCMAdditions.h"; path = "Source/OCMock/NSValue+OCMAdditions.h"; sourceTree = ""; }; 45C88E7B8B282A7217B488B0529A4485 /* OCMFunctions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMFunctions.h; path = Source/OCMock/OCMFunctions.h; sourceTree = ""; }; @@ -239,6 +236,7 @@ 4806A26F6F06A60EDC216E00AD3F6069 /* DarklyEventSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DarklyEventSource.framework; path = "DarklyEventSource-macOS.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 49DBE0583AD97FC7AFD40E44B6ADD0C3 /* OCMNotificationPoster.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMNotificationPoster.m; path = Source/OCMock/OCMNotificationPoster.m; sourceTree = ""; }; 4A47E8FDDD2E93EC278772011EC025CC /* OHHTTPStubs-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "OHHTTPStubs-dummy.m"; sourceTree = ""; }; + 4C5B36E2E39491245B2A344E35F3E13D /* DarklyEventSource-tvOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-tvOS-prefix.pch"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-prefix.pch"; sourceTree = ""; }; 4C914CB92E7CBEBC694137862D8C776F /* Pods-Darkly_tvOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Darkly_tvOS-dummy.m"; sourceTree = ""; }; 4DFF803BFA99780D0C3AFFBD95CBA6BF /* NSMethodSignature+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMethodSignature+OCMAdditions.m"; path = "Source/OCMock/NSMethodSignature+OCMAdditions.m"; sourceTree = ""; }; 4EDE5FD7DEC5932C7611067E499D375E /* Pods-Darkly_osx-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Darkly_osx-umbrella.h"; sourceTree = ""; }; @@ -253,11 +251,10 @@ 5828AAA30797BCDDA3F0712018D6D690 /* Pods-Darkly_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_iOS.release.xcconfig"; sourceTree = ""; }; 588831B3C11013BFB9C663AE9D5DE56F /* OCObserverMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCObserverMockObject.m; path = Source/OCMock/OCObserverMockObject.m; sourceTree = ""; }; 5C3D6B768DE17A3E7C6D7B12C635477B /* OCMReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMReturnValueProvider.h; path = Source/OCMock/OCMReturnValueProvider.h; sourceTree = ""; }; + 5C40E3FFD873C7D48C730A5838826A87 /* DarklyEventSource-tvOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-tvOS-umbrella.h"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-umbrella.h"; sourceTree = ""; }; 5D02AD8B359F811CAEC7E5C2A272E5DE /* OCMPassByRefSetter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMPassByRefSetter.m; path = Source/OCMock/OCMPassByRefSetter.m; sourceTree = ""; }; - 5D05371A8E378545579895FA18004BFF /* DarklyEventSource-macOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-macOS.modulemap"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS.modulemap"; sourceTree = ""; }; 5DDB0218B64211CC03C9DC1FF617998F /* OHHTTPStubsResponse.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsResponse.m; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.m; sourceTree = ""; }; 5F71D39FF301233AD6EAC6ED58023E9F /* Pods-Darkly_iOS-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Darkly_iOS-acknowledgements.markdown"; sourceTree = ""; }; - 5F919E593698DCC1B8650577A96EB8CD /* DarklyEventSource-watchOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-watchOS-dummy.m"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-dummy.m"; sourceTree = ""; }; 60700428BE87830C6BA702CCD3998F89 /* OCMExceptionReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMExceptionReturnValueProvider.h; path = Source/OCMock/OCMExceptionReturnValueProvider.h; sourceTree = ""; }; 6214AED575698BFB1B7374E4F72F399F /* Pods-DarklyTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DarklyTests-umbrella.h"; sourceTree = ""; }; 6312591EA5F95D2A26205C563B9FC872 /* OCProtocolMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCProtocolMockObject.m; path = Source/OCMock/OCProtocolMockObject.m; sourceTree = ""; }; @@ -268,18 +265,20 @@ 69137BDB374DCCF0353013C57F8D9061 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69AC1833240D28BD3D8461ED1935EDB1 /* OCMMacroState.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMMacroState.m; path = Source/OCMock/OCMMacroState.m; sourceTree = ""; }; 6BEB5371A9B9E754AC32F232018AE56C /* NSNotificationCenter+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSNotificationCenter+OCMAdditions.m"; path = "Source/OCMock/NSNotificationCenter+OCMAdditions.m"; sourceTree = ""; }; - 6EA8DF2D1B887AF27C1B52538CFBCDE3 /* DarklyEventSource-macOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-macOS-prefix.pch"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-prefix.pch"; sourceTree = ""; }; 6F1058C5F0FC886356D2FC00A9FBBF20 /* Pods-Darkly_osx-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Darkly_osx-resources.sh"; sourceTree = ""; }; - 70E090DFA4166A4D9E1ABC7C2CDCC5F3 /* DarklyEventSource-iOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DarklyEventSource-iOS-prefix.pch"; sourceTree = ""; }; + 712F0F0ED8527D8133C8E2552B8EC681 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-macOS/Info.plist"; sourceTree = ""; }; + 7195D8AD39386A9F1DD77163CD1A275D /* DarklyEventSource-macOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-macOS-prefix.pch"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-prefix.pch"; sourceTree = ""; }; 775FC1D23E9B6EA722C37873DE4F075B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 77C1F0ADE1DF2380F6FCEEA6252A8E10 /* DarklyEventSource-tvOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-tvOS-dummy.m"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS-dummy.m"; sourceTree = ""; }; 786D1550089C847D816C575010098672 /* OCMLocation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMLocation.m; path = Source/OCMock/OCMLocation.m; sourceTree = ""; }; + 792329ABC730A9F220F8B0829056777B /* DarklyEventSource-tvOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-tvOS.modulemap"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS.modulemap"; sourceTree = ""; }; 79234D9DB87E5C7FB6B8F7FAC6C79FCA /* OCMExpectationRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMExpectationRecorder.m; path = Source/OCMock/OCMExpectationRecorder.m; sourceTree = ""; }; 7BD1F6749A3FA26D87844207325DE6A1 /* OCMConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMConstraint.m; path = Source/OCMock/OCMConstraint.m; sourceTree = ""; }; + 7DFA77F39699B1284C6FC8983054870D /* DarklyEventSource-iOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "DarklyEventSource-iOS.modulemap"; sourceTree = ""; }; 819D8ECA744A54362D07EA95D9379062 /* NSValue+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSValue+OCMAdditions.m"; path = "Source/OCMock/NSValue+OCMAdditions.m"; sourceTree = ""; }; 83C7FB0444707E5FEEB30DACDFD164A0 /* OCMBoxedReturnValueProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMBoxedReturnValueProvider.h; path = Source/OCMock/OCMBoxedReturnValueProvider.h; sourceTree = ""; }; 851363804B70181A5BDC3276E1394828 /* OCMock.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = OCMock.xcconfig; sourceTree = ""; }; 85DC97C8ECB4FC19270DFB782041DEE9 /* Pods-Darkly_watchOS-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Darkly_watchOS-acknowledgements.markdown"; sourceTree = ""; }; + 887C6CAEC0919C7D49C33ED75924DF6E /* DarklyEventSource-iOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DarklyEventSource-iOS-umbrella.h"; sourceTree = ""; }; 8BBF7B3840A36892D14C230FC55B3B64 /* OCMInvocationMatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMInvocationMatcher.m; path = Source/OCMock/OCMInvocationMatcher.m; sourceTree = ""; }; 8CCDA02B757F342E6979CB5FECBCC8A0 /* Pods-Darkly_osx.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_osx.debug.xcconfig"; sourceTree = ""; }; 8D5DD619EF039D6A394E253938F85A12 /* DarklyEventSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DarklyEventSource.h; path = LDEventSource/DarklyEventSource.h; sourceTree = ""; }; @@ -288,23 +287,26 @@ 904227180DDE68F8E40C85777E8B4A62 /* OCClassMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCClassMockObject.m; path = Source/OCMock/OCClassMockObject.m; sourceTree = ""; }; 92169E8DD3128768C9013D5F2AF89DBA /* Pods-Darkly_osx.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_osx.release.xcconfig"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 95D9AA0F43AAAEF45D791A80EB1F746F /* DarklyEventSource-watchOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-watchOS-umbrella.h"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-umbrella.h"; sourceTree = ""; }; 96715FCBD819314A9A12ADE3BEFE83EC /* OCProtocolMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCProtocolMockObject.h; path = Source/OCMock/OCProtocolMockObject.h; sourceTree = ""; }; 9777CF374010928DB62BF43AC53895CE /* Pods-Darkly_watchOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_watchOS.debug.xcconfig"; sourceTree = ""; }; + 9ABFD2CAC06E13B40AE20B368339400A /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-watchOS/Info.plist"; sourceTree = ""; }; + 9CEF0E82282A5BA582E0C41D28BBBE57 /* DarklyEventSource-macOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-macOS-dummy.m"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-dummy.m"; sourceTree = ""; }; + 9E0252D54C50E1C39BCF728FE4F9350F /* DarklyEventSource-watchOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-watchOS.modulemap"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS.modulemap"; sourceTree = ""; }; 9E649BE19BCA5516709BC755EC9FEEC7 /* OCClassMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCClassMockObject.h; path = Source/OCMock/OCClassMockObject.h; sourceTree = ""; }; 9EB28608957FFF3FE5D9F73B3FBFA7F3 /* OCMFunctions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMFunctions.m; path = Source/OCMock/OCMFunctions.m; sourceTree = ""; }; 9FA926717A94389A01F7FE7C87C4FDC8 /* OCPartialMockObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCPartialMockObject.h; path = Source/OCMock/OCPartialMockObject.h; sourceTree = ""; }; + A21E27698C418BCA6A3A0BDE789A0CEE /* DarklyEventSource-watchOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-watchOS.xcconfig"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig"; sourceTree = ""; }; A252F33D314FA7E7ECBDF0DF9A105B26 /* OCMInvocationStub.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMInvocationStub.m; path = Source/OCMock/OCMInvocationStub.m; sourceTree = ""; }; A28DA38325D7E02D324E31F1806EF191 /* OCMPassByRefSetter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMPassByRefSetter.h; path = Source/OCMock/OCMPassByRefSetter.h; sourceTree = ""; }; A370FB0204072CE916A528EF832C15A0 /* Pods-Darkly_watchOS-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Darkly_watchOS-resources.sh"; sourceTree = ""; }; A3A0E677208FD6544BB57C84E476569B /* Pods-Darkly_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_iOS.debug.xcconfig"; sourceTree = ""; }; - A4157B63672F6709E0EE06D2D14D6F36 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-tvOS/Info.plist"; sourceTree = ""; }; A4424D4B5E382A3ECC8EEFECD5134053 /* Pods_Darkly_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Darkly_watchOS.framework; path = "Pods-Darkly_watchOS.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; A4ECE4E53237844F4AE3D13B41379C45 /* NSNotificationCenter+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSNotificationCenter+OCMAdditions.h"; path = "Source/OCMock/NSNotificationCenter+OCMAdditions.h"; sourceTree = ""; }; A528657BFE7C565C8EE90EC0CDCDE385 /* OCMRealObjectForwarder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMRealObjectForwarder.m; path = Source/OCMock/OCMRealObjectForwarder.m; sourceTree = ""; }; A55F61C2B80C4D9FCF16108F6CDDCAFF /* Pods_Darkly_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Darkly_osx.framework; path = "Pods-Darkly_osx.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + A6529C6A7D1184CAFA34DE77FBB3937E /* DarklyEventSource-iOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "DarklyEventSource-iOS.xcconfig"; sourceTree = ""; }; + A7C7E813043B5D1D65AD9D62D7AFC21D /* DarklyEventSource-macOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-macOS.modulemap"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS.modulemap"; sourceTree = ""; }; A8A9B0ADD858339D3D15CABD60856848 /* OCMObserverRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMObserverRecorder.h; path = Source/OCMock/OCMObserverRecorder.h; sourceTree = ""; }; - A8C4897465F74B77310822641F36F080 /* DarklyEventSource-iOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DarklyEventSource-iOS-dummy.m"; sourceTree = ""; }; A99F324709D15E97D9B7E7EFD390B810 /* OCMBoxedReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMBoxedReturnValueProvider.m; path = Source/OCMock/OCMBoxedReturnValueProvider.m; sourceTree = ""; }; A9C1CBC9DD5355EADD8612491283EB11 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A9CF35EF466BC4B915F48EF27C1846AB /* OHPathHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHPathHelpers.h; path = OHHTTPStubs/Sources/OHPathHelpers/OHPathHelpers.h; sourceTree = ""; }; @@ -313,8 +315,8 @@ AAFC77C8C368F1ECF05CE452A2FA5C9A /* Pods-Darkly_osx-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Darkly_osx-acknowledgements.plist"; sourceTree = ""; }; AB9894BF60A959DF87199364FF9F2E52 /* Pods-Darkly_iOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Darkly_iOS-dummy.m"; sourceTree = ""; }; ACDF0E08285415092448B937524BBFBC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - AE613C43360883DDF65ACF26FD21A0E5 /* DarklyEventSource-macOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-macOS.xcconfig"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig"; sourceTree = ""; }; AEDB723B04A04A5EB44E431DB76AB86F /* Pods-DarklyTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DarklyTests.release.xcconfig"; sourceTree = ""; }; + B18DCEE55CEED96588260EFCAD19B97D /* DarklyEventSource-watchOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-watchOS-prefix.pch"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-prefix.pch"; sourceTree = ""; }; B309EA5ED7C7F03F08835B7C48F3B1E8 /* OHHTTPStubsResponse.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsResponse.h; path = OHHTTPStubs/Sources/OHHTTPStubsResponse.h; sourceTree = ""; }; B67F188C9F7107615562C35BE204FB48 /* OHHTTPStubs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = OHHTTPStubs.framework; path = OHHTTPStubs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B73316F0AB2ADA478403780E72C212FD /* OHHTTPStubs+NSURLSessionConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubs+NSURLSessionConfiguration.m"; path = "OHHTTPStubs/Sources/NSURLSession/OHHTTPStubs+NSURLSessionConfiguration.m"; sourceTree = ""; }; @@ -324,9 +326,7 @@ BBC5EE03E32233D0CB90090019393036 /* DarklyEventSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DarklyEventSource.framework; path = "DarklyEventSource-iOS.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; C6929161EDF26FD1145CA76848A0BF5F /* Pods-Darkly_watchOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Darkly_watchOS-dummy.m"; sourceTree = ""; }; C9EDE1211E7858C38AF1D41AB7FEC624 /* OCMVerifier.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMVerifier.m; path = Source/OCMock/OCMVerifier.m; sourceTree = ""; }; - CA01659C19D8CEFB2F9185124CD88C19 /* DarklyEventSource-tvOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-tvOS.modulemap"; path = "../DarklyEventSource-tvOS/DarklyEventSource-tvOS.modulemap"; sourceTree = ""; }; CA0B8765C7CF08D814754C0A0F8C1203 /* NSInvocation+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSInvocation+OCMAdditions.h"; path = "Source/OCMock/NSInvocation+OCMAdditions.h"; sourceTree = ""; }; - CD22797E9155CDCA31F3577065B0C184 /* DarklyEventSource-watchOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; name = "DarklyEventSource-watchOS.modulemap"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS.modulemap"; sourceTree = ""; }; CDF9C4454BA6ADEBD018B50B158A146D /* Pods-Darkly_watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_watchOS.release.xcconfig"; sourceTree = ""; }; CF4197454D6EDFC7E82D1585BA642113 /* OCMFunctionsPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMFunctionsPrivate.h; path = Source/OCMock/OCMFunctionsPrivate.h; sourceTree = ""; }; CFC12327A0EA89C6F9DA4E18E5EC031E /* Pods-Darkly_tvOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Darkly_tvOS.modulemap"; sourceTree = ""; }; @@ -336,14 +336,15 @@ D58F9D9D286DCACCE410D1B18B947A74 /* Pods-Darkly_tvOS-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Darkly_tvOS-acknowledgements.markdown"; sourceTree = ""; }; D6B17CFA609D4F1BCEB6CD952F6BDF8D /* NSObject+OCMAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+OCMAdditions.h"; path = "Source/OCMock/NSObject+OCMAdditions.h"; sourceTree = ""; }; D922F2D72779A1967524BBBAECEF3120 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; + D93BDC50ECBE34F6A0FD8F9E1A65B72B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../DarklyEventSource-tvOS/Info.plist"; sourceTree = ""; }; DA744B745981F85B4555A78005CA3DB7 /* DarklyEventSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DarklyEventSource.framework; path = "DarklyEventSource-tvOS.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; DA88DD3505590FB8494AA98BC814B6AF /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DBC967AB84A2DB511391E4BC67F35146 /* Pods-Darkly_iOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Darkly_iOS.modulemap"; sourceTree = ""; }; DC67523FE012358DE75EE4A668A5A664 /* OHHTTPStubsResponse+JSON.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+JSON.h"; path = "OHHTTPStubs/Sources/JSON/OHHTTPStubsResponse+JSON.h"; sourceTree = ""; }; DD89BDCD8F32B7F4CE4E244B4F706C79 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DE7B054EF1D513FB1CDAF343DF48E695 /* OCPartialMockObject.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCPartialMockObject.m; path = Source/OCMock/OCPartialMockObject.m; sourceTree = ""; }; - E17394FA0678B937B45BE3B1F2950085 /* DarklyEventSource-watchOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "DarklyEventSource-watchOS.xcconfig"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig"; sourceTree = ""; }; - E1DF06BEE2041494877E39ECBA02D84F /* DarklyEventSource-iOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DarklyEventSource-iOS-umbrella.h"; sourceTree = ""; }; + E03662098C79CCBA047D87E60E9CD8DA /* DarklyEventSource-watchOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-watchOS-umbrella.h"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-umbrella.h"; sourceTree = ""; }; + E1C1F9D7DAF1E94D08AF3CD6C446409B /* DarklyEventSource-watchOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-watchOS-dummy.m"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-dummy.m"; sourceTree = ""; }; E736DD7FFDD3BE1C73A56D0CCAE7AD54 /* OCMVerifier.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMVerifier.h; path = Source/OCMock/OCMVerifier.h; sourceTree = ""; }; E7569725EF501048F400041BB722B198 /* Pods-Darkly_watchOS-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Darkly_watchOS-acknowledgements.plist"; sourceTree = ""; }; E78728B690C4681A0E67730F64F145E7 /* Pods-Darkly_iOS-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Darkly_iOS-acknowledgements.plist"; sourceTree = ""; }; @@ -356,15 +357,14 @@ EEF775C9BCEB8619F891533C3F4D5442 /* OCMInvocationExpectation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMInvocationExpectation.h; path = Source/OCMock/OCMInvocationExpectation.h; sourceTree = ""; }; EF760A95F22C50A6B60AECA5D320903C /* OHHTTPStubs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubs.h; path = OHHTTPStubs/Sources/OHHTTPStubs.h; sourceTree = ""; }; F0ECB43B373A36914B537E7B9B076175 /* OCMIndirectReturnValueProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = OCMIndirectReturnValueProvider.m; path = Source/OCMock/OCMIndirectReturnValueProvider.m; sourceTree = ""; }; - F45B985D33C4A6B647FEDEC72A2B20FC /* DarklyEventSource-macOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "DarklyEventSource-macOS-dummy.m"; path = "../DarklyEventSource-macOS/DarklyEventSource-macOS-dummy.m"; sourceTree = ""; }; F4B0192087B27BECEC0F7E1799558045 /* OCMStubRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMStubRecorder.h; path = Source/OCMock/OCMStubRecorder.h; sourceTree = ""; }; F50D3F52D7CB7847A47C5F75170511F6 /* Pods-Darkly_watchOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Darkly_watchOS-umbrella.h"; sourceTree = ""; }; F7A5FB40F0F082652C28F5E38727923F /* Pods-Darkly_tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Darkly_tvOS.release.xcconfig"; sourceTree = ""; }; + F7B5A520778565593C4D2A21DF21EABC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F90968080A13E2B5A51548EB12B78716 /* NSInvocation+OCMAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSInvocation+OCMAdditions.m"; path = "Source/OCMock/NSInvocation+OCMAdditions.m"; sourceTree = ""; }; F96D5252F5210239EB66836A4149724C /* Pods-Darkly_tvOS-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Darkly_tvOS-resources.sh"; sourceTree = ""; }; FB706AE073B73D3F57B2180519B516BC /* OHHTTPStubs.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = OHHTTPStubs.modulemap; sourceTree = ""; }; FBFEAC80AB2E00CFC60743201EA79E8E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - FE6B683A6873FEE84F18BDCB048219D7 /* DarklyEventSource-watchOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "DarklyEventSource-watchOS-prefix.pch"; path = "../DarklyEventSource-watchOS/DarklyEventSource-watchOS-prefix.pch"; sourceTree = ""; }; FF53F1EAB9D81A6DED2CC5DDC68998B5 /* OCMMacroState.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = OCMMacroState.h; path = Source/OCMock/OCMMacroState.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -501,7 +501,7 @@ 8D5DD619EF039D6A394E253938F85A12 /* DarklyEventSource.h */, AA49AFC7E73CAB7B63A97FC6963BD84B /* LDEventSource.h */, 27467853512D2003F1639D1425ABA364 /* LDEventSource.m */, - 62DC34040B4C62A10316FA35180057F4 /* Support Files */, + FE1136DCF1B09269C2A01A6F74DF5B9C /* Support Files */, ); name = DarklyEventSource; path = DarklyEventSource; @@ -563,38 +563,6 @@ name = "Targets Support Files"; sourceTree = ""; }; - 62DC34040B4C62A10316FA35180057F4 /* Support Files */ = { - isa = PBXGroup; - children = ( - 1233506F8B9067704EE12EB44DAAD3CC /* DarklyEventSource-iOS.modulemap */, - 187D2BDA10C0B70EC2472E77A35173E0 /* DarklyEventSource-iOS.xcconfig */, - A8C4897465F74B77310822641F36F080 /* DarklyEventSource-iOS-dummy.m */, - 70E090DFA4166A4D9E1ABC7C2CDCC5F3 /* DarklyEventSource-iOS-prefix.pch */, - E1DF06BEE2041494877E39ECBA02D84F /* DarklyEventSource-iOS-umbrella.h */, - 5D05371A8E378545579895FA18004BFF /* DarklyEventSource-macOS.modulemap */, - AE613C43360883DDF65ACF26FD21A0E5 /* DarklyEventSource-macOS.xcconfig */, - F45B985D33C4A6B647FEDEC72A2B20FC /* DarklyEventSource-macOS-dummy.m */, - 6EA8DF2D1B887AF27C1B52538CFBCDE3 /* DarklyEventSource-macOS-prefix.pch */, - 34979088B08D830B9639A87F473A6103 /* DarklyEventSource-macOS-umbrella.h */, - CA01659C19D8CEFB2F9185124CD88C19 /* DarklyEventSource-tvOS.modulemap */, - 3CD4B50B136405244BAAF97DD7ABCC83 /* DarklyEventSource-tvOS.xcconfig */, - 77C1F0ADE1DF2380F6FCEEA6252A8E10 /* DarklyEventSource-tvOS-dummy.m */, - 11E5214A5E825730F5D6B9804EFA6E4A /* DarklyEventSource-tvOS-prefix.pch */, - 3FF9347142BEA1E84D127A54BCCC5DB4 /* DarklyEventSource-tvOS-umbrella.h */, - CD22797E9155CDCA31F3577065B0C184 /* DarklyEventSource-watchOS.modulemap */, - E17394FA0678B937B45BE3B1F2950085 /* DarklyEventSource-watchOS.xcconfig */, - 5F919E593698DCC1B8650577A96EB8CD /* DarklyEventSource-watchOS-dummy.m */, - FE6B683A6873FEE84F18BDCB048219D7 /* DarklyEventSource-watchOS-prefix.pch */, - 95D9AA0F43AAAEF45D791A80EB1F746F /* DarklyEventSource-watchOS-umbrella.h */, - 0AB9818BBCAAD6EDFC9CB2C6106D8705 /* Info.plist */, - A4157B63672F6709E0EE06D2D14D6F36 /* Info.plist */, - 0A0C3541D5B2550F453161199C3523B7 /* Info.plist */, - 2D0C3231CA29C867AEFF3CC147611931 /* Info.plist */, - ); - name = "Support Files"; - path = "../Target Support Files/DarklyEventSource-iOS"; - sourceTree = ""; - }; 62F41E4FDE6867AD1C3F660B11AEB7B3 /* OHHTTPStubs */ = { isa = PBXGroup; children = ( @@ -842,6 +810,38 @@ path = "Target Support Files/Pods-Darkly_osx"; sourceTree = ""; }; + FE1136DCF1B09269C2A01A6F74DF5B9C /* Support Files */ = { + isa = PBXGroup; + children = ( + 7DFA77F39699B1284C6FC8983054870D /* DarklyEventSource-iOS.modulemap */, + A6529C6A7D1184CAFA34DE77FBB3937E /* DarklyEventSource-iOS.xcconfig */, + 18C38A025BC21157F653CA5A21398FE0 /* DarklyEventSource-iOS-dummy.m */, + 2BEAB801B1A9EF20CFD64E9805105EA4 /* DarklyEventSource-iOS-prefix.pch */, + 887C6CAEC0919C7D49C33ED75924DF6E /* DarklyEventSource-iOS-umbrella.h */, + A7C7E813043B5D1D65AD9D62D7AFC21D /* DarklyEventSource-macOS.modulemap */, + 4375CA90EBC88CD1948269572E93EDE5 /* DarklyEventSource-macOS.xcconfig */, + 9CEF0E82282A5BA582E0C41D28BBBE57 /* DarklyEventSource-macOS-dummy.m */, + 7195D8AD39386A9F1DD77163CD1A275D /* DarklyEventSource-macOS-prefix.pch */, + 0E33CB6687CDAB4DA1AD2E228C84B160 /* DarklyEventSource-macOS-umbrella.h */, + 792329ABC730A9F220F8B0829056777B /* DarklyEventSource-tvOS.modulemap */, + 08AAF989C5B8490560379149F700BE18 /* DarklyEventSource-tvOS.xcconfig */, + 1320E1AB0AB0D789A16983AA70F3867B /* DarklyEventSource-tvOS-dummy.m */, + 4C5B36E2E39491245B2A344E35F3E13D /* DarklyEventSource-tvOS-prefix.pch */, + 5C40E3FFD873C7D48C730A5838826A87 /* DarklyEventSource-tvOS-umbrella.h */, + 9E0252D54C50E1C39BCF728FE4F9350F /* DarklyEventSource-watchOS.modulemap */, + A21E27698C418BCA6A3A0BDE789A0CEE /* DarklyEventSource-watchOS.xcconfig */, + E1C1F9D7DAF1E94D08AF3CD6C446409B /* DarklyEventSource-watchOS-dummy.m */, + B18DCEE55CEED96588260EFCAD19B97D /* DarklyEventSource-watchOS-prefix.pch */, + E03662098C79CCBA047D87E60E9CD8DA /* DarklyEventSource-watchOS-umbrella.h */, + F7B5A520778565593C4D2A21DF21EABC /* Info.plist */, + 9ABFD2CAC06E13B40AE20B368339400A /* Info.plist */, + D93BDC50ECBE34F6A0FD8F9E1A65B72B /* Info.plist */, + 712F0F0ED8527D8133C8E2552B8EC681 /* Info.plist */, + ); + name = "Support Files"; + path = "../Target Support Files/DarklyEventSource-iOS"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1395,7 +1395,7 @@ /* Begin XCBuildConfiguration section */ 01B0A2CE48C6B2ABA62F60779E37676E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E17394FA0678B937B45BE3B1F2950085 /* DarklyEventSource-watchOS.xcconfig */; + baseConfigurationReference = A21E27698C418BCA6A3A0BDE789A0CEE /* DarklyEventSource-watchOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; @@ -1644,7 +1644,7 @@ }; 56DAED87C61EEF4C26CCC05DD9A7A23A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 187D2BDA10C0B70EC2472E77A35173E0 /* DarklyEventSource-iOS.xcconfig */; + baseConfigurationReference = A6529C6A7D1184CAFA34DE77FBB3937E /* DarklyEventSource-iOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; @@ -1708,7 +1708,7 @@ }; 5796E36BC862D49A566869330A371710 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AE613C43360883DDF65ACF26FD21A0E5 /* DarklyEventSource-macOS.xcconfig */; + baseConfigurationReference = 4375CA90EBC88CD1948269572E93EDE5 /* DarklyEventSource-macOS.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1738,7 +1738,7 @@ }; 5FF321FE52B6B3E2F6D66833F3601C2C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AE613C43360883DDF65ACF26FD21A0E5 /* DarklyEventSource-macOS.xcconfig */; + baseConfigurationReference = 4375CA90EBC88CD1948269572E93EDE5 /* DarklyEventSource-macOS.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1893,7 +1893,7 @@ }; 93B6F0E437E164A43B94B692C503BAE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E17394FA0678B937B45BE3B1F2950085 /* DarklyEventSource-watchOS.xcconfig */; + baseConfigurationReference = A21E27698C418BCA6A3A0BDE789A0CEE /* DarklyEventSource-watchOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; @@ -1957,7 +1957,7 @@ }; C1A2EBA401172237C09F831AAA6B8732 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3CD4B50B136405244BAAF97DD7ABCC83 /* DarklyEventSource-tvOS.xcconfig */; + baseConfigurationReference = 08AAF989C5B8490560379149F700BE18 /* DarklyEventSource-tvOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; @@ -2020,7 +2020,7 @@ }; C4D949D3DAFA9D9AECA84E7FE083C686 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 187D2BDA10C0B70EC2472E77A35173E0 /* DarklyEventSource-iOS.xcconfig */; + baseConfigurationReference = A6529C6A7D1184CAFA34DE77FBB3937E /* DarklyEventSource-iOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; @@ -2084,7 +2084,7 @@ }; DE0EFE356817C9BFFC410B99D9B61D39 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3CD4B50B136405244BAAF97DD7ABCC83 /* DarklyEventSource-tvOS.xcconfig */; + baseConfigurationReference = 08AAF989C5B8490560379149F700BE18 /* DarklyEventSource-tvOS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; diff --git a/Pods/Target Support Files/DarklyEventSource-iOS/DarklyEventSource-iOS.xcconfig b/Pods/Target Support Files/DarklyEventSource-iOS/DarklyEventSource-iOS.xcconfig index ca0884ff..252f9728 100644 --- a/Pods/Target Support Files/DarklyEventSource-iOS/DarklyEventSource-iOS.xcconfig +++ b/Pods/Target Support Files/DarklyEventSource-iOS/DarklyEventSource-iOS.xcconfig @@ -1,9 +1,9 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -l"objc" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/DarklyEventSource PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/DarklyEventSource-iOS/Info.plist b/Pods/Target Support Files/DarklyEventSource-iOS/Info.plist index c11c2ee4..9ae03a0c 100644 --- a/Pods/Target Support Files/DarklyEventSource-iOS/Info.plist +++ b/Pods/Target Support Files/DarklyEventSource-iOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.2 + 3.2.0 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig b/Pods/Target Support Files/DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig index 76169646..be75f38f 100644 --- a/Pods/Target Support Files/DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig +++ b/Pods/Target Support Files/DarklyEventSource-macOS/DarklyEventSource-macOS.xcconfig @@ -1,10 +1,10 @@ CODE_SIGN_IDENTITY = -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-macOS +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-macOS GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -l"objc" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/DarklyEventSource PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/DarklyEventSource-macOS/Info.plist b/Pods/Target Support Files/DarklyEventSource-macOS/Info.plist index c11c2ee4..9ae03a0c 100644 --- a/Pods/Target Support Files/DarklyEventSource-macOS/Info.plist +++ b/Pods/Target Support Files/DarklyEventSource-macOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.2 + 3.2.0 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig b/Pods/Target Support Files/DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig index ab81a203..ae813d45 100644 --- a/Pods/Target Support Files/DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig +++ b/Pods/Target Support Files/DarklyEventSource-tvOS/DarklyEventSource-tvOS.xcconfig @@ -1,9 +1,9 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-tvOS +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-tvOS GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -l"objc" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/DarklyEventSource PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/DarklyEventSource-tvOS/Info.plist b/Pods/Target Support Files/DarklyEventSource-tvOS/Info.plist index c11c2ee4..9ae03a0c 100644 --- a/Pods/Target Support Files/DarklyEventSource-tvOS/Info.plist +++ b/Pods/Target Support Files/DarklyEventSource-tvOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.2 + 3.2.0 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig b/Pods/Target Support Files/DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig index 9b25ad36..66051aa8 100644 --- a/Pods/Target Support Files/DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig +++ b/Pods/Target Support Files/DarklyEventSource-watchOS/DarklyEventSource-watchOS.xcconfig @@ -1,9 +1,9 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-watchOS +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-watchOS GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -l"objc" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/DarklyEventSource PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/DarklyEventSource-watchOS/Info.plist b/Pods/Target Support Files/DarklyEventSource-watchOS/Info.plist index c11c2ee4..9ae03a0c 100644 --- a/Pods/Target Support Files/DarklyEventSource-watchOS/Info.plist +++ b/Pods/Target Support Files/DarklyEventSource-watchOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.2 + 3.2.0 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/OCMock/OCMock.xcconfig b/Pods/Target Support Files/OCMock/OCMock.xcconfig index a9f16c41..79c443c2 100644 --- a/Pods/Target Support Files/OCMock/OCMock.xcconfig +++ b/Pods/Target Support Files/OCMock/OCMock.xcconfig @@ -1,8 +1,8 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/OCMock +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/OCMock GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/OCMock PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.xcconfig b/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.xcconfig index c1162729..530b136f 100644 --- a/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.xcconfig +++ b/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.xcconfig @@ -1,9 +1,9 @@ -CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/OHHTTPStubs +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" OTHER_LDFLAGS = -framework "CFNetwork" -framework "Foundation" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/OHHTTPStubs PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} diff --git a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests-frameworks.sh b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests-frameworks.sh index bb9b7b04..7c0b4cf7 100755 --- a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests-frameworks.sh +++ b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests-frameworks.sh @@ -6,10 +6,14 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + # This protects against multiple targets copying the same framework dependency at the same time. The solution # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") +# Copies and strips a vendored framework install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then @@ -58,12 +62,31 @@ install_framework() fi } -# Copies the dSYM of a vendored framework +# Copies and strips a vendored dSYM install_dsym() { local source="$1" if [ -r "$source" ]; then - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi fi } @@ -85,10 +108,18 @@ code_sign_if_enabled() { # Strip invalid architectures strip_invalid_archs() { binary="$1" - # Get architectures for current file - archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi stripped="" - for arch in $archs; do + for arch in $binary_archs; do if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 @@ -98,6 +129,7 @@ strip_invalid_archs() { if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi + STRIP_BINARY_RETVAL=1 } diff --git a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.debug.xcconfig b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.debug.xcconfig index d5237129..b3ce6e6a 100644 --- a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.debug.xcconfig +++ b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.debug.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS" "$PODS_CONFIGURATION_BUILD_DIR/OCMock" "$PODS_CONFIGURATION_BUILD_DIR/OHHTTPStubs" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/OCMock" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OCMock/OCMock.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OHHTTPStubs/OHHTTPStubs.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OCMock/OCMock.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -framework "OCMock" -framework "OHHTTPStubs" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.release.xcconfig b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.release.xcconfig index d5237129..b3ce6e6a 100644 --- a/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.release.xcconfig +++ b/Pods/Target Support Files/Pods-DarklyTests/Pods-DarklyTests.release.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS" "$PODS_CONFIGURATION_BUILD_DIR/OCMock" "$PODS_CONFIGURATION_BUILD_DIR/OHHTTPStubs" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/OCMock" "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OCMock/OCMock.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/OHHTTPStubs/OHHTTPStubs.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OCMock/OCMock.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -framework "OCMock" -framework "OHHTTPStubs" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.debug.xcconfig b/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.debug.xcconfig index 220d0222..981d1e12 100644 --- a/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.debug.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.debug.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.release.xcconfig b/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.release.xcconfig index 220d0222..981d1e12 100644 --- a/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.release.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_iOS/Pods-Darkly_iOS.release.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-iOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.debug.xcconfig b/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.debug.xcconfig index 6a1ff28f..05060058 100644 --- a/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.debug.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.debug.xcconfig @@ -1,10 +1,10 @@ CODE_SIGN_IDENTITY = -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-macOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-macOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-macOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-macOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.release.xcconfig b/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.release.xcconfig index 6a1ff28f..05060058 100644 --- a/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.release.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_osx/Pods-Darkly_osx.release.xcconfig @@ -1,10 +1,10 @@ CODE_SIGN_IDENTITY = -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-macOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-macOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-macOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-macOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.debug.xcconfig b/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.debug.xcconfig index 8874cf64..da289817 100644 --- a/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.debug.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.debug.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-tvOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-tvOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-tvOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-tvOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.release.xcconfig b/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.release.xcconfig index 8874cf64..da289817 100644 --- a/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.release.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_tvOS/Pods-Darkly_tvOS.release.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-tvOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-tvOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-tvOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-tvOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.debug.xcconfig b/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.debug.xcconfig index 4af047c2..1f6a2fec 100644 --- a/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.debug.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.debug.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-watchOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-watchOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-watchOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-watchOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.release.xcconfig b/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.release.xcconfig index 4af047c2..1f6a2fec 100644 --- a/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.release.xcconfig +++ b/Pods/Target Support Files/Pods-Darkly_watchOS/Pods-Darkly_watchOS.release.xcconfig @@ -1,9 +1,9 @@ -FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-watchOS" +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-watchOS" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' -OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/DarklyEventSource-watchOS/DarklyEventSource.framework/Headers" +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/DarklyEventSource-watchOS/DarklyEventSource.framework/Headers" OTHER_LDFLAGS = $(inherited) -l"objc" -framework "DarklyEventSource" -PODS_BUILD_DIR = $BUILD_DIR -PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_ROOT = ${SRCROOT}/Pods