@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]);
    }
  }
  /**
   * @throws URISyntaxException
   * @throws StorageException
   * @throws IOException
   */
  @Test
  public void testPageBlobInputStream() throws URISyntaxException, StorageException, IOException {
    final int blobLength = 16 * 1024;
    final Random randGenerator = new Random();
    String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
    final CloudPageBlob blobRef = this.container.getPageBlobReference(blobName);

    final byte[] buff = new byte[blobLength];
    randGenerator.nextBytes(buff);
    buff[0] = -1;
    buff[1] = -128;
    final ByteArrayInputStream sourceStream = new ByteArrayInputStream(buff);

    final BlobRequestOptions options = new BlobRequestOptions();
    final OperationContext operationContext = new OperationContext();
    options.setTimeoutIntervalInMs(90000);
    options.setRetryPolicyFactory(new RetryNoRetry());
    blobRef.upload(sourceStream, blobLength, null, options, operationContext);

    BlobInputStream blobStream = blobRef.openInputStream();

    for (int i = 0; i < blobLength; i++) {
      int data = blobStream.read();
      assertTrue(data >= 0);
      assertEquals(buff[i], (byte) data);
    }

    assertEquals(-1, blobStream.read());

    blobRef.delete();
  }
  @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 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 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 testCloudPageBlobDownloadRangeToByteArrayNegativeTest()
     throws URISyntaxException, StorageException, IOException {
   CloudPageBlob blob =
       this.container.getPageBlobReference(
           BlobTestHelper.generateRandomBlobNameWithPrefix("downloadrangenegative"));
   BlobTestHelper.doDownloadRangeToByteArrayNegativeTests(blob);
 }
  @Test
  public void testUploadFromByteArray() throws Exception {
    String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
    final CloudPageBlob blob = this.container.getPageBlobReference(blobName);

    this.doUploadFromByteArrayTest(blob, 4 * 512, 0, 4 * 512);
    this.doUploadFromByteArrayTest(blob, 4 * 512, 0, 2 * 512);
    this.doUploadFromByteArrayTest(blob, 4 * 512, 1 * 512, 2 * 512);
    this.doUploadFromByteArrayTest(blob, 4 * 512, 2 * 512, 2 * 512);
  }
  @Test
  public void testUploadDownloadFromFile()
      throws IOException, StorageException, URISyntaxException {
    String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
    final CloudPageBlob blob = this.container.getPageBlobReference(blobName);

    this.doUploadDownloadFileTest(blob, 512);
    this.doUploadDownloadFileTest(blob, 4096);
    this.doUploadDownloadFileTest(blob, 5 * 1024 * 1024);
    this.doUploadDownloadFileTest(blob, 11 * 1024 * 1024);
  }
  @Test
  public void testCloudPageBlobDownloadRangeToByteArray()
      throws URISyntaxException, StorageException, IOException {
    CloudPageBlob blob =
        this.container.getPageBlobReference(
            BlobTestHelper.generateRandomBlobNameWithPrefix("downloadrange"));

    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob,
        8 * 1024 * 1024,
        8 * 1024 * 1024,
        1 * 1024 * 1024,
        new Long(1 * 1024 * 1024),
        new Long(5 * 1024 * 1024));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob,
        8 * 1024 * 1024,
        8 * 1024 * 1024,
        2 * 1024 * 1024,
        new Long(2 * 1024 * 1024),
        new Long(6 * 1024 * 1024));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob,
        8 * 1024 * 1024,
        8 * 1024 * 1024,
        1 * 1024 * 1024,
        new Long(4 * 1024 * 1024),
        new Long(4 * 1024 * 1024));

    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 0, new Long(1 * 512), new Long(1 * 512));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 1 * 512, new Long(0), null);
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 1 * 512, new Long(1 * 512), null);
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 1 * 512, new Long(0), new Long(1 * 512));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 2 * 512, new Long(1 * 512), new Long(1 * 512));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 2 * 512, 4 * 512, 2 * 512, new Long(1 * 512), new Long(2 * 512));

    // Edge cases
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 1024, 1024, 1023, new Long(1023), new Long(1));
    BlobTestHelper.doDownloadRangeToByteArrayTest(blob, 1024, 1024, 0, new Long(1023), new Long(1));
    BlobTestHelper.doDownloadRangeToByteArrayTest(blob, 1024, 1024, 0, new Long(0), new Long(1));
    BlobTestHelper.doDownloadRangeToByteArrayTest(blob, 1024, 1024, 0, new Long(512), new Long(1));
    BlobTestHelper.doDownloadRangeToByteArrayTest(
        blob, 1024, 1024, 512, new Long(1023), new Long(1));
  }
  @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);
  }
  @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]);
    }
  }
  /**
   * 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 testOpenOutputStreamNoArgs() throws URISyntaxException, StorageException {
    String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testblob");
    CloudPageBlob pageBlob = this.container.getPageBlobReference(blobName);

    try {
      pageBlob.openWriteExisting();
    } catch (StorageException ex) {
      assertEquals("The specified blob does not exist.", ex.getMessage());
      assertEquals(HttpURLConnection.HTTP_NOT_FOUND, ex.getHttpStatusCode());
    }

    pageBlob.openWriteNew(1024);
    pageBlob.openWriteExisting();

    CloudPageBlob pageBlob2 = this.container.getPageBlobReference(blobName);
    pageBlob2.downloadAttributes();
    assertEquals(1024, pageBlob2.getProperties().getLength());
    assertEquals(BlobType.PAGE_BLOB, pageBlob2.getProperties().getBlobType());
  }
  @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()));
  }
  @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());
    }
  }
  @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());
    }
  }