Various improvements:
- Updated tests to run on a wider range of Alfresco servers (you can specify the expected repo version in env-cfg.plist)
- Improved error handling during session creation i.e. returns NoRepository error code instead of InvalidArgument if the repo ID is not found
- Added the ability to ignore cookies (set via session parameters)
- Changed compilation macros around workaround in CMISHttpUploadRequestAdded
- Added "-dev” to the version number
- Removed comments in release.sh accidentally committed previously
- Updated project settings for Xcode 6

git-svn-id: https://svn.apache.org/repos/asf/chemistry/objectivecmis/trunk@1627868 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ObjectiveCMIS.xcodeproj/project.pbxproj b/ObjectiveCMIS.xcodeproj/project.pbxproj
index 4baf05f..25c53c6 100644
--- a/ObjectiveCMIS.xcodeproj/project.pbxproj
+++ b/ObjectiveCMIS.xcodeproj/project.pbxproj
@@ -1088,7 +1088,7 @@
 		8280729A15153DE800EF635C /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0500;
+				LastUpgradeCheck = 0600;
 				ORGANIZATIONNAME = "Apache Software Foundation";
 			};
 			buildConfigurationList = 8280729D15153DE800EF635C /* Build configuration list for PBXProject "ObjectiveCMIS" */;
@@ -1337,8 +1337,10 @@
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -1373,8 +1375,10 @@
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
@@ -1395,7 +1399,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 580123DB196AEE010028422E /* ObjectiveCMIS.xcconfig */;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
 				CLANG_ENABLE_MODULES = YES;
 				DSTROOT = /tmp/ObjectiveCMIS.dst;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -1413,7 +1416,6 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 580123DB196AEE010028422E /* ObjectiveCMIS.xcconfig */;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
 				CLANG_ENABLE_MODULES = YES;
 				DSTROOT = /tmp/ObjectiveCMIS.dst;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -1430,7 +1432,6 @@
 		828072CB15153DE900EF635C /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
 				CLANG_ENABLE_MODULES = NO;
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(SDKROOT)/Developer/Library/Frameworks",
@@ -1446,7 +1447,6 @@
 		828072CC15153DE900EF635C /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
 				CLANG_ENABLE_MODULES = NO;
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(SDKROOT)/Developer/Library/Frameworks",
diff --git a/ObjectiveCMIS.xcodeproj/xcshareddata/xcschemes/ObjectiveCMIS.xcscheme b/ObjectiveCMIS.xcodeproj/xcshareddata/xcschemes/ObjectiveCMIS.xcscheme
index 4c68dd1..0217291 100644
--- a/ObjectiveCMIS.xcodeproj/xcshareddata/xcschemes/ObjectiveCMIS.xcscheme
+++ b/ObjectiveCMIS.xcodeproj/xcshareddata/xcschemes/ObjectiveCMIS.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0510"
+   LastUpgradeVersion = "0600"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -63,6 +63,15 @@
       ignoresPersistentStateOnLaunch = "NO"
       debugDocumentVersioning = "YES"
       allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "828072A215153DE800EF635C"
+            BuildableName = "libObjectiveCMIS.a"
+            BlueprintName = "ObjectiveCMIS"
+            ReferencedContainer = "container:ObjectiveCMIS.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <AdditionalOptions>
       </AdditionalOptions>
    </LaunchAction>
diff --git a/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubRepositoryService.m b/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubRepositoryService.m
index 3464a3b..014cb5b 100644
--- a/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubRepositoryService.m
+++ b/ObjectiveCMIS/Bindings/AtomPub/CMISAtomPubRepositoryService.m
@@ -55,7 +55,7 @@
 {
     return [self internalRetrieveRepositoriesWithCompletionBlock:^(NSError *error) {
         if (error) {
-            completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeInvalidArgument]);
+            completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeNoRepositoryFound]);
         } else {
             completionBlock([self.repositories objectForKey:repositoryId], nil);
         }
