/** * Copyright Microsoft Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.microsoft.azure.storage.file; import com.microsoft.azure.storage.Constants; import com.microsoft.azure.storage.core.Base64; import com.microsoft.azure.storage.core.Utility; import com.microsoft.azure.storage.NameValidator; import com.microsoft.azure.storage.OperationContext; import com.microsoft.azure.storage.RetryNoRetry; import com.microsoft.azure.storage.SendingRequestEvent; import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature; import com.microsoft.azure.storage.StorageErrorCodeStrings; import com.microsoft.azure.storage.StorageEvent; import com.microsoft.azure.storage.StorageException; import com.microsoft.azure.storage.TestRunners; import com.microsoft.azure.storage.blob.BlobProperties; import com.microsoft.azure.storage.blob.BlobTestHelper; import com.microsoft.azure.storage.blob.CloudBlob; import com.microsoft.azure.storage.blob.CloudBlobContainer; import com.microsoft.azure.storage.blob.CloudBlockBlob; import com.microsoft.azure.storage.blob.CloudPageBlob; import com.microsoft.azure.storage.blob.SharedAccessBlobPermissions; import com.microsoft.azure.storage.blob.SharedAccessBlobPolicy; import com.microsoft.azure.storage.TestRunners.CloudTests; import com.microsoft.azure.storage.TestRunners.DevFabricTests; import com.microsoft.azure.storage.TestRunners.DevStoreTests; import com.microsoft.azure.storage.TestRunners.SlowTests; import com.microsoft.azure.storage.core.SR; import com.microsoft.azure.storage.core.UriQueryBuilder; import com.microsoft.azure.storage.core.Utility; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.EnumSet; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.Random; import java.util.TimeZone; import static org.junit.Assert.*; /** * File Tests */ @Category(CloudTests.class) public class CloudFileTests { protected CloudFileShare share; @Before public void fileTestMethodSetUp() throws URISyntaxException, StorageException { this.share = FileTestHelper.getRandomShareReference(); this.share.create(); } @After public void fileTestMethodTearDown() throws StorageException { this.share.deleteIfExists(); } /** * Test file name validation. */ @Test public void testCloudFileNameValidation() { NameValidator.validateFileName("alpha"); NameValidator.validateFileName("4lphanum3r1c"); NameValidator.validateFileName("middle-dash"); NameValidator.validateFileName("CAPS"); NameValidator.validateFileName("$root"); invalidFileTestHelper(null, "No null.", "Invalid file name. The name may not be null, empty, or whitespace only."); invalidFileTestHelper("..", "Reserved.", "Invalid file name. This name is reserved."); invalidFileTestHelper("Clock$", "Reserved.", "Invalid file name. This name is reserved."); invalidFileTestHelper("endslash/", "No slashes.", "Invalid file name. Check MSDN for more information about valid naming."); invalidFileTestHelper("middle/slash", "No slashes.", "Invalid file name. Check MSDN for more information about valid naming."); invalidFileTestHelper("illegal\"char", "Illegal characters.", "Invalid file name. Check MSDN for more information about valid naming."); invalidFileTestHelper("illegal:char?", "Illegal characters.", "Invalid file name. Check MSDN for more information about valid naming."); invalidFileTestHelper("", "Between 1 and 255 characters.", "Invalid file name. The name may not be null, empty, or whitespace only."); invalidFileTestHelper(new String(new char[256]).replace("\0", "n"), "Between 1 and 255 characters.", "Invalid file name length. The name must be between 1 and 255 characters long."); } private void invalidFileTestHelper(String fileName, String failMessage, String exceptionMessage) { try { NameValidator.validateFileName(fileName); fail(failMessage); } catch (IllegalArgumentException e) { assertEquals(exceptionMessage, e.getMessage()); } } /** * Test file creation and deletion. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileCreateAndDelete() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); file.create(0); assertTrue(file.exists()); file.delete(); } @Test public void testCloudFileCreate() throws StorageException, URISyntaxException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); assertFalse(file.exists()); // Create file.create(512); assertTrue(file.exists()); // Create again (should succeed) file.create(128); assertTrue(file.exists()); } /** * Test file constructor. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileConstructor() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); CloudFile file2 = new CloudFile(file.getStorageUri(), file.getServiceClient().getCredentials()); assertEquals(file.getName(), file2.getName()); assertEquals(file.getStorageUri(), file2.getStorageUri()); assertEquals(file.getShare().getStorageUri(), file2.getShare().getStorageUri()); assertEquals(FileTestHelper.ensureTrailingSlash(file.getServiceClient().getStorageUri()), FileTestHelper.ensureTrailingSlash(file2.getServiceClient().getStorageUri())); CloudFile file3 = new CloudFile(file2); assertEquals(file3.getName(), file2.getName()); assertEquals(file3.getStorageUri(), file2.getStorageUri()); assertEquals(file3.getShare().getStorageUri(), file2.getShare().getStorageUri()); assertEquals(FileTestHelper.ensureTrailingSlash(file3.getServiceClient().getStorageUri()), FileTestHelper.ensureTrailingSlash(file2.getServiceClient().getStorageUri())); } /** * Test file resizing. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileResize() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); file.create(1024); assertEquals(1024, file.getProperties().getLength()); file2.downloadAttributes(); assertEquals(1024, file2.getProperties().getLength()); file2.getProperties().setContentType("text/plain"); file2.uploadProperties(); file.resize(2048); assertEquals(2048, file.getProperties().getLength()); file.downloadAttributes(); assertEquals("text/plain", file.getProperties().getContentType()); file2.downloadAttributes(); assertEquals(2048, file2.getProperties().getLength()); // Resize to 0 length file.resize(0); assertEquals(0, file.getProperties().getLength()); file.downloadAttributes(); assertEquals("text/plain", file.getProperties().getContentType()); file2.downloadAttributes(); assertEquals(0, file2.getProperties().getLength()); } /** * Test file creation with invalid sizes. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileCreateInvalidSize() throws StorageException, URISyntaxException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); try { file.create(-1); fail("Creating a file with size<0 should fail"); } catch (StorageException e) { assertEquals(e.getHttpStatusCode(), 400); assertEquals(e.getMessage(), "The value for one of the HTTP headers is not in the correct format."); } try { file.create(1L * 1024 * 1024 * 1024 * 1024 + 1); fail("Creating a file with size>1TB should fail"); } catch (StorageException e) { assertEquals(e.getHttpStatusCode(), 400); assertEquals(e.getMessage(), "The value for one of the HTTP headers is not in the correct format."); } } /** * Test file deleteIfExists. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileDeleteIfExists() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); assertFalse(file.deleteIfExists()); file.create(0); assertTrue(file.deleteIfExists()); assertFalse(file.deleteIfExists()); } /** * Test file exits method. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileExists() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); assertFalse(file2.exists()); file.create(2048); assertTrue(file2.exists()); assertEquals(2048, file2.getProperties().getLength()); file.delete(); assertFalse(file2.exists()); } /** * Test file getProperties. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileDownloadAttributes() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file29"); file.create(1024); assertEquals(1024, file.getProperties().getLength()); assertNotNull(file.getProperties().getEtag()); GregorianCalendar now = new GregorianCalendar(); now.add(GregorianCalendar.MINUTE, 5); assertTrue(file.getProperties().getLastModified().before(now.getTime())); assertNull(file.getProperties().getCacheControl()); assertNull(file.getProperties().getContentDisposition()); assertNull(file.getProperties().getContentEncoding()); assertNull(file.getProperties().getContentLanguage()); assertNull(file.getProperties().getContentType()); assertNull(file.getProperties().getContentMD5()); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file29"); file2.downloadAttributes(); assertEquals(1024, file2.getProperties().getLength()); assertEquals(file.getProperties().getEtag(), file2.getProperties().getEtag()); assertEquals(file.getProperties().getLastModified(), file2.getProperties().getLastModified()); assertNull(file2.getProperties().getCacheControl()); assertNull(file2.getProperties().getContentDisposition()); assertNull(file2.getProperties().getContentEncoding()); assertNull(file2.getProperties().getContentLanguage()); assertEquals("application/octet-stream", file2.getProperties().getContentType()); assertNull(file2.getProperties().getContentMD5()); } /** * Test file setProperties. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileSetProperties() throws StorageException, URISyntaxException, InterruptedException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); file.create(1024); String eTag = file.getProperties().getEtag(); Date lastModified = file.getProperties().getLastModified(); Thread.sleep(1000); file.getProperties().setCacheControl("no-transform"); file.getProperties().setContentDisposition("attachment"); file.getProperties().setContentEncoding("gzip"); file.getProperties().setContentLanguage("tr,en"); file.getProperties().setContentMD5("MDAwMDAwMDA="); file.getProperties().setContentType("text/html"); file.uploadProperties(); assertTrue(file.getProperties().getLastModified().after(lastModified)); assertTrue(!eTag.equals(file.getProperties().getEtag())); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); file2.downloadAttributes(); assertEquals("no-transform", file2.getProperties().getCacheControl()); assertEquals("attachment", file2.getProperties().getContentDisposition()); assertEquals("gzip", file2.getProperties().getContentEncoding()); assertEquals("tr,en", file2.getProperties().getContentLanguage()); assertEquals("MDAwMDAwMDA=", file2.getProperties().getContentMD5()); assertEquals("text/html", file2.getProperties().getContentType()); CloudFile file3 = this.share.getRootDirectoryReference().getFileReference("file1"); ByteArrayOutputStream stream = new ByteArrayOutputStream(); FileRequestOptions options = new FileRequestOptions(); options.setDisableContentMD5Validation(true); file3.download(stream, null, options, null); FileTestHelper.assertAreEqual(file2.getProperties(), file3.getProperties()); CloudFileDirectory rootDirectory = this.share.getRootDirectoryReference(); Iterator<ListFileItem> iter = rootDirectory.listFilesAndDirectories().iterator(); CloudFile file4 = null; if (iter.hasNext()) { file4 = (CloudFile) iter.next(); } else { fail("Expecting a file here."); } assertEquals(file2.getProperties().getLength(), file4.getProperties().getLength()); } /** * Test file creation with metadata. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileCreateWithMetadata() throws URISyntaxException, StorageException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); HashMap<String, String> meta = new HashMap<String, String>(); meta.put("key1", "value1"); file.setMetadata(meta); file.create(1024); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); file2.downloadAttributes(); assertEquals(1, file2.getMetadata().size()); assertEquals("value1", file2.getMetadata().get("key1")); file2.setMetadata(new HashMap<String, String>()); file2.uploadMetadata(); file.downloadAttributes(); assertEquals(0, file.getMetadata().size()); } @Test @Category(SlowTests.class) public void testCopyBlockBlobSas() throws Exception { // Create source on server. final CloudBlobContainer container = BlobTestHelper.getRandomContainerReference(); try { container.create(); final CloudBlockBlob source = container.getBlockBlobReference("source"); source.getMetadata().put("Test", "value"); final String data = "String data"; source.uploadText(data, Constants.UTF8_CHARSET, null, null, null); final CloudFile destination = doCloudBlobCopy(source, data.length()); final String copyData = destination.downloadText(Constants.UTF8_CHARSET, null, null, null); assertEquals(data, copyData); } finally { container.deleteIfExists(); } } @Test @Category(SlowTests.class) public void testCopyPageBlobSas() throws Exception { // Create source on server. final CloudBlobContainer container = BlobTestHelper.getRandomContainerReference(); try { container.create(); final CloudPageBlob source = container.getPageBlobReference("source"); source.getMetadata().put("Test", "value"); final int length = 512; final ByteArrayInputStream data = BlobTestHelper.getRandomDataStream(length); source.upload(data, length); final CloudFile destination = doCloudBlobCopy(source, length); final ByteArrayOutputStream copyData = new ByteArrayOutputStream(); destination.download(copyData); BlobTestHelper.assertStreamsAreEqual(data, new ByteArrayInputStream(copyData.toByteArray())); } finally { container.deleteIfExists(); } } @Test @Category(SlowTests.class) public void testCopyFileSasToSas() throws InvalidKeyException, URISyntaxException, StorageException, IOException, InterruptedException { this.doCloudFileCopy(true, true); } // There is no testCopyFileToSas() because there is no way for the SAS destination to access a shared key source. // This means it would require the source to have public access, which files do not support. @Test @Category(SlowTests.class) public void testCopyFileSas() throws InvalidKeyException, URISyntaxException, StorageException, IOException, InterruptedException { this.doCloudFileCopy(true, false); } @Test @Category(SlowTests.class) public void testCopyFile() throws InvalidKeyException, URISyntaxException, StorageException, IOException, InterruptedException { // This works because we use Shared Key for source and destination. // The request is then signed with the key so the service knows we are authorized to access both. this.doCloudFileCopy(false, false); } @Test public void testCopyWithChineseChars() throws StorageException, IOException, URISyntaxException { String data = "sample data chinese chars 阿䶵"; CloudFileDirectory rootDirectory = this.share.getRootDirectoryReference(); CloudFile copySource = rootDirectory.getFileReference("sourcechinescharsblob阿䶵.txt"); copySource.uploadText(data); assertEquals(rootDirectory.getUri() + "/sourcechinescharsblob阿䶵.txt", copySource.getUri().toString()); assertEquals(rootDirectory.getUri() + "/sourcechinescharsblob%E9%98%BF%E4%B6%B5.txt", copySource .getUri().toASCIIString()); CloudFile copyDestination = rootDirectory.getFileReference("destchinesecharsblob阿䶵.txt"); assertEquals(rootDirectory.getUri() + "/destchinesecharsblob阿䶵.txt", copyDestination.getUri().toString()); assertEquals(rootDirectory.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(); try { CloudFileDirectory rootDirectory = CloudFileTests.this.share.getRootDirectoryReference(); // Test the copy destination request url assertEquals(rootDirectory.getUri() + "/destchinesecharsblob%E9%98%BF%E4%B6%B5.txt", con.getURL().toString()); // Test the copy source request property assertEquals(rootDirectory.getUri() + "/sourcechinescharsblob%E9%98%BF%E4%B6%B5.txt", con.getRequestProperty("x-ms-copy-source")); } catch (Exception e) { fail("This code should not generate any exceptions."); } } }); copyDestination.startCopy(copySource.getUri(), null, null, null, ctx); copyDestination.startCopy(copySource, null, null, null, ctx); } @Test @Category({ DevFabricTests.class, DevStoreTests.class, SlowTests.class }) public void testCopyFileWithMetadataOverride() throws URISyntaxException, StorageException, IOException, InterruptedException { Calendar calendar = Calendar.getInstance(Utility.UTC_ZONE); String data = "String data"; CloudFile source = this.share.getRootDirectoryReference().getFileReference("source"); FileTestHelper.setFileProperties(source); // do this to make sure the set MD5 can be compared, otherwise when the dummy value // doesn't match the actual MD5 an exception would be thrown FileRequestOptions options = new FileRequestOptions(); options.setDisableContentMD5Validation(true); source.getMetadata().put("Test", "value"); source.uploadText(data); CloudFile copy = this.share.getRootDirectoryReference().getFileReference("copy"); copy.getMetadata().put("Test2", "value2"); String copyId = copy.startCopy(FileTestHelper.defiddler(source)); FileTestHelper.waitForCopy(copy); assertEquals(CopyStatus.SUCCESS, copy.getCopyState().getStatus()); assertEquals(source.getServiceClient().getCredentials().transformUri(source.getUri()).getPath(), copy.getCopyState().getSource().getPath()); assertEquals(data.length(), copy.getCopyState().getTotalBytes().intValue()); assertEquals(data.length(), copy.getCopyState().getBytesCopied().intValue()); assertEquals(copyId, copy.getCopyState().getCopyId()); assertTrue(copy.getCopyState().getCompletionTime().compareTo(new Date(calendar.get(Calendar.MINUTE) - 1)) > 0); String copyData = copy.downloadText(Constants.UTF8_CHARSET, null, options, null); assertEquals(data, copyData); copy.downloadAttributes(); source.downloadAttributes(); FileProperties prop1 = copy.getProperties(); FileProperties prop2 = source.getProperties(); assertEquals(prop1.getCacheControl(), prop2.getCacheControl()); assertEquals(prop1.getContentEncoding(), prop2.getContentEncoding()); assertEquals(prop1.getContentDisposition(), prop2.getContentDisposition()); assertEquals(prop1.getContentLanguage(), prop2.getContentLanguage()); assertEquals(prop1.getContentMD5(), prop2.getContentMD5()); assertEquals(prop1.getContentType(), prop2.getContentType()); assertEquals("value2", copy.getMetadata().get("Test2")); assertFalse(copy.getMetadata().containsKey("Test")); copy.delete(); } /** * Start copying a file and then abort * * @throws StorageException * @throws URISyntaxException * @throws IOException * @throws InterruptedException */ @Test @Category({ DevFabricTests.class, DevStoreTests.class }) public void testCopyFileAbort() throws StorageException, URISyntaxException, IOException { final int length = 128; CloudFile originalFile = FileTestHelper.uploadNewFile(this.share, length, null); CloudFile copyFile = this.share.getRootDirectoryReference().getFileReference(originalFile.getName() + "copyed"); copyFile.startCopy(originalFile); try { copyFile.abortCopy(copyFile.getProperties().getCopyState().getCopyId()); fail(); } catch (StorageException e) { if (!e.getErrorCode().contains("NoPendingCopyOperation")) { throw e; } } } /** * Test file stream uploading. * * @throws URISyntaxException * @throws StorageException */ @Test public void testFileUploadFromStreamTest1() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); int length = 2 * 1024; ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(length); fileRef.upload(srcStream, length); ByteArrayOutputStream dstStream = new ByteArrayOutputStream(); fileRef.download(dstStream); FileTestHelper.assertStreamsAreEqual(srcStream, new ByteArrayInputStream(dstStream.toByteArray())); length = 5 * 1024 * 1024; srcStream = FileTestHelper.getRandomDataStream(length); fileRef.upload(srcStream, length); dstStream = new ByteArrayOutputStream(); fileRef.download(dstStream); FileTestHelper.assertStreamsAreEqual(srcStream, new ByteArrayInputStream(dstStream.toByteArray())); } /** * Create a file and try to download a range of its contents * * @throws StorageException * @throws URISyntaxException * @throws IOException * @throws InterruptedException */ @Test public void testFileDownloadRangeValidationTest() throws StorageException, URISyntaxException, IOException { final int length = 5 * 1024 * 1024; final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.upload(FileTestHelper.getRandomDataStream(length), length); //Download full file fileRef.download(new ByteArrayOutputStream()); assertEquals(length, fileRef.getProperties().getLength()); //Download file range. byte[] downloadBuffer = new byte[100]; int downloadLength = fileRef.downloadRangeToByteArray(0, (long) 100, downloadBuffer, 0); assertEquals(length, fileRef.getProperties().getLength()); assertEquals(100, downloadLength); } @Test public void testFileUploadFromStreamTest() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); int length = 2 * 1024; ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(length); fileRef.upload(srcStream, length); ByteArrayOutputStream dstStream = new ByteArrayOutputStream(); fileRef.download(dstStream); FileTestHelper.assertStreamsAreEqual(srcStream, new ByteArrayInputStream(dstStream.toByteArray())); length = 5 * 1024 * 1024; srcStream = FileTestHelper.getRandomDataStream(length); fileRef.upload(srcStream, length); dstStream = new ByteArrayOutputStream(); fileRef.download(dstStream); FileTestHelper.assertStreamsAreEqual(srcStream, new ByteArrayInputStream(dstStream.toByteArray())); } @Test public void testFileUploadMD5Validation() throws URISyntaxException, StorageException, IOException, NoSuchAlgorithmException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); final int length = 4 * 1024; byte[] src = FileTestHelper.getRandomBuffer(length); ByteArrayInputStream srcStream = new ByteArrayInputStream(src); FileRequestOptions options = new FileRequestOptions(); options.setDisableContentMD5Validation(false); options.setStoreFileContentMD5(false); fileRef.upload(srcStream, length, null, options, null); fileRef.downloadAttributes(); fileRef.getProperties().setContentMD5("MDAwMDAwMDA="); fileRef.uploadProperties(null, options, null); try { fileRef.download(new ByteArrayOutputStream(), null, options, null); fail(); } catch (StorageException ex) { assertEquals(306, ex.getHttpStatusCode()); assertEquals("InvalidMd5", ex.getErrorCode()); } options.setDisableContentMD5Validation(true); fileRef.download(new ByteArrayOutputStream(), null, options, null); options.setDisableContentMD5Validation(false); final MessageDigest digest = MessageDigest.getInstance("MD5"); final String calculatedMD5 = Base64.encode(digest.digest(src)); fileRef.downloadAttributes(); fileRef.getProperties().setContentMD5(calculatedMD5); fileRef.uploadProperties(null, options, null); fileRef.download(new ByteArrayOutputStream(), null, options, null); fileRef.downloadToByteArray(new byte[4096], 0); FileInputStream stream = fileRef.openRead(); stream.mark(length); stream.read(new byte[4096]); try { HashMap<String, String> metadata = new HashMap<String, String>(); metadata.put("a", "value"); fileRef.setMetadata(metadata); fileRef.uploadMetadata(); stream.reset(); stream.read(new byte[4096]); } catch (IOException e) { assertEquals(e.getCause().getMessage(), "The conditionals specified for this operation did not match server."); } final CloudFile fileRef2 = this.share.getRootDirectoryReference().getFileReference(fileName); assertNull(fileRef2.getProperties().getContentMD5()); byte[] target = new byte[4]; fileRef2.downloadRangeToByteArray(0L, 4L, target, 0); assertEquals(calculatedMD5, fileRef2.getProperties().getContentMD5()); } @Test public void testFileContentMD5NewFileTest() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); FileRequestOptions options = new FileRequestOptions(); options.setStoreFileContentMD5(true); options.setDisableContentMD5Validation(false); File tempFile = File.createTempFile("sourceFile", ".tmp"); file.uploadFromFile(tempFile.getAbsolutePath(), null, options, null); } /** * Test requesting stored content MD5 with OpenWriteExisting(). * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileOpenWriteExistingWithMD5() throws URISyntaxException, StorageException, IOException { String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.create(512); FileRequestOptions options = new FileRequestOptions(); options.setStoreFileContentMD5(true); options.setDisableContentMD5Validation(false); try { fileRef.openWriteExisting(null, options, null); fail("Expect failure due to requesting MD5 calculation"); } catch (IllegalArgumentException e) { } } @Test public void testFileEmptyHeaderSigningTest() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); final int length = 2 * 1024; ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(length); OperationContext context = new OperationContext(); context.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() { @Override public void eventOccurred(SendingRequestEvent eventArg) { HttpURLConnection connection = (HttpURLConnection) eventArg.getConnectionObject(); connection.setRequestProperty("x-ms-foo", ""); } }); fileRef.upload(srcStream, length, null, null, context); fileRef.download(new ByteArrayOutputStream(), null, null, context); } /** * Test downloading a file range. * * @throws URISyntaxException * @throws StorageException */ @Test public void testFileDownloadRangeTest() throws URISyntaxException, StorageException, IOException { byte[] buffer = FileTestHelper.getRandomBuffer(2 * 1024); CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); ByteArrayInputStream wholeFile = new ByteArrayInputStream(buffer); file.upload(wholeFile, 2 * 1024); ByteArrayOutputStream fileStream = new ByteArrayOutputStream(); try { file.downloadRange(0, new Long(0), fileStream); } catch (IndexOutOfBoundsException ex) { } file.downloadRange(0, new Long(1024), fileStream); assertEquals(fileStream.size(), 1024); FileTestHelper.assertStreamsAreEqualAtIndex(new ByteArrayInputStream(fileStream.toByteArray()), wholeFile, 0, 0, 1024, 2 * 1024); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); try { file.downloadRange(1024, new Long(0), fileStream); } catch (IndexOutOfBoundsException ex) { } ByteArrayOutputStream fileStream2 = new ByteArrayOutputStream(); file2.downloadRange(1024, new Long(1024), fileStream2); FileTestHelper.assertStreamsAreEqualAtIndex(new ByteArrayInputStream(fileStream2.toByteArray()), wholeFile, 0, 1024, 1024, 2 * 1024); FileTestHelper.assertAreEqual(file, file2); } @Test public void testCloudFileDownloadToByteArray() throws URISyntaxException, StorageException, IOException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); FileTestHelper.doDownloadTest(file, 1 * 512, 2 * 512, 0); FileTestHelper.doDownloadTest(file, 1 * 512, 2 * 512, 1 * 512); FileTestHelper.doDownloadTest(file, 2 * 512, 4 * 512, 1 * 512); FileTestHelper.doDownloadTest(file, 5 * 1024 * 1024, 5 * 1024 * 1024, 0); FileTestHelper.doDownloadTest(file, 5 * 1024 * 1024, 6 * 1024 * 1024, 512); } @Test public void testCloudFileDownloadRangeToByteArray() throws URISyntaxException, StorageException, IOException { CloudFile file = this.share.getRootDirectoryReference().getFileReference( FileTestHelper.generateRandomFileName()); FileTestHelper.doDownloadRangeToByteArrayTest(file, 8 * 1024 * 1024, 8 * 1024 * 1024, 1 * 1024 * 1024, new Long(1 * 1024 * 1024), new Long(5 * 1024 * 1024)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 8 * 1024 * 1024, 8 * 1024 * 1024, 2 * 1024 * 1024, new Long(2 * 1024 * 1024), new Long(6 * 1024 * 1024)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 8 * 1024 * 1024, 8 * 1024 * 1024, 1 * 1024 * 1024, new Long(4 * 1024 * 1024), new Long(4 * 1024 * 1024)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 0, new Long(1 * 512), new Long(1 * 512)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 1 * 512, new Long(0), null); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 1 * 512, new Long(1 * 512), null); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 1 * 512, new Long(0), new Long(1 * 512)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 2 * 512, new Long(1 * 512), new Long( 1 * 512)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 2 * 512, 4 * 512, 2 * 512, new Long(1 * 512), new Long( 2 * 512)); // Edge cases FileTestHelper.doDownloadRangeToByteArrayTest(file, 1024, 1024, 1023, new Long(1023), new Long(1)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 1024, 1024, 0, new Long(1023), new Long(1)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 1024, 1024, 0, new Long(0), new Long(1)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 1024, 1024, 0, new Long(512), new Long(1)); FileTestHelper.doDownloadRangeToByteArrayTest(file, 1024, 1024, 512, new Long(1023), new Long(1)); } @Test public void testCloudFileDownloadRangeToByteArrayNegativeTest() throws URISyntaxException, StorageException, IOException { CloudFile file = this.share.getRootDirectoryReference().getFileReference( FileTestHelper.generateRandomFileName()); FileTestHelper.doDownloadRangeToByteArrayNegativeTests(file); } /* @Test public void testCloudFileUploadFromStreamWithAccessCondition() throws URISyntaxException, StorageException, IOException { CloudFile file1 = share.getRootDirectoryReference().getFileReference("file1"); AccessCondition accessCondition = AccessCondition.generateIfNoneMatchCondition("\"*\""); final int length = 6 * 512; ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(length); file1.upload(srcStream, length, accessCondition, null, null); srcStream.reset(); file1.create(1024); accessCondition = AccessCondition.generateIfNoneMatchCondition(file1.getProperties().getEtag()); try { file1.upload(srcStream, length, accessCondition, null, null); } catch (StorageException ex) { Assert.assertEquals(HttpURLConnection.HTTP_PRECON_FAILED, ex.getHttpStatusCode()); } srcStream.reset(); accessCondition = AccessCondition.generateIfMatchCondition(file1.getProperties().getEtag()); file1.upload(srcStream, length, accessCondition, null, null); srcStream.reset(); CloudFile file2 = share.getRootDirectoryReference().getFileReference("file2"); file2.create(1024); accessCondition = AccessCondition.generateIfMatchCondition(file1.getProperties().getEtag()); try { file1.upload(srcStream, length, accessCondition, null, null); } catch (StorageException ex) { Assert.assertEquals(HttpURLConnection.HTTP_PRECON_FAILED, ex.getHttpStatusCode()); } srcStream.reset(); accessCondition = AccessCondition.generateIfNoneMatchCondition(file2.getProperties().getEtag()); file1.upload(srcStream, length, accessCondition, null, null); } */ /** * Test file input stream. * * @throws URISyntaxException * @throws StorageException * @throws IOException */ @Test public void testCloudFileInputStream() throws URISyntaxException, StorageException, IOException { final int fileLength = 16 * 1024; final Random randGenerator = new Random(); String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); final byte[] buff = new byte[fileLength]; randGenerator.nextBytes(buff); buff[0] = -1; buff[1] = -128; final ByteArrayInputStream sourceStream = new ByteArrayInputStream(buff); final FileRequestOptions options = new FileRequestOptions(); final OperationContext operationContext = new OperationContext(); options.setTimeoutIntervalInMs(90000); options.setRetryPolicyFactory(new RetryNoRetry()); fileRef.upload(sourceStream, fileLength, null, options, operationContext); com.microsoft.azure.storage.file.FileInputStream fileStream = fileRef.openRead(); for (int i = 0; i < fileLength; i++) { int data = fileStream.read(); assertTrue(data >= 0); assertEquals(buff[i], (byte) data); } assertEquals(-1, fileStream.read()); fileRef.delete(); } /** * Test file uploading from byte arrays. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileUploadFromByteArray() throws Exception { String fileName = FileTestHelper.generateRandomFileName(); final CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); this.doUploadFromByteArrayTest(file, 4 * 512, 0, 4 * 512); this.doUploadFromByteArrayTest(file, 4 * 512, 0, 2 * 512); this.doUploadFromByteArrayTest(file, 4 * 512, 1 * 512, 2 * 512); this.doUploadFromByteArrayTest(file, 4 * 512, 2 * 512, 2 * 512); } /** * Test file upload and download using text. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileUploadDownloadFromText() throws IOException, StorageException, URISyntaxException { String fileName = FileTestHelper.generateRandomFileName(); final CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); String textFile = "string of text to upload to a file. The_quick_brown_fox_jumps_over_the_lazy_dog. 1!\". "."; file.uploadText(textFile); String result = file.downloadText(); assertEquals(textFile, result); } /** * Test file upload and download using io files. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileUploadDownloadFromFile() throws IOException, StorageException, URISyntaxException { String fileName = FileTestHelper.generateRandomFileName(); final CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); File ioFile = new File("garbage.file"); try { assertFalse(ioFile.exists()); file.downloadToFile("garbage.file"); fail("Shouldn't be able to download nonexistent file."); } catch (StorageException e) { assertFalse(ioFile.exists()); } this.doUploadDownloadFileTest(file, 512); this.doUploadDownloadFileTest(file, 4096); this.doUploadDownloadFileTest(file, 5 * 1024 * 1024); this.doUploadDownloadFileTest(file, 11 * 1024 * 1024); } private void doUploadFromByteArrayTest(CloudFile file, int bufferSize, int bufferOffset, int count) throws Exception { byte[] buffer = FileTestHelper.getRandomBuffer(bufferSize); byte[] downloadedBuffer = new byte[bufferSize]; file.uploadFromByteArray(buffer, bufferOffset, count); file.downloadToByteArray(downloadedBuffer, 0); int i = 0; for (; i < count; i++) { assertEquals(buffer[i + bufferOffset], downloadedBuffer[i]); } for (; i < downloadedBuffer.length; i++) { assertEquals(0, downloadedBuffer[i]); } } private void doUploadDownloadFileTest(CloudFile file, int fileSize) throws IOException, StorageException, URISyntaxException { File sourceFile = File.createTempFile("sourceFile", ".tmp"); File destinationFile = new File(sourceFile.getParentFile(), "destinationFile.tmp"); try { byte[] buffer = FileTestHelper.getRandomBuffer(fileSize); java.io.FileOutputStream fos = new java.io.FileOutputStream(sourceFile); fos.write(buffer); fos.close(); file.uploadFromFile(sourceFile.getAbsolutePath()); file.downloadToFile(destinationFile.getAbsolutePath()); assertTrue("Destination file does not exist.", destinationFile.exists()); assertEquals("Destination file does not match input file.", fileSize, destinationFile.length()); java.io.FileInputStream fis = new java.io.FileInputStream(destinationFile); byte[] readBuffer = new byte[fileSize]; fis.read(readBuffer); fis.close(); for (int i = 0; i < fileSize; i++) { assertEquals("File contents do not match.", buffer[i], readBuffer[i]); } } finally { if (sourceFile.exists()) { sourceFile.delete(); } if (destinationFile.exists()) { destinationFile.delete(); } } } /** * Test file range uploads. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileUploadRange() throws URISyntaxException, StorageException, IOException { int fileLengthToUse = 8 * 512; byte[] buffer = FileTestHelper.getRandomBuffer(8 * 512); String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.create(fileLengthToUse); FileRequestOptions options = new FileRequestOptions(); options.setUseTransactionalContentMD5(true); // Upload one page (page 0) ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer); fileRef.uploadRange(inputStream, 0, 512, null, options, null); // Upload pages 2-4 inputStream = new ByteArrayInputStream(buffer, 512, 3 * 512); fileRef.uploadRange(inputStream, 2 * 512, 3 * 512, null, options, null); // Now, we expect the first 512 bytes of the file 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) byte[] result = new byte[fileLengthToUse]; fileRef.downloadToByteArray(result, 0); for (int i = 0; i < 512; i++) { assertEquals(buffer[i], result[i]); } for (int i = 0; i < 512; i++) { assertEquals(0, result[i + 512]); } for (int i = 0; i < 3 * 512; i++) { assertEquals(buffer[i + 512], result[i + 2 * 512]); } for (int i = 0; i < 3 * 512; i++) { assertEquals(0, result[i + 5 * 512]); } inputStream = new ByteArrayInputStream(buffer); } @Test @Category({ DevFabricTests.class, DevStoreTests.class }) public void testVerifyTransactionalMD5ValidationMissingOverallMD5() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); final int length = 3*1024; ByteArrayInputStream srcStream = BlobTestHelper.getRandomDataStream(length); FileRequestOptions options = new FileRequestOptions(); options.setDisableContentMD5Validation(true); options.setStoreFileContentMD5(false); fileRef.upload(srcStream, length, null, options, null); options.setDisableContentMD5Validation(false); options.setStoreFileContentMD5(true); options.setUseTransactionalContentMD5(true); final CloudFile fileRef2 = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef2.downloadRange(1024, (long)1024, new ByteArrayOutputStream(), null, options, null); assertNull(fileRef2.getProperties().getContentMD5()); } /** * Test clearing file ranges. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileClearRange() throws URISyntaxException, StorageException, IOException { int fileLengthToUse = 8 * 512; byte[] buffer = FileTestHelper.getRandomBuffer(8 * 512); String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.create(fileLengthToUse); // Upload one page (page 0) ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer); fileRef.uploadRange(inputStream, 0, fileLengthToUse); fileRef.clearRange(3 * 512, 2 * 512); byte[] result = new byte[fileLengthToUse]; fileRef.downloadToByteArray(result, 0); int i = 0; for (; i < 3 * 512; i++) { assertEquals(buffer[i], result[i]); } for (; i < 5 * 512; i++) { assertEquals(0, result[i]); } for (; i < 8 * 512; i++) { assertEquals(buffer[i], result[i]); } } /** * Test file resizing. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileResize2() throws StorageException, URISyntaxException { CloudFile file = this.share.getRootDirectoryReference().getFileReference("file1"); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference("file1"); file.create(1024); assertEquals(1024, file.getProperties().getLength()); file2.downloadAttributes(); assertEquals(1024, file2.getProperties().getLength()); file2.getProperties().setContentType("text/plain"); file2.uploadProperties(); file.resize(2048); assertEquals(2048, file.getProperties().getLength()); file.downloadAttributes(); assertEquals("text/plain", file.getProperties().getContentType()); file2.downloadAttributes(); assertEquals(2048, file2.getProperties().getLength()); } /** * Test file range downloading. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileDownloadRange() throws StorageException, URISyntaxException, IOException { int fileLengthToUse = 8 * 512; byte[] buffer = FileTestHelper.getRandomBuffer(8 * 512); String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.create(fileLengthToUse); // Upload one page (page 0) ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer); fileRef.uploadRange(inputStream, 0, 512); // Upload pages 2-4 inputStream = new ByteArrayInputStream(buffer, 512, 3 * 512); fileRef.uploadRange(inputStream, 2 * 512, 3 * 512); // Now, we expect the first 512 bytes of the file 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) ArrayList<FileRange> actualFileRanges = fileRef.downloadFileRanges(); ArrayList<FileRange> expectedFileRanges = new ArrayList<FileRange>(); expectedFileRanges.add(new FileRange(0, 512 - 1)); expectedFileRanges.add(new FileRange(2 * 512, 2 * 512 + 3 * 512 - 1)); assertEquals(expectedFileRanges.size(), actualFileRanges.size()); for (int i = 0; i < expectedFileRanges.size(); i++) { assertEquals(expectedFileRanges.get(i).getStartOffset(), actualFileRanges.get(i).getStartOffset()); assertEquals(expectedFileRanges.get(i).getEndOffset(), actualFileRanges.get(i).getEndOffset()); } } /** * Test downloadAttributes. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileUploadDownloadFileProperties() throws URISyntaxException, StorageException, IOException { final int length = 512; // do this to make sure the set MD5 can be compared without an exception being thrown FileRequestOptions options = new FileRequestOptions(); options.setDisableContentMD5Validation(true); // with explicit upload/download of properties String fileName1 = FileTestHelper.generateRandomFileName(); CloudFile fileRef1 = this.share.getRootDirectoryReference().getFileReference(fileName1); fileRef1.upload(FileTestHelper.getRandomDataStream(length), length); FileTestHelper.setFileProperties(fileRef1); FileProperties props1 = fileRef1.getProperties(); fileRef1.uploadProperties(); fileRef1.downloadAttributes(null, options, null); FileProperties props2 = fileRef1.getProperties(); FileTestHelper.assertAreEqual(props1, props2); // by uploading/downloading the file fileName1 = FileTestHelper.generateRandomFileName(); fileRef1 = this.share.getRootDirectoryReference().getFileReference(fileName1); FileTestHelper.setFileProperties(fileRef1); props1 = fileRef1.getProperties(); fileRef1.upload(FileTestHelper.getRandomDataStream(length), length); fileRef1.download(new ByteArrayOutputStream(), null, options, null); props2 = fileRef1.getProperties(); FileTestHelper.assertAreEqual(props1, props2); } /** * Test FileOutputStream. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileOpenOutputStream() throws URISyntaxException, StorageException, IOException { int fileLengthToUse = 8 * 512; byte[] buffer = FileTestHelper.getRandomBuffer(8 * 512); String fileName = FileTestHelper.generateRandomFileName(); final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); fileRef.create(fileLengthToUse); FileOutputStream fileOutputStream = fileRef.openWriteNew(fileLengthToUse); ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer); fileOutputStream = fileRef.openWriteNew(fileLengthToUse); inputStream = new ByteArrayInputStream(buffer); fileOutputStream.write(inputStream, 512); inputStream = new ByteArrayInputStream(buffer, 512, 3 * 512); fileOutputStream.write(inputStream, 3 * 512); fileOutputStream.close(); byte[] result = new byte[fileLengthToUse]; fileRef.downloadToByteArray(result, 0); int i = 0; for (; i < 4 * 512; i++) { assertEquals(buffer[i], result[i]); } for (; i < 8 * 512; i++) { assertEquals(0, result[i]); } } /** * Test FileOutputStream. * * @throws URISyntaxException * @throws StorageException */ @Test public void testCloudFileOpenOutputStreamNoArgs() throws URISyntaxException, StorageException { String fileName = FileTestHelper.generateRandomFileName(); CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); try { file.openWriteExisting(); } catch (StorageException ex) { assertEquals("The specified resource does not exist.", ex.getMessage()); assertEquals(HttpURLConnection.HTTP_NOT_FOUND, ex.getHttpStatusCode()); } file.openWriteNew(1024); file.openWriteExisting(); CloudFile file2 = this.share.getRootDirectoryReference().getFileReference(fileName); file2.downloadAttributes(); assertEquals(1024, file2.getProperties().getLength()); } /** * Test specific deleteIfExists case. * * @throws URISyntaxException * @throws StorageException * @throws IOException */ @Test @Category({ DevFabricTests.class, DevStoreTests.class }) public void testCloudFileDeleteIfExistsErrorCode() throws URISyntaxException, StorageException, IOException { CloudFileClient client = FileTestHelper.createCloudFileClient(); CloudFileShare share = client.getShareReference(FileTestHelper.generateRandomShareName()); share.create(); CloudFileDirectory directory = share.getRootDirectoryReference().getDirectoryReference("directory"); directory.create(); final CloudFile file = directory.getFileReference("file"); try { file.delete(); fail("File should not already exist."); } catch (StorageException e) { assertEquals(StorageErrorCodeStrings.RESOURCE_NOT_FOUND, e.getErrorCode()); } assertFalse(file.exists()); assertFalse(file.deleteIfExists()); file.create(2); assertTrue(file.exists()); assertTrue(file.deleteIfExists()); assertFalse(file.deleteIfExists()); // check if second condition works in delete if exists OperationContext ctx = new OperationContext(); ctx.getSendingRequestEventHandler().addListener(new StorageEvent<SendingRequestEvent>() { @Override public void eventOccurred(SendingRequestEvent eventArg) { if (((HttpURLConnection) eventArg.getConnectionObject()).getRequestMethod().equals("DELETE")) { try { file.delete(); assertFalse(file.exists()); } catch (StorageException e) { fail("Delete should succeed."); } catch (URISyntaxException e) { fail("Delete should succeed."); } } } }); // The second delete of a file will return a 404 file.create(2); assertFalse(file.deleteIfExists(null, null, ctx)); } /** * @throws StorageException * @throws URISyntaxException * @throws IOException * @throws InterruptedException */ @Test @Category({ DevFabricTests.class, DevStoreTests.class, SlowTests.class }) public void testFileNamePlusEncoding() throws StorageException, URISyntaxException, IOException, InterruptedException { CloudFile originalFile = FileTestHelper.uploadNewFile(this.share, 1024 /* length */, null); CloudFile copyFile = this.share.getRootDirectoryReference().getFileReference(originalFile.getName() + "copyed"); copyFile.startCopy(originalFile); FileTestHelper.waitForCopy(copyFile); copyFile.downloadAttributes(); originalFile.downloadAttributes(); FileProperties prop1 = copyFile.getProperties(); FileProperties prop2 = originalFile.getProperties(); assertEquals(prop1.getCacheControl(), prop2.getCacheControl()); assertEquals(prop1.getContentEncoding(), prop2.getContentEncoding()); assertEquals(prop1.getContentDisposition(), prop2.getContentDisposition()); assertEquals(prop1.getContentLanguage(), prop2.getContentLanguage()); assertEquals(prop1.getContentMD5(), prop2.getContentMD5()); assertEquals(prop1.getContentType(), prop2.getContentType()); } @Test @Category({ DevFabricTests.class, DevStoreTests.class }) public void testFileGetRangeContentMD5Bounds() throws StorageException, IOException, URISyntaxException { { CloudFile file = FileTestHelper.uploadNewFile(this.share, 5 * Constants.MB, null); FileRequestOptions options = new FileRequestOptions(); OperationContext opContext = new OperationContext(); try { FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB, true); FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB + 1, true); fail("The request for range ContentMD5 should have thrown an Exception for exceeding the limit."); } catch (IllegalArgumentException e) { assertEquals(e.getMessage(), String.format("The value of the parameter 'count' should be between 1 and %1d.", Constants.MAX_RANGE_CONTENT_MD5)); } } } private CloudFile doCloudBlobCopy(CloudBlob source, int length) throws Exception { Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); cal.setTime(new Date()); cal.add(Calendar.MINUTE, 5); // Source SAS must have read permissions SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy(); policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ)); policy.setSharedAccessExpiryTime(cal.getTime()); String sasToken = source.generateSharedAccessSignature(policy, null, null); // Get destination reference final CloudFile destination = this.share.getRootDirectoryReference().getFileReference("destination"); // Start copy and wait for completion StorageCredentialsSharedAccessSignature credentials = new StorageCredentialsSharedAccessSignature(sasToken); Constructor<? extends CloudBlob> blobType = source.getClass().getConstructor(URI.class); String copyId = destination.startCopy(blobType.newInstance(credentials.transformUri(source.getUri()))); FileTestHelper.waitForCopy(destination); destination.downloadAttributes(); // Check original file references for equality assertEquals(CopyStatus.SUCCESS, destination.getCopyState().getStatus()); assertEquals(source.getServiceClient().getCredentials().transformUri(source.getUri()).getPath(), destination.getCopyState().getSource().getPath()); assertEquals(length, destination.getCopyState().getTotalBytes().intValue()); assertEquals(length, destination.getCopyState().getBytesCopied().intValue()); assertEquals(copyId, destination.getProperties().getCopyState().getCopyId()); // Attempt to abort the completed copy operation. try { destination.abortCopy(destination.getCopyState().getCopyId()); FileTestHelper.waitForCopy(destination); fail(); } catch (StorageException ex) { assertEquals(HttpURLConnection.HTTP_CONFLICT, ex.getHttpStatusCode()); } assertNotNull(destination.getProperties().getEtag()); assertFalse(source.getProperties().getEtag().equals(destination.getProperties().getEtag())); source.downloadAttributes(); FileProperties prop1 = destination.getProperties(); BlobProperties prop2 = source.getProperties(); assertEquals(prop1.getCacheControl(), prop2.getCacheControl()); assertEquals(prop1.getContentEncoding(), prop2.getContentEncoding()); assertEquals(prop1.getContentLanguage(), prop2.getContentLanguage()); assertEquals(prop1.getContentMD5(), prop2.getContentMD5()); assertEquals(prop1.getContentType(), prop2.getContentType()); assertEquals("value", destination.getMetadata().get("Test")); return destination; } private void doCloudFileCopy(boolean sourceIsSas, boolean destinationIsSas) throws URISyntaxException, StorageException, IOException, InvalidKeyException, InterruptedException { // Create source on server. final CloudFile source = this.share.getRootDirectoryReference().getFileReference("source"); final String data = "String data"; source.getMetadata().put("Test", "value"); source.uploadText(data, Constants.UTF8_CHARSET, null, null, null); Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC")); cal.setTime(new Date()); cal.add(Calendar.MINUTE, 5); CloudFile copySource = source; if (sourceIsSas) { // Source SAS must have read permissions SharedAccessFilePolicy policy = new SharedAccessFilePolicy(); policy.setPermissions(EnumSet.of(SharedAccessFilePermissions.READ)); policy.setSharedAccessExpiryTime(cal.getTime()); String sasToken = source.generateSharedAccessSignature(policy, null, null); // Get source file reference StorageCredentialsSharedAccessSignature credentials = new StorageCredentialsSharedAccessSignature(sasToken); copySource = new CloudFile(credentials.transformUri(source.getUri())); } // Get destination reference final CloudFile destination = this.share.getRootDirectoryReference().getFileReference("destination"); CloudFile copyDestination = destination; if (destinationIsSas) { // Destination SAS must have write permissions SharedAccessFilePolicy policy = new SharedAccessFilePolicy(); policy.setPermissions(EnumSet.of(SharedAccessFilePermissions.READ, SharedAccessFilePermissions.WRITE)); policy.setSharedAccessExpiryTime(cal.getTime()); String sasToken = destination.generateSharedAccessSignature(policy, null, null); // Get destination file reference StorageCredentialsSharedAccessSignature credentials = new StorageCredentialsSharedAccessSignature(sasToken); copyDestination = new CloudFile(destination.getUri(), credentials); } // Start copy and wait for completion String copyId = copyDestination.startCopy(copySource); FileTestHelper.waitForCopy(copyDestination); destination.downloadAttributes(); // Check original file references for equality assertEquals(CopyStatus.SUCCESS, destination.getCopyState().getStatus()); assertEquals(source.getServiceClient().getCredentials().transformUri(source.getUri()).getPath(), destination.getCopyState().getSource().getPath()); assertEquals(data.length(), destination.getCopyState().getTotalBytes().intValue()); assertEquals(data.length(), destination.getCopyState().getBytesCopied().intValue()); assertEquals(copyId, destination.getProperties().getCopyState().getCopyId()); if (!destinationIsSas) { try { copyDestination.abortCopy(destination.getCopyState().getCopyId()); } catch (StorageException ex) { assertEquals(HttpURLConnection.HTTP_CONFLICT, ex.getHttpStatusCode()); } } assertNotNull(destination.getProperties().getEtag()); assertFalse(source.getProperties().getEtag().equals(destination.getProperties().getEtag())); String copyData = destination.downloadText(Constants.UTF8_CHARSET, null, null, null); assertEquals(data, copyData); FileProperties prop1 = destination.getProperties(); FileProperties prop2 = source.getProperties(); assertEquals(prop1.getCacheControl(), prop2.getCacheControl()); assertEquals(prop1.getContentEncoding(), prop2.getContentEncoding()); assertEquals(prop1.getContentLanguage(), prop2.getContentLanguage()); assertEquals(prop1.getContentMD5(), prop2.getContentMD5()); assertEquals(prop1.getContentType(), prop2.getContentType()); assertEquals("value", destination.getMetadata().get("Test")); destination.delete(); source.delete(); } //@Test public void testUnsupportedFileApisWithinShareSnapshot() throws StorageException, URISyntaxException { CloudFileShare snapshot = this.share.createSnapshot(); CloudFile file = snapshot.getRootDirectoryReference().getFileReference("file"); try { file.create(1024); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.delete(); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.uploadMetadata(); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.abortCopy(null); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.clearRange(0, 512); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.startCopy(file); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } try { file.upload(null, 512); fail("Shouldn't get here"); } catch (IllegalArgumentException e) { assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); } catch (IOException e) { fail("Shouldn't get here"); } snapshot.delete(); } //@Test public void testSupportedFileApisInShareSnapshot() throws StorageException, URISyntaxException, UnsupportedEncodingException { CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); dir.deleteIfExists(); dir.create(); CloudFile file = dir.getFileReference("file"); file.create(1024); HashMap<String, String> meta = new HashMap<String, String>(); meta.put("key1", "value1"); file.setMetadata(meta); file.uploadMetadata(); CloudFileShare snapshot = this.share.createSnapshot(); CloudFile snapshotFile = snapshot.getRootDirectoryReference() .getDirectoryReference("dir1").getFileReference("file"); HashMap<String, String> meta2 = new HashMap<String, String>(); meta2.put("key2", "value2"); file.setMetadata(meta2); file.uploadMetadata(); snapshotFile.downloadAttributes(); assertTrue(snapshotFile.getMetadata().size() == 1 && snapshotFile.getMetadata().get("key1").equals("value1")); assertNotNull(snapshotFile.getProperties().getEtag()); file.downloadAttributes(); assertTrue(file.getMetadata().size() == 1 && file.getMetadata().get("key2").equals("value2")); assertNotNull(file.getProperties().getEtag()); assertNotEquals(file.getProperties().getEtag(), snapshotFile.getProperties().getEtag()); final UriQueryBuilder uriBuilder = new UriQueryBuilder(); uriBuilder.add("sharesnapshot", snapshot.snapshotID); CloudFile snapshotFile2 = new CloudFile(uriBuilder.addToURI(file.getUri()), this.share.getServiceClient().getCredentials()); assertEquals(snapshot.snapshotID, snapshotFile2.getShare().snapshotID); assertTrue(snapshotFile2.exists()); snapshot.delete(); } }