/**
* Copyright Microsoft Corporation
* <p/>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.azure.storage.table;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.TestRunners.CloudTests;
import com.microsoft.azure.storage.TestRunners.DevFabricTests;
import com.microsoft.azure.storage.TestRunners.DevStoreTests;
import com.microsoft.azure.storage.core.SR;
import com.microsoft.azure.storage.table.TableRequestOptions.PropertyResolver;
import com.microsoft.azure.storage.table.TableTestHelper.Class1;
import com.microsoft.azure.storage.table.TableTestHelper.Class2;
import com.microsoft.azure.storage.table.TableTestHelper.EmptyClass;
import com.microsoft.azure.storage.table.TableTestHelper.EmptyClassDynamic;
import com.microsoft.azure.storage.table.TableTestHelper.class1class2PropertyResolver;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import static org.junit.Assert.*;
/**
* Table Operation Tests
*/
@Category({DevFabricTests.class, DevStoreTests.class, CloudTests.class})
public class TableOperationTests {
private CloudTable table;
@Before
public void tableOperationTestMethodSetUp() throws URISyntaxException, StorageException {
this.table = TableTestHelper.getRandomTableReference();
this.table.createIfNotExists();
}
@After
public void tableOperationTestMethodTearDown() throws StorageException {
this.table.deleteIfExists();
}
@Test
public void testPropertyCacheDisable() {
try {
TableServiceEntity.getReflectedEntityCache().put(this.getClass(), new HashMap<String, PropertyPair>());
TableServiceEntity.setReflectedEntityCacheDisabled(true);
assertEquals(true, TableServiceEntity.isReflectedEntityCacheDisabled());
assertTrue(TableServiceEntity.getReflectedEntityCache().isEmpty());
TableServiceEntity.setReflectedEntityCacheDisabled(false);
assertEquals(false, TableServiceEntity.isReflectedEntityCacheDisabled());
} finally {
TableServiceEntity.setReflectedEntityCacheDisabled(false);
}
}
@Test
public void testRetrieveWithNullResolver() {
try {
TableOperation.retrieve("foo", "blah", (EntityResolver<?>) null);
} catch (IllegalArgumentException ex) {
assertEquals(ex.getMessage(),
String.format(SR.ARGUMENT_NULL_OR_EMPTY, SR.QUERY_REQUIRES_VALID_CLASSTYPE_OR_RESOLVER));
}
}
@Test
public void testEntityWithSingleQuote() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
EmptyClass ref = new EmptyClass();
ref.setPartitionKey("partition'key");
ref.setRowKey("row'key");
this.table.execute(TableOperation.insert(ref), options, null);
this.table.execute(TableOperation.merge(ref), options, null);
this.table.execute(TableOperation.insertOrReplace(ref), options, null);
this.table.execute(TableOperation.insertOrMerge(ref), options, null);
this.table.execute(TableOperation.replace(ref), options, null);
this.table.execute(TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), EmptyClass.class), options, null);
this.table.execute(TableOperation.delete(ref), options, null);
}
@Test
public void testInsertEntityWithoutPartitionKeyRowKey() {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
EmptyClass ref = new EmptyClass();
ref.setPartitionKey("jxscl_odata");
try {
this.table.execute(TableOperation.insert(ref), options, null);
fail("Inserts should not allow null row keys.");
} catch (IllegalArgumentException e) {
// continue, this is appropriate
} catch (Exception e) {
fail("Inserts with null row key should fail with an IllegalArgumentException thrown by assert not null.");
}
ref.setPartitionKey(null);
ref.setRowKey(UUID.randomUUID().toString());
try {
this.table.execute(TableOperation.insert(ref), options, null);
fail("Inserts should not allow null partition keys.");
} catch (IllegalArgumentException e) {
// continue, this is appropriate
} catch (Exception e) {
fail("Inserts with null partition key should fail with an IllegalArgumentException thrown by assert not null.");
}
}
@Test
public void testInsertEntityWithPropertyMoreThan255chars() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
DynamicTableEntity ref = new DynamicTableEntity();
String propName = "";
for (int m = 0; m < 256; m++) {
propName = propName.concat("a");
}
ref.getProperties().put(propName, new EntityProperty("test"));
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
try {
this.table.execute(TableOperation.insert(ref), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Bad Request");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The property name exceeds the maximum allowed length (255)."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "PropertyNameTooLong");
}
}
@Test
public void testInsertEntityOver1MB() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
// 1mb right here
ref.setD(new byte[1024 * 1024]);
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
try {
this.table.execute(TableOperation.insert(ref), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Bad Request");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The entity is larger than the maximum allowed size (1MB)."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "EntityTooLarge");
}
}
@Test
public void testInsertEntityWithNumericProperty() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
DynamicTableEntity ref = new DynamicTableEntity();
String propName = "";
for (int m = 0; m < 255; m++) {
propName = propName.concat(Integer.toString(m % 9));
}
ref.getProperties().put(propName, new EntityProperty("test"));
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
try {
this.table.execute(TableOperation.insert(ref), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Bad Request");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage().startsWith("The property name is invalid."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "PropertyNameInvalid");
}
}
@Test
public void testDeleteFail() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
this.table.execute(TableOperation.insert(ref), options, null);
String oldEtag = ref.getEtag();
// update entity
ref.setA("updated");
this.table.execute(TableOperation.replace(ref), options, null);
ref.setEtag(oldEtag);
try {
this.table.execute(TableOperation.delete(ref), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Precondition Failed");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The update condition specified in the request was not satisfied."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "UpdateConditionNotSatisfied");
}
TableResult res2 = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), Class1.class), options, null);
ref = res2.getResultAsType();
// actually delete it
this.table.execute(TableOperation.delete(ref), options, null);
// now try to delete it and fail
try {
this.table.execute(TableOperation.delete(ref), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Not Found");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The specified resource does not exist."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "ResourceNotFound");
}
}
@Test
public void testMergeFail() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
// Insert base entity
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
this.table.execute(TableOperation.insert(baseEntity), options, null);
Class2 secondEntity = new Class2();
secondEntity.setL("foo_L");
secondEntity.setM("foo_M");
secondEntity.setN("foo_N");
secondEntity.setO("foo_O");
secondEntity.setPartitionKey(baseEntity.getPartitionKey());
secondEntity.setRowKey(baseEntity.getRowKey());
secondEntity.setEtag(baseEntity.getEtag());
String oldEtag = baseEntity.getEtag();
this.table.execute(TableOperation.merge(secondEntity), options, null);
secondEntity.setEtag(oldEtag);
secondEntity.setL("updated");
try {
this.table.execute(TableOperation.merge(secondEntity), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Precondition Failed");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The update condition specified in the request was not satisfied."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "UpdateConditionNotSatisfied");
}
// retrieve entity
TableResult queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
DynamicTableEntity retrievedEntity = queryResult.getResultAsType();
this.table.execute(TableOperation.delete(retrievedEntity), options, null);
try {
this.table.execute(TableOperation.merge(secondEntity), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Not Found");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The specified resource does not exist."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "ResourceNotFound");
}
}
@Test
public void testInsertFail() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
TableOperation op = TableOperation.insert(ref);
this.table.execute(op, options, null);
try {
this.table.execute(op, options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Conflict");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The specified entity already exists"));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "EntityAlreadyExists");
}
}
@Test
public void testReplaceFail() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
// Insert entity
this.table.execute(TableOperation.insert(baseEntity), options, null);
String oldEtag = baseEntity.getEtag();
TableResult queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
// Retrieve entity
DynamicTableEntity retrievedEntity = queryResult.<DynamicTableEntity>getResultAsType();
assertNotNull("Property D", retrievedEntity.getProperties().get("D"));
assertTrue(Arrays.equals(baseEntity.getD(), retrievedEntity.getProperties().get("D").getValueAsByteArray()));
// Remove property and update
retrievedEntity.getProperties().remove("D");
this.table.execute(TableOperation.replace(retrievedEntity), options, null);
retrievedEntity.setEtag(oldEtag);
try {
this.table.execute(TableOperation.replace(retrievedEntity), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Precondition Failed");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The update condition specified in the request was not satisfied."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "UpdateConditionNotSatisfied");
}
// delete entity
queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
this.table.execute(TableOperation.delete((DynamicTableEntity) queryResult.getResultAsType()), options, null);
try {
this.table.execute(TableOperation.replace(retrievedEntity), options, null);
fail();
} catch (TableServiceException ex) {
assertEquals(ex.getMessage(), "Not Found");
assertTrue(ex.getExtendedErrorInformation().getErrorMessage()
.startsWith("The specified resource does not exist."));
assertEquals(ex.getExtendedErrorInformation().getErrorCode(), "ResourceNotFound");
}
}
@Test
public void testEmptyRetrieve() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
TableResult res = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), Class1.class), options, null);
assertNull(res.getResult());
assertEquals(res.getHttpStatusCode(), HttpURLConnection.HTTP_NOT_FOUND);
}
@Test
public void testInsertEmptyEntity() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.Json);
EmptyClass ref = new EmptyClass();
ref.setPartitionKey("jxscl_odata");
ref.setRowKey("echo_default" + UUID.randomUUID().toString());
TableResult res = this.table.execute(TableOperation.insert(ref), options, null);
assertEquals(HttpURLConnection.HTTP_NO_CONTENT, res.getHttpStatusCode());
EmptyClassDynamic refDynamic = new EmptyClassDynamic();
refDynamic.setPartitionKey("jxscl_odata");
refDynamic.setRowKey("echo_default" + UUID.randomUUID().toString());
res = this.table.execute(TableOperation.insert(refDynamic), options, null);
assertEquals(HttpURLConnection.HTTP_NO_CONTENT, res.getHttpStatusCode());
}
@Test
public void testDelete() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testDelete(options);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testDelete(options);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testDelete(options);
}
private void testDelete(TableRequestOptions options) throws StorageException {
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
TableOperation op = TableOperation.insert(ref);
this.table.execute(op, options, null);
this.table.execute(TableOperation.delete(ref), options, null);
TableResult res2 = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), Class1.class), options, null);
assertTrue(res2.getResult() == null);
}
@Test
public void testInsertOrMerge() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testInsertOrMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testInsertOrMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testInsertOrMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testInsertOrMerge(options, true);
}
private void testInsertOrMerge(TableRequestOptions options, boolean usePropertyResolver) throws StorageException {
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
Class2 secondEntity = new Class2();
secondEntity.setL("foo_L");
secondEntity.setM("foo_M");
secondEntity.setN("foo_N");
secondEntity.setO("foo_O");
secondEntity.setPartitionKey(baseEntity.getPartitionKey());
secondEntity.setRowKey(baseEntity.getRowKey());
secondEntity.setEtag(baseEntity.getEtag());
// Insert or merge Entity - ENTITY DOES NOT EXIST NOW.
TableResult insertResult = this.table.execute(TableOperation.insertOrMerge(baseEntity), options, null);
assertEquals(insertResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT);
assertNotNull(insertResult.getEtag());
// Insert or replace Entity - ENTITY EXISTS -> WILL MERGE
this.table.execute(TableOperation.insertOrMerge(secondEntity), options, null);
// Retrieve entity
if (usePropertyResolver) {
PropertyResolver resolver = new class1class2PropertyResolver();
options.setPropertyResolver(resolver);
}
TableResult queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
DynamicTableEntity retrievedEntity = queryResult.<DynamicTableEntity>getResultAsType();
assertNotNull("Property A", retrievedEntity.getProperties().get("A"));
assertEquals(baseEntity.getA(), retrievedEntity.getProperties().get("A").getValueAsString());
assertNotNull("Property B", retrievedEntity.getProperties().get("B"));
assertEquals(baseEntity.getB(), retrievedEntity.getProperties().get("B").getValueAsString());
assertNotNull("Property C", retrievedEntity.getProperties().get("C"));
assertEquals(baseEntity.getC(), retrievedEntity.getProperties().get("C").getValueAsString());
assertNotNull("Property D", retrievedEntity.getProperties().get("D"));
assertTrue(Arrays.equals(baseEntity.getD(), retrievedEntity.getProperties().get("D").getValueAsByteArray()));
// Validate New properties exist
assertNotNull("Property L", retrievedEntity.getProperties().get("L"));
assertEquals(secondEntity.getL(), retrievedEntity.getProperties().get("L").getValueAsString());
assertNotNull("Property M", retrievedEntity.getProperties().get("M"));
assertEquals(secondEntity.getM(), retrievedEntity.getProperties().get("M").getValueAsString());
assertNotNull("Property N", retrievedEntity.getProperties().get("N"));
assertEquals(secondEntity.getN(), retrievedEntity.getProperties().get("N").getValueAsString());
assertNotNull("Property O", retrievedEntity.getProperties().get("O"));
assertEquals(secondEntity.getO(), retrievedEntity.getProperties().get("O").getValueAsString());
}
@Test
public void testInsertOrReplace() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testInsertOrReplace(options);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testInsertOrReplace(options);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testInsertOrReplace(options);
}
private void testInsertOrReplace(TableRequestOptions options) throws StorageException {
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
Class2 secondEntity = new Class2();
secondEntity.setL("foo_L");
secondEntity.setM("foo_M");
secondEntity.setN("foo_N");
secondEntity.setO("foo_O");
secondEntity.setPartitionKey(baseEntity.getPartitionKey());
secondEntity.setRowKey(baseEntity.getRowKey());
secondEntity.setEtag(baseEntity.getEtag());
// Insert or replace Entity - ENTITY DOES NOT EXIST NOW.
TableResult insertResult = this.table.execute(TableOperation.insertOrReplace(baseEntity), options, null);
assertEquals(insertResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT);
assertNotNull(insertResult.getEtag());
// Insert or replace Entity - ENTITY EXISTS -> WILL REPLACE
this.table.execute(TableOperation.insertOrReplace(secondEntity), options, null);
// Retrieve entity
TableResult queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
DynamicTableEntity retrievedEntity = queryResult.getResultAsType();
// Validate old properties dont exist
assertTrue(retrievedEntity.getProperties().get("A") == null);
assertTrue(retrievedEntity.getProperties().get("B") == null);
assertTrue(retrievedEntity.getProperties().get("C") == null);
assertTrue(retrievedEntity.getProperties().get("D") == null);
// Validate New properties exist
assertNotNull("Property L", retrievedEntity.getProperties().get("L"));
assertEquals(secondEntity.getL(), retrievedEntity.getProperties().get("L").getValueAsString());
assertNotNull("Property M", retrievedEntity.getProperties().get("M"));
assertEquals(secondEntity.getM(), retrievedEntity.getProperties().get("M").getValueAsString());
assertNotNull("Property N", retrievedEntity.getProperties().get("N"));
assertEquals(secondEntity.getN(), retrievedEntity.getProperties().get("N").getValueAsString());
assertNotNull("Property O", retrievedEntity.getProperties().get("O"));
assertEquals(secondEntity.getO(), retrievedEntity.getProperties().get("O").getValueAsString());
}
@Test
public void testMerge() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testMerge(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testMerge(options, true);
}
private void testMerge(TableRequestOptions options, boolean usePropertyResolver) throws StorageException {
// Insert base entity
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
this.table.execute(TableOperation.insert(baseEntity), options, null);
Class2 secondEntity = new Class2();
secondEntity.setL("foo_L");
secondEntity.setM("foo_M");
secondEntity.setN("foo_N");
secondEntity.setO("foo_O");
secondEntity.setPartitionKey(baseEntity.getPartitionKey());
secondEntity.setRowKey(baseEntity.getRowKey());
secondEntity.setEtag(baseEntity.getEtag());
TableResult mergeResult = this.table.execute(TableOperation.merge(secondEntity), options, null);
assertEquals(mergeResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT);
assertNotNull(mergeResult.getEtag());
// retrieve result
if (usePropertyResolver) {
PropertyResolver resolver = new class1class2PropertyResolver();
options.setPropertyResolver(resolver);
}
TableResult res2 = this.table.execute(TableOperation.retrieve(secondEntity.getPartitionKey(),
secondEntity.getRowKey(), DynamicTableEntity.class), options, null);
DynamicTableEntity mergedEntity = (DynamicTableEntity) res2.getResult();
assertNotNull("Property A", mergedEntity.getProperties().get("A"));
assertEquals(baseEntity.getA(), mergedEntity.getProperties().get("A").getValueAsString());
assertNotNull("Property B", mergedEntity.getProperties().get("B"));
assertEquals(baseEntity.getB(), mergedEntity.getProperties().get("B").getValueAsString());
assertNotNull("Property C", mergedEntity.getProperties().get("C"));
assertEquals(baseEntity.getC(), mergedEntity.getProperties().get("C").getValueAsString());
assertNotNull("Property D", mergedEntity.getProperties().get("D"));
assertTrue(Arrays.equals(baseEntity.getD(), mergedEntity.getProperties().get("D").getValueAsByteArray()));
assertNotNull("Property L", mergedEntity.getProperties().get("L"));
assertEquals(secondEntity.getL(), mergedEntity.getProperties().get("L").getValueAsString());
assertNotNull("Property M", mergedEntity.getProperties().get("M"));
assertEquals(secondEntity.getM(), mergedEntity.getProperties().get("M").getValueAsString());
assertNotNull("Property N", mergedEntity.getProperties().get("N"));
assertEquals(secondEntity.getN(), mergedEntity.getProperties().get("N").getValueAsString());
assertNotNull("Property O", mergedEntity.getProperties().get("O"));
assertEquals(secondEntity.getO(), mergedEntity.getProperties().get("O").getValueAsString());
}
@Test
public void testReplace() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testReplace(options);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testReplace(options);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testReplace(options);
}
private void testReplace(TableRequestOptions options) throws StorageException {
Class1 baseEntity = new Class1();
baseEntity.setA("foo_A");
baseEntity.setB("foo_B");
baseEntity.setC("foo_C");
baseEntity.setD(new byte[]{0, 1, 2});
baseEntity.setPartitionKey("jxscl_odata");
baseEntity.setRowKey(UUID.randomUUID().toString());
// Insert entity
this.table.execute(TableOperation.insert(baseEntity), options, null);
TableResult queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
// Retrieve entity
DynamicTableEntity retrievedEntity = queryResult.<DynamicTableEntity>getResultAsType();
assertNotNull("Property D", retrievedEntity.getProperties().get("D"));
assertTrue(Arrays.equals(baseEntity.getD(), retrievedEntity.getProperties().get("D").getValueAsByteArray()));
// Remove property and update
retrievedEntity.getProperties().remove("D");
TableResult replaceResult = this.table.execute(TableOperation.replace(retrievedEntity), options, null);
assertEquals(replaceResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT);
assertNotNull(replaceResult.getEtag());
// Retrieve Entity
queryResult = this.table
.execute(TableOperation.retrieve(baseEntity.getPartitionKey(), baseEntity.getRowKey(),
DynamicTableEntity.class), options, null);
retrievedEntity = queryResult.<DynamicTableEntity>getResultAsType();
// Validate
assertNotNull("Property A", retrievedEntity.getProperties().get("A"));
assertEquals(baseEntity.getA(), retrievedEntity.getProperties().get("A").getValueAsString());
assertNotNull("Property B", retrievedEntity.getProperties().get("B"));
assertEquals(baseEntity.getB(), retrievedEntity.getProperties().get("B").getValueAsString());
assertNotNull("Property C", retrievedEntity.getProperties().get("C"));
assertEquals(baseEntity.getC(), retrievedEntity.getProperties().get("C").getValueAsString());
assertTrue(retrievedEntity.getProperties().get("D") == null);
}
@Test
public void testInsert() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testInsert(options);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testInsert(options);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testInsert(options);
}
private void testInsert(TableRequestOptions options) throws StorageException {
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
// 1mb right here
ref.setD(new byte[1024]);
ref.setPartitionKey("jxscl_odata");
ref.setRowKey("echo_default" + UUID.randomUUID().toString());
TableResult res = this.table.execute(TableOperation.insert(ref), options, null);
assertEquals(HttpURLConnection.HTTP_NO_CONTENT, res.getHttpStatusCode());
ref.setRowKey("echo" + UUID.randomUUID().toString());
res = this.table.execute(TableOperation.insert(ref, true), options, null);
assertEquals(HttpURLConnection.HTTP_CREATED, res.getHttpStatusCode());
ref.setRowKey("echo_off" + UUID.randomUUID().toString());
res = this.table.execute(TableOperation.insert(ref, false), options, null);
assertEquals(HttpURLConnection.HTTP_NO_CONTENT, res.getHttpStatusCode());
}
@Test
public void testRetrieveWithoutEntityResolver() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testRetrieveWithoutEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testRetrieveWithoutEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testRetrieveWithoutEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testRetrieveWithoutEntityResolver(options, true);
}
private void testRetrieveWithoutEntityResolver(TableRequestOptions options, boolean usePropertyResolver)
throws StorageException {
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
if (usePropertyResolver) {
options.setPropertyResolver(ref);
}
// with cache on
this.table.execute(TableOperation.insert(ref), options, null);
TableResult res = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), Class1.class), options, null);
Class1 retrievedEnt = res.getResultAsType();
assertEquals(ref.getA(), retrievedEnt.getA());
assertTrue(Arrays.equals(ref.getD(), retrievedEnt.getD()));
// with cache off
TableServiceEntity.setReflectedEntityCacheDisabled(true);
try {
res = this.table.execute(TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), Class1.class),
options, null);
retrievedEnt = res.getResultAsType();
assertEquals(ref.getA(), retrievedEnt.getA());
assertTrue(Arrays.equals(ref.getD(), retrievedEnt.getD()));
} finally {
TableServiceEntity.setReflectedEntityCacheDisabled(false);
}
}
@Test
public void testRetrieveWithEntityResolver() throws StorageException {
TableRequestOptions options = new TableRequestOptions();
options.setTablePayloadFormat(TablePayloadFormat.JsonFullMetadata);
testRetrieveWithEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.Json);
testRetrieveWithEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testRetrieveWithEntityResolver(options, false);
options.setTablePayloadFormat(TablePayloadFormat.JsonNoMetadata);
testRetrieveWithEntityResolver(options, true);
}
private void testRetrieveWithEntityResolver(TableRequestOptions options, boolean usePropertyResolver)
throws StorageException {
Class1 ref = new Class1();
ref.setA("foo_A");
ref.setB("foo_B");
ref.setC("foo_C");
ref.setD(new byte[]{0, 1, 2});
ref.setPartitionKey("jxscl_odata");
ref.setRowKey(UUID.randomUUID().toString());
// with cache on
TableOperation op = TableOperation.insert(ref);
this.table.execute(op, options, null);
TableResult res4 = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), new EntityResolver<Class1>() {
@Override
public Class1 resolve(String partitionKey, String rowKey, Date timeStamp,
HashMap<String, EntityProperty> properties, String etag) {
Class1 result = new Class1();
result.setA(properties.get("A").getValueAsString());
result.setD(properties.get("D").getValueAsByteArray());
return result;
}
}), options, null);
Class1 retrievedEnt = (Class1) res4.getResult();
assertEquals(ref.getA(), retrievedEnt.getA());
assertTrue(Arrays.equals(ref.getD(), retrievedEnt.getD()));
// with cache off
TableServiceEntity.setReflectedEntityCacheDisabled(true);
try {
res4 = this.table.execute(
TableOperation.retrieve(ref.getPartitionKey(), ref.getRowKey(), new EntityResolver<Class1>() {
@Override
public Class1 resolve(String partitionKey, String rowKey, Date timeStamp,
HashMap<String, EntityProperty> properties, String etag) {
Class1 result = new Class1();
result.setA(properties.get("A").getValueAsString());
result.setD(properties.get("D").getValueAsByteArray());
return result;
}
}), options, null);
retrievedEnt = (Class1) res4.getResult();
assertEquals(ref.getA(), retrievedEnt.getA());
assertTrue(Arrays.equals(ref.getD(), retrievedEnt.getD()));
} finally {
TableServiceEntity.setReflectedEntityCacheDisabled(false);
}
}
}