Skip to content

Commit

Permalink
Merge pull request #10 from emgerner-msft/master
Browse files Browse the repository at this point in the history
Android Storage Client Library 0.5.0
  • Loading branch information
emgerner-msft committed Apr 2, 2015
2 parents 7dfbe74 + f37855a commit abf92ec
Show file tree
Hide file tree
Showing 49 changed files with 1,285 additions and 826 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ tmp/**/*
*.swp
*~.nib
local.properties
.settings/**
*/.settings/**
.loadpath

# External tool builders
Expand Down
11 changes: 11 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
2015.04.02 Version 0.5.0
* Fixed a bug for all listing API's where next() would sometimes throw an exception if hasNext() had not been called even if there were more elements to iterate on.
* Added sequence number to the blob properties. This is populated for page blobs.
* Creating a page blob sets its length property.
* Added support for page blob sequence numbers and sequence number access conditions.
* Fixed a bug in abort copy where the lease access condition was not sent to the service.
* Fixed an issue in startCopyFromBlob where if the URI of the source blob contained certain non-ASCII characters they would not be encoded appropriately. This would result in Authorization failures.
* Fixed a bug in BlobOutputStream and FileOutputStream where flush added data to a request pool rather than immediately committing it to the Azure service.
* Refactored to remove the blob, queue, and file package dependency on table in the error handling code.
* Added additional client-side logging for REST requests, responses, and errors.

2015.01 Version 0.4.1
* Fixed a bug for Android 5.0 only that caused auth failures on deletes.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ First, add mavenCentral to your repositories by adding the following to your gra
Then, add a dependency by adding the following to your gradle build file:

dependencies {
compile 'com.microsoft.azure.android:azure-storage-android:0.4.1@aar'
compile 'com.microsoft.azure.android:azure-storage-android:0.5.0@aar'
}

###Option 4: aar via Maven
Expand All @@ -55,7 +55,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
<dependency>
<groupId>com.microsoft.azure.android</groupId>
<artifactId>azure-storage-android</artifactId>
<version>0.4.1</version>
<version>0.5.0</version>
<type>aar</type>
</dependency>
```
Expand Down
2 changes: 1 addition & 1 deletion microsoft-azure-storage-samples/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.microsoft.azure.storage.samples"
android:versionCode="0"
android:versionName="0.4.1" >
android:versionName="0.5.0" >

<uses-sdk
android:minSdkVersion="15"
Expand Down
2 changes: 1 addition & 1 deletion microsoft-azure-storage-test/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.microsoft.azure.android.test"
android:versionCode="0"
android:versionName="0.4.1" >
android:versionName="0.5.0" >

<uses-sdk
android:minSdkVersion="15"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,14 +770,6 @@ else if (client.getClass().equals(CloudQueueClient.class)) {

/**
* Takes a CorsRule and tries to upload it. Then tries to download it and compares it to the initial CorsRule.
*
* @param rule
* @param client
* TODO
* @param props
* TODO
* @throws StorageException
* @throws InterruptedException
*/
private void testCorsRules(CorsRule rule, ServiceClient client, ServiceProperties props) throws StorageException,
InterruptedException {
Expand All @@ -792,15 +784,6 @@ private void testCorsRules(CorsRule rule, ServiceClient client, ServicePropertie
/**
* Takes a List of CorsRules and tries to upload them. Then tries to download them and compares the list to the
* initial CorsRule List.
*
* @param client
* TODO
* @param props
* TODO
* @param rule
*
* @throws StorageException
* @throws InterruptedException
*/
private void testCorsRules(List<CorsRule> corsRules, ServiceClient client, ServiceProperties props)
throws StorageException, InterruptedException {
Expand All @@ -817,9 +800,6 @@ private void testCorsRules(List<CorsRule> corsRules, ServiceClient client, Servi

/**
* Checks two ServiceProperties for equality
*
* @param propsA
* @param propsB
*/
private static void assertServicePropertiesAreEqual(ServiceProperties propsA, ServiceProperties propsB) {
if (propsA.getLogging() != null && propsB.getLogging() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,15 @@ public void testStorageCredentialsSharedKey() throws URISyntaxException, Storage
}

public void testStorageCredentialsSAS() throws URISyntaxException, StorageException {
String token = "?sp=abcde&api-version=2014-02-14&sig=1";

String token = "?sig=1&api-version=2014-02-14&sp=abcde";
StorageCredentialsSharedAccessSignature cred = new StorageCredentialsSharedAccessSignature(token);

assertNull(cred.getAccountName());

URI testUri = new URI("http://test/abc");
assertEquals(testUri + token, cred.transformUri(testUri).toString());

testUri = new URI("http://test/abc?query=a&query2=b");
String expectedUri = "http://test/abc?api-version=2014-02-14&sp=abcde&query=a&query2=b&sig=1";
String expectedUri = "http://test/abc?sig=1&api-version=2014-02-14&query=a&sp=abcde&query2=b";
assertEquals(expectedUri, cred.transformUri(testUri).toString());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ public static void assertAreEqual(BlobProperties prop1, BlobProperties prop2) {
Assert.assertEquals(prop1.getEtag(), prop2.getEtag());
Assert.assertEquals(prop1.getLastModified(), prop2.getLastModified());
Assert.assertEquals(prop1.getLength(), prop2.getLength());
Assert.assertEquals(prop1.getPageBlobSequenceNumber(), prop2.getPageBlobSequenceNumber());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.UUID;

import junit.framework.Assert;
import junit.framework.TestCase;

import android.annotation.SuppressLint;
import com.microsoft.azure.storage.Constants;
import com.microsoft.azure.storage.NameValidator;
import com.microsoft.azure.storage.OperationContext;
Expand Down Expand Up @@ -433,6 +433,34 @@ public void testCloudBlobContainerListBlobs() throws StorageException, IOExcepti
assertTrue(blobNames.size() == 0);
}

/**
* List the blobs in a container with next(). This tests for the item in the changelog: "Fixed a bug for all
* listing API's where next() would sometimes throw an exception if hasNext() had not been called even if
* there were more elements to iterate on."
*
* @throws URISyntaxException
* @throws StorageException
* @throws IOException
*/
public void testCloudBlobContainerListBlobsNext() throws StorageException, IOException, URISyntaxException {
this.container.create();

int numBlobs = 10;
List<String> blobNames = BlobTestHelper.uploadNewBlobs(this.container, BlobType.PAGE_BLOB, 10, 512, null);
assertEquals(numBlobs, blobNames.size());

// hasNext first
Iterator<ListBlobItem> iter = this.container.listBlobs().iterator();
iter.hasNext();
iter.next();
iter.next();

// next without hasNext
iter = this.container.listBlobs().iterator();
iter.next();
iter.next();
}

/**
* Try to list the blobs in a container to ensure maxResults validation is working.
*
Expand Down Expand Up @@ -590,7 +618,8 @@ private static void assertPermissionsEqual(BlobContainerPermissions expected, Bl
* @throws StorageException
* @throws URISyntaxException
*/
private static void assertCreatedAndListedBlobsEquivalent(CloudBlockBlob createdBlob, CloudBlockBlob listedBlob,
@SuppressLint("UseValueOf")
private static void assertCreatedAndListedBlobsEquivalent(CloudBlockBlob createdBlob, CloudBlockBlob listedBlob,
int length) throws StorageException, URISyntaxException{
assertEquals(createdBlob.getContainer().getName(), listedBlob.getContainer().getName());
assertEquals(createdBlob.getMetadata(), listedBlob.getMetadata());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ private void testFlatListingWithDirectory(String delimiter, CloudBlobContainer c
null), get22.getUri());
}

public void testFlatListingWithDirectorySegmented() throws URISyntaxException, StorageException {
// Re-enable after fix in 3.0 with int->Integer
public void ignoreTestFlatListingWithDirectorySegmented() throws URISyntaxException, StorageException {
for (int i = 0; i < delimiters.length; i++) {
CloudBlobContainer container = null;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,41 @@ public void testCopyBlockBlobTest() throws InvalidKeyException, URISyntaxExcepti
InterruptedException {
this.doCloudBlockBlobCopy(false, false);
}

public void testCopyWithChineseChars() throws StorageException, IOException, URISyntaxException {
String data = "sample data chinese chars 阿䶵";
CloudBlockBlob copySource = container.getBlockBlobReference("sourcechinescharsblob阿䶵.txt");
copySource.uploadText(data);

assertEquals(this.container.getUri() + "/sourcechinescharsblob阿䶵.txt", copySource.getUri().toString());
assertEquals(this.container.getUri() + "/sourcechinescharsblob%E9%98%BF%E4%B6%B5.txt",
copySource.getUri().toASCIIString());

CloudBlockBlob copyDestination = container.getBlockBlobReference("destchinesecharsblob阿䶵.txt");

assertEquals(this.container.getUri() + "/destchinesecharsblob阿䶵.txt", copyDestination.getUri().toString());
assertEquals(this.container.getUri() + "/destchinesecharsblob%E9%98%BF%E4%B6%B5.txt",
copyDestination.getUri().toASCIIString());

OperationContext ctx = new OperationContext();
ctx.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() {
@Override
public void eventOccurred(SendingRequestEvent eventArg) {
HttpURLConnection con = (HttpURLConnection) eventArg.getConnectionObject();

// Test the copy destination request url
assertEquals(CloudBlockBlobTests.this.container.getUri() + "/destchinesecharsblob%E9%98%BF%E4%B6%B5.txt",
con.getURL().toString());

// Test the copy source request property
assertEquals(CloudBlockBlobTests.this.container.getUri() + "/sourcechinescharsblob%E9%98%BF%E4%B6%B5.txt",
con.getRequestProperty("x-ms-copy-source"));
}
});

copyDestination.startCopyFromBlob(copySource.getUri(), null, null, null, ctx);
copyDestination.startCopyFromBlob(copySource, null, null, null, ctx);
}

public void testCopyBlockBlobWithMetadataOverride() throws URISyntaxException, StorageException, IOException,
InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,14 +670,17 @@ public void testUploadPages() throws URISyntaxException, StorageException, IOExc
String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
final CloudPageBlob blobRef = this.container.getPageBlobReference(blobName);
blobRef.create(blobLengthToUse);
assertNull(blobRef.getProperties().getPageBlobSequenceNumber());

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

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

// 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)
Expand Down Expand Up @@ -729,10 +732,12 @@ public void testClearPages() throws URISyntaxException, StorageException, IOExce
String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
final CloudPageBlob blobRef = this.container.getPageBlobReference(blobName);
blobRef.create(blobLengthToUse);
assertNull(blobRef.getProperties().getPageBlobSequenceNumber());

// Upload one page (page 0)
ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
blobRef.uploadPages(inputStream, 0, blobLengthToUse);
assertNotNull(blobRef.getProperties().getPageBlobSequenceNumber());

try {
blobRef.clearPages(0, 256);
Expand All @@ -751,6 +756,7 @@ public void testClearPages() throws URISyntaxException, StorageException, IOExce
}

blobRef.clearPages(3 * 512, 2 * 512);
assertNotNull(blobRef.getProperties().getPageBlobSequenceNumber());

byte[] result = new byte[blobLengthToUse];
blobRef.downloadToByteArray(result, 0);
Expand All @@ -776,21 +782,26 @@ public void testResize() throws StorageException, URISyntaxException {

blob.create(1024);
assertEquals(1024, blob.getProperties().getLength());
assertNull(blob.getProperties().getPageBlobSequenceNumber());

blob2.downloadAttributes();
assertEquals(1024, blob2.getProperties().getLength());
assertNull(blob.getProperties().getPageBlobSequenceNumber());

blob2.getProperties().setContentType("text/plain");
blob2.uploadProperties();

blob.resize(2048);
assertEquals(2048, blob.getProperties().getLength());
assertNotNull(blob.getProperties().getPageBlobSequenceNumber());

blob.downloadAttributes();
assertEquals("text/plain", blob.getProperties().getContentType());
assertNotNull(blob.getProperties().getPageBlobSequenceNumber());

blob2.downloadAttributes();
assertEquals(2048, blob2.getProperties().getLength());
assertNotNull(blob.getProperties().getPageBlobSequenceNumber());
}

public void testDownloadPages() throws StorageException, URISyntaxException, IOException {
Expand Down
Loading

0 comments on commit abf92ec

Please sign in to comment.