Skip to content

Commit

Permalink
Merge pull request Azure#258 from mirobers/master
Browse files Browse the repository at this point in the history
Release 7.0.0
  • Loading branch information
mirobers authored Feb 6, 2018
2 parents 9556398 + eed0a19 commit b796935
Show file tree
Hide file tree
Showing 67 changed files with 1,511 additions and 391 deletions.
14 changes: 10 additions & 4 deletions BreakingChanges.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
Changes in 6.0.0
Changes in 7.0.0

OTHER
* Upgraded Key Vault dependency to 1.0. Users of the IKey and IKeyResolver interfaces should note the interface changes in this version.
* The getErrorCode method of StorageExtendedErrorInformation is now deprecated. Use the corresponding methods in RequestResult and StorageException instead.

Changes in 6.0.0

FILE
* Many File service APIs can now throw a URISyntaxException.
* Changed listShares() ShareListingDetails parameter to be an enum set like what is done for listing blobs.
* Many File service APIs can now throw a URISyntaxException.
* Changed listShares() ShareListingDetails parameter to be an enum set like what is done for listing blobs.

OTHER
* DefaultEndpointsProtocol will now be explicitly included in generated connection strings.
* Connection string parsing has been substantially re-written and expanded. Please refer to current documentation about connection string formats.

Changes in 5.1.1
OTHER
* Reverted the code from 5.1.0 because it contained a regression and an accidental change.
* Reverted the code from 5.1.0 because it contained a regression and an accidental change.

Changes in 5.0.0

Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The Azure Storage development team uses Intellij. However, any preferred IDE or

### Configuration
The only step to configure testing is to setup a configuration file or connection string via environment variables. To use the connection string route, create an environment variable named "storageConnection". To use the configuration file route, create an environment variable named "storageTestConfiguration" with the path to a TestConfigurations.xml file with this [template](https://github.com/Azure/azure-storage-java/blob/master/microsoft-azure-storage-test/res/TestConfigurations.xml).
Alternatively, you can fill in microsoft-azure-storage-test/res/TestConfigurations.xml with the appropriate information.

### Running
To actually run tests, right click on the test class in the Package Explorer or the individual test in the Outline and select Run As->JUnitTest. All tests or tests grouped by service can be run using the test runners in the com.microsoft.azure.storage package TestRunners file. Running all tests from the top of the package explorer will result in each test being run multiple times as the package explorer will also run every test runner.
Expand Down
11 changes: 11 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
2018.02.05 Version 7.0.0
* Support for 2017-07-29 REST version. Please see our REST api documentation and blogs for information about the related added features.
* Added support for soft delete feature. If a delete retention policy is enabled through the set service properties API, then blobs or snapshots can be deleted softly and retained for a specified number of days, before being permanently removed by garbage collection.
* When a storage request fails, the error code may now be retrieved directly from the RequestResult and StorageException classes. This error code is populated even in cases where there is no StorageExtendedErrorInformation available, such as in calls to FetchAttributes.
* Queue messages may now be inserted with infinite duration by specifying -1 as the timeToLiveInSeconds parameter to addMessage.
* Improved performance of blob uploadFromFile APIs to avoid unnecessary buffering.
* Improved performance when streaming directly from a FileInputStream to avoid unnecessary buffering.
* Switched to using fixed length streaming mode in the HTTP client to avoid unnecessary buffering.
* Upgraded Key Vault dependency to 1.0.
* Fixed a bug preventing openInputStream from working on a blob snapshot.

2017.11.01 Version 6.1.0
* Added support for the last time the tier was modified.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import java.util.ArrayList;
import java.util.List;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class AlwaysRetry extends RetryPolicy implements RetryPolicyFactory {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;

import org.apache.commons.lang3.concurrent.ConcurrentUtils;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import com.microsoft.azure.keyvault.core.IKey;
import com.microsoft.azure.keyvault.core.IKeyResolver;
Expand All @@ -32,8 +32,10 @@ public void add(IKey key)
}

@Override
public Future<IKey> resolveKeyAsync(String keyId)
public ListenableFuture<IKey> resolveKeyAsync(String keyId)
{
return ConcurrentUtils.constantFuture(this.keys.get(keyId));
SettableFuture<IKey> future = SettableFuture.create();
future.set(this.keys.get(keyId));
return future;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,6 @@ public void testErrorReceivingResponseEvent() throws URISyntaxException, Storage
BlobRequestOptions options = new BlobRequestOptions();
options.setRetryPolicyFactory(new RetryNoRetry());

// setting the sending request event handler to trigger an exception.
// this is a retryable exception
eventContext.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() {
@Override
public void eventOccurred(SendingRequestEvent eventArg) {
HttpURLConnection connection = (HttpURLConnection) eventArg.getConnectionObject();
connection.setFixedLengthStreamingMode(0);
}
});

eventContext.getErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
@Override
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
Expand All @@ -186,13 +176,15 @@ public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
}
});

