@Override
  @Test(groups = {"integration", "live"})
  public void testEntrySet() throws IOException, InterruptedException {
    String bucketName = getContainerName();
    try {
      final BlobMap map = createMap(context, bucketName);
      putFiveStrings(map);
      assertConsistencyAwareMapSize(map, 5);
      Set<Entry<String, Blob>> entries = map.entrySet();
      assertEquals(entries.size(), 5);
      for (Entry<String, Blob> entry : entries) {
        assertEquals(
            fiveStrings.get(entry.getKey()), getContentAsStringOrNullAndClose(entry.getValue()));
        Blob blob = entry.getValue();
        blob.setPayload("");
        Payloads.calculateMD5(blob);
        entry.setValue(blob);
      }
      assertConsistencyAware(
          new Runnable() {
            public void run() {
              for (Blob blob : map.values()) {
                try {
                  assertEquals(getContentAsStringOrNullAndClose(blob), "");
                } catch (IOException e) {
                  Throwables.propagate(e);
                }
              }
            }
          });

    } finally {
      returnContainer(bucketName);
    }
  }
 @Override
 protected void putStringWithMD5(Map<String, Blob> map, String key, String text)
     throws IOException {
   Blob blob = context.getBlobStore().newBlob(key);
   blob.setPayload(text);
   Payloads.calculateMD5(blob);
   map.put(key, blob);
 }
 protected SwiftObject newSwiftObject(String data, String key) throws IOException {
   SwiftObject object = getApi().newSwiftObject();
   object.getInfo().setName(key);
   object.setPayload(data);
   Payloads.calculateMD5(object);
   object.getInfo().setContentType("text/plain");
   object.getInfo().getMetadata().put("Metadata", "metadata-value");
   return object;
 }
 @Test(groups = {"integration", "live"})
 public void testPut() throws IOException, InterruptedException {
   String bucketName = getContainerName();
   try {
     Map<String, Blob> map = createMap(context, bucketName);
     Blob blob = context.getBlobStore().newBlob("one");
     blob.setPayload(Strings2.toInputStream("apple"));
     Payloads.calculateMD5(blob);
     Blob old = map.put(blob.getMetadata().getName(), blob);
     getOneReturnsAppleAndOldValueIsNull(map, old);
     blob.setPayload(Strings2.toInputStream("bear"));
     Payloads.calculateMD5(blob);
     Blob apple = map.put(blob.getMetadata().getName(), blob);
     getOneReturnsBearAndOldValueIsApple(map, apple);
   } finally {
     returnContainer(bucketName);
   }
 }
  /**
   * Calculates the object MD5 and returns it as eTag
   *
   * @param object
   * @return
   */
  private String getEtag(Blob object) {
    try {
      Payloads.calculateMD5(object, crypto.md5());
    } catch (IOException ex) {
      logger.error(
          ex,
          "An error occurred calculating MD5 for object with name %s.",
          object.getMetadata().getName());
      Throwables.propagate(ex);
    }

    String eTag = CryptoStreams.hex(object.getPayload().getContentMetadata().getContentMD5());
    return eTag;
  }
 @Test(groups = {"integration", "live"})
 public void testContains()
     throws InterruptedException, ExecutionException, TimeoutException, IOException {
   String bucketName = getContainerName();
   try {
     Map<String, Blob> map = createMap(context, bucketName);
     putStringWithMD5(map, "one", "apple");
     Blob blob = context.getBlobStore().newBlob("one");
     blob.setPayload("apple");
     Payloads.calculateMD5(blob);
     assertConsistencyAwareContainsValue(map, blob);
   } finally {
     returnContainer(bucketName);
   }
 }
  @Test(
      timeOut = 5 * 60 * 1000,
      dependsOnMethods = {"testCreateContainer", "testCreatePublicContainer"})
  public void testObjectOperations() throws Exception {
    String data = "Here is my data";

    // Test PUT with string data, ETag hash, and a piece of metadata
    AzureBlob object = client.newBlob();
    object.getProperties().setName("object");
    object.setPayload(data);
    Payloads.calculateMD5(object);
    object.getProperties().getContentMetadata().setContentType("text/plain");
    object.getProperties().getMetadata().put("mykey", "metadata-value");
    byte[] md5 = object.getProperties().getContentMetadata().getContentMD5();
    String newEtag = client.putBlob(privateContainer, object);
    assertEquals(
        CryptoStreams.hex(md5),
        CryptoStreams.hex(object.getProperties().getContentMetadata().getContentMD5()));

    // Test HEAD of missing object
    assert client.getBlobProperties(privateContainer, "non-existent-object") == null;

    // Test HEAD of object
    BlobProperties metadata =
        client.getBlobProperties(privateContainer, object.getProperties().getName());
    // TODO assertEquals(metadata.getName(), object.getProperties().getName());
    // we can't check this while hacking around lack of content-md5, as GET of the first byte will
    // show incorrect length 1, the returned size, as opposed to the real length. This is an ok
    // tradeoff, as a container list will contain the correct size of the objects in an
    // inexpensive fashion
    // http://code.google.com/p/jclouds/issues/detail?id=92
    // assertEquals(metadata.getSize(), data.length());
    assertEquals(metadata.getContentMetadata().getContentType(), "text/plain");
    // Azure doesn't return the Content-MD5 on head request..
    assertEquals(
        CryptoStreams.hex(md5),
        CryptoStreams.hex(object.getProperties().getContentMetadata().getContentMD5()));
    assertEquals(metadata.getETag(), newEtag);
    assertEquals(metadata.getMetadata().entrySet().size(), 1);
    assertEquals(metadata.getMetadata().get("mykey"), "metadata-value");

    // // Test POST to update object's metadata
    // Multimap<String, String> userMetadata = LinkedHashMultimap.create();
    // userMetadata.put("New-Metadata-1", "value-1");
    // userMetadata.put("New-Metadata-2", "value-2");
    // assertTrue(client.setBlobProperties(privateContainer, object.getProperties().getName(),
    // userMetadata));

    // Test GET of missing object
    assert client.getBlob(privateContainer, "non-existent-object") == null;

    // Test GET of object (including updated metadata)
    AzureBlob getBlob = client.getBlob(privateContainer, object.getProperties().getName());
    assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), data);
    // TODO assertEquals(getBlob.getName(), object.getProperties().getName());
    assertEquals(
        getBlob.getPayload().getContentMetadata().getContentLength(), new Long(data.length()));
    assertEquals(getBlob.getProperties().getContentMetadata().getContentType(), "text/plain");
    assertEquals(
        CryptoStreams.hex(md5),
        CryptoStreams.hex(getBlob.getProperties().getContentMetadata().getContentMD5()));
    assertEquals(newEtag, getBlob.getProperties().getETag());
    // wait until we can update metadata
    // assertEquals(getBlob.getProperties().getMetadata().entries().size(), 2);
    // assertEquals(
    // Iterables.getLast(getBlob.getProperties().getMetadata().get("New-Metadata-1")),
    // "value-1");
    // assertEquals(
    // Iterables.getLast(getBlob.getProperties().getMetadata().get("New-Metadata-2")),
    // "value-2");
    assertEquals(metadata.getMetadata().entrySet().size(), 1);
    assertEquals(metadata.getMetadata().get("mykey"), "metadata-value");

    // test listing
    ListBlobsResponse response =
        client.listBlobs(
            privateContainer,
            ListBlobsOptions.Builder.prefix(
                    object
                        .getProperties()
                        .getName()
                        .substring(0, object.getProperties().getName().length() - 1))
                .maxResults(1)
                .includeMetadata());
    assertEquals(response.size(), 1);
    assertEquals(Iterables.getOnlyElement(response).getName(), object.getProperties().getName());
    assertEquals(
        Iterables.getOnlyElement(response).getMetadata(),
        ImmutableMap.of("mykey", "metadata-value"));

    // Test PUT with invalid ETag (as if object's data was corrupted in transit)
    String correctEtag = newEtag;
    String incorrectEtag = "0" + correctEtag.substring(1);
    object.getProperties().setETag(incorrectEtag);
    try {
      client.putBlob(privateContainer, object);
    } catch (Throwable e) {
      assertEquals(e.getCause().getClass(), HttpResponseException.class);
      assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 422);
    }

    ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
    object = client.newBlob();
    object.getProperties().setName("chunked-object");
    object.setPayload(bais);
    object.getPayload().getContentMetadata().setContentLength(new Long(data.getBytes().length));
    newEtag = client.putBlob(privateContainer, object);
    assertEquals(
        CryptoStreams.hex(md5),
        CryptoStreams.hex(getBlob.getProperties().getContentMetadata().getContentMD5()));

    // Test GET with options
    // Non-matching ETag
    try {
      client.getBlob(
          privateContainer,
          object.getProperties().getName(),
          GetOptions.Builder.ifETagDoesntMatch(newEtag));
    } catch (Exception e) {
      assertEquals(e.getCause().getClass(), HttpResponseException.class);
      assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 304);
    }

    // Matching ETag TODO this shouldn't fail!!!
    try {
      getBlob =
          client.getBlob(
              privateContainer,
              object.getProperties().getName(),
              GetOptions.Builder.ifETagMatches(newEtag));
      assertEquals(getBlob.getProperties().getETag(), newEtag);
    } catch (HttpResponseException e) {
      assertEquals(e.getResponse().getStatusCode(), 412);
    }

    // Range
    // doesn't work per
    // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/479fa63f-51df-4b66-96b5-33ae362747b6
    // getBlob = client
    // .getBlob(privateContainer, object.getProperties().getName(),
    // GetOptions.Builder.startAt(8)).get(120,
    // TimeUnit.SECONDS);
    // assertEquals(Utils.toStringAndClose((InputStream) getBlob.getData()), data.substring(8));

    client.deleteBlob(privateContainer, "object");
    client.deleteBlob(privateContainer, "chunked-object");
  }