Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit e902393

Browse files
authored
Merge pull request #191 from jofriedm-msft/master
5.4.0 Release
2 parents 3e771ab + 44fb4db commit e902393

32 files changed

+1456
-109
lines changed

ChangeLog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2017.07.12 Version 5.4.0
2+
* Added ErrorReceivingResponseEvent which fires when a network error occurs before the responseReceivedEvent fires. If the responseReceivedEvent fires sucessfully, this new event will not fire.
3+
* For Premium Accounts only, added support for getting and setting the tier on a page blob. The tier can also be set when creating or copying from an existing page blob.
4+
* Added support for server side encryption for File Service.
5+
16
2017.06.21 Version 5.3.1
27
* Fixed a bug in specific upload case for block blobs. This only affects uploads greater than the max put blob threshold, that have increased the streamWriteSizeInBytes beyond the 4 MB and storeBlobContentMD5 has been disabled.
38
* In some cases in the above mentioned upload path, fixed a bug where StorageExceptions were being thrown instead of IOExceptions.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
3030
<dependency>
3131
<groupId>com.microsoft.azure</groupId>
3232
<artifactId>azure-storage</artifactId>
33-
<version>5.3.1</version>
33+
<version>5.4.0</version>
3434
</dependency>
3535
```
3636

microsoft-azure-storage-samples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<dependency>
2727
<groupId>com.microsoft.azure</groupId>
2828
<artifactId>azure-storage</artifactId>
29-
<version>5.3.1</version>
29+
<version>5.4.0</version>
3030
</dependency>
3131
<dependency>
3232
<groupId>com.microsoft.azure</groupId>

microsoft-azure-storage-test/res/TestConfigurations.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<TestConfigurations>
22
<TargetTestTenant>ProductionTenant</TargetTestTenant>
3+
<TargetPremiumBlobTenant>ProductionTenant</TargetPremiumBlobTenant>
34
<TenantConfigurations>
45
<TenantConfiguration>
56
<TenantName>DevStore</TenantName>

microsoft-azure-storage-test/src/com/microsoft/azure/storage/EventFiringTests.java

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,20 @@
1414
*/
1515
package com.microsoft.azure.storage;
1616

17-
import com.microsoft.azure.storage.blob.BlobRequestOptions;
18-
import com.microsoft.azure.storage.blob.CloudBlobClient;
19-
import com.microsoft.azure.storage.blob.CloudBlobContainer;
17+
import com.microsoft.azure.storage.blob.*;
2018
import com.microsoft.azure.storage.core.SR;
2119
import com.microsoft.azure.storage.TestRunners.CloudTests;
2220
import com.microsoft.azure.storage.TestRunners.DevFabricTests;
2321
import com.microsoft.azure.storage.TestRunners.DevStoreTests;
2422

23+
import org.apache.http.protocol.HTTP;
2524
import org.junit.Test;
2625
import org.junit.experimental.categories.Category;
2726

27+
import java.io.ByteArrayInputStream;
28+
import java.io.IOException;
2829
import java.net.HttpURLConnection;
30+
import java.net.SocketException;
2931
import java.net.URISyntaxException;
3032
import java.util.ArrayList;
3133

@@ -111,6 +113,22 @@ public void eventOccurred(ResponseReceivedEvent eventArg) {
111113
}
112114
});
113115

116+
eventContext.getErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
117+
118+
@Override
119+
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
120+
fail("This event should not trigger");
121+
}
122+
});
123+
124+
OperationContext.getGlobalErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
125+
126+
@Override
127+
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
128+
fail("This event should not trigger");
129+
}
130+
});
131+
114132
assertEquals(0, callList.size());
115133
assertEquals(0, globalCallList.size());
116134

@@ -138,6 +156,85 @@ public void eventOccurred(ResponseReceivedEvent eventArg) {
138156
assertEquals(2, globalCallList.size());
139157
}
140158

159+
@Test
160+
public void testErrorReceivingResponseEvent() throws URISyntaxException, StorageException {
161+
final ArrayList<Boolean> callList = new ArrayList<Boolean>();
162+
final ArrayList<Boolean> globalCallList = new ArrayList<Boolean>();
163+
164+
OperationContext eventContext = new OperationContext();
165+
BlobRequestOptions options = new BlobRequestOptions();
166+
options.setRetryPolicyFactory(new RetryNoRetry());
167+
168+
// setting the sending request event handler to trigger an exception.
169+
// this is a retryable exception
170+
eventContext.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() {
171+
@Override
172+
public void eventOccurred(SendingRequestEvent eventArg) {
173+
HttpURLConnection connection = (HttpURLConnection) eventArg.getConnectionObject();
174+
connection.setFixedLengthStreamingMode(0);
175+
}
176+
});
177+
178+
eventContext.getErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
179+
@Override
180+
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
181+
assertEquals(eventArg.getRequestResult(), eventArg.getOpContext().getLastResult());
182+
callList.add(true);
183+
}
184+
});
185+
186+
OperationContext.getGlobalErrorReceivingResponseEventHandler().addListener(new StorageEvent<ErrorReceivingResponseEvent>() {
187+
@Override
188+
public void eventOccurred(ErrorReceivingResponseEvent eventArg) {
189+
assertEquals(eventArg.getRequestResult(), eventArg.getOpContext().getLastResult());
190+
globalCallList.add(true);
191+
}
192+
});
193+
194+
CloudBlobClient blobClient = TestHelper.createCloudBlobClient();
195+
CloudBlobContainer container = blobClient.getContainerReference("container1");
196+
container.createIfNotExists();
197+
198+
try {
199+
CloudBlockBlob blob1 = container.getBlockBlobReference("blob1");
200+
try {
201+
String blockID = String.format("%08d", 1);
202+
blob1.uploadBlock(blockID, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);
203+
} catch (Exception e) { }
204+
205+
// make sure both the local and globab context update
206+
assertEquals(1, callList.size());
207+
assertEquals(1, globalCallList.size());
208+
209+
// make sure only global updates by replacing the local with a no-op event
210+
eventContext
211+
.setErrorReceivingResponseEventHandler(new StorageEventMultiCaster<ErrorReceivingResponseEvent, StorageEvent<ErrorReceivingResponseEvent>>());
212+
try {
213+
String blockID2 = String.format("%08d", 2);
214+
blob1.uploadBlock(blockID2, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);
215+
} catch (Exception e) { }
216+
217+
assertEquals(1, callList.size());
218+
assertEquals(2, globalCallList.size());
219+
220+
// make sure global does not update by replacing the global with a no-op
221+
OperationContext
222+
.setGlobalErrorReceivingResponseEventHandler(new StorageEventMultiCaster<ErrorReceivingResponseEvent, StorageEvent<ErrorReceivingResponseEvent>>());
223+
224+
// make sure neither update
225+
try {
226+
String blockID3 = String.format("%08d", 3);
227+
blob1.uploadBlock(blockID3, BlobTestHelper.getRandomDataStream(10), 10, null, options, eventContext);
228+
} catch (Exception e) { }
229+
230+
assertEquals(1, callList.size());
231+
assertEquals(2, globalCallList.size());
232+
}
233+
finally {
234+
container.deleteIfExists();
235+
}
236+
}
237+
141238
@Test
142239
public void testRequestCompletedEvents() throws URISyntaxException, StorageException {
143240
final ArrayList<Boolean> callList = new ArrayList<Boolean>();

microsoft-azure-storage-test/src/com/microsoft/azure/storage/TestHelper.java

Lines changed: 105 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.microsoft.azure.storage;
1616

1717
import static org.junit.Assert.*;
18+
import static org.junit.Assume.assumeNotNull;
1819

1920
import java.io.ByteArrayInputStream;
2021
import java.io.File;
@@ -39,6 +40,7 @@
3940
import javax.xml.parsers.DocumentBuilderFactory;
4041
import javax.xml.parsers.ParserConfigurationException;
4142

43+
import org.junit.AssumptionViolatedException;
4244
import org.w3c.dom.DOMException;
4345
import org.w3c.dom.Document;
4446
import org.w3c.dom.Node;
@@ -58,6 +60,9 @@ public class TestHelper {
5860
private static Tenant tenant;
5961
private static StorageCredentialsAccountAndKey credentials;
6062
private static CloudStorageAccount account;
63+
private static Tenant premiumBlobTenant;
64+
private static StorageCredentialsAccountAndKey premiumBlobCredentials;
65+
private static CloudStorageAccount premiumBlobAccount;
6166

6267
private final static boolean enableFiddler = true;
6368
private final static boolean requireSecondaryEndpoint = false;
@@ -67,6 +72,11 @@ public static CloudBlobClient createCloudBlobClient() throws StorageException {
6772
return client;
6873
}
6974

75+
public static CloudBlobClient createPremiumCloudBlobClient() throws StorageException {
76+
CloudBlobClient client = getPremiumBlobAccount().createCloudBlobClient();
77+
return client;
78+
}
79+
7080
public static CloudBlobClient createCloudBlobClient(SharedAccessAccountPolicy policy, boolean useHttps)
7181
throws StorageException, InvalidKeyException, URISyntaxException {
7282

@@ -328,12 +338,12 @@ private static CloudStorageAccount getAccount() throws StorageException {
328338
account = CloudStorageAccount.parse(cloudAccount);
329339
}
330340
else if (accountConfig != null) {
331-
tenant = readTestConfigsFromXml(new File(accountConfig));
341+
readTestConfigsFromXml(new File(accountConfig), false);
332342
setAccountAndCredentials();
333343
}
334344
else {
335345
URL localTestConfig = TestHelper.class.getClassLoader().getResource("TestConfigurations.xml");
336-
tenant = readTestConfigsFromXml(new File(localTestConfig.getPath()));
346+
readTestConfigsFromXml(new File(localTestConfig.getPath()), false);
337347
setAccountAndCredentials();
338348
}
339349
}
@@ -344,6 +354,47 @@ else if (accountConfig != null) {
344354
return account;
345355
}
346356

357+
private static CloudStorageAccount getPremiumBlobAccount() throws StorageException {
358+
// Only do this the first time TestBase is called as storage account is static
359+
if (premiumBlobAccount == null) {
360+
//enable fiddler
361+
if (enableFiddler)
362+
enableFiddler();
363+
364+
// try to get the environment variable with the test configuration file path
365+
String accountConfig;
366+
try {
367+
accountConfig = System.getenv("storageTestConfiguration");
368+
}
369+
catch (SecurityException e) {
370+
accountConfig = null;
371+
}
372+
373+
// if storageConnection is set, use that as an account string
374+
// if storageTestConfiguration is set, use that as a path to the configurations file
375+
// if neither are set, use the local configurations file at TestConfigurations.xml
376+
try {
377+
if (accountConfig != null) {
378+
readTestConfigsFromXml(new File(accountConfig), true);
379+
setAccountAndCredentials();
380+
}
381+
else {
382+
URL localTestConfig = TestHelper.class.getClassLoader().getResource("TestConfigurations.xml");
383+
readTestConfigsFromXml(new File(localTestConfig.getPath()), true);
384+
setAccountAndCredentials();
385+
}
386+
}
387+
catch (AssumptionViolatedException e) {
388+
throw e;
389+
}
390+
catch (Exception e) {
391+
throw StorageException.translateClientException(e);
392+
}
393+
}
394+
395+
return premiumBlobAccount;
396+
}
397+
347398
private static void setAccountAndCredentials() {
348399
if (requireSecondaryEndpoint)
349400
tenant.assertSecondaryEndpoint();
@@ -353,9 +404,17 @@ private static void setAccountAndCredentials() {
353404
tenant.getQueueServiceSecondaryEndpoint()), new StorageUri(tenant.getTableServiceEndpoint(),
354405
tenant.getTableServiceSecondaryEndpoint()), new StorageUri(tenant.getFileServiceEndpoint(),
355406
tenant.getFileServiceSecondaryEndpoint()));
407+
408+
if (premiumBlobTenant != null) {
409+
premiumBlobCredentials = new StorageCredentialsAccountAndKey(premiumBlobTenant.getAccountName(), premiumBlobTenant.getAccountKey());
410+
premiumBlobAccount = new CloudStorageAccount(premiumBlobCredentials, new StorageUri(premiumBlobTenant.getBlobServiceEndpoint(), premiumBlobTenant.getBlobServiceSecondaryEndpoint()),
411+
null,
412+
null,
413+
null);
414+
}
356415
}
357416

358-
private static Tenant readTestConfigsFromXml(File testConfigurations) throws ParserConfigurationException,
417+
private static void readTestConfigsFromXml(File testConfigurations, boolean premiumBlob) throws ParserConfigurationException,
359418
SAXException, IOException, DOMException, URISyntaxException {
360419

361420
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
@@ -372,7 +431,14 @@ private static Tenant readTestConfigsFromXml(File testConfigurations) throws Par
372431
throw new IllegalArgumentException("No TargetTestTenant specified.");
373432
}
374433

375-
Tenant tenant = null;
434+
Node premiumBlobTenantNode = testConfigs.getElementsByTagName("TargetPremiumBlobTenant").item(0);
435+
String premiumBlobTenantName = null;
436+
if (premiumBlobTenantNode != null) {
437+
premiumBlobTenantName = premiumBlobTenantNode.getTextContent();
438+
}
439+
440+
tenant = null;
441+
premiumBlobTenant = null;
376442
final NodeList tenantNodes = testConfigs.getElementsByTagName("TenantName");
377443
for (int i = 0; i < tenantNodes.getLength(); i++) {
378444
if (tenantNodes.item(i).getTextContent().equals(targetTenant)) {
@@ -436,18 +502,50 @@ else if (name.equals("TableHttpsPortOverride")) {
436502
else if (name.equals("FileHttpsPortOverride")) {
437503
tenant.setFileHttpsPortOverride(Integer.parseInt(node.getTextContent()));
438504
}
439-
else {
505+
else if (!premiumBlob){
440506
throw new IllegalArgumentException(String.format(
441507
"Invalid child of TenantConfiguration with name: %s", name));
442508
}
443509
}
444510
}
445511
}
512+
513+
if (tenantNodes.item(i).getTextContent().equals(premiumBlobTenantName)) {
514+
premiumBlobTenant = new Tenant();
515+
Node parent = tenantNodes.item(i).getParentNode();
516+
final NodeList childNodes = parent.getChildNodes();
517+
for (int j = 0; j < childNodes.getLength(); j++) {
518+
final Node node = childNodes.item(j);
519+
520+
if (node.getNodeType() != Node.ELEMENT_NODE) {
521+
// do nothing
522+
} else {
523+
final String name = node.getNodeName();
524+
525+
if (name.equals("TenantName")) {
526+
premiumBlobTenant.setTenantName(node.getTextContent());
527+
} else if (name.equals("TenantType")) {
528+
// do nothing, we don't track this field
529+
} else if (name.equals("AccountName")) {
530+
premiumBlobTenant.setAccountName(node.getTextContent());
531+
} else if (name.equals("AccountKey")) {
532+
premiumBlobTenant.setAccountKey(node.getTextContent());
533+
} else if (name.equals("BlobServiceEndpoint")) {
534+
premiumBlobTenant.setBlobServiceEndpoint(new URI(node.getTextContent()));
535+
} else if (name.equals("BlobServiceSecondaryEndpoint")) {
536+
premiumBlobTenant.setBlobServiceSecondaryEndpoint(new URI(node.getTextContent()));
537+
}
538+
}
539+
}
540+
}
446541
}
447542

448-
if (tenant == null) {
543+
if (tenant == null && !premiumBlob) {
449544
throw new IllegalArgumentException("TargetTestTenant specified did not exist in TenantConfigurations.");
450545
}
451-
return tenant;
546+
547+
if (premiumBlobTenant == null && premiumBlob) {
548+
assumeNotNull(premiumBlobTenant);
549+
}
452550
}
453551
}

microsoft-azure-storage-test/src/com/microsoft/azure/storage/TestRunners.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ public interface CloudTests {
105105
public interface DevFabricTests {
106106
}
107107

108+
public interface PremiumBlobTests {
109+
}
110+
108111
// Test suites
109112
@RunWith(Suite.class)
110113
@SuiteClasses({ AccountSasTests.class, EventFiringTests.class, GenericTests.class, LoggerTests.class,
@@ -116,7 +119,8 @@ public static class CoreTestSuite {
116119
@RunWith(Suite.class)
117120
@SuiteClasses({ BlobOutputStreamTests.class, CloudBlobClientTests.class, CloudBlobContainerTests.class,
118121
CloudBlobDirectoryTests.class, CloudAppendBlobTests.class, CloudBlockBlobTests.class, CloudPageBlobTests.class,
119-
CloudBlobClientEncryptionTests.class, CloudBlobServerEncryptionTests.class, LeaseTests.class, SasTests.class })
122+
CloudBlobClientEncryptionTests.class, CloudBlobServerEncryptionTests.class, LeaseTests.class, SasTests.class,
123+
PremiumBlobTests.class })
120124
public static class BlobTestSuite {
121125
}
122126

@@ -177,4 +181,9 @@ public static class DevFabricNoSecondarySuite {
177181
@SuiteClasses(AllTestSuite.class)
178182
public static class FastTestSuite {
179183
}
184+
185+
@RunWith(Categories.class)
186+
@IncludeCategory(PremiumBlobTests.class)
187+
public static class PremiumBlobTestSuite {
188+
}
180189
}

0 commit comments

Comments
 (0)