diff --git a/ObjectiveCMIS/Bindings/Browser/CMISBrowserRepositoryService.m b/ObjectiveCMIS/Bindings/Browser/CMISBrowserRepositoryService.m
index 5e75011..c8222d7 100644
--- a/ObjectiveCMIS/Bindings/Browser/CMISBrowserRepositoryService.m
+++ b/ObjectiveCMIS/Bindings/Browser/CMISBrowserRepositoryService.m
@@ -53,7 +53,7 @@
 {
     return [self internalRetrieveRepositoriesWithCompletionBlock:^(NSError *error) {
         if (error) {
-            completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeInvalidArgument]);
+            completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeNoRepositoryFound]);
         } else {
             completionBlock([self.repositories objectForKey:repositoryId], nil);
         }
diff --git a/ObjectiveCMIS/Client/CMISSession.m b/ObjectiveCMIS/Client/CMISSession.m
index 1b9c521..6a75c9e 100644
--- a/ObjectiveCMIS/Client/CMISSession.m
+++ b/ObjectiveCMIS/Client/CMISSession.m
@@ -153,11 +153,10 @@
         self.repositoryInfo = repositoryInfo;
         if (self.repositoryInfo == nil) {
             if (error) {
-                CMISLogError(@"Error because repositoryInfo is nil: %@", error.description);
-                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeInvalidArgument]);
+                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeNoRepositoryFound]);
             } else {
-                completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
-                                                     detailedDescription:@"Could not fetch repository information"]);
+                completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeNoRepositoryFound
+                                                     detailedDescription:[NSString stringWithFormat:@"Invalid repository id provided: %@", self.sessionParameters.repositoryId]]);
             }
         } else {
             // no errors have occurred so set authenticated flag and return success flag
diff --git a/ObjectiveCMIS/Common/CMISErrors.m b/ObjectiveCMIS/Common/CMISErrors.m
index 5abf5b7..71552dc 100644
--- a/ObjectiveCMIS/Common/CMISErrors.m
+++ b/ObjectiveCMIS/Common/CMISErrors.m
@@ -34,9 +34,9 @@
 NSString * const kCMISErrorDescriptionUnknown = @"Unknown Error";
 NSString * const kCMISErrorDescriptionConnection = @"Connection Error";
 NSString * const kCMISErrorDescriptionProxyAuthentication = @"Proxy Authentication Error";
-NSString * const kCMISErrorDescriptionUnauthorized = @"Unauthorized access error";
-NSString * const kCMISErrorDescriptionNoRootFolderFound =  @"Root Folder Not Found Error";
-NSString * const kCMISErrorDescriptionRepositoryNotFound =  @"Repository Not Found Error";
+NSString * const kCMISErrorDescriptionUnauthorized = @"Unauthorized Access";
+NSString * const kCMISErrorDescriptionNoRootFolderFound =  @"Root Folder Not Found";
+NSString * const kCMISErrorDescriptionRepositoryNotFound =  @"Repository Not Found";
 NSString * const kCMISErrorDescriptionCancelled = @"Operation Cancelled";
 NSString * const kCMISErrorDescriptionParsingFailed = @"Parsing Failed";
 NSString * const kCMISErrorDescriptionNoNetworkConnection = @"No Network Connection";
@@ -44,7 +44,7 @@
 //General errors as defined in 2.2.1.4.1 of spec
 NSString * const kCMISErrorDescriptionInvalidArgument = @"Invalid Argument Error";
 NSString * const kCMISErrorDescriptionObjectNotFound = @"Object Not Found Error";
-NSString * const kCMISErrorDescriptionNotSupported = @"Not supported Error";
+NSString * const kCMISErrorDescriptionNotSupported = @"Not Supported Error";
 NSString * const kCMISErrorDescriptionPermissionDenied = @"Permission Denied Error";
 NSString * const kCMISErrorDescriptionRuntime = @"Runtime Error";
 
diff --git a/ObjectiveCMIS/Common/CMISSessionParameters.h b/ObjectiveCMIS/Common/CMISSessionParameters.h
index 53bc2de..fb9af14 100644
--- a/ObjectiveCMIS/Common/CMISSessionParameters.h
+++ b/ObjectiveCMIS/Common/CMISSessionParameters.h
@@ -46,6 +46,12 @@
  */
 extern NSString * const kCMISSessionParameterTypeDefinitionCacheSize;
 
+/**
+ * Key for setting whether cookies should be added to requests. 
+ * Value should be a boolean flag, default is YES.
+ */
+extern NSString * const kCMISSessionParameterSendCookies;
+
 
 @interface CMISSessionParameters : NSObject
 
diff --git a/ObjectiveCMIS/Common/CMISSessionParameters.m b/ObjectiveCMIS/Common/CMISSessionParameters.m
index a561bdd..1958d19 100644
--- a/ObjectiveCMIS/Common/CMISSessionParameters.m
+++ b/ObjectiveCMIS/Common/CMISSessionParameters.m
@@ -23,7 +23,7 @@
 NSString * const kCMISSessionParameterObjectConverterClassName = @"session_param_object_converter_class";
 NSString * const kCMISSessionParameterLinkCacheSize = @"session_param_cache_size_links";
 NSString * const kCMISSessionParameterTypeDefinitionCacheSize = @"session_param_cache_size_type_definition";
-
+NSString * const kCMISSessionParameterSendCookies = @"session_param_send_cookies";
 
 @interface CMISSessionParameters ()
 @property (nonatomic, assign, readwrite) CMISBindingType bindingType;
diff --git a/ObjectiveCMIS/ObjectiveCMIS.xcconfig b/ObjectiveCMIS/ObjectiveCMIS.xcconfig
index 7593867..251f000 100644
--- a/ObjectiveCMIS/ObjectiveCMIS.xcconfig
+++ b/ObjectiveCMIS/ObjectiveCMIS.xcconfig
@@ -16,7 +16,7 @@
 // under the License.
 
 // Library version number
-OBJECTIVECMIS_VERSION=0.5
+OBJECTIVECMIS_VERSION=0.5-dev
 
 // Allow selected config variables to be accessible in code
 OTHER_CFLAGS=-DOBJECTIVECMIS_VERSION="@\"${OBJECTIVECMIS_VERSION}\""
diff --git a/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m b/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
index a3494e7..858b7e5 100644
--- a/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
+++ b/ObjectiveCMIS/Utils/CMISDefaultNetworkProvider.m
@@ -310,6 +310,13 @@
     [request setHTTPMethod:httpMethod];
     CMISLogDebug(@"HTTP %@: %@", httpMethod, [url absoluteString]);
     
+    // turn off cookies if configured to do so
+    id sendCookies = [session objectForKey:kCMISSessionParameterSendCookies];
+    if (sendCookies && ![sendCookies boolValue])
+    {
+        request.HTTPShouldHandleCookies = NO;
+    }
+    
     return request;
 }
 