OperationContext.getGlobalErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
StorageEvent<ErrorReceivingResponseEvent> globalEvent = new StorageEvent<ErrorReceivingResponseEvent>() {
@Override
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
assertEquals(eventArg.getRequestResult(), eventArg.getOpContext().getLastResult());
globalCallList.add(true);
}
});
};

OperationContext.getGlobalErrorReceivingResponseEventHandler().addListener(globalEvent);

CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("container1");
Expand All @@ -202,10 +194,12 @@ public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
CloudBlockBlob blob1 = container.getBlockBlobReference("blob1");
try {
String blockID = String.format("%08d", 1);
blob1.uploadBlock(blockID, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);

// Trigger an error receiving the response by sending more bytes than the stream has.
blob1.uploadBlock(blockID, BlobTestHelper.getRandomDataStream(10), 11, null, options, eventContext);
} catch (Exception e) { }

// make sure both the local and globab context update
// make sure both the local and global context update
assertEquals(1, callList.size());
assertEquals(1, globalCallList.size());

Expand All @@ -214,7 +208,9 @@ public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
.setErrorReceivingResponseEventHandler(new StorageEventMultiCaster<ErrorReceivingResponseEvent, StorageEvent<ErrorReceivingResponseEvent>>());
try {
String blockID2 = String.format("%08d", 2);
blob1.uploadBlock(blockID2, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);

// Trigger an error receiving the response by sending more bytes than the stream has.
blob1.uploadBlock(blockID2, BlobTestHelper.getRandomDataStream(10), 11, null, options, eventContext);
} catch (Exception e) { }

assertEquals(1, callList.size());
Expand All @@ -227,13 +223,17 @@ public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
// make sure neither update
try {
String blockID3 = String.format("%08d", 3);
blob1.uploadBlock(blockID3, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);

// Trigger an error receiving the response by sending more bytes than the stream has.
blob1.uploadBlock(blockID3, BlobTestHelper.getRandomDataStream(10), 11, null, options, eventContext);
} catch (Exception e) { }

