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

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

    BlobOutputStream blobOutputStream = blobRef.openWriteNew(blobLengthToUse);
    ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);

    blobOutputStream = blobRef.openWriteNew(blobLengthToUse);
    inputStream = new ByteArrayInputStream(buffer);
    blobOutputStream.write(inputStream, 512);

    inputStream = new ByteArrayInputStream(buffer, 512, 3 * 512);
    blobOutputStream.write(inputStream, 3 * 512);

    blobOutputStream.close();

    byte[] result = new byte[blobLengthToUse];
    blobRef.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
  public void testPageBlobDownloadRangeTest()
      throws URISyntaxException, StorageException, IOException {
    byte[] buffer = BlobTestHelper.getRandomBuffer(2 * 1024);

    CloudPageBlob blob = this.container.getPageBlobReference("blob1");
    ByteArrayInputStream wholeBlob = new ByteArrayInputStream(buffer);
    blob.upload(wholeBlob, 2 * 1024);

    ByteArrayOutputStream blobStream = new ByteArrayOutputStream();
    try {
      blob.downloadRange(0, new Long(0), blobStream);
    } catch (IndexOutOfBoundsException ex) {

    }

    blob.downloadRange(0, new Long(1024), blobStream);
    assertEquals(blobStream.size(), 1024);
    BlobTestHelper.assertStreamsAreEqualAtIndex(
        new ByteArrayInputStream(blobStream.toByteArray()), wholeBlob, 0, 0, 1024, 2 * 1024);

    CloudPageBlob blob2 = this.container.getPageBlobReference("blob1");
    try {
      blob.downloadRange(1024, new Long(0), blobStream);
    } catch (IndexOutOfBoundsException ex) {

    }

    ByteArrayOutputStream blobStream2 = new ByteArrayOutputStream();
    blob2.downloadRange(1024, new Long(1024), blobStream2);
    BlobTestHelper.assertStreamsAreEqualAtIndex(
        new ByteArrayInputStream(blobStream2.toByteArray()), wholeBlob, 1024, 1024, 1024, 2 * 1024);

    BlobTestHelper.assertAreEqual(blob, blob2);
  }
  @Test
  public void testOpenOutputStreamNotAligned() throws StorageException, URISyntaxException {
    int blobLengthToUse = 8 * 512;
    byte[] buffer = BlobTestHelper.getRandomBuffer(8 * 512);

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

    try {
      blobRef.openWriteNew(blobLengthToUse + 1);
      fail("Did not throw expected exception on non-512-byte-aligned offset");
    } catch (IllegalArgumentException ex) {
      assertEquals(SR.INVALID_PAGE_BLOB_LENGTH, ex.getMessage());
    }

    BlobOutputStream blobOutputStream = blobRef.openWriteNew(blobLengthToUse);

    ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);

    try {
      blobOutputStream.write(inputStream, 511);
      blobOutputStream.close();
      fail("Did not throw expected exception on non-512-byte-aligned length");
    } catch (IOException ex) {
      assertEquals(String.format(SR.INVALID_NUMBER_OF_BYTES_IN_THE_BUFFER, 511), ex.getMessage());
    }
  }
  @Test
  public void testPageBlobCopyWithMetadataOverride()
      throws URISyntaxException, StorageException, IOException, InterruptedException {
    Calendar calendar = Calendar.getInstance(Utility.UTC_ZONE);
    CloudPageBlob source = this.container.getPageBlobReference("source");

    byte[] buffer = BlobTestHelper.getRandomBuffer(512);
    ByteArrayInputStream stream = new ByteArrayInputStream(buffer);

    source.upload(stream, buffer.length);

    source.getMetadata().put("Test", "value");
    source.uploadMetadata();

    CloudPageBlob copy = this.container.getPageBlobReference("copy");
    copy.getMetadata().put("Test2", "value2");
    String copyId = copy.startCopy(BlobTestHelper.defiddler(source));
    BlobTestHelper.waitForCopy(copy);

    assertEquals(CopyStatus.SUCCESS, copy.getCopyState().getStatus());
    assertEquals(source.getQualifiedUri().getPath(), copy.getCopyState().getSource().getPath());
    assertEquals(buffer.length, copy.getCopyState().getTotalBytes().intValue());
    assertEquals(buffer.length, copy.getCopyState().getBytesCopied().intValue());
    assertEquals(copyId, copy.getCopyState().getCopyId());
    assertTrue(
        copy.getCopyState()
                .getCompletionTime()
                .compareTo(new Date(calendar.get(Calendar.MINUTE) - 1))
            > 0);

    ByteArrayOutputStream copyStream = new ByteArrayOutputStream();
    copy.download(copyStream);
    BlobTestHelper.assertStreamsAreEqual(
        stream, new ByteArrayInputStream(copyStream.toByteArray()));

    copy.downloadAttributes();
    source.downloadAttributes();
    BlobProperties prop1 = copy.getProperties();
    BlobProperties 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();
  }
  @Test
  public void testClearPages() throws URISyntaxException, StorageException, IOException {
    int blobLengthToUse = 8 * 512;
    byte[] buffer = BlobTestHelper.getRandomBuffer(8 * 512);

    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);
      fail("Did not throw expected exception on non-512-byte-aligned length");
    } catch (IllegalArgumentException ex) {
      assertEquals(SR.INVALID_PAGE_BLOB_LENGTH, ex.getMessage());
    }

    try {
      blobRef.clearPages(3 * 256, 3 * 512);
      fail("Did not throw expected exception on non-512-byte-aligned offset");
    } catch (IllegalArgumentException ex) {
      assertEquals(SR.INVALID_PAGE_START_OFFSET, ex.getMessage());
    }

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

    byte[] result = new byte[blobLengthToUse];
    blobRef.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]);
    }
  }
  private void doUploadFromByteArrayTest(
      CloudPageBlob blob, int bufferSize, int bufferOffset, int count) throws Exception {
    byte[] buffer = BlobTestHelper.getRandomBuffer(bufferSize);
    byte[] downloadedBuffer = new byte[bufferSize];

    blob.uploadFromByteArray(buffer, bufferOffset, count);
    blob.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]);
    }
  }
  @Test
  public void testDownloadPages() throws StorageException, URISyntaxException, IOException {
    int blobLengthToUse = 8 * 512;
    byte[] buffer = BlobTestHelper.getRandomBuffer(8 * 512);

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

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

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

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

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

    assertEquals(expectedPageRanges.size(), actualPageRanges.size());
    for (int i = 0; i < expectedPageRanges.size(); i++) {
      assertEquals(
          expectedPageRanges.get(i).getStartOffset(), actualPageRanges.get(i).getStartOffset());
      assertEquals(
          expectedPageRanges.get(i).getEndOffset(), actualPageRanges.get(i).getEndOffset());
    }
  }
  private void doUploadDownloadFileTest(CloudPageBlob blob, int fileSize)
      throws IOException, StorageException {
    File sourceFile = File.createTempFile("sourceFile", ".tmp");
    File destinationFile = new File(sourceFile.getParentFile(), "destinationFile.tmp");

    try {

      byte[] buffer = BlobTestHelper.getRandomBuffer(fileSize);
      FileOutputStream fos = new FileOutputStream(sourceFile);
      fos.write(buffer);
      fos.close();
      blob.uploadFromFile(sourceFile.getAbsolutePath());

      blob.downloadToFile(destinationFile.getAbsolutePath());
      assertTrue("Destination file does not exist.", destinationFile.exists());
      assertEquals(
          "Destination file does not match input file.", fileSize, destinationFile.length());
      FileInputStream fis = new 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
  public void testUploadPages() throws URISyntaxException, StorageException, IOException {
    int blobLengthToUse = 8 * 512;
    byte[] buffer = BlobTestHelper.getRandomBuffer(8 * 512);

    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)
    // 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[blobLengthToUse];
    blobRef.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);

    try {
      blobRef.uploadPages(inputStream, 0, 256);
      fail("Did not throw expected exception on non-512-byte-aligned length");
    } catch (IllegalArgumentException ex) {
      assertEquals(SR.INVALID_PAGE_BLOB_LENGTH, ex.getMessage());
    }

    try {
      blobRef.uploadPages(inputStream, 3 * 256, 3 * 512);
      fail("Did not throw expected exception on non-512-byte-aligned offset");
    } catch (IllegalArgumentException ex) {
      assertEquals(SR.INVALID_PAGE_START_OFFSET, ex.getMessage());
    }
  }
  @Test
  public void testPageBlobCopyFromSnapshot()
      throws StorageException, IOException, URISyntaxException, InterruptedException {
    CloudPageBlob source = this.container.getPageBlobReference("source");

    byte[] buffer = BlobTestHelper.getRandomBuffer(512);
    ByteArrayInputStream stream = new ByteArrayInputStream(buffer);

    source.upload(stream, buffer.length);

    source.getMetadata().put("Test", "value");
    source.uploadMetadata();

    CloudPageBlob snapshot = (CloudPageBlob) source.createSnapshot();

    // Modify source
    byte[] buffer2 = BlobTestHelper.getRandomBuffer(512);
    ByteArrayInputStream stream2 = new ByteArrayInputStream(buffer2);
    source.getMetadata().put("Test", "newvalue");
    source.uploadMetadata();
    source.getProperties().setContentMD5(null);
    source.upload(stream2, buffer.length);

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    source.download(outputStream);

    ByteArrayOutputStream snapshotStream = new ByteArrayOutputStream();
    snapshot.download(snapshotStream);
    BlobTestHelper.assertStreamsAreEqual(
        stream2, new ByteArrayInputStream(outputStream.toByteArray()));
    BlobTestHelper.assertStreamsAreEqual(
        stream, new ByteArrayInputStream(snapshotStream.toByteArray()));

    source.downloadAttributes();
    snapshot.downloadAttributes();
    assertFalse(source.getMetadata().get("Test").equals(snapshot.getMetadata().get("Test")));

    CloudPageBlob copy = this.container.getPageBlobReference("copy");
    String copyId = copy.startCopy(BlobTestHelper.defiddler(snapshot));
    BlobTestHelper.waitForCopy(copy);

    ByteArrayOutputStream copyStream = new ByteArrayOutputStream();
    copy.download(copyStream);

    assertEquals(CopyStatus.SUCCESS, copy.getCopyState().getStatus());
    BlobTestHelper.assertStreamsAreEqual(
        stream, new ByteArrayInputStream(copyStream.toByteArray()));
    assertEquals(copyId, copy.getProperties().getCopyState().getCopyId());

    copy.downloadAttributes();
    BlobProperties prop1 = copy.getProperties();
    BlobProperties prop2 = snapshot.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("value", copy.getMetadata().get("Test"));

    copy.delete();
  }