Skip to content

Commit

Permalink
Merge pull request Azure#8 from wastore/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
esummers-msft committed Apr 6, 2016
2 parents a5790ab + ed3e065 commit a204a9a
Show file tree
Hide file tree
Showing 12 changed files with 662 additions and 33 deletions.
5 changes: 5 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2016.x.x Version 4.2.0
* Added support for setting a library-wide proxy. The default proxy can be set on OperationContext.
* Added support in Page Blob for getting a list of differing page ranges between snapshot versions.
* Added support in Page Blob for getting ranges of pages.

2016.03.31 Version 4.1.0
* Added support for client side encryption for blobs, queues and tables.
* Since the encryption preview, added functionality where uploading encrypted blobs can be done with just PutBlob, not PutBlock + PutBlockList, if the blob is small enough.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -119,7 +122,74 @@ public void testReadTimeoutIssue() throws URISyntaxException, StorageException,
container2.deleteIfExists();
}
}

@Test
public void testProxy() throws URISyntaxException, StorageException {
CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("container1");

// Use a request-level proxy
OperationContext opContext = new OperationContext();
opContext.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.1.1.1", 8888)));

// Turn of retries to make the failure happen faster
BlobRequestOptions opt = new BlobRequestOptions();
opt.setRetryPolicyFactory(new RetryNoRetry());

// Unfortunately HttpURLConnection doesn't expose a getter and the usingProxy method it does have doesn't
// work as one would expect and will always for us return false. So, we validate by making sure the request
// fails when we set a bad proxy rather than check the proxy setting itself.
try {
container.exists(null, opt, opContext);
fail("Bad proxy should throw an exception.");
}
catch (StorageException e) {
assertEquals(ConnectException.class, e.getCause().getClass());
assertEquals("Connection timed out: connect", e.getCause().getMessage());
}
}

@Test
public void testDefaultProxy() throws URISyntaxException, StorageException {
CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("container1");

// Use a default proxy
OperationContext.setDefaultProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.1.1.1", 8888)));

// Turn of retries to make the failure happen faster
BlobRequestOptions opt = new BlobRequestOptions();
opt.setRetryPolicyFactory(new RetryNoRetry());

// Unfortunately HttpURLConnection doesn't expose a getter and the usingProxy method it does have doesn't
// work as one would expect and will always for us return false. So, we validate by making sure the request
// fails when we set a bad proxy rather than check the proxy setting itself succeeding.
try {
container.exists(null, opt, null);
fail("Bad proxy should throw an exception.");
}
catch (StorageException e) {
assertEquals(ConnectException.class, e.getCause().getClass());
assertEquals("Connection timed out: connect", e.getCause().getMessage());
}
}

@Test
public void testProxyOverridesDefault() throws URISyntaxException, StorageException {
CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
CloudBlobContainer container = blobClient.getContainerReference("container1");

// Set a default proxy
OperationContext.setDefaultProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("10.1.1.1", 8888)));

// Override it with no proxy
OperationContext opContext = new OperationContext();
opContext.setProxy(Proxy.NO_PROXY);

// Should succeed as request-level proxy should override the bad default proxy
container.exists(null, null, opContext);
}