assertEquals(1, callList.size());
assertEquals(2, globalCallList.size());
}
finally {
// Remove the global listener if it wasn't removed already.
OperationContext.getGlobalErrorReceivingResponseEventHandler().removeListener(globalEvent);
container.deleteIfExists();
}
}
Expand Down Expand Up @@ -338,7 +338,7 @@ public void eventOccurred(RetryingEvent eventArg) {
catch (StorageException e) {
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, e.getHttpStatusCode());
assertEquals("The specified container does not exist.", e.getMessage());
assertEquals(StorageErrorCode.RESOURCE_NOT_FOUND.toString(), e.getErrorCode());
assertEquals(StorageErrorCodeStrings.CONTAINER_NOT_FOUND, e.getErrorCode());
}
assertEquals(1, callList.size());
assertEquals(1, globalCallList.size());
Expand All @@ -351,7 +351,7 @@ public void eventOccurred(RetryingEvent eventArg) {
catch (StorageException e) {
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, e.getHttpStatusCode());
assertEquals("The specified container does not exist.", e.getMessage());
assertEquals(StorageErrorCode.RESOURCE_NOT_FOUND.toString(), e.getErrorCode());
assertEquals(StorageErrorCodeStrings.CONTAINER_NOT_FOUND, e.getErrorCode());
}
assertEquals(1, callList.size());
assertEquals(2, globalCallList.size());
Expand All @@ -368,7 +368,7 @@ public void eventOccurred(RetryingEvent eventArg) {
catch (StorageException e) {
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, e.getHttpStatusCode());
assertEquals("The specified container does not exist.", e.getMessage());
assertEquals(StorageErrorCode.RESOURCE_NOT_FOUND.toString(), e.getErrorCode());
assertEquals(StorageErrorCodeStrings.CONTAINER_NOT_FOUND, e.getErrorCode());
}
assertEquals(1, callList.size());
assertEquals(2, globalCallList.size());
Expand Down Expand Up @@ -422,7 +422,7 @@ public void eventOccurred(RequestCompletedEvent eventArg) {
catch (StorageException e) {
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, e.getHttpStatusCode());
assertEquals("The specified container does not exist.", e.getMessage());
assertEquals(StorageErrorCode.RESOURCE_NOT_FOUND.toString(), e.getErrorCode());
assertEquals(StorageErrorCodeStrings.CONTAINER_NOT_FOUND, e.getErrorCode());
}

assertEquals(2, sendingCallList.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@
*/
package com.microsoft.azure.storage;

import com.microsoft.azure.storage.blob.BlobOutputStream;
import com.microsoft.azure.storage.blob.BlobRequestOptions;
import com.microsoft.azure.storage.blob.BlobTestHelper;
import com.microsoft.azure.storage.blob.CloudBlobClient;
import com.microsoft.azure.storage.blob.CloudBlobContainer;
import com.microsoft.azure.storage.blob.CloudBlockBlob;
import com.microsoft.azure.storage.blob.*;
import com.microsoft.azure.storage.core.BaseRequest;
import com.microsoft.azure.storage.core.SR;
import com.microsoft.azure.storage.core.Utility;
import com.microsoft.azure.storage.queue.CloudQueue;
Expand Down Expand Up @@ -476,4 +472,45 @@ private static String generateRandomContainerName() {
String containerName = "container" + UUID.randomUUID().toString();
return containerName.replace("-", "");
}

@Test
public void testErrorCodeFromHeader() throws URISyntaxException, StorageException, IOException {
CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference(generateRandomContainerName());

CloudAppendBlob appendBlob = container.getAppendBlobReference("testAppend");

try {
container.createIfNotExists();
OperationContext ctx = new OperationContext();
appendBlob.createOrReplace();

// Verify that the error code is set on a non HEAD request
try {
appendBlob.delete(DeleteSnapshotsOption.NONE, AccessCondition.generateIfMatchCondition("garbage"),
null, ctx);
}
catch (Exception e) {
// Validate that the error code is set on the exception and the result
assertEquals(((StorageException)e).getErrorCode(), StorageErrorCodeStrings.CONDITION_NOT_MET);
assertEquals(ctx.getLastResult().getErrorCode(), StorageErrorCodeStrings.CONDITION_NOT_MET);
}

// Verify that the error code is set on a HEAD request
try {
appendBlob.downloadAttributes(AccessCondition.generateIfMatchCondition("garbage"), null, ctx);
}
catch (Exception e) {
assertEquals(((StorageException)e).getErrorCode(), StorageErrorCodeStrings.CONDITION_NOT_MET);
assertEquals(ctx.getLastResult().getErrorCode(), StorageErrorCodeStrings.CONDITION_NOT_MET);
}

// Verify that the ErrorCode is not set on a successful request
appendBlob.delete(DeleteSnapshotsOption.NONE, null, null, ctx);
assertEquals(ctx.getLastResult().getErrorCode(), null);
}
finally {
container.deleteIfExists();
}
}
}
Loading

0 comments on commit b796935

Please sign in to comment.