/** * Copyright Microsoft Corporation * * 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 * * 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 static org.junit.Assert.*; import java.net.URISyntaxException; import java.util.Date; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; 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; /** * Table Operation Tests */ @Category({ DevFabricTests.class, DevStoreTests.class, CloudTests.class }) public class TableDateTests { private CloudTable table; @Before public void tableTestMethodSetUp() throws URISyntaxException, StorageException { this.table = TableTestHelper.getRandomTableReference(); this.table.createIfNotExists(); } @After public void tableTestMethodTearDown() throws StorageException { this.table.deleteIfExists(); } @Test public void testTableQueryRoundTripDate() throws URISyntaxException, StorageException { // 2014-12-07T09:15:12.123Z from Java testRoundTripDate(new Date(1417943712123L)); // 2015-01-14T14:53:32.800Z from Java testRoundTripDate(new Date(1421247212800L)); } @Test public void testRoundTripDateJsonAtom() throws URISyntaxException, StorageException { // JSON // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, false, TablePayloadFormat.Json); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, false, TablePayloadFormat.Json); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, false, TablePayloadFormat.Json); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, false, TablePayloadFormat.Json); // JSON NO METADATA // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, false, TablePayloadFormat.JsonNoMetadata); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, false, TablePayloadFormat.JsonNoMetadata); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, false, TablePayloadFormat.JsonNoMetadata); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, false, TablePayloadFormat.JsonNoMetadata); } @Test public void testRoundTripDateJsonAtomCrossVersion() throws URISyntaxException, StorageException { // JSON // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, false, TablePayloadFormat.Json); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, false, TablePayloadFormat.Json); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, false, TablePayloadFormat.Json); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, false, TablePayloadFormat.Json); // JSON NO METADATA // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, false, TablePayloadFormat.JsonNoMetadata); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, false, TablePayloadFormat.JsonNoMetadata); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, false, TablePayloadFormat.JsonNoMetadata); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, false, TablePayloadFormat.JsonNoMetadata); } @Test public void testRoundTripDateJsonAtomWithBackwardCompatibility() throws URISyntaxException, StorageException { // JSON // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, true, TablePayloadFormat.Json); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, true, TablePayloadFormat.Json); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, true, TablePayloadFormat.Json); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, true, TablePayloadFormat.Json); // JSON NO METADATA // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, true, TablePayloadFormat.JsonNoMetadata); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, true, TablePayloadFormat.JsonNoMetadata); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, true, TablePayloadFormat.JsonNoMetadata); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, true, TablePayloadFormat.JsonNoMetadata); } @Test public void testRoundTripDateJsonAtomCrossVersionWithBackwardCompatibility() throws URISyntaxException, StorageException { // JSON // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, true, TablePayloadFormat.Json); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, true, TablePayloadFormat.Json); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, true, TablePayloadFormat.Json); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, true, TablePayloadFormat.Json); // JSON NO METADATA // 2014-12-07T09:15:12.123Z from Java testTableQueryRoundTripDate( "2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, true, TablePayloadFormat.JsonNoMetadata); // 2015-01-14T14:53:32.800Z from Java testTableQueryRoundTripDate( "2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, true, TablePayloadFormat.JsonNoMetadata); // 2014-11-29T22:55:21.9876543Z from .Net testTableQueryRoundTripDate( "2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, true, TablePayloadFormat.JsonNoMetadata); // 2015-02-14T03:11:13.0000229Z from .Net testTableQueryRoundTripDate( "2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, true, TablePayloadFormat.JsonNoMetadata); } private void testRoundTripDate(final Date date) throws URISyntaxException, StorageException { final String partitionKey = "partitionTest"; // DateBackwardCompatibility off String rowKey = TableTestHelper.generateRandomKeyName(); DateTestEntity entity = new DateTestEntity(partitionKey, rowKey); entity.setDate(date); TableOperation put = TableOperation.insertOrReplace(entity); this.table.execute(put); TableOperation get = TableOperation.retrieve(partitionKey, rowKey, DateTestEntity.class); entity = this.table.execute(get).getResultAsType(); assertEquals(date.getTime(), entity.getDate().getTime()); // DateBackwardCompatibility on rowKey = TableTestHelper.generateRandomKeyName(); entity = new DateTestEntity(partitionKey, rowKey); entity.setDate(date); put = TableOperation.insertOrReplace(entity); this.table.execute(put); get = TableOperation.retrieve(partitionKey, rowKey, DateTestEntity.class); final TableRequestOptions options = new TableRequestOptions(); options.setDateBackwardCompatibility(true); entity = this.table.execute(get, options, null).getResultAsType(); assertEquals(date.getTime(), entity.getDate().getTime()); // DateBackwardCompatibility off final String dateKey = "date"; final EntityProperty property = new EntityProperty(date); rowKey = TableTestHelper.generateRandomKeyName(); DynamicTableEntity dynamicEntity = new DynamicTableEntity(partitionKey, rowKey); dynamicEntity.getProperties().put(dateKey, property); put = TableOperation.insertOrReplace(dynamicEntity); this.table.execute(put); get = TableOperation.retrieve(partitionKey, rowKey, DynamicTableEntity.class); dynamicEntity = this.table.execute(get).getResultAsType(); assertEquals(date.getTime(), dynamicEntity.getProperties().get(dateKey).getValueAsDate().getTime()); // DateBackwardCompatibility on rowKey = TableTestHelper.generateRandomKeyName(); dynamicEntity = new DynamicTableEntity(partitionKey, rowKey); dynamicEntity.getProperties().put(dateKey, property); put = TableOperation.insertOrReplace(dynamicEntity); this.table.execute(put); get = TableOperation.retrieve(partitionKey, rowKey, DynamicTableEntity.class); options.setDateBackwardCompatibility(true); dynamicEntity = this.table.execute(get, options, null).getResultAsType(); assertEquals(date.getTime(), dynamicEntity.getProperties().get(dateKey).getValueAsDate().getTime()); } private void testTableQueryRoundTripDate(final String dateString, final long milliseconds, final int ticks, final boolean writtenPre2, final boolean dateBackwardCompatibility, TablePayloadFormat format) throws URISyntaxException, StorageException { assertTrue(ticks >= 0); // ticks is non-negative assertTrue(ticks <= 9999); // ticks do not overflow into milliseconds final String partitionKey = "partitionTest"; final String dateKey = "date"; long expectedMilliseconds = milliseconds; if (dateBackwardCompatibility && (milliseconds % 1000 == 0) && (ticks < 1000)) { // when no milliseconds are present dateBackwardCompatibility causes up to 3 digits of ticks // to be read as milliseconds expectedMilliseconds += ticks; } else if (writtenPre2 && !dateBackwardCompatibility && (ticks == 0)) { // without DateBackwardCompatibility, milliseconds stored by Java prior to 2.0.0 are lost expectedMilliseconds -= expectedMilliseconds % 1000; } // Create a property for how the service would store the dateString EntityProperty property = new EntityProperty(dateString, EdmType.DATE_TIME); String rowKey = TableTestHelper.generateRandomKeyName(); DynamicTableEntity dynamicEntity = new DynamicTableEntity(partitionKey, rowKey); dynamicEntity.getProperties().put(dateKey, property); // Add the entity to the table TableOperation put = TableOperation.insertOrReplace(dynamicEntity); this.table.execute(put); // Specify the options TableRequestOptions options = new TableRequestOptions(); options.setDateBackwardCompatibility(dateBackwardCompatibility); options.setTablePayloadFormat(format); // Fetch the entity from the table TableOperation get = TableOperation.retrieve(partitionKey, rowKey, DynamicTableEntity.class); dynamicEntity = this.table.execute(get, options, null).getResultAsType(); // Ensure the date matches our expectations assertEquals(expectedMilliseconds, dynamicEntity.getProperties().get(dateKey).getValueAsDate().getTime()); } private static class DateTestEntity extends TableServiceEntity { private Date value; @SuppressWarnings("unused") public DateTestEntity() { } public DateTestEntity(String partition, String key) { super(partition, key); } public Date getDate() { return this.value; } public void setDate(Date value) { this.value = value; } } }