/**
* Make sure that if a request throws an error when it is being built that the request is not sent.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;

import org.junit.After;
Expand Down Expand Up @@ -831,40 +833,132 @@ public void testResize() throws StorageException, URISyntaxException {
assertNotNull(blob.getProperties().getPageBlobSequenceNumber());
}

@Test
public void testDownloadPages() throws StorageException, URISyntaxException, IOException {
private CloudPageBlob setUpPageRanges() throws StorageException, URISyntaxException, IOException {
int blobLengthToUse = 8 * 512;
byte[] buffer = BlobTestHelper.getRandomBuffer(8 * 512);
byte[] buffer = BlobTestHelper.getRandomBuffer(blobLengthToUse);

String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
final CloudPageBlob blobRef = this.container.getPageBlobReference(blobName);
blobRef.create(blobLengthToUse);

// Upload one page (page 0)
// Upload page 0
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
blobRef.uploadPages(inputStream, 0, 512);

// Upload pages 2-4
inputStream = new ByteArrayInputStream(buffer, 512, 3 * 512);
blobRef.uploadPages(inputStream, 2 * 512, 3 * 512);

// Now, we expect the first 512 bytes of the blob to be the first 512 bytes of the random buffer (page 0)
// the next 512 bytes should be 0 (page 1)
// The next 3 * 512 bytes should be equal to bytes (512 -> 4 * 512) of the random buffer (pages 2-4)
// The next 3 * 512 bytes should be 0 (pages 5-7)

// Upload page 6
inputStream = new ByteArrayInputStream(buffer, 3 * 512, 512);
blobRef.uploadPages(inputStream, 6 * 512, 512);

// Page0: 512 bytes should be the first 512 bytes of the random buffer (page 0)
// Page1: 512 bytes should be 0
// Page2-4: 3 * 512 bytes should be equal to bytes (512 -> 4 * 512) of the random buffer (pages 2-4)
// Page5: 512 bytes should be 0
// Page6: 512 bytes should be the 4th 512 byte segmented of the random buffer
// Page7-8: 2 * 512 bytes should be 0
return blobRef;
}

@Test
public void testDownloadPages() throws StorageException, URISyntaxException, IOException {
final CloudPageBlob blobRef = setUpPageRanges();

ArrayList<PageRange> actualPageRanges = blobRef.downloadPageRanges();
ArrayList<PageRange> expectedPageRanges = new ArrayList<PageRange>();
expectedPageRanges.add(new PageRange(0, 512 - 1));
expectedPageRanges.add(new PageRange(2 * 512, 2 * 512 + 3 * 512 - 1));
expectedPageRanges.add(new PageRange(2 * 512, 5 * 512 - 1));
expectedPageRanges.add(new PageRange(6 * 512, 7 * 512 - 1));

assertEquals(expectedPageRanges.size(), actualPageRanges.size());
for (int i = 0; i < expectedPageRanges.size(); i++) {
assertEquals(expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
assertEquals(expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
}
}

@Test
public void testDownloadPageRangesWithOffset() throws StorageException, URISyntaxException, IOException {
final CloudPageBlob blobRef = setUpPageRanges();

List<PageRange> actualPageRanges = blobRef.downloadPageRanges((long)1*512, null);
List<PageRange> expectedPageRanges = new ArrayList<PageRange>();
expectedPageRanges.add(new PageRange(2 * 512, 5 * 512 - 1));
expectedPageRanges.add(new PageRange(6 * 512, 7 * 512 - 1));

assertEquals(expectedPageRanges.size(), actualPageRanges.size());
for (int i = 0; i < expectedPageRanges.size(); i++) {
assertEquals(expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
assertEquals(expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
}
}

@Test
public void testDownloadPageRangesWithOffsetAndLength() throws StorageException, URISyntaxException, IOException {
final CloudPageBlob blobRef = setUpPageRanges();

List<PageRange> actualPageRanges = blobRef.downloadPageRanges((long)1*512, (long)5*512);
List<PageRange> expectedPageRanges = new ArrayList<PageRange>();
expectedPageRanges.add(new PageRange(2 * 512, 5 * 512 - 1));

assertEquals(expectedPageRanges.size(), actualPageRanges.size());
for (int i = 0; i < expectedPageRanges.size(); i++) {
assertEquals(expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
assertEquals(expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
}
}

@Test
public void testDownloadPageRangeDiff() throws StorageException, URISyntaxException, IOException {
final CloudPageBlob blobRef = setUpPageRanges();
final CloudPageBlob snapshot = (CloudPageBlob) blobRef.createSnapshot();

// Add page 1
InputStream inputStream = new ByteArrayInputStream(BlobTestHelper.getRandomBuffer(512));
inputStream = new ByteArrayInputStream(BlobTestHelper.getRandomBuffer(512));
blobRef.uploadPages(inputStream, 0, 512);

// Clear page 6
blobRef.clearPages(6 * 512, 512);

List<PageRangeDiff> actualPageRanges = blobRef.downloadPageRangesDiff(snapshot.getSnapshotID());
List<PageRangeDiff> expectedPageRanges = new ArrayList<PageRangeDiff>();
expectedPageRanges.add(new PageRangeDiff(0, 512 - 1, false));
expectedPageRanges.add(new PageRangeDiff(6 * 512, 7 * 512 - 1, true));

assertEquals(expectedPageRanges.size(), actualPageRanges.size());
for (int i = 0; i < expectedPageRanges.size(); i++) {
assertEquals(expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
assertEquals(expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
assertEquals(expectedPageRanges.get(i).isCleared(), actualPageRanges.get(i).isCleared());
}
}

@Test
public void testDownloadPageRangeDiffWithOffsetAndLength() throws StorageException, URISyntaxException, IOException {
final CloudPageBlob blobRef = setUpPageRanges();
final CloudPageBlob snapshot = (CloudPageBlob) blobRef.createSnapshot();

// Add page 1
InputStream inputStream = new ByteArrayInputStream(BlobTestHelper.getRandomBuffer(512));
blobRef.uploadPages(inputStream, 0, 512);

List<PageRangeDiff> actualPageRanges = blobRef.downloadPageRangesDiff(snapshot.getSnapshotID(), (long) 0,
(long) 5 * 512, null, null, null);

List<PageRangeDiff> expectedPageRanges = new ArrayList<PageRangeDiff>();
expectedPageRanges.add(new PageRangeDiff(0, 512 - 1, false));

assertEquals(expectedPageRanges.size(), actualPageRanges.size());
for (int i = 0; i < expectedPageRanges.size(); i++) {
assertEquals(expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
assertEquals(expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
assertEquals(expectedPageRanges.get(i).isCleared(), actualPageRanges.get(i).isCleared());
}
}

@Test
public void testUploadDownloadBlobProperties() throws URISyntaxException, StorageException, IOException {
final int length = 512;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ public static class HeaderConstants {
/**
* The current storage version header value.
*/
public static final String TARGET_STORAGE_VERSION = "2015-04-05";
public static final String TARGET_STORAGE_VERSION = "2015-07-08";

