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
  public void testObjectOperations() throws Exception {
    String containerName = getContainerName();
    try {
      // Test PUT with string data, ETag hash, and a piece of metadata
      String data = "Here is my data";
      String key = "object";
      SwiftObject object = newSwiftObject(data, key);
      byte[] md5 = object.getPayload().getContentMetadata().getContentMD5();
      String newEtag = getApi().putObject(containerName, object);
      assert newEtag != null;

      assertEquals(
          base16().lowerCase().encode(md5),
          base16().lowerCase().encode(object.getPayload().getContentMetadata().getContentMD5()));

      // Test HEAD of missing object
      assert getApi().getObjectInfo(containerName, "non-existent-object") == null;

      // Test HEAD of object
      MutableObjectInfoWithMetadata metadata =
          getApi().getObjectInfo(containerName, object.getInfo().getName());
      assertEquals(metadata.getName(), object.getInfo().getName());

      assertEquals(metadata.getBytes(), Long.valueOf(data.length()));
      assert metadata.getContentType().startsWith("text/plain") : metadata.getContentType();

      assertEquals(
          base16().lowerCase().encode(md5), base16().lowerCase().encode(metadata.getHash()));
      assertEquals(metadata.getHash(), base16().lowerCase().decode(newEtag));
      assertEquals(metadata.getMetadata().entrySet().size(), 1);
      assertEquals(metadata.getMetadata().get("metadata"), "metadata-value");

      // // Test POST to update object's metadata
      Map<String, String> userMetadata = Maps.newHashMap();
      userMetadata.put("New-Metadata-1", "value-1");
      userMetadata.put("New-Metadata-2", "value-2");
      assertTrue(getApi().setObjectInfo(containerName, object.getInfo().getName(), userMetadata));

      // Test GET of missing object
      assert getApi().getObject(containerName, "non-existent-object") == null;
      // Test GET of object (including updated metadata)
      SwiftObject getBlob = getApi().getObject(containerName, object.getInfo().getName());
      assertEquals(Strings2.toString(getBlob.getPayload()), data);
      // TODO assertEquals(getBlob.getName(),
      // object.getMetadata().getName());
      assertEquals(getBlob.getInfo().getBytes(), Long.valueOf(data.length()));
      testGetObjectContentType(getBlob);
      assertEquals(
          base16().lowerCase().encode(md5),
          base16().lowerCase().encode(getBlob.getInfo().getHash()));
      assertEquals(base16().lowerCase().decode(newEtag), getBlob.getInfo().getHash());
      assertEquals(getBlob.getInfo().getMetadata().entrySet().size(), 2);
      assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-1"), "value-1");
      assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-2"), "value-2");

      // Test PUT with invalid ETag (as if object's data was corrupted in
      // transit)
      String correctEtag = newEtag;
      String incorrectEtag = "0" + correctEtag.substring(1);
      object.getInfo().setHash(base16().lowerCase().decode(incorrectEtag));
      try {
        getApi().putObject(containerName, object);
      } catch (HttpResponseException e) {
        assertEquals(e.getResponse().getStatusCode(), 422);
      }

      // Test PUT chunked/streamed upload with data of "unknown" length
      ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes(Charsets.UTF_8));
      SwiftObject blob = getApi().newSwiftObject();
      blob.getInfo().setName("chunked-object");
      blob.setPayload(bais);
      newEtag = getApi().putObject(containerName, blob);
      assertEquals(
          base16().lowerCase().encode(md5),
          base16().lowerCase().encode(getBlob.getInfo().getHash()));

      // Test GET with options
      // Non-matching ETag
      try {
        getApi()
            .getObject(
                containerName,
                object.getInfo().getName(),
                GetOptions.Builder.ifETagDoesntMatch(newEtag));
      } catch (HttpResponseException e) {
        assertEquals(e.getResponse().getStatusCode(), 304);
      }

      // Matching ETag
      getBlob =
          getApi()
              .getObject(
                  containerName,
                  object.getInfo().getName(),
                  GetOptions.Builder.ifETagMatches(newEtag));
      assertEquals(getBlob.getInfo().getHash(), base16().lowerCase().decode(newEtag));
      getBlob =
          getApi()
              .getObject(containerName, object.getInfo().getName(), GetOptions.Builder.startAt(8));
      assertEquals(Strings2.toString(getBlob.getPayload()), data.substring(8));

    } finally {
      returnContainer(containerName);
    }
  }