@Test
  public void testBlobUploadWithoutMD5Validation()
      throws URISyntaxException, StorageException, IOException {
    final String pageBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testPageBlob");
    final CloudPageBlob pageBlobRef = this.container.getPageBlobReference(pageBlobName);

    final int length = 2 * 1024;
    ByteArrayInputStream srcStream = BlobTestHelper.getRandomDataStream(length);
    BlobRequestOptions options = new BlobRequestOptions();
    options.setDisableContentMD5Validation(false);
    options.setStoreBlobContentMD5(false);

    pageBlobRef.upload(srcStream, length, null, options, null);
    pageBlobRef.downloadAttributes();
    pageBlobRef.getProperties().setContentMD5("MDAwMDAwMDA=");
    pageBlobRef.uploadProperties(null, options, null);

    try {
      pageBlobRef.download(new ByteArrayOutputStream(), null, options, null);
      fail();
    } catch (StorageException ex) {
      assertEquals(306, ex.getHttpStatusCode());
      assertEquals("InvalidMd5", ex.getErrorCode());
    }

    options.setDisableContentMD5Validation(true);
    pageBlobRef.download(new ByteArrayOutputStream(), null, options, null);
  }
  @Test
  public void testBlobEmptyHeaderSigningTest()
      throws URISyntaxException, StorageException, IOException {
    final String pageBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testPageBlob");
    final CloudPageBlob pageBlobRef = this.container.getPageBlobReference(pageBlobName);

    final int length = 2 * 1024;
    ByteArrayInputStream srcStream = BlobTestHelper.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", "");
              }
            });

    pageBlobRef.upload(srcStream, length, null, null, context);
    pageBlobRef.download(new ByteArrayOutputStream(), null, null, context);
  }
  @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 testPageBlobUploadFromStreamTest()
      throws URISyntaxException, StorageException, IOException {
    final String pageBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testPageBlob");
    final CloudPageBlob pageBlobRef = this.container.getPageBlobReference(pageBlobName);

    int length = 2 * 1024;
    ByteArrayInputStream srcStream = BlobTestHelper.getRandomDataStream(length);
    pageBlobRef.upload(srcStream, length);
    ByteArrayOutputStream dstStream = new ByteArrayOutputStream();
    pageBlobRef.download(dstStream);
    BlobTestHelper.assertStreamsAreEqual(
        srcStream, new ByteArrayInputStream(dstStream.toByteArray()));

    length = 5 * 1024 * 1024;
    srcStream = BlobTestHelper.getRandomDataStream(length);
    pageBlobRef.upload(srcStream, length);
    dstStream = new ByteArrayOutputStream();
    pageBlobRef.download(dstStream);
    BlobTestHelper.assertStreamsAreEqual(
        srcStream, new ByteArrayInputStream(dstStream.toByteArray()));
  }
  /**
   * Create a blob and try to download a range of its contents
   *
   * @throws StorageException
   * @throws URISyntaxException
   * @throws IOException
   * @throws InterruptedException
   */
  @Test
  public void testPageBlobDownloadRangeValidationTest()
      throws StorageException, URISyntaxException, IOException {
    final int length = 5 * 1024 * 1024;

    final String blockBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob");
    final CloudPageBlob pageBlobRef = this.container.getPageBlobReference(blockBlobName);

    pageBlobRef.upload(BlobTestHelper.getRandomDataStream(length), length);

    // Download full blob
    pageBlobRef.download(new ByteArrayOutputStream());
    assertEquals(length, pageBlobRef.getProperties().getLength());

    // Download blob range.
    byte[] downloadBuffer = new byte[100];
    int downloadLength = pageBlobRef.downloadRangeToByteArray(0, (long) 100, downloadBuffer, 0);
    assertEquals(length, pageBlobRef.getProperties().getLength());
    assertEquals(100, downloadLength);
  }
  @Test
  public void testUploadDownloadBlobProperties()
      throws URISyntaxException, StorageException, IOException {
    final int length = 512;

    // do this to make sure the set MD5 can be compared without an exception being thrown
    BlobRequestOptions options = new BlobRequestOptions();
    options.setDisableContentMD5Validation(true);

    // with explicit upload/download of properties
    String pageBlobName1 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob");
    CloudPageBlob pageBlobRef1 = this.container.getPageBlobReference(pageBlobName1);

    pageBlobRef1.upload(BlobTestHelper.getRandomDataStream(length), length);

    BlobTestHelper.setBlobProperties(pageBlobRef1);
    BlobProperties props1 = pageBlobRef1.getProperties();
    pageBlobRef1.uploadProperties();

    pageBlobRef1.downloadAttributes(null, options, null);
    BlobProperties props2 = pageBlobRef1.getProperties();

    BlobTestHelper.assertAreEqual(props1, props2);

    // by uploading/downloading the blob
    pageBlobName1 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob");
    pageBlobRef1 = this.container.getPageBlobReference(pageBlobName1);

    BlobTestHelper.setBlobProperties(pageBlobRef1);
    props1 = pageBlobRef1.getProperties();

    pageBlobRef1.upload(BlobTestHelper.getRandomDataStream(length), length);

    pageBlobRef1.download(new ByteArrayOutputStream(), null, options, null);
    props2 = pageBlobRef1.getProperties();

    BlobTestHelper.assertAreEqual(props1, props2);
  }
  /**
   * Create a snapshot
   *
   * @throws StorageException
   * @throws URISyntaxException
   * @throws IOException
   * @throws InterruptedException
   */
  @Test
  public void testPageBlobSnapshotValidationTest()
      throws StorageException, URISyntaxException, IOException {
    final int length = 1024;
    CloudPageBlob blockBlobRef =
        (CloudPageBlob)
            BlobTestHelper.uploadNewBlob(
                this.container, BlobType.PAGE_BLOB, "originalBlob", length, null);
    final CloudBlob blobSnapshot = blockBlobRef.createSnapshot();

    for (ListBlobItem blob :
        this.container.listBlobs(null, true, EnumSet.allOf(BlobListingDetails.class), null, null)) {
      final ByteArrayOutputStream outStream = new ByteArrayOutputStream(length);
      ((CloudBlob) blob).download(outStream);
    }

    ByteArrayOutputStream outStream = new ByteArrayOutputStream(length);

    blobSnapshot.download(outStream);
    byte[] retrievedBuff = outStream.toByteArray();
    assertEquals(length, retrievedBuff.length);

    // Read operation should work fine.
    blobSnapshot.downloadAttributes();

    final CloudPageBlob blobSnapshotUsingRootUri =
        this.container.getPageBlobReference(blockBlobRef.getName(), blobSnapshot.getSnapshotID());
    outStream = new ByteArrayOutputStream(length);

    blobSnapshotUsingRootUri.download(outStream);
    retrievedBuff = outStream.toByteArray();
    assertEquals(length, retrievedBuff.length);
    assertEquals(blobSnapshot.getSnapshotID(), blobSnapshotUsingRootUri.getSnapshotID());

    // Expect an IllegalArgumentException from upload.
    try {
      final Random randGenerator = new Random();
      final byte[] buff = new byte[length];
      randGenerator.nextBytes(buff);
      blobSnapshot.upload(new ByteArrayInputStream(buff), -1);
      fail("Expect an IllegalArgumentException from upload");
    } catch (IllegalArgumentException e) {
      assertEquals(
          "Cannot perform this operation on a blob representing a snapshot.", e.getMessage());
    }

    // Expect an IllegalArgumentException from uploadMetadata.
    try {
      blobSnapshot.uploadMetadata();
      fail("Expect an IllegalArgumentException from uploadMetadata");
    } catch (IllegalArgumentException e) {
      assertEquals(
          "Cannot perform this operation on a blob representing a snapshot.", e.getMessage());
    }

    // Expect an IllegalArgumentException from uploadProperties.
    try {
      blobSnapshot.uploadProperties();
      fail("Expect an IllegalArgumentException from uploadProperties");
    } catch (IllegalArgumentException e) {
      assertEquals(
          "Cannot perform this operation on a blob representing a snapshot.", e.getMessage());
    }

    // Expect an IllegalArgumentException from createSnapshot.
    try {
      blobSnapshot.createSnapshot();
      fail("Expect an IllegalArgumentException from createSnapshot");
    } catch (IllegalArgumentException e) {
      assertEquals(
          "Cannot perform this operation on a blob representing a snapshot.", e.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();
  }