/**
* The header that specifies the next visible time for a queue message.
Expand All @@ -601,7 +601,7 @@ public static class HeaderConstants {
/**
* Specifies the value to use for UserAgent header.
*/
public static final String USER_AGENT_VERSION = "4.1.0";
public static final String USER_AGENT_VERSION = "4.2.0";

/**
* The default type for content-type and accept
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@ public final class OperationContext {

/**
* Indicates whether the client library should produce log entries by default. The default can be overridden to
* enable logging for an individual operation context instance by using {@link setLoggingEnabled}.
* enable logging for an individual operation context instance by using {@link #setLoggingEnabled}.
*/
private static boolean enableLoggingByDefault = false;

/**
* Indicates whether the client library should use a proxy by default. The default can be overridden to
* enable proxy for an individual operation context instance by using {@link #setProxy}.
*/
private static Proxy proxyDefault;

/**
* Represents a proxy to be used when making a request.
Expand Down Expand Up @@ -208,7 +214,8 @@ public org.slf4j.Logger getLogger() {
}

/**
* Gets a proxy which will be used when making a request. Default is <code>null</code>.
* Gets a proxy which will be used when making a request. Default is <code>null</code>. To set a proxy to use by
* default, use {@link #setDefaultProxy}
*
* @return A {@link java.net.Proxy} to use when making a request.
*/
Expand Down Expand Up @@ -391,7 +398,8 @@ public void setLogger(final org.slf4j.Logger logger) {
}

/**
* Sets a proxy which will be used when making a request. Default is <code>null</code>.
* Sets a proxy which will be used when making a request. Default is <code>null</code>. To set a proxy to use by
* default, use {@link #setDefaultProxy}
*
* @param proxy
* A {@link java.net.Proxy} to use when making a request.
Expand Down Expand Up @@ -530,4 +538,25 @@ public static boolean isLoggingEnabledByDefault() {
public static void setLoggingEnabledByDefault(boolean enableLoggingByDefault) {
OperationContext.enableLoggingByDefault = enableLoggingByDefault;
}

/**
* Gets the default proxy used by the client library if enabled. The default can be overridden
* to enable a proxy for an individual operation context instance by using {@link #setProxy}.
*
* @return The default {@link java.net.Proxy} if set; otherwise <code>null</code>
*/
public static Proxy getDefaultProxy() {
return OperationContext.proxyDefault;
}

/**
* Specifies the proxy the client library should use by default. The default can be overridden
* to turn on a proxy for an individual operation context instance by using {@link #setProxy}.
*
* @param defaultProxy
* The {@link java.net.Proxy} to use by default, or <code>null</code> to not use a proxy.
*/
public static void setDefaultProxy(Proxy defaultProxy) {
OperationContext.proxyDefault = defaultProxy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ final class BlobConstants {
*/
public static final String BLOCK_LIST_ELEMENT = "BlockList";

/**
* XML element for clear ranges.
*/
public static final String CLEAR_RANGE_ELEMENT = "ClearRange";

/**
* XML element for committed blocks.
*/
Expand Down Expand Up @@ -187,6 +192,11 @@ final class BlobConstants {
*/
public static final String PAGE_WRITE = Constants.PREFIX_FOR_STORAGE_HEADER + "page-write";

/**
* Query component value for previous snapshot.
*/
public static final String PREV_SNAPSHOT = "prevsnapshot";

/**
* The header for specifying the sequence number.
*/
Expand Down
Loading

0 comments on commit a204a9a

Please sign in to comment.