diff --git a/ObjectiveCMIS/Utils/CMISHttpRequest.m b/ObjectiveCMIS/Utils/CMISHttpRequest.m
index 1f06cf4..dd8aa59 100644
--- a/ObjectiveCMIS/Utils/CMISHttpRequest.m
+++ b/ObjectiveCMIS/Utils/CMISHttpRequest.m
@@ -89,10 +89,16 @@
     
     [self.authenticationProvider.httpHeadersToApply enumerateKeysAndObjectsUsingBlock:^(NSString *headerName, NSString *header, BOOL *stop) {
         [urlRequest addValue:header forHTTPHeaderField:headerName];
+        if ([CMISLog sharedInstance].logLevel == CMISLogLevelTrace) {
+            CMISLogTrace(@"Added header: %@ with value: %@", headerName, header);
+        }
     }];
     
     [self.additionalHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *headerName, NSString *header, BOOL *stop) {
         [urlRequest addValue:header forHTTPHeaderField:headerName];
+        if ([CMISLog sharedInstance].logLevel == CMISLogLevelTrace) {
+            CMISLogTrace(@"Added header: %@ with value: %@", headerName, header);
+        }
     }];
     
     self.connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:NO];
diff --git a/ObjectiveCMIS/Utils/CMISHttpUploadRequest.m b/ObjectiveCMIS/Utils/CMISHttpUploadRequest.m
index bede01c..a8a9e14 100644
--- a/ObjectiveCMIS/Utils/CMISHttpUploadRequest.m
+++ b/ObjectiveCMIS/Utils/CMISHttpUploadRequest.m
@@ -309,11 +309,13 @@
     switch (eventCode){
         case NSStreamEventOpenCompleted:{
 #if TARGET_OS_IPHONE
-            // this fix breaks POST requests on MacOS targets
+#ifndef __IPHONE_8_0
+            // this workaround breaks POST requests on MacOS targets and iOS 8
             if (self.combinedInputStream.streamStatus != NSStreamStatusOpen) {
                 [self.combinedInputStream open]; // this seems to work around the 'Stream ... is sending an event before being opened' Apple bug
             }
 #endif
+#endif
         }
             break;
 
diff --git a/ObjectiveCMISTests/CMISBaseTest.h b/ObjectiveCMISTests/CMISBaseTest.h
index 1b6ff1a..7fa4e64 100644
--- a/ObjectiveCMISTests/CMISBaseTest.h
+++ b/ObjectiveCMISTests/CMISBaseTest.h
@@ -32,6 +32,7 @@
 @property (nonatomic, strong) CMISSessionParameters *parameters;
 @property (nonatomic, strong) CMISSession *session;
 @property (nonatomic, strong) CMISFolder *rootFolder;
+@property (nonatomic, strong) NSString *expectedRepositoryVersion;
 @property BOOL testCompleted;
 
 #pragma mark Running the test
diff --git a/ObjectiveCMISTests/CMISBaseTest.m b/ObjectiveCMISTests/CMISBaseTest.m
index 943a1b8..0c557a3 100644
--- a/ObjectiveCMISTests/CMISBaseTest.m
+++ b/ObjectiveCMISTests/CMISBaseTest.m
@@ -58,6 +58,9 @@
         NSString *repositoryId = [envDict valueForKey:@"repositoryId"];
         NSString *username = [envDict valueForKey:@"username"];
         NSString *password = [envDict valueForKey:@"password"];
+        
+        // store the expected repo version
+        self.expectedRepositoryVersion = [envDict valueForKey:@"repositoryVersion"];
 
         // ensure there is a binding value, default to atom
         if (binding == nil)
@@ -115,21 +118,26 @@
     }
     [CMISSession connectWithSessionParameters:self.parameters completionBlock:^(CMISSession *session, NSError *error){
         if (nil == session) {
-            XCTFail(@"Failed to create session: %@", error.localizedDescription);
+            XCTFail(@"Failed to create session: %@", [self failureMessageFromError:error]);
             self.testCompleted = YES;
         } else {
             self.session = session;
             XCTAssertTrue(self.session.isAuthenticated, @"Session should be authenticated");
             [self.session retrieveRootFolderWithCompletionBlock:^(CMISFolder *rootFolder, NSError *error) {
-                XCTAssertNil(error, @"Error while retrieving root folder: %@", [error description]);
+                XCTAssertNil(error, @"Error while retrieving root folder: %@", [self failureMessageFromError:error]);
                 XCTAssertNotNil(rootFolder, @"rootFolder object should not be nil");
                 if (rootFolder)
                 {
                     [self.session retrieveObjectByPath:@"/ios-test" completionBlock:^(CMISObject *object, NSError *error) {
-                        self.rootFolder = (CMISFolder *)object;
-                        XCTAssertNil(error, @"Error while retrieving root folder: %@", [error description]);
-                        XCTAssertNotNil(self.rootFolder, @"/ios-test rootFolder object should not be nil");
-                        completionBlock();
+                        if (object == nil) {
+                            XCTFail(@"Error while retrieving ios-test folder: %@", [self failureMessageFromError:error]);
+                            self.testCompleted = YES;
+                        }
+                        else {
+                            self.rootFolder = (CMISFolder *)object;
+                            XCTAssertNotNil(self.rootFolder, @"/ios-test folder object should not be nil");
+                            completionBlock();
+                        }
                     }];
                 }
             }];
@@ -231,5 +239,32 @@
     return [[self testDateFormatter] stringFromDate:[NSDate date]];
 }
 
+- (NSString *)failureMessageFromError:(NSError *)error
+{
+    // just return if error has not been provided
+    if (error == nil)
+    {
+        return nil;
+    }
+    
+    NSString *message = error.localizedDescription;
+    
+    // add the failure reason, if there is one!
+    if (error.localizedFailureReason != nil)
+    {
+        message = [message stringByAppendingFormat:@" - %@", error.localizedFailureReason];
+    }
+    else
+    {
+        // try looking for an underlying error and output the whole error object
+        NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey];
+        if (underlyingError != nil)
+        {
+            message = [message stringByAppendingFormat:@" - %@", underlyingError];
+        }
+    }
+    
+    return message;
+}
 
 @end
\ No newline at end of file
diff --git a/ObjectiveCMISTests/ObjectiveCMISTests.m b/ObjectiveCMISTests/ObjectiveCMISTests.m
index 6fc85d1..8b4582f 100644
--- a/ObjectiveCMISTests/ObjectiveCMISTests.m
+++ b/ObjectiveCMISTests/ObjectiveCMISTests.m
@@ -153,7 +153,9 @@
         bogusParams.repositoryId = self.parameters.repositoryId;
         bogusParams.username = @"bogus";
         bogusParams.password = @"sugob";
-
+        // make sure we don't reuse the cookie from session created in setup
+        [bogusParams setObject:@(NO) forKey:kCMISSessionParameterSendCookies];
+        
         [CMISSession connectWithSessionParameters:bogusParams completionBlock:^(CMISSession *session, NSError *error){
             XCTAssertNil(session, @"we should not get back a valid session");
             if (nil == session) {
@@ -176,7 +178,11 @@
         XCTAssertNotNil(repoInfo, @"repoInfo object should not be nil");
 
         // check the repository info is what we expect
-        XCTAssertTrue([repoInfo.productVersion rangeOfString:@"4."].length > 0, @"Product Version should be 4.x.x, but was %@", repoInfo.productVersion);
+        if (self.expectedRepositoryVersion)
+        {
+            XCTAssertTrue([repoInfo.productVersion hasPrefix:self.expectedRepositoryVersion],
+                          @"Expected productVersion to start with %@ but was %@", self.expectedRepositoryVersion, repoInfo.productVersion);
+        }
         XCTAssertTrue([repoInfo.productName hasPrefix:@"Alfresco"], @"Product name should start with Alfresco, but was %@", repoInfo.productName);
         XCTAssertTrue([repoInfo.vendorName isEqualToString:@"Alfresco"], @"Vendor name should be Alfresco, but was %@", repoInfo.vendorName);
 
@@ -223,7 +229,15 @@
             XCTAssertTrue(objectTypeIdDef.propertyType == CMISPropertyTypeId, @"Expected objectTypeId type to be id");
             XCTAssertTrue(objectTypeIdDef.cardinality == CMISCardinalitySingle, @"Expected objectTypeId cardinality to be single");
             XCTAssertTrue(objectTypeIdDef.updatability == CMISUpdatabilityOnCreate, @"Expected objectTypeId updatability to be oncreate");
-            XCTAssertTrue(objectTypeIdDef.required, @"Expected objectTypeId to be required");
+            if ([self.session.repositoryInfo.productVersion hasPrefix:@"3."])
+            {
+                // a bug on 3.x Alfresco servers flagged this property as optional
+                XCTAssertFalse(objectTypeIdDef.required, @"Expected objectTypeId to not be required");
+            }
+            else
+            {
+                XCTAssertTrue(objectTypeIdDef.required, @"Expected objectTypeId to be required");
+            }
             
             // test secondary type id when using the 1.1 bindings
             CMISPropertyDefinition *secondaryTypeIdDef = typeDef.propertyDefinitions[@"cmis:secondaryObjectTypeIds"];
@@ -429,7 +443,8 @@
 - (void)testCancelDownload
 {
     [self runTest:^ {
-         [self.session retrieveObjectByPath:@"/ios-test/activiti-modeler.png" completionBlock:^(CMISObject *object, NSError *error) {
+         __block BOOL cancelPossible = YES;
+         [self.session retrieveObjectByPath:@"/ios-test/millenium-dome-exif.jpg" completionBlock:^(CMISObject *object, NSError *error) {
              CMISDocument *document = (CMISDocument *)object;
              XCTAssertNil(error, @"Error while retrieving object: %@", [error description]);
 
@@ -445,8 +460,13 @@
                  NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&fileError];
                  XCTAssertNil(fileError, @"Could not verify attributes of file %@: %@", filePath, [fileError description]);
                  XCTAssertTrue([fileAttributes fileSize] > 0, @"Expected at least some bytes but found an empty file");
-                 XCTAssertTrue([fileAttributes fileSize] < document.contentStreamLength, @"Could not cancel download before the complete file was downloaded");
-                                          
+                                                
+                 // if we managed to cancel check we don't have the whole file
+                 if (cancelPossible)
+                 {
+                     XCTAssertTrue([fileAttributes fileSize] < document.contentStreamLength, @"Cancel was successful so expected smaller file size");
+                 }
+                                                
                  // Nice boys clean up after themselves
                  [[NSFileManager defaultManager] removeItemAtPath:filePath error:&fileError];
                  XCTAssertNil(fileError, @"Could not remove file %@: %@", filePath, [fileError description]);
@@ -454,6 +474,11 @@
                  self.testCompleted = YES;
              } progressBlock:^(unsigned long long bytesDownloaded, unsigned long long bytesTotal) {
                  CMISLogDebug(@"download progress %llu/%llu", bytesDownloaded, bytesTotal);
+                 if (bytesDownloaded == bytesTotal)
+                 {
+                     cancelPossible = NO;
+                     CMISLogWarning(@"whole file was recieved in one chunk!");
+                 }
                  if (bytesDownloaded > 0) { // as soon as some data was downloaded cancel the request
                      [self.request cancel];
                      CMISLogDebug(@"download cancelled");
@@ -942,7 +967,7 @@
                         XCTAssertTrue([document.name isEqualToString:versionOfDocument.name], @"Other version of same document does not have the same name");
                         XCTAssertFalse([document.versionLabel isEqualToString:versionOfDocument.versionLabel], @"Other version of same document should have different version label");
                         XCTAssertTrue([previousModifiedDate compare:versionOfDocument.lastModificationDate] == NSOrderedDescending,
-                                     @"Versions of document should be ordered descending by creation date");
+                                     @"Versions of document should be ordered descending by creation date (%@ vs %@)", previousModifiedDate, versionOfDocument.lastModificationDate);
                         previousModifiedDate = versionOfDocument.lastModificationDate;
                     }
                 }
@@ -1506,9 +1531,9 @@
                 XCTAssertTrue(namePropertyDefiniton.inherited, @"Expected inherited property to be true");
                 XCTAssertTrue(namePropertyDefiniton.queryable, @"Expected queryable property to be true");
                 XCTAssertTrue(namePropertyDefiniton.orderable, @"Expected orderable property to be true");
-                if ([self.session.repositoryInfo.productVersion hasPrefix:@"4.0."])
+                if ([self.session.repositoryInfo.productVersion hasPrefix:@"3."] || [self.session.repositoryInfo.productVersion hasPrefix:@"4.0."])
                 {
-                    // due to a bug on 4.0 servers the required property was set to false
+                    // due to a bug on 3.x and 4.0 servers the required property was set to false
                     XCTAssertFalse(namePropertyDefiniton.required, @"Expected required property to be false");
                 }
                 else
diff --git a/ObjectiveCMISTests/env-cfg.plist b/ObjectiveCMISTests/env-cfg.plist
index d605ede..9bbe7cd 100644
--- a/ObjectiveCMISTests/env-cfg.plist
+++ b/ObjectiveCMISTests/env-cfg.plist
@@ -8,13 +8,15 @@
 			<key>disabled</key>
 			<false/>
 			<key>summary</key>
-			<string>Alfresco v4.0.0 Enterprise. Legacy (Webscript)</string>
+			<string>Alfresco v4.0.2 Enterprise. Legacy (Webscript)</string>
 			<key>username</key>
 			<string>cmis</string>
 			<key>password</key>
 			<string>unittest</string>
 			<key>url</key>
 			<string>http://ec2-176-34-173-67.eu-west-1.compute.amazonaws.com/alfresco/service/api/cmis</string>
+			<key>repositoryVersion</key>
+			<string>4.0.2</string>
 			<key>repositoryId</key>
 			<string>62e5f6d6-7c82-47f8-ad45-c2cbcc5a4e23</string>
 		</dict>
@@ -22,13 +24,15 @@
 			<key>disabled</key>
 			<false/>
 			<key>summary</key>
-			<string>Alfresco v4.0.0 Enterprise. OpenCMIS AtomPub 1.0</string>
+			<string>Alfresco v4.0.2 Enterprise. OpenCMIS AtomPub 1.0</string>
 			<key>username</key>
 			<string>cmis</string>
 			<key>password</key>
 			<string>unittest</string>
 			<key>url</key>
 			<string>http://ec2-176-34-173-67.eu-west-1.compute.amazonaws.com/alfresco/cmisatom</string>
+			<key>repositoryVersion</key>
+			<string>4.0.2</string>
 			<key>repositoryId</key>
 			<string>62e5f6d6-7c82-47f8-ad45-c2cbcc5a4e23</string>
 		</dict>
@@ -43,6 +47,8 @@
 			<string>unittest</string>
 			<key>url</key>
 			<string>http://ec2-54-195-83-189.eu-west-1.compute.amazonaws.com/alfresco/api/-default-/public/cmis/versions/1.0/atom</string>
+			<key>repositoryVersion</key>
+			<string>4.2.0</string>
 			<key>repositoryId</key>
 			<string>-default-</string>
 		</dict>
@@ -59,6 +65,8 @@
 			<string>unittest</string>
 			<key>url</key>
 			<string>http://ec2-54-195-83-189.eu-west-1.compute.amazonaws.com/alfresco/api/-default-/public/cmis/versions/1.1/browser</string>
+			<key>repositoryVersion</key>
+			<string>4.2.0</string>
 			<key>repositoryId</key>
 			<string>-default-</string>
 		</dict>
diff --git a/release.sh b/release.sh
index 03b4046..b6e19d1 100755
--- a/release.sh
+++ b/release.sh
@@ -101,13 +101,13 @@
 
 cd release
 
-#gpg --armor --output $OBJECTIVECMIS_PACK_SRC.asc --detach-sig $OBJECTIVECMIS_PACK_SRC
-#gpg --print-md MD5 $OBJECTIVECMIS_PACK_SRC > $OBJECTIVECMIS_PACK_SRC.md5
-#gpg --print-md SHA512 $OBJECTIVECMIS_PACK_SRC > $OBJECTIVECMIS_PACK_SRC.sha
+gpg --armor --output $OBJECTIVECMIS_PACK_SRC.asc --detach-sig $OBJECTIVECMIS_PACK_SRC
+gpg --print-md MD5 $OBJECTIVECMIS_PACK_SRC > $OBJECTIVECMIS_PACK_SRC.md5
+gpg --print-md SHA512 $OBJECTIVECMIS_PACK_SRC > $OBJECTIVECMIS_PACK_SRC.sha
 
-#gpg --armor --output $OBJECTIVECMIS_PACK_BIN.asc --detach-sig $OBJECTIVECMIS_PACK_BIN
-#gpg --print-md MD5 $OBJECTIVECMIS_PACK_BIN > $OBJECTIVECMIS_PACK_BIN.md5
-#gpg --print-md SHA512 $OBJECTIVECMIS_PACK_BIN > $OBJECTIVECMIS_PACK_BIN.sha
+gpg --armor --output $OBJECTIVECMIS_PACK_BIN.asc --detach-sig $OBJECTIVECMIS_PACK_BIN
+gpg --print-md MD5 $OBJECTIVECMIS_PACK_BIN > $OBJECTIVECMIS_PACK_BIN.md5
+gpg --print-md SHA512 $OBJECTIVECMIS_PACK_BIN > $OBJECTIVECMIS_PACK_BIN.sha
 
 
 cd ..