diff options
author | Artur Signell <artur@vaadin.com> | 2012-08-30 15:27:50 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2012-08-30 16:08:05 +0300 |
commit | 876182aaa34682503338a4dcdd119b3ebc256f97 (patch) | |
tree | 8e54b81cfcbecb5c54b725ca3a612b6e18e228cd /server | |
parent | 691220a5b24370d56f7c15d5a05c57a6c76dcb83 (diff) | |
download | vaadin-framework-876182aaa34682503338a4dcdd119b3ebc256f97.tar.gz vaadin-framework-876182aaa34682503338a4dcdd119b3ebc256f97.zip |
Moved server tests from tests/server-side to server/tests/src (#9299)
Diffstat (limited to 'server')
143 files changed, 21200 insertions, 0 deletions
diff --git a/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java new file mode 100644 index 0000000000..3c74a45bd7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractBeanContainerTest.java @@ -0,0 +1,81 @@ +package com.vaadin.data.util; + +import com.vaadin.data.util.AbstractBeanContainer; +import com.vaadin.data.util.BeanContainer; +import com.vaadin.data.util.BeanItemContainer; + +/** + * Automated test for {@link AbstractBeanContainer}. + * + * Only a limited subset of the functionality is tested here, the rest in tests + * of subclasses including {@link BeanItemContainer} and {@link BeanContainer}. + */ +public abstract class AbstractBeanContainerTest extends + AbstractInMemoryContainerTest { + + public static class Person { + private String name; + + public Person(String name) { + setName(name); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public static class ClassName { + // field names match constants in parent test class + private String fullyQualifiedName; + private String simpleName; + private String reverseFullyQualifiedName; + private Integer idNumber; + + public ClassName(String fullyQualifiedName, Integer idNumber) { + this.fullyQualifiedName = fullyQualifiedName; + simpleName = AbstractContainerTest + .getSimpleName(fullyQualifiedName); + reverseFullyQualifiedName = reverse(fullyQualifiedName); + this.idNumber = idNumber; + } + + public String getFullyQualifiedName() { + return fullyQualifiedName; + } + + public void setFullyQualifiedName(String fullyQualifiedName) { + this.fullyQualifiedName = fullyQualifiedName; + } + + public String getSimpleName() { + return simpleName; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } + + public String getReverseFullyQualifiedName() { + return reverseFullyQualifiedName; + } + + public void setReverseFullyQualifiedName( + String reverseFullyQualifiedName) { + this.reverseFullyQualifiedName = reverseFullyQualifiedName; + } + + public Integer getIdNumber() { + return idNumber; + } + + public void setIdNumber(Integer idNumber) { + this.idNumber = idNumber; + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java new file mode 100644 index 0000000000..b0151a6690 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractContainerTest.java @@ -0,0 +1,649 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Filterable; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.SimpleStringFilter; + +public abstract class AbstractContainerTest extends TestCase { + + /** + * Helper class for testing e.g. listeners expecting events to be fired. + */ + protected abstract static class AbstractEventCounter { + private int eventCount = 0; + private int lastAssertedEventCount = 0; + + /** + * Increment the event count. To be called by subclasses e.g. from a + * listener method. + */ + protected void increment() { + ++eventCount; + } + + /** + * Check that no one event has occurred since the previous assert call. + */ + public void assertNone() { + Assert.assertEquals(lastAssertedEventCount, eventCount); + } + + /** + * Check that exactly one event has occurred since the previous assert + * call. + */ + public void assertOnce() { + Assert.assertEquals(++lastAssertedEventCount, eventCount); + } + + /** + * Reset the counter and the expected count. + */ + public void reset() { + eventCount = 0; + lastAssertedEventCount = 0; + } + } + + /** + * Test class for counting item set change events and verifying they have + * been received. + */ + protected static class ItemSetChangeCounter extends AbstractEventCounter + implements ItemSetChangeListener { + + @Override + public void containerItemSetChange(ItemSetChangeEvent event) { + increment(); + } + + } + + // #6043: for items that have been filtered out, Container interface does + // not specify what to return from getItem() and getContainerProperty(), so + // need checkGetItemNull parameter for the test to be usable for most + // current containers + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize) { + Container.Indexed indexed = null; + if (container instanceof Container.Indexed) { + indexed = (Container.Indexed) container; + } + + List<Object> itemIdList = new ArrayList<Object>(container.getItemIds()); + + // size() + assertEquals(expectedSize, container.size()); + assertEquals(expectedSize, itemIdList.size()); + + // first item, last item + Object first = itemIdList.get(0); + Object last = itemIdList.get(itemIdList.size() - 1); + + assertEquals(expectedFirstItemId, first); + assertEquals(expectedLastItemId, last); + + // containsId + assertFalse(container.containsId(itemIdNotInSet)); + assertTrue(container.containsId(itemIdInSet)); + + // getItem + if (checkGetItemNull) { + assertNull(container.getItem(itemIdNotInSet)); + } + assertNotNull(container.getItem(itemIdInSet)); + + // getContainerProperty + for (Object propId : container.getContainerPropertyIds()) { + if (checkGetItemNull) { + assertNull(container.getContainerProperty(itemIdNotInSet, + propId)); + } + assertNotNull(container.getContainerProperty(itemIdInSet, propId)); + } + + if (indexed != null) { + // firstItemId + assertEquals(first, indexed.firstItemId()); + + // lastItemId + assertEquals(last, indexed.lastItemId()); + + // nextItemId + assertEquals(itemIdList.get(1), indexed.nextItemId(first)); + + // prevItemId + assertEquals(itemIdList.get(itemIdList.size() - 2), + indexed.prevItemId(last)); + + // isFirstId + assertTrue(indexed.isFirstId(first)); + assertFalse(indexed.isFirstId(last)); + + // isLastId + assertTrue(indexed.isLastId(last)); + assertFalse(indexed.isLastId(first)); + + // indexOfId + assertEquals(0, indexed.indexOfId(first)); + assertEquals(expectedSize - 1, indexed.indexOfId(last)); + + // getIdByIndex + assertEquals(indexed.getIdByIndex(0), first); + assertEquals(indexed.getIdByIndex(expectedSize - 1), last); + + } + + } + + protected static final Object FULLY_QUALIFIED_NAME = "fullyQualifiedName"; + protected static final Object SIMPLE_NAME = "simpleName"; + protected static final Object REVERSE_FULLY_QUALIFIED_NAME = "reverseFullyQualifiedName"; + protected static final Object ID_NUMBER = "idNumber"; + + protected void testBasicContainerOperations(Container container) { + initializeContainer(container); + + // Basic container + validateContainer(container, sampleData[0], + sampleData[sampleData.length - 1], sampleData[10], "abc", true, + sampleData.length); + } + + protected void testContainerOrdered(Container.Ordered container) { + Object id = container.addItem(); + assertNotNull(id); + Item item = container.getItem(id); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + Object newFirstId = container.addItemAfter(null); + assertNotNull(newFirstId); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(Object) + Object newSecondItemId = container.addItemAfter(newFirstId); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(newSecondItemId); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(Object,Object) + Object fifthId = new Object(); + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + protected void testContainerIndexed(Container.Indexed container, + Object itemId, int itemPosition, boolean testAddEmptyItemAt, + Object newItemId, boolean testAddItemAtWithId) { + initializeContainer(container); + + // indexOfId + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + + // getIdByIndex + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + + // addItemAt + if (testAddEmptyItemAt) { + Object addedId = container.addItemAt(itemPosition); + Assert.assertEquals(itemPosition, container.indexOfId(addedId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(addedId, container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + + Object newFirstId = container.addItemAt(0); + Assert.assertEquals(0, container.indexOfId(newFirstId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newFirstId, container.firstItemId()); + Assert.assertEquals(newFirstId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Object newLastId = container.addItemAt(container.size()); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newLastId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newLastId, container.lastItemId()); + Assert.assertEquals(newLastId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Assert.assertTrue(container.removeItem(addedId)); + Assert.assertTrue(container.removeItem(newFirstId)); + Assert.assertTrue(container.removeItem(newLastId)); + + Assert.assertFalse( + "Removing non-existing item should indicate failure", + container.removeItem(addedId)); + } + + // addItemAt + if (testAddItemAtWithId) { + container.addItemAt(itemPosition, newItemId); + Assert.assertEquals(itemPosition, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(0, newItemId); + Assert.assertEquals(0, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.firstItemId()); + Assert.assertEquals(newItemId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(container.size(), newItemId); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.lastItemId()); + Assert.assertEquals(newItemId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + } + } + + protected void testContainerFiltering(Container.Filterable container) { + initializeContainer(container); + + // Filter by "contains ab" + container.addContainerFilter(new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false)); + + validateContainer(container, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TabSheet", "com.vaadin.client.Focusable", + "com.vaadin.data.Buffered", isFilteredOutItemNull(), 20); + + // Filter by "contains da" (reversed as ad here) + container.removeAllContainerFilters(); + container.addContainerFilter(new SimpleStringFilter( + REVERSE_FULLY_QUALIFIED_NAME, "ad", false, false)); + + validateContainer(container, "com.vaadin.data.Buffered", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.client.ui.VUriFragmentUtility", + isFilteredOutItemNull(), 37); + } + + /** + * Override in subclasses to return false if the container getItem() method + * returns a non-null value for an item that has been filtered out. + * + * @return + */ + protected boolean isFilteredOutItemNull() { + return true; + } + + protected void testContainerSortingAndFiltering(Container.Sortable sortable) { + Filterable filterable = (Filterable) sortable; + + initializeContainer(sortable); + + // Filter by "contains ab" + filterable.addContainerFilter(new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false)); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(sortable, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.data.util.BeanItem", isFilteredOutItemNull(), 20); + } + + protected void testContainerSorting(Container.Filterable container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds().contains( + REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.Application", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + sampleData.length); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.ui.BaseFieldFactory", "blah", true, + sampleData.length); + + } + + protected void initializeContainer(Container container) { + Assert.assertTrue(container.removeAllItems()); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + Item item = container.addItem(id); + + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i); + } + } + + protected static String getSimpleName(String name) { + if (name.contains(".")) { + return name.substring(name.lastIndexOf('.') + 1); + } else { + return name; + } + } + + protected static String reverse(String string) { + return new StringBuilder(string).reverse().toString(); + } + + protected final String[] sampleData = { + "com.vaadin.annotations.AutoGenerated", "com.vaadin.Application", + "com.vaadin.data.Buffered", "com.vaadin.data.BufferedValidatable", + "com.vaadin.data.Container", "com.vaadin.data.Item", + "com.vaadin.data.Property", "com.vaadin.data.util.BeanItem", + "com.vaadin.data.util.BeanItemContainer", + "com.vaadin.data.util.ContainerHierarchicalWrapper", + "com.vaadin.data.util.ContainerOrderedWrapper", + "com.vaadin.data.util.DefaultItemSorter", + "com.vaadin.data.util.FilesystemContainer", + "com.vaadin.data.util.Filter", + "com.vaadin.data.util.HierarchicalContainer", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.data.util.ItemSorter", + "com.vaadin.data.util.MethodProperty", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.data.util.PropertyFormatter", + "com.vaadin.data.util.PropertysetItem", + "com.vaadin.data.util.QueryContainer", + "com.vaadin.data.util.TextFileProperty", + "com.vaadin.data.Validatable", + "com.vaadin.data.validator.AbstractStringValidator", + "com.vaadin.data.validator.AbstractValidator", + "com.vaadin.data.validator.CompositeValidator", + "com.vaadin.data.validator.DoubleValidator", + "com.vaadin.data.validator.EmailValidator", + "com.vaadin.data.validator.IntegerValidator", + "com.vaadin.data.validator.NullValidator", + "com.vaadin.data.validator.RegexpValidator", + "com.vaadin.data.validator.StringLengthValidator", + "com.vaadin.data.Validator", "com.vaadin.event.Action", + "com.vaadin.event.ComponentEventListener", + "com.vaadin.event.EventRouter", "com.vaadin.event.FieldEvents", + "com.vaadin.event.ItemClickEvent", "com.vaadin.event.LayoutEvents", + "com.vaadin.event.ListenerMethod", + "com.vaadin.event.MethodEventSource", + "com.vaadin.event.MouseEvents", "com.vaadin.event.ShortcutAction", + "com.vaadin.launcher.DemoLauncher", + "com.vaadin.launcher.DevelopmentServerLauncher", + "com.vaadin.launcher.util.BrowserLauncher", + "com.vaadin.service.ApplicationContext", + "com.vaadin.service.FileTypeResolver", + "com.vaadin.server.ApplicationResource", + "com.vaadin.server.ClassResource", + "com.vaadin.server.CompositeErrorMessage", + "com.vaadin.server.DownloadStream", + "com.vaadin.server.ErrorMessage", + "com.vaadin.server.ExternalResource", + "com.vaadin.server.FileResource", + "com.vaadin.client.ApplicationConfiguration", + "com.vaadin.client.ApplicationConnection", + "com.vaadin.client.BrowserInfo", + "com.vaadin.client.ClientExceptionHandler", + "com.vaadin.client.ComponentDetail", + "com.vaadin.client.ComponentDetailMap", + "com.vaadin.client.ComponentLocator", "com.vaadin.client.Console", + "com.vaadin.client.Container", + "com.vaadin.client.ContainerResizedListener", + "com.vaadin.client.CSSRule", "com.vaadin.client.DateTimeService", + "com.vaadin.client.DefaultWidgetSet", + "com.vaadin.client.Focusable", + "com.vaadin.client.HistoryImplIEVaadin", + "com.vaadin.client.LocaleNotLoadedException", + "com.vaadin.client.LocaleService", + "com.vaadin.client.MouseEventDetails", + "com.vaadin.client.NullConsole", "com.vaadin.client.Paintable", + "com.vaadin.client.RenderInformation", + "com.vaadin.client.RenderSpace", + "com.vaadin.client.StyleConstants", + "com.vaadin.client.TooltipInfo", "com.vaadin.client.ui.Action", + "com.vaadin.client.ui.ActionOwner", + "com.vaadin.client.ui.AlignmentInfo", + "com.vaadin.client.ui.CalendarEntry", + "com.vaadin.client.ui.ClickEventHandler", + "com.vaadin.client.ui.Field", "com.vaadin.client.ui.Icon", + "com.vaadin.client.ui.layout.CellBasedLayout", + "com.vaadin.client.ui.layout.ChildComponentContainer", + "com.vaadin.client.ui.layout.Margins", + "com.vaadin.client.ui.LayoutClickEventHandler", + "com.vaadin.client.ui.MenuBar", "com.vaadin.client.ui.MenuItem", + "com.vaadin.client.ui.richtextarea.VRichTextArea", + "com.vaadin.client.ui.richtextarea.VRichTextToolbar", + "com.vaadin.client.ui.ShortcutActionHandler", + "com.vaadin.client.ui.SubPartAware", "com.vaadin.client.ui.Table", + "com.vaadin.client.ui.TreeAction", + "com.vaadin.client.ui.TreeImages", + "com.vaadin.client.ui.VAbsoluteLayout", + "com.vaadin.client.ui.VAccordion", "com.vaadin.client.ui.VButton", + "com.vaadin.client.ui.VCalendarPanel", + "com.vaadin.client.ui.VCheckBox", + "com.vaadin.client.ui.VContextMenu", + "com.vaadin.client.ui.VCssLayout", + "com.vaadin.client.ui.VCustomComponent", + "com.vaadin.client.ui.VCustomLayout", + "com.vaadin.client.ui.VDateField", + "com.vaadin.client.ui.VDateFieldCalendar", + "com.vaadin.client.ui.VEmbedded", + "com.vaadin.client.ui.VFilterSelect", "com.vaadin.client.ui.VForm", + "com.vaadin.client.ui.VFormLayout", + "com.vaadin.client.ui.VGridLayout", + "com.vaadin.client.ui.VHorizontalLayout", + "com.vaadin.client.ui.VLabel", "com.vaadin.client.ui.VLink", + "com.vaadin.client.ui.VListSelect", + "com.vaadin.client.ui.VMarginInfo", + "com.vaadin.client.ui.VMenuBar", + "com.vaadin.client.ui.VNativeButton", + "com.vaadin.client.ui.VNativeSelect", + "com.vaadin.client.ui.VNotification", + "com.vaadin.client.ui.VOptionGroup", + "com.vaadin.client.ui.VOptionGroupBase", + "com.vaadin.client.ui.VOrderedLayout", + "com.vaadin.client.ui.VOverlay", "com.vaadin.client.ui.VPanel", + "com.vaadin.client.ui.VPasswordField", + "com.vaadin.client.ui.VPopupCalendar", + "com.vaadin.client.ui.VPopupView", + "com.vaadin.client.ui.VProgressIndicator", + "com.vaadin.client.ui.VScrollTable", + "com.vaadin.client.ui.VSlider", "com.vaadin.client.ui.VSplitPanel", + "com.vaadin.client.ui.VSplitPanelHorizontal", + "com.vaadin.client.ui.VSplitPanelVertical", + "com.vaadin.client.ui.VTablePaging", + "com.vaadin.client.ui.VTabsheet", + "com.vaadin.client.ui.VTabsheetBase", + "com.vaadin.client.ui.VTabsheetPanel", + "com.vaadin.client.ui.VTextArea", + "com.vaadin.client.ui.VTextField", + "com.vaadin.client.ui.VTextualDate", "com.vaadin.client.ui.VTime", + "com.vaadin.client.ui.VTree", + "com.vaadin.client.ui.VTwinColSelect", + "com.vaadin.client.ui.VUnknownComponent", + "com.vaadin.client.ui.VUpload", + "com.vaadin.client.ui.VUriFragmentUtility", + "com.vaadin.client.ui.VVerticalLayout", + "com.vaadin.client.ui.VView", "com.vaadin.client.ui.VWindow", + "com.vaadin.client.UIDL", "com.vaadin.client.Util", + "com.vaadin.client.ValueMap", "com.vaadin.client.VCaption", + "com.vaadin.client.VCaptionWrapper", + "com.vaadin.client.VDebugConsole", + "com.vaadin.client.VErrorMessage", "com.vaadin.client.VTooltip", + "com.vaadin.client.VUIDLBrowser", "com.vaadin.client.WidgetMap", + "com.vaadin.client.WidgetSet", + "com.vaadin.server.AbstractApplicationPortlet", + "com.vaadin.server.AbstractApplicationServlet", + "com.vaadin.server.AbstractCommunicationManager", + "com.vaadin.server.AbstractWebApplicationContext", + "com.vaadin.server.ApplicationPortlet", + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.server.ApplicationRunnerServlet", + "com.vaadin.server.ApplicationServlet", + "com.vaadin.server.ChangeVariablesErrorEvent", + "com.vaadin.server.CommunicationManager", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.server.Constants", + "com.vaadin.server.GAEApplicationServlet", + "com.vaadin.server.HttpServletRequestListener", + "com.vaadin.server.HttpUploadStream", + "com.vaadin.server.JsonPaintTarget", + "com.vaadin.server.PortletApplicationContext", + "com.vaadin.server.PortletApplicationContext2", + "com.vaadin.server.PortletCommunicationManager", + "com.vaadin.server.PortletRequestListener", + "com.vaadin.server.RestrictedRenderResponse", + "com.vaadin.server.SessionExpiredException", + "com.vaadin.server.SystemMessageException", + "com.vaadin.server.WebApplicationContext", + "com.vaadin.server.WebBrowser", + "com.vaadin.server.widgetsetutils.ClassPathExplorer", + "com.vaadin.server.widgetsetutils.WidgetMapGenerator", + "com.vaadin.server.widgetsetutils.WidgetSetBuilder", + "com.vaadin.server.KeyMapper", "com.vaadin.server.Paintable", + "com.vaadin.server.PaintException", + "com.vaadin.server.PaintTarget", + "com.vaadin.server.ParameterHandler", "com.vaadin.server.Resource", + "com.vaadin.server.Scrollable", "com.vaadin.server.Sizeable", + "com.vaadin.server.StreamResource", + "com.vaadin.server.SystemError", "com.vaadin.server.Terminal", + "com.vaadin.server.ThemeResource", + "com.vaadin.server.UploadStream", "com.vaadin.server.URIHandler", + "com.vaadin.server.UserError", "com.vaadin.server.VariableOwner", + "com.vaadin.tools.ReflectTools", + "com.vaadin.tools.WidgetsetCompiler", + "com.vaadin.ui.AbsoluteLayout", "com.vaadin.ui.AbstractComponent", + "com.vaadin.ui.AbstractComponentContainer", + "com.vaadin.ui.AbstractField", "com.vaadin.ui.AbstractLayout", + "com.vaadin.ui.AbstractOrderedLayout", + "com.vaadin.ui.AbstractSelect", "com.vaadin.ui.Accordion", + "com.vaadin.ui.Alignment", "com.vaadin.ui.AlignmentUtils", + "com.vaadin.ui.BaseFieldFactory", "com.vaadin.ui.Button", + "com.vaadin.ui.CheckBox", "com.vaadin.ui.ClientWidget", + "com.vaadin.ui.ComboBox", "com.vaadin.ui.Component", + "com.vaadin.ui.ComponentContainer", "com.vaadin.ui.CssLayout", + "com.vaadin.ui.CustomComponent", "com.vaadin.ui.CustomLayout", + "com.vaadin.ui.DateField", "com.vaadin.ui.DefaultFieldFactory", + "com.vaadin.ui.Embedded", "com.vaadin.ui.ExpandLayout", + "com.vaadin.ui.Field", "com.vaadin.ui.FieldFactory", + "com.vaadin.ui.Form", "com.vaadin.ui.FormFieldFactory", + "com.vaadin.ui.FormLayout", "com.vaadin.ui.GridLayout", + "com.vaadin.ui.HorizontalLayout", "com.vaadin.ui.InlineDateField", + "com.vaadin.ui.Label", "com.vaadin.ui.Layout", + "com.vaadin.ui.Link", "com.vaadin.ui.ListSelect", + "com.vaadin.ui.LoginForm", "com.vaadin.ui.MenuBar", + "com.vaadin.ui.NativeButton", "com.vaadin.ui.NativeSelect", + "com.vaadin.ui.OptionGroup", "com.vaadin.ui.OrderedLayout", + "com.vaadin.ui.Panel", "com.vaadin.ui.PopupDateField", + "com.vaadin.ui.PopupView", "com.vaadin.ui.ProgressIndicator", + "com.vaadin.ui.RichTextArea", "com.vaadin.ui.Select", + "com.vaadin.ui.Slider", "com.vaadin.ui.SplitPanel", + "com.vaadin.ui.Table", "com.vaadin.ui.TableFieldFactory", + "com.vaadin.ui.TabSheet", "com.vaadin.ui.TextField", + "com.vaadin.ui.Tree", "com.vaadin.ui.TwinColSelect", + "com.vaadin.ui.Upload", "com.vaadin.ui.UriFragmentUtility", + "com.vaadin.ui.VerticalLayout", "com.vaadin.ui.Window", + "com.vaadin.util.SerializerHelper", "org.vaadin.test.LastClass" }; + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java new file mode 100644 index 0000000000..772cd250ce --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractHierarchicalContainerTest.java @@ -0,0 +1,256 @@ +package com.vaadin.data.util; + +import java.util.Collection; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Hierarchical; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; + +public abstract class AbstractHierarchicalContainerTest extends + AbstractContainerTest { + + /** + * @param container + * The container to validate + * @param expectedFirstItemId + * Expected first item id + * @param expectedLastItemId + * Expected last item id + * @param itemIdInSet + * An item id that is in the container + * @param itemIdNotInSet + * An item id that is not in the container + * @param checkGetItemNull + * true if getItem() should return null for itemIdNotInSet, false + * to skip the check (container.containsId() is checked in any + * case) + * @param expectedSize + * Expected number of items in the container. Not related to + * hierarchy. + * @param expectedTraversalSize + * Expected number of items found when traversing from the roots + * down to all available nodes. + * @param expectedRootSize + * Expected number of root items + * @param rootsHaveChildren + * true if all roots have children, false otherwise (skips some + * asserts) + */ + protected void validateHierarchicalContainer(Hierarchical container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize, int expectedRootSize, + boolean rootsHaveChildren) { + + validateContainer(container, expectedFirstItemId, expectedLastItemId, + itemIdInSet, itemIdNotInSet, checkGetItemNull, expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(expectedRootSize, rootIds.size()); + + for (Object rootId : rootIds) { + // All roots must be in container + assertTrue(container.containsId(rootId)); + + // All roots must have no parent + assertNull(container.getParent(rootId)); + + // all roots must be roots + assertTrue(container.isRoot(rootId)); + + if (rootsHaveChildren) { + // all roots have children allowed in this case + assertTrue(container.areChildrenAllowed(rootId)); + + // all roots have children in this case + Collection<?> children = container.getChildren(rootId); + assertNotNull(rootId + " should have children", children); + assertTrue(rootId + " should have children", + (children.size() > 0)); + // getParent + for (Object childId : children) { + assertEquals(container.getParent(childId), rootId); + } + + } + } + + // isRoot should return false for unknown items + assertFalse(container.isRoot(itemIdNotInSet)); + + // hasChildren should return false for unknown items + assertFalse(container.hasChildren(itemIdNotInSet)); + + // areChildrenAllowed should return false for unknown items + assertFalse(container.areChildrenAllowed(itemIdNotInSet)); + + // removeItem of unknown items should return false + assertFalse(container.removeItem(itemIdNotInSet)); + + assertEquals(expectedSize, countNodes(container)); + + validateHierarchy(container); + } + + private int countNodes(Hierarchical container) { + int totalNodes = 0; + for (Object rootId : container.rootItemIds()) { + totalNodes += countNodes(container, rootId); + } + + return totalNodes; + } + + private int countNodes(Hierarchical container, Object itemId) { + int nodes = 1; // This + Collection<?> children = container.getChildren(itemId); + if (children != null) { + for (Object id : children) { + nodes += countNodes(container, id); + } + } + + return nodes; + } + + private void validateHierarchy(Hierarchical container) { + for (Object rootId : container.rootItemIds()) { + validateHierarchy(container, rootId, null); + } + } + + private void validateHierarchy(Hierarchical container, Object itemId, + Object parentId) { + Collection<?> children = container.getChildren(itemId); + + // getParent + assertEquals(container.getParent(itemId), parentId); + + if (!container.areChildrenAllowed(itemId)) { + // If no children is allowed the item should have no children + assertFalse(container.hasChildren(itemId)); + assertTrue(children == null || children.size() == 0); + + return; + } + if (children != null) { + for (Object id : children) { + validateHierarchy(container, id, itemId); + } + } + } + + protected void testHierarchicalContainer(Container.Hierarchical container) { + initializeContainer(container); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void testHierarchicalSorting(Container.Hierarchical container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 and PROP2 for this test + assertTrue(sortable.getSortableContainerPropertyIds().contains( + FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds().contains( + REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateHierarchicalContainer(container, + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void initializeContainer(Container.Hierarchical container) { + container.removeAllItems(); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + + // Add path as parent + String paths[] = id.split("\\."); + String path = paths[0]; + // Adds "com" and other items multiple times so should return null + // for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME).setValue(getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + } + for (int j = 1; j < paths.length; j++) { + String parent = path; + path = path + "." + paths[j]; + + // Adds "com" and other items multiple times so should return + // null for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + + } + assertTrue(container.setChildrenAllowed(parent, true)); + assertTrue( + "Failed to set " + parent + " as parent for " + path, + container.setParent(path, parent)); + } + + Item item = container.getItem(id); + assertNotNull(item); + String parent = id.substring(0, id.lastIndexOf('.')); + assertTrue(container.setParent(id, parent)); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME).setValue( + getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME).setValue( + reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i % 2); + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java b/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java new file mode 100644 index 0000000000..bbad33c5bc --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/AbstractInMemoryContainerTest.java @@ -0,0 +1,6 @@ +package com.vaadin.data.util; + +public abstract class AbstractInMemoryContainerTest extends + AbstractContainerTest { + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java new file mode 100644 index 0000000000..9037e303a8 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanContainerTest.java @@ -0,0 +1,460 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import junit.framework.Assert; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.AbstractBeanContainer.BeanIdResolver; + +public class BeanContainerTest extends AbstractBeanContainerTest { + + protected static class PersonNameResolver implements + BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return bean != null ? bean.getName() : null; + } + + } + + protected static class NullResolver implements + BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return null; + } + + } + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanContainer<String, ClassName> getContainer() { + return new BeanContainer<String, ClassName>(ClassName.class); + } + + @Override + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanContainer<String, ClassName> beanItemContainer = (BeanContainer<String, ClassName>) container; + + beanItemContainer.removeAllItems(); + + for (Entry<String, ClassName> entry : nameToBean.entrySet()) { + beanItemContainer.addItem(entry.getKey(), entry.getValue()); + } + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + public void testSorting() { + testContainerSorting(getContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanContainer differs from other containers + public void testContainerOrdered() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + String id = "test1"; + + Item item = container.addItem(id, "value"); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId, "newFirstValue"); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId, + "newSecondValue"); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId, + "fourthValue"); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId, "fifthValue"); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + // TODO test Container.Indexed interface operation - testContainerIndexed()? + + public void testAddItemAt() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + container.addItem("id1", "value1"); + // id1 + container.addItemAt(0, "id2", "value2"); + // id2, id1 + container.addItemAt(1, "id3", "value3"); + // id2, id3, id1 + container.addItemAt(container.size(), "id4", "value4"); + // id2, id3, id1, id4 + + assertNull(container.addItemAt(-1, "id5", "value5")); + assertNull(container.addItemAt(container.size() + 1, "id6", "value6")); + + assertEquals(4, container.size()); + assertEquals("id2", container.getIdByIndex(0)); + assertEquals("id3", container.getIdByIndex(1)); + assertEquals("id1", container.getIdByIndex(2)); + assertEquals("id4", container.getIdByIndex(3)); + } + + public void testUnsupportedMethods() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.addItem("John", new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItem(null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(null, null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0, new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + public void testRemoveContainerProperty() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + container.addBean(new Person("John")); + + Assert.assertEquals("John", + container.getContainerProperty("John", "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty("John", "name")); + + Assert.assertNotNull(container.getItem("John")); + // property removed also from item + Assert.assertNull(container.getItem("John").getItemProperty("name")); + } + + public void testAddNullBeans() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.addItem("id1", null)); + assertNull(container.addItemAfter(null, "id2", null)); + assertNull(container.addItemAt(0, "id3", null)); + + assertEquals(0, container.size()); + } + + public void testAddNullId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + Person john = new Person("John"); + + assertNull(container.addItem(null, john)); + assertNull(container.addItemAfter(null, null, john)); + assertNull(container.addItemAt(0, null, john)); + + assertEquals(0, container.size()); + } + + public void testEmptyContainer() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.firstItemId()); + assertNull(container.lastItemId()); + + assertEquals(0, container.size()); + + // could test more about empty container + } + + public void testAddBeanWithoutResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container + .addAll(Arrays.asList(new Person[] { new Person("Jack") })); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + public void testAddAllWithNullItemId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container + .setBeanIdResolver(new BeanIdResolver<String, AbstractBeanContainerTest.Person>() { + + @Override + public String getIdForBean(Person bean) { + return bean.getName(); + } + }); + + List<Person> persons = new ArrayList<Person>(); + persons.add(new Person("John")); + persons.add(new Person("Marc")); + persons.add(new Person(null)); + persons.add(new Person("foo")); + + try { + container.addAll(persons); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + container.removeAllItems(); + persons.remove(2); + container.addAll(persons); + assertEquals(3, container.size()); + } + + public void testAddBeanWithNullResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container.setBeanIdResolver(new NullResolver()); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + public void testAddBeanWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList(new Person[] { new Person("Jill"), + new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + public void testAddNullBeansWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNull(container.addBean(null)); + assertNull(container.addBeanAfter(null, null)); + assertNull(container.addBeanAt(0, null)); + + assertEquals(0, container.size()); + } + + public void testAddBeanWithPropertyResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdProperty("name"); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList(new Person[] { new Person("Jill"), + new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + public void testAddNestedContainerProperty() { + BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + container.setBeanIdProperty("name"); + + container.addBean(new NestedMethodPropertyTest.Person("John", + new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540))); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", + container.getContainerProperty("John", "address.street") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java new file mode 100644 index 0000000000..38f317fef1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerSortTest.java @@ -0,0 +1,170 @@ +package com.vaadin.data.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.data.util.DefaultItemSorter; + +public class BeanItemContainerSortTest { + public class Person { + private String name; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + private int age; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public class Parent extends Person { + private Set<Person> children = new HashSet<Person>(); + + public void setChildren(Set<Person> children) { + this.children = children; + } + + public Set<Person> getChildren() { + return children; + } + } + + String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko", + "Pekka", "John" }; + int[] ages = new int[] { 10, 20, 50, 12, 64, 67 }; + String[] sortedByAge = new String[] { names[0], names[3], names[1], + names[2], names[4], names[5] }; + + public BeanItemContainer<Person> getContainer() { + BeanItemContainer<Person> bc = new BeanItemContainer<Person>( + Person.class); + for (int i = 0; i < names.length; i++) { + Person p = new Person(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + + } + + public BeanItemContainer<Parent> getParentContainer() { + BeanItemContainer<Parent> bc = new BeanItemContainer<Parent>( + Parent.class); + for (int i = 0; i < names.length; i++) { + Parent p = new Parent(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + } + + @Test + public void testSort() { + testSort(true); + } + + public void testSort(boolean b) { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "name" }, new boolean[] { b }); + + List<String> asList = Arrays.asList(names); + Collections.sort(asList); + if (!b) { + Collections.reverse(asList); + } + + int i = 0; + for (String string : asList) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testReverseSort() { + testSort(false); + } + + @Test + public void primitiveSorting() { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = 0; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void customSorting() { + BeanItemContainer<Person> container = getContainer(); + + // custom sorter using the reverse order + container.setItemSorter(new DefaultItemSorter() { + @Override + public int compare(Object o1, Object o2) { + return -super.compare(o1, o2); + } + }); + + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = container.size() - 1; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i--); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testGetSortableProperties() { + BeanItemContainer<Person> container = getContainer(); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + + @Test + public void testGetNonSortableProperties() { + BeanItemContainer<Parent> container = getParentContainer(); + + Assert.assertEquals(3, container.getContainerPropertyIds().size()); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java new file mode 100644 index 0000000000..29043b1670 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java @@ -0,0 +1,718 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItemContainer; + +/** + * Test basic functionality of BeanItemContainer. + * + * Most sorting related tests are in {@link BeanItemContainerSortTest}. + */ +public class BeanItemContainerTest extends AbstractBeanContainerTest { + + // basics from the common container test + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanItemContainer<ClassName> getContainer() { + return new BeanItemContainer<ClassName>(ClassName.class); + } + + @Override + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanItemContainer<ClassName> beanItemContainer = (BeanItemContainer<ClassName>) container; + + beanItemContainer.removeAllItems(); + + Iterator<ClassName> it = nameToBean.values().iterator(); + while (it.hasNext()) { + beanItemContainer.addBean(it.next()); + } + } + + @Override + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, + boolean checkGetItemNull, int expectedSize) { + Object notInSet = nameToBean.get(itemIdNotInSet); + if (notInSet == null && itemIdNotInSet != null) { + notInSet = new ClassName(String.valueOf(itemIdNotInSet), 9999); + } + super.validateContainer(container, nameToBean.get(expectedFirstItemId), + nameToBean.get(expectedLastItemId), + nameToBean.get(itemIdInSet), notInSet, checkGetItemNull, + expectedSize); + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + public void testSorting() { + testContainerSorting(getContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanItemContainer differs from other containers + public void testContainerOrdered() { + BeanItemContainer<String> container = new BeanItemContainer<String>( + String.class); + + String id = "test1"; + + Item item = container.addBean(id); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(Object) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(Object,Object) + Object fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + public void testContainerIndexed() { + testContainerIndexed(getContainer(), nameToBean.get(sampleData[2]), 2, + false, new ClassName("org.vaadin.test.Test", 8888), true); + } + + @SuppressWarnings("deprecation") + public void testCollectionConstructors() { + List<ClassName> classNames = new ArrayList<ClassName>(); + classNames.add(new ClassName("a.b.c.Def", 1)); + classNames.add(new ClassName("a.b.c.Fed", 2)); + classNames.add(new ClassName("b.c.d.Def", 3)); + + // note that this constructor is problematic, users should use the + // version that + // takes the bean class as a parameter + BeanItemContainer<ClassName> container = new BeanItemContainer<ClassName>( + classNames); + + Assert.assertEquals(3, container.size()); + Assert.assertEquals(classNames.get(0), container.firstItemId()); + Assert.assertEquals(classNames.get(1), container.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container.lastItemId()); + + BeanItemContainer<ClassName> container2 = new BeanItemContainer<ClassName>( + ClassName.class, classNames); + + Assert.assertEquals(3, container2.size()); + Assert.assertEquals(classNames.get(0), container2.firstItemId()); + Assert.assertEquals(classNames.get(1), container2.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container2.lastItemId()); + } + + // this only applies to the collection constructor with no type parameter + @SuppressWarnings("deprecation") + public void testEmptyCollectionConstructor() { + try { + new BeanItemContainer<ClassName>((Collection<ClassName>) null); + Assert.fail("Initializing BeanItemContainer from a null collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + try { + new BeanItemContainer<ClassName>(new ArrayList<ClassName>()); + Assert.fail("Initializing BeanItemContainer from an empty collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + } + + public void testItemSetChangeListeners() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + + initializeContainer(container); + counter.reset(); + container.addBean(cn1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + // no notification if already in container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + public void testItemSetChangeListenersFiltering() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + ClassName other = new ClassName("com.example.Other", 3333); + + // simply adding or removing container filters should cause event + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + + // perform operations while filtering container + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + counter.assertOnce(); + + // passes filter + container.addBean(cn1); + counter.assertOnce(); + + // passes filter but already in the container + container.addBean(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + + // passes filter + container.addItem(cn1); + counter.assertOnce(); + // already in the container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + // does not pass filter + container.addItem(other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals( + "com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + // does not pass filter + // note: testAddRemoveWhileFiltering() checks position for these after + // removing filter etc, here concentrating on listeners + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), other); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + container.removeItem(cn1); + counter.assertOnce(); + + // does not pass filter + + initializeContainer(container); + counter.reset(); + // not visible + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertNone(); + + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + + public void testAddRemoveWhileFiltering() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + Person william = new Person("William"); + Person julia = new Person("Julia"); + Person george = new Person("George"); + Person mark = new Person("Mark"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // add a bean that passes the filter + container.addBean(jack); + assertEquals(3, container.size()); + assertEquals(jack, container.lastItemId()); + // john, jane, (matthew), jack + + // add beans that do not pass the filter + container.addBean(michael); + // john, jane, (matthew), jack, (michael) + container.addItemAfter(null, william); + // (william), john, jane, (matthew), jack, (michael) + + // add after an item that is shown + container.addItemAfter(john, george); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + // add after an item that is not shown does nothing + container.addItemAfter(william, julia); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + container.addItemAt(1, julia); + // (william), john, julia, (george), jane, (matthew), jack, (michael) + + container.addItemAt(2, mark); + // (william), john, julia, (mark), (george), jane, (matthew), jack, + // (michael) + + container.removeItem(matthew); + // (william), john, julia, (mark), (george), jane, jack, (michael) + + assertEquals(4, container.size()); + assertEquals(jack, container.lastItemId()); + + container.removeContainerFilters("name"); + + assertEquals(8, container.size()); + assertEquals(william, container.firstItemId()); + assertEquals(john, container.nextItemId(william)); + assertEquals(julia, container.nextItemId(john)); + assertEquals(mark, container.nextItemId(julia)); + assertEquals(george, container.nextItemId(mark)); + assertEquals(jane, container.nextItemId(george)); + assertEquals(jack, container.nextItemId(jane)); + assertEquals(michael, container.lastItemId()); + } + + public void testRefilterOnPropertyModification() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // #6053 currently, modification of an item that is not visible does not + // trigger refiltering - should it? + // matthew.setName("Julia"); + // assertEquals(3, container.size()); + // john, jane, julia + + john.setName("Mark"); + assertEquals(2, container.size()); + // (mark), jane, julia + + container.removeAllContainerFilters(); + + assertEquals(3, container.size()); + } + + public void testAddAll() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + + // addAll + container.addAll(Arrays.asList(jack, michael)); + // john, jane, matthew, jack, michael + + assertEquals(5, container.size()); + assertEquals(jane, container.nextItemId(john)); + assertEquals(matthew, container.nextItemId(jane)); + assertEquals(jack, container.nextItemId(matthew)); + assertEquals(michael, container.nextItemId(jack)); + } + + public void testUnsupportedMethods() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + container.addBean(new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + public void testRemoveContainerProperty() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + Assert.assertEquals("John", container + .getContainerProperty(john, "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty(john, "name")); + + Assert.assertNotNull(container.getItem(john)); + // property removed also from item + Assert.assertNull(container.getItem(john).getItemProperty("name")); + } + + public void testAddNullBean() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + assertNull(container.addItem(null)); + assertNull(container.addItemAfter(null, null)); + assertNull(container.addItemAfter(john, null)); + assertNull(container.addItemAt(0, null)); + + assertEquals(1, container.size()); + } + + public void testBeanIdResolver() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + + assertSame(john, container.getBeanIdResolver().getIdForBean(john)); + } + + public void testNullBeanClass() { + try { + new BeanItemContainer<Object>((Class<Object>) null); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testAddNestedContainerProperty() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", + 20540)); + container.addBean(john); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", + container.getContainerProperty(john, "address.street") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/BeanItemTest.java b/server/tests/src/com/vaadin/data/util/BeanItemTest.java new file mode 100644 index 0000000000..e1ad75796c --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/BeanItemTest.java @@ -0,0 +1,333 @@ +package com.vaadin.data.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +/** + * Test BeanItem specific features. + * + * Only public API is tested, not the methods with package visibility. + * + * See also {@link PropertySetItemTest}, which tests the base class. + */ +public class BeanItemTest extends TestCase { + + @SuppressWarnings("unused") + protected static class MySuperClass { + private int superPrivate = 1; + private int superPrivate2 = 2; + protected double superProtected = 3.0; + private double superProtected2 = 4.0; + public boolean superPublic = true; + private boolean superPublic2 = true; + + public int getSuperPrivate() { + return superPrivate; + } + + public void setSuperPrivate(int superPrivate) { + this.superPrivate = superPrivate; + } + + public double getSuperProtected() { + return superProtected; + } + + public void setSuperProtected(double superProtected) { + this.superProtected = superProtected; + } + + public boolean isSuperPublic() { + return superPublic; + } + + public void setSuperPublic(boolean superPublic) { + this.superPublic = superPublic; + } + + } + + protected static class MyClass extends MySuperClass { + private String name; + public int value = 123; + + public MyClass(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setNoField(String name) { + } + + public String getNoField() { + return "no field backing this setter"; + } + + public String getName2() { + return name; + } + } + + protected static class MyClass2 extends MyClass { + public MyClass2(String name) { + super(name); + } + + @Override + public void setName(String name) { + super.setName(name + "2"); + } + + @Override + public String getName() { + return super.getName() + "2"; + } + + @Override + public String getName2() { + return super.getName(); + } + + public void setName2(String name) { + super.setName(name); + } + } + + protected static interface MySuperInterface { + public int getSuper1(); + + public void setSuper1(int i); + + public int getOverride(); + } + + protected static interface MySuperInterface2 { + public int getSuper2(); + } + + protected static interface MySubInterface extends MySuperInterface, + MySuperInterface2 { + public int getSub(); + + public void setSub(int i); + + @Override + public int getOverride(); + + public void setOverride(int i); + } + + public void testGetProperties() { + BeanItem<MySuperClass> item = new BeanItem<MySuperClass>( + new MySuperClass()); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(3, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + } + + public void testGetSuperClassProperties() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + Assert.assertTrue(itemPropertyIds.contains("name")); + Assert.assertTrue(itemPropertyIds.contains("noField")); + Assert.assertTrue(itemPropertyIds.contains("name2")); + } + + public void testOverridingProperties() { + BeanItem<MyClass2> item = new BeanItem<MyClass2>(new MyClass2("bean2")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + Assert.assertTrue(MyClass2.class.equals(item.getBean().getClass())); + + // check that name2 accessed via MyClass2, not MyClass + Assert.assertFalse(item.getItemProperty("name2").isReadOnly()); + } + + public void testGetInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class.getDeclaredMethod( + "getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySuperInterface.class); + + Assert.assertEquals(2, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertTrue(property.isReadOnly()); + } + + public void testGetSuperInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class.getDeclaredMethod( + "getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySubInterface.class); + + Assert.assertEquals(4, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("sub")); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("super2")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertFalse(property.isReadOnly()); + } + + public void testPropertyExplicitOrder() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name"); + ids.add("superPublic"); + ids.add("name2"); + ids.add("noField"); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testPropertyExplicitOrder2() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + new String[] { "name", "superPublic", "name2", "noField" }); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testPropertyBadPropertyName() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name3"); + ids.add("name"); + + // currently silently ignores non-existent properties + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertFalse(it.hasNext()); + } + + public void testRemoveProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("name2"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("name2")); + } + + public void testRemoveSuperProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("superPrivate"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("superPrivate")); + } + + public void testPropertyTypes() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertTrue(Integer.class.equals(item.getItemProperty( + "superPrivate").getType())); + Assert.assertTrue(Double.class.equals(item.getItemProperty( + "superProtected").getType())); + Assert.assertTrue(Boolean.class.equals(item.getItemProperty( + "superPublic").getType())); + Assert.assertTrue(String.class.equals(item.getItemProperty("name") + .getType())); + } + + public void testPropertyReadOnly() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertFalse(item.getItemProperty("name").isReadOnly()); + Assert.assertTrue(item.getItemProperty("name2").isReadOnly()); + } + + public void testCustomProperties() throws Exception { + LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>> propertyDescriptors = new LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>>(); + propertyDescriptors.put( + "myname", + new MethodPropertyDescriptor<BeanItemTest.MyClass>("myname", + MyClass.class, MyClass.class + .getDeclaredMethod("getName"), MyClass.class + .getDeclaredMethod("setName", String.class))); + MyClass instance = new MyClass("bean1"); + Constructor<BeanItem> constructor = BeanItem.class + .getDeclaredConstructor(Object.class, Map.class); + constructor.setAccessible(true); + BeanItem<MyClass> item = constructor.newInstance(instance, + propertyDescriptors); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + } + + public void testAddRemoveProperty() throws Exception { + MethodPropertyDescriptor<BeanItemTest.MyClass> pd = new MethodPropertyDescriptor<BeanItemTest.MyClass>( + "myname", MyClass.class, + MyClass.class.getDeclaredMethod("getName"), + MyClass.class.getDeclaredMethod("setName", String.class)); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + + item.addItemProperty("myname", pd.createProperty(item.getBean())); + Assert.assertEquals(7, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + item.removeItemProperty("myname"); + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java b/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java new file mode 100644 index 0000000000..f4bb794e5c --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/FileSystemContainerTest.java @@ -0,0 +1,16 @@ +package com.vaadin.data.util; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Test; + +public class FileSystemContainerTest { + + @Test + public void nonExistingDirectory() { + FilesystemContainer fsc = new FilesystemContainer(new File( + "/non/existing")); + Assert.assertTrue(fsc.getItemIds().isEmpty()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java new file mode 100644 index 0000000000..640ede8743 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/NestedMethodPropertyTest.java @@ -0,0 +1,327 @@ +package com.vaadin.data.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class NestedMethodPropertyTest extends TestCase { + + public static class Address implements Serializable { + private String street; + private int postalCodePrimitive; + private Integer postalCodeObject; + + public Address(String street, int postalCode) { + this.street = street; + postalCodePrimitive = postalCode; + postalCodeObject = postalCode; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getStreet() { + return street; + } + + public void setPostalCodePrimitive(int postalCodePrimitive) { + this.postalCodePrimitive = postalCodePrimitive; + } + + public int getPostalCodePrimitive() { + return postalCodePrimitive; + } + + public void setPostalCodeObject(Integer postalCodeObject) { + this.postalCodeObject = postalCodeObject; + } + + public Integer getPostalCodeObject() { + return postalCodeObject; + } + + // read-only boolean property + public boolean isBoolean() { + return true; + } + } + + public static class Person implements Serializable { + private String name; + private Address address; + + public Person(String name, Address address) { + this.name = name; + this.address = address; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Address getAddress() { + return address; + } + } + + public static class Team implements Serializable { + private String name; + private Person manager; + + public Team(String name, Person manager) { + this.name = name; + this.manager = manager; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setManager(Person manager) { + this.manager = manager; + } + + public Person getManager() { + return manager; + } + } + + private Address oldMill; + private Person joonas; + private Team vaadin; + + @Override + public void setUp() { + oldMill = new Address("Ruukinkatu 2-4", 20540); + joonas = new Person("Joonas", oldMill); + vaadin = new Team("Vaadin", joonas); + } + + @Override + public void tearDown() { + vaadin = null; + joonas = null; + oldMill = null; + } + + public void testSingleLevelNestedSimpleProperty() { + NestedMethodProperty<String> nameProperty = new NestedMethodProperty<String>( + vaadin, "name"); + + Assert.assertEquals(String.class, nameProperty.getType()); + Assert.assertEquals("Vaadin", nameProperty.getValue()); + } + + public void testSingleLevelNestedObjectProperty() { + NestedMethodProperty<Person> managerProperty = new NestedMethodProperty<Person>( + vaadin, "manager"); + + Assert.assertEquals(Person.class, managerProperty.getType()); + Assert.assertEquals(joonas, managerProperty.getValue()); + } + + public void testMultiLevelNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertEquals(String.class, managerNameProperty.getType()); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + + Assert.assertEquals(Address.class, addressProperty.getType()); + Assert.assertEquals(oldMill, addressProperty.getValue()); + + Assert.assertEquals(String.class, streetProperty.getType()); + Assert.assertEquals("Ruukinkatu 2-4", streetProperty.getValue()); + + Assert.assertEquals(Integer.class, + postalCodePrimitiveProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodePrimitiveProperty.getValue()); + + Assert.assertEquals(Integer.class, postalCodeObjectProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodeObjectProperty.getValue()); + + Assert.assertEquals(Boolean.class, booleanProperty.getType()); + Assert.assertEquals(Boolean.TRUE, booleanProperty.getValue()); + } + + public void testEmptyPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, ""); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, " "); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testInvalidPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, ".manager"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager..name"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testInvalidNestedPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "member"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.pet"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.address.city"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + public void testNullNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + + joonas.setAddress(null); + try { + streetProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + + vaadin.setManager(null); + try { + managerNameProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + try { + streetProperty.getValue(); + fail(); + } catch (Exception e) { + // should get exception + } + + vaadin.setManager(joonas); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + } + + public void testMultiLevelNestedPropertySetValue() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + + managerNameProperty.setValue("Joonas L"); + Assert.assertEquals("Joonas L", joonas.getName()); + streetProperty.setValue("Ruukinkatu"); + Assert.assertEquals("Ruukinkatu", oldMill.getStreet()); + postalCodePrimitiveProperty.setValue(0); + postalCodeObjectProperty.setValue(1); + Assert.assertEquals(0, oldMill.getPostalCodePrimitive()); + Assert.assertEquals(Integer.valueOf(1), oldMill.getPostalCodeObject()); + + postalCodeObjectProperty.setValue(null); + Assert.assertNull(oldMill.getPostalCodeObject()); + + Address address2 = new Address("Other street", 12345); + addressProperty.setValue(address2); + Assert.assertEquals("Other street", streetProperty.getValue()); + } + + public void testSerialization() throws IOException, ClassNotFoundException { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(streetProperty); + @SuppressWarnings("unchecked") + NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Assert.assertEquals("Ruukinkatu 2-4", property2.getValue()); + } + + public void testIsReadOnly() { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertFalse(streetProperty.isReadOnly()); + Assert.assertTrue(booleanProperty.isReadOnly()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java b/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java new file mode 100644 index 0000000000..99ca58ba42 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/ObjectPropertyTest.java @@ -0,0 +1,97 @@ +package com.vaadin.data.util; + +import junit.framework.TestCase; + +import org.junit.Assert; + +public class ObjectPropertyTest extends TestCase { + + public static class TestSuperClass { + private String name; + + public TestSuperClass(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return getName(); + } + } + + public static class TestSubClass extends TestSuperClass { + public TestSubClass(String name) { + super("Subclass: " + name); + } + } + + private TestSuperClass super1 = new TestSuperClass("super1"); + private TestSubClass sub1 = new TestSubClass("sub1"); + + public void testSimple() { + ObjectProperty<TestSuperClass> prop1 = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop1.getValue().getName()); + prop1 = new ObjectProperty<TestSuperClass>(super1); + Assert.assertEquals("super1", prop1.getValue().getName()); + + ObjectProperty<TestSubClass> prop2 = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + prop2 = new ObjectProperty<TestSubClass>(sub1); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + } + + public void testSetValueObjectSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + public void testSetValueObjectSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + public void testSetValueStringSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + public void testSetValueStringSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + public void testMixedGenerics() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + sub1); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + Assert.assertEquals(prop.getType(), TestSubClass.class); + // create correct subclass based on the runtime type of the instance + // given to ObjectProperty constructor, which is a subclass of the type + // parameter + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java new file mode 100644 index 0000000000..c4ed12efc0 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PerformanceTestIndexedContainer.java @@ -0,0 +1,117 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.util.IndexedContainer; + +public class PerformanceTestIndexedContainer extends TestCase { + + private static final int REPEATS = 10; + private final static int ITEMS = 50000; + private static final long ADD_ITEM_FAIL_THRESHOLD = 200; + // TODO should improve performance of these methods + private static final long ADD_ITEM_AT_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD = 200; + + public void testAddItemPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItem(); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItem()", + ADD_ITEM_FAIL_THRESHOLD); + } + + public void testAddItemAtPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAt(0); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAt()", + ADD_ITEM_AT_FAIL_THRESHOLD); + } + + public void testAddItemAfterPerformance() { + Object initialId = "Item0"; + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(initialId); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAfter(initialId); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAfter()", + ADD_ITEM_AFTER_FAIL_THRESHOLD); + } + + public void testAddItemAfterLastPerformance() { + // TODO running with less items because slow otherwise + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS / 3; i++) { + c.addItemAfter(c.lastItemId()); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS / 3, times, "IndexedContainer.addItemAfter(lastId)", + ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD); + } + + public void testAddItemsConstructorPerformance() { + Collection<Object> items = new ArrayList<Object>(50000); + for (int i = 0; i < ITEMS; ++i) { + items.add(new Object()); + } + + SortedSet<Long> times = new TreeSet<Long>(); + for (int j = 0; j < REPEATS; ++j) { + long start = System.currentTimeMillis(); + new IndexedContainer(items); + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer(Collection)", + ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD); + } + + private void checkMedian(int items, Collection<Long> times, + String methodName, long threshold) { + long median = median(times); + System.out.println(methodName + " timings (ms) for " + items + + " items: " + times); + Assert.assertTrue(methodName + " too slow, median time " + median + + "ms for " + items + " items", median <= threshold); + } + + private Long median(Collection<Long> times) { + ArrayList<Long> list = new ArrayList<Long>(times); + Collections.sort(list); + // not exact median in some cases, but good enough + return list.get(list.size() / 2); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java new file mode 100644 index 0000000000..14e70d76d4 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PropertyDescriptorTest.java @@ -0,0 +1,55 @@ +package com.vaadin.data.util; + +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.Property; +import com.vaadin.data.util.NestedMethodPropertyTest.Person; + +public class PropertyDescriptorTest extends TestCase { + public void testMethodPropertyDescriptorSerialization() throws Exception { + PropertyDescriptor[] pds = Introspector.getBeanInfo(Person.class) + .getPropertyDescriptors(); + + MethodPropertyDescriptor<Person> descriptor = null; + + for (PropertyDescriptor pd : pds) { + if ("name".equals(pd.getName())) { + descriptor = new MethodPropertyDescriptor<Person>(pd.getName(), + String.class, pd.getReadMethod(), pd.getWriteMethod()); + break; + } + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(descriptor); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> descriptor2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = descriptor2.createProperty(new Person("John", + null)); + Assert.assertEquals("John", property.getValue()); + } + + public void testNestedPropertyDescriptorSerialization() throws Exception { + NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>( + "name", Person.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(pd); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = pd2.createProperty(new Person("John", null)); + Assert.assertEquals("John", property.getValue()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java b/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java new file mode 100644 index 0000000000..a3169332ec --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/PropertySetItemTest.java @@ -0,0 +1,405 @@ +package com.vaadin.data.util; + +import java.util.Iterator; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.data.Item.PropertySetChangeEvent; +import com.vaadin.data.Item.PropertySetChangeListener; + +public class PropertySetItemTest extends TestCase { + + private static final String ID1 = "id1"; + private static final String ID2 = "id2"; + private static final String ID3 = "id3"; + + private static final String VALUE1 = "value1"; + private static final String VALUE2 = "value2"; + private static final String VALUE3 = "value3"; + + private ObjectProperty<String> prop1; + private ObjectProperty<String> prop2; + private ObjectProperty<String> prop3; + + private PropertySetChangeListener propertySetListenerMock; + private PropertySetChangeListener propertySetListenerMock2; + + @Override + protected void setUp() throws Exception { + prop1 = new ObjectProperty<String>(VALUE1, String.class); + prop2 = new ObjectProperty<String>(VALUE2, String.class); + prop3 = new ObjectProperty<String>(VALUE3, String.class); + + propertySetListenerMock = EasyMock + .createStrictMock(PropertySetChangeListener.class); + propertySetListenerMock2 = EasyMock + .createMock(PropertySetChangeListener.class); + } + + @Override + protected void tearDown() throws Exception { + prop1 = null; + prop2 = null; + prop3 = null; + + propertySetListenerMock = null; + propertySetListenerMock2 = null; + } + + private PropertysetItem createPropertySetItem() { + return new PropertysetItem(); + } + + public void testEmptyItem() { + PropertysetItem item = createPropertySetItem(); + Assert.assertNotNull(item.getItemPropertyIds()); + Assert.assertEquals(0, item.getItemPropertyIds().size()); + } + + public void testGetProperty() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertNull(item.getItemProperty(ID1)); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertNull(item.getItemProperty(ID2)); + } + + public void testAddSingleProperty() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Object firstValue = item.getItemPropertyIds().iterator().next(); + Assert.assertEquals(ID1, firstValue); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testAddMultipleProperties() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + item.addItemProperty(ID2, prop2); + Assert.assertEquals(2, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertEquals(prop2, item.getItemProperty(ID2)); + + item.addItemProperty(ID3, prop3); + Assert.assertEquals(3, item.getItemPropertyIds().size()); + } + + public void testAddedPropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID2, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + public void testAddPropertyTwice() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + Assert.assertFalse(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testCannotChangeProperty() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + Assert.assertFalse(item.addItemProperty(ID1, prop2)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + public void testRemoveProperty() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.removeItemProperty(ID1); + + Assert.assertEquals(0, item.getItemPropertyIds().size()); + Assert.assertNull(item.getItemProperty(ID1)); + } + + public void testRemovePropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + item.removeItemProperty(ID2); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + public void testRemoveNonExistentListener() { + PropertysetItem item = createPropertySetItem(); + item.removeListener(propertySetListenerMock); + } + + public void testRemoveListenerTwice() { + PropertysetItem item = createPropertySetItem(); + item.addListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + } + + public void testAddPropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange(EasyMock + .isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.addItemProperty(ID1, prop1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener when adding a + // property + item.removeListener(propertySetListenerMock); + item.addItemProperty(ID2, prop2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + public void testRemovePropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange(EasyMock + .isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.removeItemProperty(ID1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener + item.removeListener(propertySetListenerMock); + item.removeItemProperty(ID2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + public void testItemEqualsNull() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertFalse(item.equals(null)); + } + + public void testEmptyItemEquals() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertTrue(item1.equals(item2)); + } + + public void testItemEqualsSingleProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + PropertysetItem item4 = createPropertySetItem(); + item4.addItemProperty(ID1, prop2); + PropertysetItem item5 = createPropertySetItem(); + item5.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item1.equals(item3)); + Assert.assertFalse(item1.equals(item4)); + Assert.assertFalse(item1.equals(item5)); + + Assert.assertTrue(item2.equals(item3)); + Assert.assertFalse(item2.equals(item4)); + Assert.assertFalse(item2.equals(item5)); + + Assert.assertFalse(item3.equals(item4)); + Assert.assertFalse(item3.equals(item5)); + + Assert.assertFalse(item4.equals(item5)); + + Assert.assertFalse(item2.equals(item1)); + } + + public void testItemEqualsMultipleProperties() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + item3.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + + Assert.assertTrue(item2.equals(item3)); + } + + public void testItemEqualsPropertyOrder() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID2, prop2); + item2.addItemProperty(ID1, prop1); + + Assert.assertFalse(item1.equals(item2)); + } + + public void testEqualsSingleListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testEqualsMultipleListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.addListener(propertySetListenerMock2); + + item2.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock2); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testEqualsAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + public void testItemHashCodeEmpty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddProperties() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + // hashCodes can be equal even if items are different + + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addListener(propertySetListenerMock); + // hashCodes can be equal even if items are different + + item2.addListener(propertySetListenerMock); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddRemoveProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addItemProperty(ID1, prop1); + item1.removeItemProperty(ID1); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testItemHashCodeAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + public void testToString() { + // toString() behavior is specified in the class javadoc + PropertysetItem item = createPropertySetItem(); + + Assert.assertEquals("", item.toString()); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(String.valueOf(prop1.getValue()), item.toString()); + + item.addItemProperty(ID2, prop2); + + Assert.assertEquals( + String.valueOf(prop1.getValue()) + " " + + String.valueOf(prop2.getValue()), item.toString()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java b/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java new file mode 100644 index 0000000000..ff6de50651 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestContainerHierarchicalWrapper.java @@ -0,0 +1,42 @@ +package com.vaadin.data.util; + +import java.util.Collection; + +public class TestContainerHierarchicalWrapper extends + AbstractHierarchicalContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + public void testHierarchicalContainer() { + testHierarchicalContainer(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + public void testRemoveSubtree() { + testRemoveHierarchicalWrapperSubtree(new ContainerHierarchicalWrapper( + new IndexedContainer())); + } + + protected void testRemoveHierarchicalWrapperSubtree( + ContainerHierarchicalWrapper container) { + initializeContainer(container); + + // remove root item + container.removeItemRecursively("org"); + + int packages = 21 + 3 - 3; + int expectedSize = sampleData.length + packages - 1; + + validateContainer(container, "com", "com.vaadin.util.SerializerHelper", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(1, rootIds.size()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestContainerSorting.java b/server/tests/src/com/vaadin/data/util/TestContainerSorting.java new file mode 100644 index 0000000000..497699605a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestContainerSorting.java @@ -0,0 +1,224 @@ +package com.vaadin.data.util; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.tests.util.TestUtil; + +public class TestContainerSorting extends TestCase { + + private static final String ITEM_DATA_MINUS2_NULL = "Data -2 null"; + private static final String ITEM_DATA_MINUS2 = "Data -2"; + private static final String ITEM_DATA_MINUS1 = "Data -1"; + private static final String ITEM_DATA_MINUS1_NULL = "Data -1 null"; + private static final String ITEM_ANOTHER_NULL = "Another null"; + private static final String ITEM_STRING_2 = "String 2"; + private static final String ITEM_STRING_NULL2 = "String null"; + private static final String ITEM_STRING_1 = "String 1"; + + private static final String PROPERTY_INTEGER_NULL2 = "integer-null"; + private static final String PROPERTY_INTEGER_NOT_NULL = "integer-not-null"; + private static final String PROPERTY_STRING_NULL = "string-null"; + private static final String PROPERTY_STRING_ID = "string-not-null"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testEmptyFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "aasdfasdfasdf", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + + } + + public void testFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "a", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, + new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS2_NULL, }); + } + + public void testIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_STRING_1, ITEM_STRING_2, ITEM_STRING_NULL2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, new boolean[] { + true, false, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_DATA_MINUS1, ITEM_DATA_MINUS1_NULL, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, new boolean[] { + true, true, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS1, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + } + + public void testHierarchicalContainer() { + HierarchicalContainer hc = new HierarchicalContainer(); + populateContainer(hc); + hc.sort(new Object[] { "name" }, new boolean[] { true }); + verifyOrder(hc, new String[] { "Audi", "C++", "Call of Duty", "Cars", + "English", "Fallout", "Finnish", "Ford", "Games", "Java", + "Might and Magic", "Natural languages", "PHP", + "Programming languages", "Python", "Red Alert", "Swedish", + "Toyota", "Volvo" }); + TestUtil.assertArrays( + hc.rootItemIds().toArray(), + new Integer[] { nameToId.get("Cars"), nameToId.get("Games"), + nameToId.get("Natural languages"), + nameToId.get("Programming languages") }); + TestUtil.assertArrays( + hc.getChildren(nameToId.get("Games")).toArray(), + new Integer[] { nameToId.get("Call of Duty"), + nameToId.get("Fallout"), + nameToId.get("Might and Magic"), + nameToId.get("Red Alert") }); + } + + private static void populateContainer(HierarchicalContainer container) { + container.addContainerProperty("name", String.class, null); + + addItem(container, "Games", null); + addItem(container, "Call of Duty", "Games"); + addItem(container, "Might and Magic", "Games"); + addItem(container, "Fallout", "Games"); + addItem(container, "Red Alert", "Games"); + + addItem(container, "Cars", null); + addItem(container, "Toyota", "Cars"); + addItem(container, "Volvo", "Cars"); + addItem(container, "Audi", "Cars"); + addItem(container, "Ford", "Cars"); + + addItem(container, "Natural languages", null); + addItem(container, "Swedish", "Natural languages"); + addItem(container, "English", "Natural languages"); + addItem(container, "Finnish", "Natural languages"); + + addItem(container, "Programming languages", null); + addItem(container, "C++", "Programming languages"); + addItem(container, "PHP", "Programming languages"); + addItem(container, "Java", "Programming languages"); + addItem(container, "Python", "Programming languages"); + + } + + private static int index = 0; + private static Map<String, Integer> nameToId = new HashMap<String, Integer>(); + private static Map<Integer, String> idToName = new HashMap<Integer, String>(); + + public static void addItem(IndexedContainer container, String string, + String parent) { + nameToId.put(string, index); + idToName.put(index, string); + + Item item = container.addItem(index); + item.getItemProperty("name").setValue(string); + + if (parent != null && container instanceof HierarchicalContainer) { + ((HierarchicalContainer) container).setParent(index, + nameToId.get(parent)); + } + + index++; + } + + private void verifyOrder(Container.Sortable ic, Object[] idOrder) { + int size = ic.size(); + Object[] actual = new Object[size]; + Iterator<?> i = ic.getItemIds().iterator(); + int index = 0; + while (i.hasNext()) { + Object o = i.next(); + if (o.getClass() == Integer.class + && idOrder[index].getClass() == String.class) { + o = idToName.get(o); + } + actual[index++] = o; + } + + TestUtil.assertArrays(actual, idOrder); + + } + + private void populate(IndexedContainer ic) { + addItem(ic, ITEM_STRING_1, ITEM_STRING_1, 1, 1); + addItem(ic, ITEM_STRING_NULL2, null, 0, null); + addItem(ic, ITEM_STRING_2, ITEM_STRING_2, 2, 2); + addItem(ic, ITEM_ANOTHER_NULL, null, 0, null); + addItem(ic, ITEM_DATA_MINUS1, ITEM_DATA_MINUS1, -1, -1); + addItem(ic, ITEM_DATA_MINUS1_NULL, null, -1, null); + addItem(ic, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2, -2, -2); + addItem(ic, ITEM_DATA_MINUS2_NULL, null, -2, null); + } + + private Item addItem(Container ic, String id, String string_null, + int integer, Integer integer_null) { + Item i = ic.addItem(id); + i.getItemProperty(PROPERTY_STRING_ID).setValue(id); + i.getItemProperty(PROPERTY_STRING_NULL).setValue(string_null); + i.getItemProperty(PROPERTY_INTEGER_NOT_NULL).setValue(integer); + i.getItemProperty(PROPERTY_INTEGER_NULL2).setValue(integer_null); + + return i; + } + + private void addProperties(IndexedContainer ic) { + ic.addContainerProperty("id", String.class, null); + ic.addContainerProperty(PROPERTY_STRING_ID, String.class, ""); + ic.addContainerProperty(PROPERTY_STRING_NULL, String.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NULL2, Integer.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NOT_NULL, Integer.class, 0); + ic.addContainerProperty("comparable-null", Integer.class, 0); + } + + public class MyObject implements Comparable<MyObject> { + private String data; + + @Override + public int compareTo(MyObject o) { + if (o == null) { + return 1; + } + + if (o.data == null) { + return data == null ? 0 : 1; + } else if (data == null) { + return -1; + } else { + return data.compareTo(o.data); + } + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java b/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java new file mode 100644 index 0000000000..10bc71c3a7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestHierarchicalContainer.java @@ -0,0 +1,263 @@ +package com.vaadin.data.util; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; + +public class TestHierarchicalContainer extends + AbstractHierarchicalContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new HierarchicalContainer()); + } + + public void testFiltering() { + testContainerFiltering(new HierarchicalContainer()); + } + + public void testSorting() { + testContainerSorting(new HierarchicalContainer()); + } + + public void testOrdered() { + testContainerOrdered(new HierarchicalContainer()); + } + + public void testHierarchicalSorting() { + testHierarchicalSorting(new HierarchicalContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new HierarchicalContainer()); + } + + public void testRemovingItemsFromFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + + container.removeItem("com.vaadin.ui.TabSheet"); + // Parent for the removed item must be null because the item is no + // longer in the container + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull("Parent should be null, is " + p1, p1); + + container.removeAllItems(); + p1 = container.getParent("com.vaadin.client.Focusable"); + assertNull("Parent should be null, is " + p1, p1); + + } + + public void testParentWhenRemovingFilterFromContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + p1 = container.getParent("com.vaadin.client.ui.VPopupCalendar"); + assertNull(p1); + container.removeAllContainerFilters(); + p1 = container.getParent("com.vaadin.client.ui.VPopupCalendar"); + assertEquals("com.vaadin.client.ui", p1); + + } + + public void testChangeParentInFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Tab", false, false); + + // Change parent of filtered item + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + container.setParent("com.vaadin.ui.TabSheet", "com.vaadin"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin", p1); + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + container.setParent("com.vaadin.ui.TabSheet", null); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull(p1); + + // root -> non-root + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + + } + + public void testHierarchicalFilteringWithParents() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + + // Filter by "contains ab" + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + + // 20 items match the filters and the have 8 parents that should also be + // included + // only one root "com" should exist + // filtered + int expectedSize = 29; + int expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.ui.TabSheet", "com.vaadin.client.Focusable", + "blah", true, expectedSize, expectedRoots, true); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 6; + int classes = 112; + + expectedSize = packages + classes; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.client.WidgetSet", + "com.vaadin.client.ui.VSplitPanelVertical", "blah", true, + expectedSize, expectedRoots, true); + + // Additionally remove all without 'm' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "m", false, false); + + expectedSize = 7 + 18; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.client.ui.VUriFragmentUtility", + "com.vaadin.client.ui.layout.ChildComponentContainer", "blah", + true, expectedSize, expectedRoots, true); + + } + + public void testRemoveLastChild() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + c.removeItem("child"); + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + public void testRemoveLastChildFromFiltered() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + // Dummy filter that does not remove any items + c.addContainerFilter(new Filter() { + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return true; + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return true; + } + }); + c.removeItem("child"); + + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + public void testHierarchicalFilteringWithoutParents() { + HierarchicalContainer container = new HierarchicalContainer(); + + initializeContainer(container); + container.setIncludeParentsWhenFiltering(false); + + // Filter by "contains ab" + container.addContainerFilter(SIMPLE_NAME, "ab", false, false); + + // 20 items match the filter. + // com.vaadin.data.BufferedValidatable + // com.vaadin.data.Validatable + // com.vaadin.client.Focusable + // com.vaadin.client.Paintable + // com.vaadin.client.ui.Table + // com.vaadin.client.ui.VLabel + // com.vaadin.client.ui.VScrollTable + // com.vaadin.client.ui.VTablePaging + // com.vaadin.client.ui.VTabsheet + // com.vaadin.client.ui.VTabsheetBase + // com.vaadin.client.ui.VTabsheetPanel + // com.vaadin.server.ChangeVariablesErrorEvent + // com.vaadin.server.Paintable + // com.vaadin.server.Scrollable + // com.vaadin.server.Sizeable + // com.vaadin.server.VariableOwner + // com.vaadin.ui.Label + // com.vaadin.ui.Table + // com.vaadin.ui.TableFieldFactory + // com.vaadin.ui.TabSheet + // all become roots. + int expectedSize = 20; + int expectedRoots = 20; + + validateHierarchicalContainer(container, + "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TabSheet", "com.vaadin.client.ui.VTabsheetBase", + "blah", true, expectedSize, expectedRoots, false); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 3; + int classes = 110; + + expectedSize = packages + classes; + expectedRoots = 35 + 1; // com.vaadin.client.ui + + // com.vaadin.client.* + + // Sorting is case insensitive + validateHierarchicalContainer(container, + "com.vaadin.client.ApplicationConfiguration", + "com.vaadin.client.WidgetSet", + "com.vaadin.client.ui.VOptionGroup", "blah", true, + expectedSize, expectedRoots, false); + + // Additionally remove all without 'P' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "P", false, false); + + expectedSize = 13; + expectedRoots = expectedSize; + + validateHierarchicalContainer(container, "com.vaadin.client.Paintable", + "com.vaadin.client.ui.VTabsheetPanel", + "com.vaadin.client.ui.VPopupCalendar", "blah", true, + expectedSize, expectedRoots, false); + + } +} diff --git a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java new file mode 100644 index 0000000000..156ff83883 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java @@ -0,0 +1,271 @@ +package com.vaadin.data.util; + +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; + +public class TestIndexedContainer extends AbstractInMemoryContainerTest { + + public void testBasicOperations() { + testBasicContainerOperations(new IndexedContainer()); + } + + public void testFiltering() { + testContainerFiltering(new IndexedContainer()); + } + + public void testSorting() { + testContainerSorting(new IndexedContainer()); + } + + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new IndexedContainer()); + } + + public void testContainerOrdered() { + testContainerOrdered(new IndexedContainer()); + } + + public void testContainerIndexed() { + testContainerIndexed(new IndexedContainer(), sampleData[2], 2, true, + "newItemId", true); + } + + public void testItemSetChangeListeners() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + String id1 = "id1"; + String id2 = "id2"; + String id3 = "id3"; + + initializeContainer(container); + counter.reset(); + container.addItem(); + counter.assertOnce(); + container.addItem(id1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0); + counter.assertOnce(); + container.addItemAt(0, id1); + counter.assertOnce(); + container.addItemAt(0, id2); + counter.assertOnce(); + container.addItemAt(container.size(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAt(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null); + counter.assertOnce(); + container.addItemAfter(null, id1); + counter.assertOnce(); + container.addItemAfter(id1); + counter.assertOnce(); + container.addItemAfter(id1, id2); + counter.assertOnce(); + container.addItemAfter(container.firstItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAfter(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeItem(sampleData[0]); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + public void testAddRemoveContainerFilter() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + // simply adding or removing container filters should cause events + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + } + + // TODO other tests should check positions after removing filter etc, + // here concentrating on listeners + public void testItemSetChangeListenersFiltering() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + // no real change, so no notification required + counter.assertNone(); + + String id1 = "com.example.Test1"; + String id2 = "com.example.Test2"; + String id3 = "com.example.Other"; + + // perform operations while filtering container + + Item item; + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItem(id1); + // no event if filtered out + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter after change + item = container.addItemAt(0, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAt(0, id1); + counter.assertNone(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItemAfter(null, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAfter(null, id1); + counter.assertNone(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + + // does not pass filter + + // TODO implement rest + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(null, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.firstItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.lastItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(0, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(1, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(container.size(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + item = container.addItem(id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + container.removeItem(id1); + counter.assertOnce(); + // already removed + container.removeItem(id1); + counter.assertNone(); + + item = container.addItem(id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + // not visible + container.removeItem(id3); + counter.assertNone(); + + // remove all + + initializeContainer(container); + item = container.addItem(id1); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java new file mode 100644 index 0000000000..6f96c3a51a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/AbstractFilterTest.java @@ -0,0 +1,97 @@ +package com.vaadin.data.util.filter; + +import junit.framework.TestCase; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; + +public abstract class AbstractFilterTest<FILTERTYPE extends Filter> extends + TestCase { + + protected static final String PROPERTY1 = "property1"; + protected static final String PROPERTY2 = "property2"; + + protected static class TestItem<T1, T2> extends PropertysetItem { + + public TestItem(T1 value1, T2 value2) { + addItemProperty(PROPERTY1, new ObjectProperty<T1>(value1)); + addItemProperty(PROPERTY2, new ObjectProperty<T2>(value2)); + } + } + + protected static class NullProperty implements Property<String> { + + @Override + public String getValue() { + return null; + } + + @Override + public void setValue(Object newValue) throws ReadOnlyException { + throw new ReadOnlyException(); + } + + @Override + public Class<String> getType() { + return String.class; + } + + @Override + public boolean isReadOnly() { + return true; + } + + @Override + public void setReadOnly(boolean newStatus) { + // do nothing + } + + } + + public static class SameItemFilter implements Filter { + + private final Item item; + private final Object propertyId; + + public SameItemFilter(Item item) { + this(item, ""); + } + + public SameItemFilter(Item item, Object propertyId) { + this.item = item; + this.propertyId = propertyId; + } + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return this.item == item; + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return this.propertyId != null ? this.propertyId.equals(propertyId) + : true; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + SameItemFilter other = (SameItemFilter) obj; + return item == other.item + && (propertyId == null ? other.propertyId == null + : propertyId.equals(other.propertyId)); + } + + @Override + public int hashCode() { + return item.hashCode(); + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java new file mode 100644 index 0000000000..fdd5b8a645 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/AndOrFilterTest.java @@ -0,0 +1,232 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; + +public class AndOrFilterTest extends AbstractFilterTest<AbstractJunctionFilter> { + + protected Item item1 = new BeanItem<Integer>(1); + protected Item item2 = new BeanItem<Integer>(2); + + public void testNoFilterAnd() { + Filter filter = new And(); + + Assert.assertTrue(filter.passesFilter(null, item1)); + } + + public void testSingleFilterAnd() { + Filter filter = new And(new SameItemFilter(item1)); + + Assert.assertTrue(filter.passesFilter(null, item1)); + Assert.assertFalse(filter.passesFilter(null, item2)); + } + + public void testTwoFilterAnd() { + Filter filter1 = new And(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2 = new And(new SameItemFilter(item1), new SameItemFilter( + item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertFalse(filter2.passesFilter(null, item2)); + } + + public void testThreeFilterAnd() { + Filter filter1 = new And(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item1)); + Filter filter2 = new And(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertFalse(filter2.passesFilter(null, item2)); + } + + public void testNoFilterOr() { + Filter filter = new Or(); + + Assert.assertFalse(filter.passesFilter(null, item1)); + } + + public void testSingleFilterOr() { + Filter filter = new Or(new SameItemFilter(item1)); + + Assert.assertTrue(filter.passesFilter(null, item1)); + Assert.assertFalse(filter.passesFilter(null, item2)); + } + + public void testTwoFilterOr() { + Filter filter1 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2 = new Or(new SameItemFilter(item1), new SameItemFilter( + item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertTrue(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testThreeFilterOr() { + Filter filter1 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item1)); + Filter filter2 = new Or(new SameItemFilter(item1), new SameItemFilter( + item1), new SameItemFilter(item2)); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + + Assert.assertTrue(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testAndEqualsHashCode() { + Filter filter0 = new And(); + Filter filter0b = new And(); + Filter filter1a = new And(new SameItemFilter(item1)); + Filter filter1a2 = new And(new SameItemFilter(item1)); + Filter filter1b = new And(new SameItemFilter(item2)); + Filter filter2a = new And(new SameItemFilter(item1), + new SameItemFilter(item1)); + Filter filter2b = new And(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter filter2b2 = new And(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter other0 = new Or(); + Filter other1 = new Or(new SameItemFilter(item1)); + + Assert.assertEquals(filter0, filter0); + Assert.assertEquals(filter0, filter0b); + Assert.assertFalse(filter0.equals(filter1a)); + Assert.assertFalse(filter0.equals(other0)); + Assert.assertFalse(filter0.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter1b)); + Assert.assertFalse(filter1a.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter2a)); + Assert.assertFalse(filter2a.equals(filter1a)); + + Assert.assertFalse(filter2a.equals(filter2b)); + Assert.assertEquals(filter2b, filter2b2); + + // hashCode() + Assert.assertEquals(filter0.hashCode(), filter0.hashCode()); + Assert.assertEquals(filter0.hashCode(), filter0b.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a2.hashCode()); + Assert.assertEquals(filter2a.hashCode(), filter2a.hashCode()); + Assert.assertEquals(filter2b.hashCode(), filter2b2.hashCode()); + } + + public void testOrEqualsHashCode() { + Filter filter0 = new Or(); + Filter filter0b = new Or(); + Filter filter1a = new Or(new SameItemFilter(item1)); + Filter filter1a2 = new Or(new SameItemFilter(item1)); + Filter filter1b = new Or(new SameItemFilter(item2)); + Filter filter2a = new Or(new SameItemFilter(item1), new SameItemFilter( + item1)); + Filter filter2b = new Or(new SameItemFilter(item1), new SameItemFilter( + item2)); + Filter filter2b2 = new Or(new SameItemFilter(item1), + new SameItemFilter(item2)); + Filter other0 = new And(); + Filter other1 = new And(new SameItemFilter(item1)); + + Assert.assertEquals(filter0, filter0); + Assert.assertEquals(filter0, filter0b); + Assert.assertFalse(filter0.equals(filter1a)); + Assert.assertFalse(filter0.equals(other0)); + Assert.assertFalse(filter0.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter1b)); + Assert.assertFalse(filter1a.equals(other1)); + + Assert.assertFalse(filter1a.equals(filter2a)); + Assert.assertFalse(filter2a.equals(filter1a)); + + Assert.assertFalse(filter2a.equals(filter2b)); + Assert.assertEquals(filter2b, filter2b2); + + // hashCode() + Assert.assertEquals(filter0.hashCode(), filter0.hashCode()); + Assert.assertEquals(filter0.hashCode(), filter0b.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a.hashCode()); + Assert.assertEquals(filter1a.hashCode(), filter1a2.hashCode()); + Assert.assertEquals(filter2a.hashCode(), filter2a.hashCode()); + Assert.assertEquals(filter2b.hashCode(), filter2b2.hashCode()); + } + + public void testAndAppliesToProperty() { + Filter filter0 = new And(); + Filter filter1a = new And(new SameItemFilter(item1, "a")); + Filter filter1b = new And(new SameItemFilter(item1, "b")); + Filter filter2aa = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "a")); + Filter filter2ab = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b")); + Filter filter3abc = new And(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b"), new SameItemFilter(item1, "c")); + + // empty And does not filter out anything + Assert.assertFalse(filter0.appliesToProperty("a")); + Assert.assertFalse(filter0.appliesToProperty("d")); + + Assert.assertTrue(filter1a.appliesToProperty("a")); + Assert.assertFalse(filter1a.appliesToProperty("b")); + Assert.assertFalse(filter1b.appliesToProperty("a")); + Assert.assertTrue(filter1b.appliesToProperty("b")); + + Assert.assertTrue(filter2aa.appliesToProperty("a")); + Assert.assertFalse(filter2aa.appliesToProperty("b")); + Assert.assertTrue(filter2ab.appliesToProperty("a")); + Assert.assertTrue(filter2ab.appliesToProperty("b")); + + Assert.assertTrue(filter3abc.appliesToProperty("a")); + Assert.assertTrue(filter3abc.appliesToProperty("b")); + Assert.assertTrue(filter3abc.appliesToProperty("c")); + Assert.assertFalse(filter3abc.appliesToProperty("d")); + } + + public void testOrAppliesToProperty() { + Filter filter0 = new Or(); + Filter filter1a = new Or(new SameItemFilter(item1, "a")); + Filter filter1b = new Or(new SameItemFilter(item1, "b")); + Filter filter2aa = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "a")); + Filter filter2ab = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b")); + Filter filter3abc = new Or(new SameItemFilter(item1, "a"), + new SameItemFilter(item1, "b"), new SameItemFilter(item1, "c")); + + // empty Or filters out everything + Assert.assertTrue(filter0.appliesToProperty("a")); + Assert.assertTrue(filter0.appliesToProperty("d")); + + Assert.assertTrue(filter1a.appliesToProperty("a")); + Assert.assertFalse(filter1a.appliesToProperty("b")); + Assert.assertFalse(filter1b.appliesToProperty("a")); + Assert.assertTrue(filter1b.appliesToProperty("b")); + + Assert.assertTrue(filter2aa.appliesToProperty("a")); + Assert.assertFalse(filter2aa.appliesToProperty("b")); + Assert.assertTrue(filter2ab.appliesToProperty("a")); + Assert.assertTrue(filter2ab.appliesToProperty("b")); + + Assert.assertTrue(filter3abc.appliesToProperty("a")); + Assert.assertTrue(filter3abc.appliesToProperty("b")); + Assert.assertTrue(filter3abc.appliesToProperty("c")); + Assert.assertFalse(filter3abc.appliesToProperty("d")); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java new file mode 100644 index 0000000000..99e8429a51 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/CompareFilterTest.java @@ -0,0 +1,260 @@ +package com.vaadin.data.util.filter; + +import java.util.Date; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Compare.Greater; +import com.vaadin.data.util.filter.Compare.GreaterOrEqual; +import com.vaadin.data.util.filter.Compare.Less; +import com.vaadin.data.util.filter.Compare.LessOrEqual; + +public class CompareFilterTest extends AbstractFilterTest<Compare> { + + protected Item itemNull; + protected Item itemEmpty; + protected Item itemA; + protected Item itemB; + protected Item itemC; + + protected final Filter equalB = new Equal(PROPERTY1, "b"); + protected final Filter greaterB = new Greater(PROPERTY1, "b"); + protected final Filter lessB = new Less(PROPERTY1, "b"); + protected final Filter greaterEqualB = new GreaterOrEqual(PROPERTY1, "b"); + protected final Filter lessEqualB = new LessOrEqual(PROPERTY1, "b"); + + protected final Filter equalNull = new Equal(PROPERTY1, null); + protected final Filter greaterNull = new Greater(PROPERTY1, null); + protected final Filter lessNull = new Less(PROPERTY1, null); + protected final Filter greaterEqualNull = new GreaterOrEqual(PROPERTY1, + null); + protected final Filter lessEqualNull = new LessOrEqual(PROPERTY1, null); + + @Override + protected void setUp() throws Exception { + super.setUp(); + itemNull = new PropertysetItem(); + itemNull.addItemProperty(PROPERTY1, new ObjectProperty<String>(null, + String.class)); + itemEmpty = new PropertysetItem(); + itemEmpty.addItemProperty(PROPERTY1, new ObjectProperty<String>("", + String.class)); + itemA = new PropertysetItem(); + itemA.addItemProperty(PROPERTY1, new ObjectProperty<String>("a", + String.class)); + itemB = new PropertysetItem(); + itemB.addItemProperty(PROPERTY1, new ObjectProperty<String>("b", + String.class)); + itemC = new PropertysetItem(); + itemC.addItemProperty(PROPERTY1, new ObjectProperty<String>("c", + String.class)); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + itemNull = null; + itemEmpty = null; + itemA = null; + itemB = null; + } + + public void testCompareString() { + Assert.assertFalse(equalB.passesFilter(null, itemEmpty)); + Assert.assertFalse(equalB.passesFilter(null, itemA)); + Assert.assertTrue(equalB.passesFilter(null, itemB)); + Assert.assertFalse(equalB.passesFilter(null, itemC)); + + Assert.assertFalse(greaterB.passesFilter(null, itemEmpty)); + Assert.assertFalse(greaterB.passesFilter(null, itemA)); + Assert.assertFalse(greaterB.passesFilter(null, itemB)); + Assert.assertTrue(greaterB.passesFilter(null, itemC)); + + Assert.assertTrue(lessB.passesFilter(null, itemEmpty)); + Assert.assertTrue(lessB.passesFilter(null, itemA)); + Assert.assertFalse(lessB.passesFilter(null, itemB)); + Assert.assertFalse(lessB.passesFilter(null, itemC)); + + Assert.assertFalse(greaterEqualB.passesFilter(null, itemEmpty)); + Assert.assertFalse(greaterEqualB.passesFilter(null, itemA)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemB)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemC)); + + Assert.assertTrue(lessEqualB.passesFilter(null, itemEmpty)); + Assert.assertTrue(lessEqualB.passesFilter(null, itemA)); + Assert.assertTrue(lessEqualB.passesFilter(null, itemB)); + Assert.assertFalse(lessEqualB.passesFilter(null, itemC)); + } + + public void testCompareWithNull() { + // null comparisons: null is less than any other value + Assert.assertFalse(equalB.passesFilter(null, itemNull)); + Assert.assertTrue(greaterB.passesFilter(null, itemNull)); + Assert.assertFalse(lessB.passesFilter(null, itemNull)); + Assert.assertTrue(greaterEqualB.passesFilter(null, itemNull)); + Assert.assertFalse(lessEqualB.passesFilter(null, itemNull)); + + Assert.assertTrue(equalNull.passesFilter(null, itemNull)); + Assert.assertFalse(greaterNull.passesFilter(null, itemNull)); + Assert.assertFalse(lessNull.passesFilter(null, itemNull)); + Assert.assertTrue(greaterEqualNull.passesFilter(null, itemNull)); + Assert.assertTrue(lessEqualNull.passesFilter(null, itemNull)); + + Assert.assertFalse(equalNull.passesFilter(null, itemA)); + Assert.assertFalse(greaterNull.passesFilter(null, itemA)); + Assert.assertTrue(lessNull.passesFilter(null, itemA)); + Assert.assertFalse(greaterEqualNull.passesFilter(null, itemA)); + Assert.assertTrue(lessEqualNull.passesFilter(null, itemA)); + } + + public void testCompareInteger() { + int negative = -1; + int zero = 0; + int positive = 1; + + Item itemNegative = new PropertysetItem(); + itemNegative.addItemProperty(PROPERTY1, new ObjectProperty<Integer>( + negative, Integer.class)); + Item itemZero = new PropertysetItem(); + itemZero.addItemProperty(PROPERTY1, new ObjectProperty<Integer>(zero, + Integer.class)); + Item itemPositive = new PropertysetItem(); + itemPositive.addItemProperty(PROPERTY1, new ObjectProperty<Integer>( + positive, Integer.class)); + + Filter equalZero = new Equal(PROPERTY1, zero); + Assert.assertFalse(equalZero.passesFilter(null, itemNegative)); + Assert.assertTrue(equalZero.passesFilter(null, itemZero)); + Assert.assertFalse(equalZero.passesFilter(null, itemPositive)); + + Filter isPositive = new Greater(PROPERTY1, zero); + Assert.assertFalse(isPositive.passesFilter(null, itemNegative)); + Assert.assertFalse(isPositive.passesFilter(null, itemZero)); + Assert.assertTrue(isPositive.passesFilter(null, itemPositive)); + + Filter isNegative = new Less(PROPERTY1, zero); + Assert.assertTrue(isNegative.passesFilter(null, itemNegative)); + Assert.assertFalse(isNegative.passesFilter(null, itemZero)); + Assert.assertFalse(isNegative.passesFilter(null, itemPositive)); + + Filter isNonNegative = new GreaterOrEqual(PROPERTY1, zero); + Assert.assertFalse(isNonNegative.passesFilter(null, itemNegative)); + Assert.assertTrue(isNonNegative.passesFilter(null, itemZero)); + Assert.assertTrue(isNonNegative.passesFilter(null, itemPositive)); + + Filter isNonPositive = new LessOrEqual(PROPERTY1, zero); + Assert.assertTrue(isNonPositive.passesFilter(null, itemNegative)); + Assert.assertTrue(isNonPositive.passesFilter(null, itemZero)); + Assert.assertFalse(isNonPositive.passesFilter(null, itemPositive)); + } + + public void testCompareDate() { + Date now = new Date(); + // new Date() is only accurate to the millisecond, so repeating it gives + // the same date + Date earlier = new Date(now.getTime() - 1); + Date later = new Date(now.getTime() + 1); + + Item itemEarlier = new PropertysetItem(); + itemEarlier.addItemProperty(PROPERTY1, new ObjectProperty<Date>( + earlier, Date.class)); + Item itemNow = new PropertysetItem(); + itemNow.addItemProperty(PROPERTY1, new ObjectProperty<Date>(now, + Date.class)); + Item itemLater = new PropertysetItem(); + itemLater.addItemProperty(PROPERTY1, new ObjectProperty<Date>(later, + Date.class)); + + Filter equalNow = new Equal(PROPERTY1, now); + Assert.assertFalse(equalNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(equalNow.passesFilter(null, itemNow)); + Assert.assertFalse(equalNow.passesFilter(null, itemLater)); + + Filter after = new Greater(PROPERTY1, now); + Assert.assertFalse(after.passesFilter(null, itemEarlier)); + Assert.assertFalse(after.passesFilter(null, itemNow)); + Assert.assertTrue(after.passesFilter(null, itemLater)); + + Filter before = new Less(PROPERTY1, now); + Assert.assertTrue(before.passesFilter(null, itemEarlier)); + Assert.assertFalse(before.passesFilter(null, itemNow)); + Assert.assertFalse(before.passesFilter(null, itemLater)); + + Filter afterOrNow = new GreaterOrEqual(PROPERTY1, now); + Assert.assertFalse(afterOrNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(afterOrNow.passesFilter(null, itemNow)); + Assert.assertTrue(afterOrNow.passesFilter(null, itemLater)); + + Filter beforeOrNow = new LessOrEqual(PROPERTY1, now); + Assert.assertTrue(beforeOrNow.passesFilter(null, itemEarlier)); + Assert.assertTrue(beforeOrNow.passesFilter(null, itemNow)); + Assert.assertFalse(beforeOrNow.passesFilter(null, itemLater)); + } + + public void testCompareAppliesToProperty() { + Filter filterA = new Equal("a", 1); + Filter filterB = new Equal("b", 1); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testCompareEqualsHashCode() { + // most checks with Equal filter, then only some with others + Filter equalNull2 = new Equal(PROPERTY1, null); + Filter equalNullProperty2 = new Equal(PROPERTY2, null); + Filter equalEmpty = new Equal(PROPERTY1, ""); + Filter equalEmpty2 = new Equal(PROPERTY1, ""); + Filter equalEmptyProperty2 = new Equal(PROPERTY2, ""); + Filter equalA = new Equal(PROPERTY1, "a"); + Filter equalB2 = new Equal(PROPERTY1, "b"); + Filter equalBProperty2 = new Equal(PROPERTY2, "b"); + + Filter greaterEmpty = new Greater(PROPERTY1, ""); + + // equals() + Assert.assertEquals(equalNull, equalNull); + Assert.assertEquals(equalNull, equalNull2); + Assert.assertFalse(equalNull.equals(equalNullProperty2)); + Assert.assertFalse(equalNull.equals(equalEmpty)); + Assert.assertFalse(equalNull.equals(equalB)); + + Assert.assertEquals(equalEmpty, equalEmpty); + Assert.assertFalse(equalEmpty.equals(equalNull)); + Assert.assertEquals(equalEmpty, equalEmpty2); + Assert.assertFalse(equalEmpty.equals(equalEmptyProperty2)); + Assert.assertFalse(equalEmpty.equals(equalB)); + + Assert.assertEquals(equalB, equalB); + Assert.assertFalse(equalB.equals(equalNull)); + Assert.assertFalse(equalB.equals(equalEmpty)); + Assert.assertEquals(equalB, equalB2); + Assert.assertFalse(equalB.equals(equalBProperty2)); + Assert.assertFalse(equalB.equals(equalA)); + + Assert.assertEquals(greaterB, greaterB); + Assert.assertFalse(greaterB.equals(lessB)); + Assert.assertFalse(greaterB.equals(greaterEqualB)); + Assert.assertFalse(greaterB.equals(lessEqualB)); + + Assert.assertFalse(greaterNull.equals(greaterEmpty)); + Assert.assertFalse(greaterNull.equals(greaterB)); + Assert.assertFalse(greaterEmpty.equals(greaterNull)); + Assert.assertFalse(greaterEmpty.equals(greaterB)); + Assert.assertFalse(greaterB.equals(greaterNull)); + Assert.assertFalse(greaterB.equals(greaterEmpty)); + + // hashCode() + Assert.assertEquals(equalNull.hashCode(), equalNull2.hashCode()); + Assert.assertEquals(equalEmpty.hashCode(), equalEmpty2.hashCode()); + Assert.assertEquals(equalB.hashCode(), equalB2.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java new file mode 100644 index 0000000000..6f90273de1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/IsNullFilterTest.java @@ -0,0 +1,57 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; + +public class IsNullFilterTest extends AbstractFilterTest<IsNull> { + + public void testIsNull() { + Item item1 = new PropertysetItem(); + item1.addItemProperty("a", new ObjectProperty<String>(null, + String.class)); + item1.addItemProperty("b", + new ObjectProperty<String>("b", String.class)); + Item item2 = new PropertysetItem(); + item2.addItemProperty("a", + new ObjectProperty<String>("a", String.class)); + item2.addItemProperty("b", new ObjectProperty<String>(null, + String.class)); + + Filter filter1 = new IsNull("a"); + Filter filter2 = new IsNull("b"); + + Assert.assertTrue(filter1.passesFilter(null, item1)); + Assert.assertFalse(filter1.passesFilter(null, item2)); + Assert.assertFalse(filter2.passesFilter(null, item1)); + Assert.assertTrue(filter2.passesFilter(null, item2)); + } + + public void testIsNullAppliesToProperty() { + Filter filterA = new IsNull("a"); + Filter filterB = new IsNull("b"); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testIsNullEqualsHashCode() { + Filter filter1 = new IsNull("a"); + Filter filter1b = new IsNull("a"); + Filter filter2 = new IsNull("b"); + + // equals() + Assert.assertEquals(filter1, filter1b); + Assert.assertFalse(filter1.equals(filter2)); + Assert.assertFalse(filter1.equals(new And())); + + // hashCode() + Assert.assertEquals(filter1.hashCode(), filter1b.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java new file mode 100644 index 0000000000..c3b666e6f7 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/NotFilterTest.java @@ -0,0 +1,50 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; + +public class NotFilterTest extends AbstractFilterTest<Not> { + + protected Item item1 = new BeanItem<Integer>(1); + protected Item item2 = new BeanItem<Integer>(2); + + public void testNot() { + Filter origFilter = new SameItemFilter(item1); + Filter filter = new Not(origFilter); + + Assert.assertTrue(origFilter.passesFilter(null, item1)); + Assert.assertFalse(origFilter.passesFilter(null, item2)); + Assert.assertFalse(filter.passesFilter(null, item1)); + Assert.assertTrue(filter.passesFilter(null, item2)); + } + + public void testANotAppliesToProperty() { + Filter filterA = new Not(new SameItemFilter(item1, "a")); + Filter filterB = new Not(new SameItemFilter(item1, "b")); + + Assert.assertTrue(filterA.appliesToProperty("a")); + Assert.assertFalse(filterA.appliesToProperty("b")); + Assert.assertFalse(filterB.appliesToProperty("a")); + Assert.assertTrue(filterB.appliesToProperty("b")); + } + + public void testNotEqualsHashCode() { + Filter origFilter = new SameItemFilter(item1); + Filter filter1 = new Not(origFilter); + Filter filter1b = new Not(new SameItemFilter(item1)); + Filter filter2 = new Not(new SameItemFilter(item2)); + + // equals() + Assert.assertEquals(filter1, filter1b); + Assert.assertFalse(filter1.equals(filter2)); + Assert.assertFalse(filter1.equals(origFilter)); + Assert.assertFalse(filter1.equals(new And())); + + // hashCode() + Assert.assertEquals(filter1.hashCode(), filter1b.hashCode()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java b/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java new file mode 100644 index 0000000000..bc63d57752 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/filter/SimpleStringFilterTest.java @@ -0,0 +1,130 @@ +package com.vaadin.data.util.filter; + +import junit.framework.Assert; + +public class SimpleStringFilterTest extends + AbstractFilterTest<SimpleStringFilter> { + + protected static TestItem<String, String> createTestItem() { + return new TestItem<String, String>("abcde", "TeSt"); + } + + protected TestItem<String, String> getTestItem() { + return createTestItem(); + } + + protected SimpleStringFilter f(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix) { + return new SimpleStringFilter(propertyId, filterString, ignoreCase, + onlyMatchPrefix); + } + + protected boolean passes(Object propertyId, String filterString, + boolean ignoreCase, boolean onlyMatchPrefix) { + return f(propertyId, filterString, ignoreCase, onlyMatchPrefix) + .passesFilter(null, getTestItem()); + } + + public void testStartsWithCaseSensitive() { + Assert.assertTrue(passes(PROPERTY1, "ab", false, true)); + Assert.assertTrue(passes(PROPERTY1, "", false, true)); + + Assert.assertFalse(passes(PROPERTY2, "ab", false, true)); + Assert.assertFalse(passes(PROPERTY1, "AB", false, true)); + } + + public void testStartsWithCaseInsensitive() { + Assert.assertTrue(passes(PROPERTY1, "AB", true, true)); + Assert.assertTrue(passes(PROPERTY2, "te", true, true)); + Assert.assertFalse(passes(PROPERTY2, "AB", true, true)); + } + + public void testContainsCaseSensitive() { + Assert.assertTrue(passes(PROPERTY1, "ab", false, false)); + Assert.assertTrue(passes(PROPERTY1, "abcde", false, false)); + Assert.assertTrue(passes(PROPERTY1, "cd", false, false)); + Assert.assertTrue(passes(PROPERTY1, "e", false, false)); + Assert.assertTrue(passes(PROPERTY1, "", false, false)); + + Assert.assertFalse(passes(PROPERTY2, "ab", false, false)); + Assert.assertFalse(passes(PROPERTY1, "es", false, false)); + } + + public void testContainsCaseInsensitive() { + Assert.assertTrue(passes(PROPERTY1, "AB", true, false)); + Assert.assertTrue(passes(PROPERTY1, "aBcDe", true, false)); + Assert.assertTrue(passes(PROPERTY1, "CD", true, false)); + Assert.assertTrue(passes(PROPERTY1, "", true, false)); + + Assert.assertTrue(passes(PROPERTY2, "es", true, false)); + + Assert.assertFalse(passes(PROPERTY2, "ab", true, false)); + } + + public void testAppliesToProperty() { + SimpleStringFilter filter = f(PROPERTY1, "ab", false, true); + Assert.assertTrue(filter.appliesToProperty(PROPERTY1)); + Assert.assertFalse(filter.appliesToProperty(PROPERTY2)); + Assert.assertFalse(filter.appliesToProperty("other")); + } + + public void testEqualsHashCode() { + SimpleStringFilter filter = f(PROPERTY1, "ab", false, true); + + SimpleStringFilter f1 = f(PROPERTY2, "ab", false, true); + SimpleStringFilter f1b = f(PROPERTY2, "ab", false, true); + SimpleStringFilter f2 = f(PROPERTY1, "cd", false, true); + SimpleStringFilter f2b = f(PROPERTY1, "cd", false, true); + SimpleStringFilter f3 = f(PROPERTY1, "ab", true, true); + SimpleStringFilter f3b = f(PROPERTY1, "ab", true, true); + SimpleStringFilter f4 = f(PROPERTY1, "ab", false, false); + SimpleStringFilter f4b = f(PROPERTY1, "ab", false, false); + + // equal but not same instance + Assert.assertEquals(f1, f1b); + Assert.assertEquals(f2, f2b); + Assert.assertEquals(f3, f3b); + Assert.assertEquals(f4, f4b); + + // more than one property differ + Assert.assertFalse(f1.equals(f2)); + Assert.assertFalse(f1.equals(f3)); + Assert.assertFalse(f1.equals(f4)); + Assert.assertFalse(f2.equals(f1)); + Assert.assertFalse(f2.equals(f3)); + Assert.assertFalse(f2.equals(f4)); + Assert.assertFalse(f3.equals(f1)); + Assert.assertFalse(f3.equals(f2)); + Assert.assertFalse(f3.equals(f4)); + Assert.assertFalse(f4.equals(f1)); + Assert.assertFalse(f4.equals(f2)); + Assert.assertFalse(f4.equals(f3)); + + // only one property differs + Assert.assertFalse(filter.equals(f1)); + Assert.assertFalse(filter.equals(f2)); + Assert.assertFalse(filter.equals(f3)); + Assert.assertFalse(filter.equals(f4)); + + Assert.assertFalse(f1.equals(null)); + Assert.assertFalse(f1.equals(new Object())); + + Assert.assertEquals(f1.hashCode(), f1b.hashCode()); + Assert.assertEquals(f2.hashCode(), f2b.hashCode()); + Assert.assertEquals(f3.hashCode(), f3b.hashCode()); + Assert.assertEquals(f4.hashCode(), f4b.hashCode()); + } + + public void testNonExistentProperty() { + Assert.assertFalse(passes("other1", "ab", false, true)); + } + + public void testNullValueForProperty() { + TestItem<String, String> item = createTestItem(); + item.addItemProperty("other1", new NullProperty()); + + Assert.assertFalse(f("other1", "ab", false, true).passesFilter(null, + item)); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java new file mode 100644 index 0000000000..057527307f --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/AllTests.java @@ -0,0 +1,145 @@ +package com.vaadin.data.util.sqlcontainer; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import com.vaadin.data.util.sqlcontainer.connection.J2EEConnectionPoolTest; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPoolTest; +import com.vaadin.data.util.sqlcontainer.filters.BetweenTest; +import com.vaadin.data.util.sqlcontainer.filters.LikeTest; +import com.vaadin.data.util.sqlcontainer.generator.SQLGeneratorsTest; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryTest; +import com.vaadin.data.util.sqlcontainer.query.QueryBuilderTest; +import com.vaadin.data.util.sqlcontainer.query.TableQueryTest; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; + +@RunWith(Suite.class) +@SuiteClasses({ SimpleJDBCConnectionPoolTest.class, + J2EEConnectionPoolTest.class, LikeTest.class, QueryBuilderTest.class, + FreeformQueryTest.class, RowIdTest.class, SQLContainerTest.class, + SQLContainerTableQueryTest.class, ColumnPropertyTest.class, + TableQueryTest.class, SQLGeneratorsTest.class, UtilTest.class, + TicketTests.class, BetweenTest.class, ReadOnlyRowIdTest.class }) +public class AllTests { + /* Set the DB used for testing here! */ + public enum DB { + HSQLDB, MYSQL, POSTGRESQL, MSSQL, ORACLE; + } + + /* 0 = HSQLDB, 1 = MYSQL, 2 = POSTGRESQL, 3 = MSSQL, 4 = ORACLE */ + public static final DB db = DB.HSQLDB; + + /* Auto-increment column offset (HSQLDB = 0, MYSQL = 1, POSTGRES = 1) */ + public static int offset; + /* Garbage table creation query (=three queries for oracle) */ + public static String createGarbage; + public static String createGarbageSecond; + public static String createGarbageThird; + /* DB Drivers, urls, usernames and passwords */ + public static String dbDriver; + public static String dbURL; + public static String dbUser; + public static String dbPwd; + /* People -test table creation statement(s) */ + public static String peopleFirst; + public static String peopleSecond; + public static String peopleThird; + /* Versioned -test table createion statement(s) */ + public static String[] versionStatements; + /* SQL Generator used during the testing */ + public static SQLGenerator sqlGen; + + /* Set DB-specific settings based on selected DB */ + static { + sqlGen = new DefaultSQLGenerator(); + switch (db) { + case HSQLDB: + offset = 0; + createGarbage = "create table garbage (id integer generated always as identity, type varchar(32), PRIMARY KEY(id))"; + dbDriver = "org.hsqldb.jdbc.JDBCDriver"; + dbURL = "jdbc:hsqldb:mem:sqlcontainer"; + dbUser = "SA"; + dbPwd = ""; + peopleFirst = "create table people (id integer generated always as identity, name varchar(32), AGE INTEGER)"; + peopleSecond = "alter table people add primary key (id)"; + versionStatements = new String[] { + "create table versioned (id integer generated always as identity, text varchar(255), version tinyint default 0)", + "alter table versioned add primary key (id)" }; + break; + case MYSQL: + offset = 1; + createGarbage = "create table GARBAGE (ID integer auto_increment, type varchar(32), PRIMARY KEY(ID))"; + dbDriver = "com.mysql.jdbc.Driver"; + dbURL = "jdbc:mysql:///sqlcontainer"; + dbUser = "sqlcontainer"; + dbPwd = "sqlcontainer"; + peopleFirst = "create table PEOPLE (ID integer auto_increment not null, NAME varchar(32), AGE INTEGER, primary key(ID))"; + peopleSecond = null; + versionStatements = new String[] { + "create table VERSIONED (ID integer auto_increment not null, TEXT varchar(255), VERSION tinyint default 0, primary key(ID))", + "CREATE TRIGGER upd_version BEFORE UPDATE ON VERSIONED" + + " FOR EACH ROW SET NEW.VERSION = OLD.VERSION+1" }; + break; + case POSTGRESQL: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" serial PRIMARY KEY, \"TYPE\" varchar(32))"; + dbDriver = "org.postgresql.Driver"; + dbURL = "jdbc:postgresql://localhost:5432/test"; + dbUser = "postgres"; + dbPwd = "postgres"; + peopleFirst = "create table PEOPLE (\"ID\" serial primary key, \"NAME\" VARCHAR(32), \"AGE\" INTEGER)"; + peopleSecond = null; + versionStatements = new String[] { + "create table VERSIONED (\"ID\" serial primary key, \"TEXT\" VARCHAR(255), \"VERSION\" INTEGER DEFAULT 0)", + "CREATE OR REPLACE FUNCTION zz_row_version() RETURNS TRIGGER AS $$" + + "BEGIN" + + " IF TG_OP = 'UPDATE'" + + " AND NEW.\"VERSION\" = old.\"VERSION\"" + + " AND ROW(NEW.*) IS DISTINCT FROM ROW (old.*)" + + " THEN" + + " NEW.\"VERSION\" := NEW.\"VERSION\" + 1;" + + " END IF;" + " RETURN NEW;" + "END;" + + "$$ LANGUAGE plpgsql;", + "CREATE TRIGGER \"mytable_modify_dt_tr\" BEFORE UPDATE" + + " ON VERSIONED FOR EACH ROW" + + " EXECUTE PROCEDURE \"public\".\"zz_row_version\"();" }; + break; + case MSSQL: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" int identity(1,1) primary key, \"TYPE\" varchar(32))"; + dbDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + dbURL = "jdbc:sqlserver://localhost:1433;databaseName=tempdb;"; + dbUser = "sa"; + dbPwd = "sa"; + peopleFirst = "create table PEOPLE (\"ID\" int identity(1,1) primary key, \"NAME\" VARCHAR(32), \"AGE\" INTEGER)"; + peopleSecond = null; + versionStatements = new String[] { "create table VERSIONED (\"ID\" int identity(1,1) primary key, \"TEXT\" VARCHAR(255), \"VERSION\" rowversion not null)" }; + sqlGen = new MSSQLGenerator(); + break; + case ORACLE: + offset = 1; + createGarbage = "create table GARBAGE (\"ID\" integer primary key, \"TYPE\" varchar2(32))"; + createGarbageSecond = "create sequence garbage_seq start with 1 increment by 1 nomaxvalue"; + createGarbageThird = "create trigger garbage_trigger before insert on GARBAGE for each row begin select garbage_seq.nextval into :new.ID from dual; end;"; + dbDriver = "oracle.jdbc.OracleDriver"; + dbURL = "jdbc:oracle:thin:test/test@localhost:1521:XE"; + dbUser = "test"; + dbPwd = "test"; + peopleFirst = "create table PEOPLE (\"ID\" integer primary key, \"NAME\" VARCHAR2(32), \"AGE\" INTEGER)"; + peopleSecond = "create sequence people_seq start with 1 increment by 1 nomaxvalue"; + peopleThird = "create trigger people_trigger before insert on PEOPLE for each row begin select people_seq.nextval into :new.ID from dual; end;"; + versionStatements = new String[] { + "create table VERSIONED (\"ID\" integer primary key, \"TEXT\" VARCHAR(255), \"VERSION\" INTEGER DEFAULT 0)", + "create sequence versioned_seq start with 1 increment by 1 nomaxvalue", + "create trigger versioned_trigger before insert on VERSIONED for each row begin select versioned_seq.nextval into :new.ID from dual; end;", + "create sequence versioned_version start with 1 increment by 1 nomaxvalue", + "create trigger versioned_version_trigger before insert or update on VERSIONED for each row begin select versioned_version.nextval into :new.VERSION from dual; end;" }; + sqlGen = new OracleGenerator(); + break; + } + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java new file mode 100644 index 0000000000..09f620cc2a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/ColumnPropertyTest.java @@ -0,0 +1,315 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; + +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Property.ReadOnlyException; +import com.vaadin.data.util.sqlcontainer.ColumnProperty.NotNullableException; +import com.vaadin.data.util.sqlcontainer.query.QueryDelegate; + +public class ColumnPropertyTest { + + @Test + public void constructor_legalParameters_shouldSucceed() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertNotNull(cp); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_missingPropertyId_shouldFail() { + new ColumnProperty(null, false, true, true, false, "Ville", + String.class); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_missingType_shouldFail() { + new ColumnProperty("NAME", false, true, true, false, "Ville", null); + } + + @Test + public void getValue_defaultValue_returnsVille() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertEquals("Ville", cp.getValue()); + } + + @Test + public void setValue_readWriteNullable_returnsKalle() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue("Kalle"); + Assert.assertEquals("Kalle", cp.getValue()); + EasyMock.verify(container); + } + + @Test(expected = ReadOnlyException.class) + public void setValue_readOnlyNullable_shouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", true, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + EasyMock.replay(container); + cp.setValue("Kalle"); + EasyMock.verify(container); + } + + @Test + public void setValue_readWriteNullable_nullShouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + EasyMock.verify(container); + } + + @Test(expected = NotNullableException.class) + public void setValue_readWriteNotNullable_nullShouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, false, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue(null); + Assert.assertNotNull(cp.getValue()); + EasyMock.verify(container); + } + + @Test + public void getType_normal_returnsStringClass() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertSame(String.class, cp.getType()); + } + + @Test + public void isReadOnly_readWriteNullable_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + Assert.assertFalse(cp.isReadOnly()); + } + + @Test + public void isReadOnly_readOnlyNullable_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", true, true, true, + false, "Ville", String.class); + Assert.assertTrue(cp.isReadOnly()); + } + + @Test + public void setReadOnly_readOnlyChangeAllowed_shouldSucceed() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + cp.setReadOnly(true); + Assert.assertTrue(cp.isReadOnly()); + } + + @Test + public void setReadOnly_readOnlyChangeDisallowed_shouldFail() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + cp.setReadOnly(true); + Assert.assertFalse(cp.isReadOnly()); + } + + @Test + public void getPropertyId_normal_returnsNAME() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + Assert.assertEquals("NAME", cp.getPropertyId()); + } + + @Test + public void isModified_valueModified_returnsTrue() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + RowItem owner = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(cp)); + container.itemChangeNotification(owner); + EasyMock.replay(container); + cp.setValue("Kalle"); + Assert.assertEquals("Kalle", cp.getValue()); + Assert.assertTrue(cp.isModified()); + EasyMock.verify(container); + } + + @Test + public void isModified_valueNotModified_returnsFalse() { + ColumnProperty cp = new ColumnProperty("NAME", false, false, true, + false, "Ville", String.class); + Assert.assertFalse(cp.isModified()); + } + + @Test + public void setValue_nullOnNullable_shouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, + false, "asdf", String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + } + + @Test + public void setValue_resetTonullOnNullable_shouldWork() { + ColumnProperty cp = new ColumnProperty("NAME", false, true, true, false, + null, String.class); + SQLContainer container = EasyMock.createMock(SQLContainer.class); + new RowItem(container, new RowId(new Object[] { 1 }), Arrays.asList(cp)); + cp.setValue("asdf"); + Assert.assertEquals("asdf", cp.getValue()); + cp.setValue(null); + Assert.assertNull(cp.getValue()); + } + + @Test + public void setValue_sendsItemChangeNotification() throws SQLException { + + class TestContainer extends SQLContainer { + Object value = null; + boolean modified = false; + + public TestContainer(QueryDelegate delegate) throws SQLException { + super(delegate); + } + + @Override + public void itemChangeNotification(RowItem changedItem) { + ColumnProperty cp = (ColumnProperty) changedItem + .getItemProperty("NAME"); + value = cp.getValue(); + modified = cp.isModified(); + } + } + + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Statement statement = EasyMock.createNiceMock(Statement.class); + EasyMock.replay(statement); + + ResultSetMetaData metadata = EasyMock + .createNiceMock(ResultSetMetaData.class); + EasyMock.replay(metadata); + + ResultSet resultSet = EasyMock.createNiceMock(ResultSet.class); + EasyMock.expect(resultSet.getStatement()).andReturn(statement); + EasyMock.expect(resultSet.getMetaData()).andReturn(metadata); + EasyMock.replay(resultSet); + + QueryDelegate delegate = EasyMock.createNiceMock(QueryDelegate.class); + EasyMock.expect(delegate.getResults(0, 1)).andReturn(resultSet); + EasyMock.replay(delegate); + + TestContainer container = new TestContainer(delegate); + + new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(property)); + + property.setValue("Kalle"); + Assert.assertEquals("Kalle", container.value); + Assert.assertTrue(container.modified); + } + + @Test + public void versionColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + property.setVersionColumn(true); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void neverWritableColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", true, false, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void writableColumnsShouldBeInValueMap_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Assert.assertTrue(property.isPersistent()); + } + + @Test + public void writableButReadOnlyColumnsShouldNotBeInValueMap_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", true, true, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isPersistent()); + } + + @Test + public void primKeysShouldBeRowIdentifiers_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + true, "Ville", String.class); + + Assert.assertTrue(property.isRowIdentifier()); + } + + @Test + public void versionColumnsShouldBeRowIdentifiers_shouldReturnTrue() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + property.setVersionColumn(true); + + Assert.assertTrue(property.isRowIdentifier()); + } + + @Test + public void nonPrimKeyOrVersionColumnsShouldBeNotRowIdentifiers_shouldReturnFalse() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + Assert.assertFalse(property.isRowIdentifier()); + } + + @Test + public void getOldValueShouldReturnPreviousValue_shouldReturnVille() { + ColumnProperty property = new ColumnProperty("NAME", false, true, true, + false, "Ville", String.class); + + // Here we really don't care about the container management, but in + // order to set the value for a column the owner (RowItem) must be set + // and to create the owner we must have a container... + ArrayList<ColumnProperty> properties = new ArrayList<ColumnProperty>(); + properties.add(property); + + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + RowItem rowItem = new RowItem(container, new RowId(new Object[] { 1 }), + Arrays.asList(property)); + + property.setValue("Kalle"); + // Just check that the new value was actually set... + Assert.assertEquals("Kalle", property.getValue()); + // Assert that old value is the original value... + Assert.assertEquals("Ville", property.getOldValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java new file mode 100644 index 0000000000..489f780d61 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/DataGenerator.java @@ -0,0 +1,139 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; + +public class DataGenerator { + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static void addPeopleToDatabase(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("drop table PEOPLE"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence people_seq"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + statement.execute(AllTests.peopleFirst); + if (AllTests.peopleSecond != null) { + statement.execute(AllTests.peopleSecond); + } + if (AllTests.db == DB.ORACLE) { + statement.execute(AllTests.peopleThird); + } + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Ville', '23')"); + statement.executeUpdate("insert into people values('Kalle', '7')"); + statement.executeUpdate("insert into people values('Pelle', '18')"); + statement.executeUpdate("insert into people values('Börje', '64')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Ville', '23')"); + statement + .executeUpdate("insert into people values(default, 'Kalle', '7')"); + statement + .executeUpdate("insert into people values(default, 'Pelle', '18')"); + statement + .executeUpdate("insert into people values(default, 'Börje', '64')"); + } + statement.close(); + statement = conn.createStatement(); + ResultSet rs = statement.executeQuery("select * from PEOPLE"); + Assert.assertTrue(rs.next()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void addFiveThousandPeople(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + for (int i = 4; i < 5000; i++) { + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Person " + + i + "', '" + i % 99 + "')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Person " + + i + "', '" + i % 99 + "')"); + } + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void addVersionedData(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("DROP TABLE VERSIONED"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence versioned_seq"); + statement.execute("drop sequence versioned_version"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + for (String stmtString : AllTests.versionStatements) { + statement.execute(stmtString); + } + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into VERSIONED values('Junk', default)"); + } else { + statement + .executeUpdate("insert into VERSIONED values(default, 'Junk', default)"); + } + statement.close(); + statement = conn.createStatement(); + ResultSet rs = statement.executeQuery("select * from VERSIONED"); + Assert.assertTrue(rs.next()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + public static void createGarbage(JDBCConnectionPool connectionPool) + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + try { + statement.execute("drop table GARBAGE"); + if (AllTests.db == DB.ORACLE) { + statement.execute("drop sequence garbage_seq"); + } + } catch (SQLException e) { + // Will fail if table doesn't exist, which is OK. + conn.rollback(); + } + statement.execute(AllTests.createGarbage); + if (AllTests.db == DB.ORACLE) { + statement.execute(AllTests.createGarbageSecond); + statement.execute(AllTests.createGarbageThird); + } + conn.commit(); + connectionPool.releaseConnection(conn); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java new file mode 100644 index 0000000000..b0e2a232ca --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/FreeformQueryUtil.java @@ -0,0 +1,71 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; + +public class FreeformQueryUtil { + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static StatementHelper getQueryWithFilters(List<Filter> filters, + int offset, int limit) { + StatementHelper sh = new StatementHelper(); + if (AllTests.db == DB.MSSQL) { + if (limit > 1) { + offset++; + limit--; + } + StringBuilder query = new StringBuilder(); + query.append("SELECT * FROM (SELECT row_number() OVER ("); + query.append("ORDER BY \"ID\" ASC"); + query.append(") AS rownum, * FROM \"PEOPLE\""); + + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + query.append(") AS a WHERE a.rownum BETWEEN ").append(offset) + .append(" AND ").append(Integer.toString(offset + limit)); + sh.setQueryString(query.toString()); + return sh; + } else if (AllTests.db == DB.ORACLE) { + if (limit > 1) { + offset++; + limit--; + } + StringBuilder query = new StringBuilder(); + query.append("SELECT * FROM (SELECT x.*, ROWNUM AS " + + "\"rownum\" FROM (SELECT * FROM \"PEOPLE\""); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + query.append(") x) WHERE \"rownum\" BETWEEN ? AND ?"); + sh.addParameterValue(offset); + sh.addParameterValue(offset + limit); + sh.setQueryString(query.toString()); + return sh; + } else { + StringBuilder query = new StringBuilder("SELECT * FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters(filters, sh)); + } + if (limit != 0 || offset != 0) { + query.append(" LIMIT ? OFFSET ?"); + sh.addParameterValue(limit); + sh.addParameterValue(offset); + } + sh.setQueryString(query.toString()); + return sh; + } + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java new file mode 100644 index 0000000000..d2b6ee2555 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/ReadOnlyRowIdTest.java @@ -0,0 +1,50 @@ +package com.vaadin.data.util.sqlcontainer; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.ReadOnlyRowId; + +public class ReadOnlyRowIdTest { + + @Test + public void getRowNum_shouldReturnRowNumGivenInConstructor() { + int rowNum = 1337; + ReadOnlyRowId rid = new ReadOnlyRowId(rowNum); + Assert.assertEquals(rowNum, rid.getRowNum()); + } + + @Test + public void hashCode_shouldBeEqualToHashCodeOfRowNum() { + int rowNum = 1337; + ReadOnlyRowId rid = new ReadOnlyRowId(rowNum); + Assert.assertEquals(Integer.valueOf(rowNum).hashCode(), rid.hashCode()); + } + + @Test + public void equals_compareWithNull_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + Assert.assertFalse(rid.equals(null)); + } + + @Test + public void equals_compareWithSameInstance_shouldBeTrue() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + ReadOnlyRowId rid2 = rid; + Assert.assertTrue(rid.equals(rid2)); + } + + @Test + public void equals_compareWithOtherType_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + Assert.assertFalse(rid.equals(new Object())); + } + + @Test + public void equals_compareWithOtherRowId_shouldBeFalse() { + ReadOnlyRowId rid = new ReadOnlyRowId(1337); + ReadOnlyRowId rid2 = new ReadOnlyRowId(42); + Assert.assertFalse(rid.equals(rid2)); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java new file mode 100644 index 0000000000..399db06869 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/RowIdTest.java @@ -0,0 +1,55 @@ +package com.vaadin.data.util.sqlcontainer; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.RowId; + +public class RowIdTest { + + @Test + public void constructor_withArrayOfPrimaryKeyColumns_shouldSucceed() { + RowId id = new RowId(new Object[] { "id", "name" }); + Assert.assertArrayEquals(new Object[] { "id", "name" }, id.getId()); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor_withNullParameter_shouldFail() { + new RowId(null); + } + + @Test + public void hashCode_samePrimaryKeys_sameResult() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id", "name" }); + Assert.assertEquals(id.hashCode(), id2.hashCode()); + } + + @Test + public void hashCode_differentPrimaryKeys_differentResult() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id" }); + Assert.assertFalse(id.hashCode() == id2.hashCode()); + } + + @Test + public void equals_samePrimaryKeys_returnsTrue() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id", "name" }); + Assert.assertEquals(id, id2); + } + + @Test + public void equals_differentPrimaryKeys_returnsFalse() { + RowId id = new RowId(new Object[] { "id", "name" }); + RowId id2 = new RowId(new Object[] { "id" }); + Assert.assertFalse(id.equals(id2.hashCode())); + } + + @Test + public void equals_differentDataType_returnsFalse() { + RowId id = new RowId(new Object[] { "id", "name" }); + Assert.assertFalse(id.equals("Tudiluu")); + Assert.assertFalse(id.equals(new Integer(1337))); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java new file mode 100644 index 0000000000..438c40823d --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTableQueryTest.java @@ -0,0 +1,1519 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; + +public class SQLContainerTableQueryTest { + + private static final int offset = AllTests.offset; + private static final String createGarbage = AllTests.createGarbage; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void constructor_withTableQuery_shouldSucceed() throws SQLException { + new SQLContainer(new TableQuery("people", connectionPool, + AllTests.sqlGen)); + } + + @Test + public void containsId_withTableQueryAndExistingId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertTrue(container.containsId(new RowId( + new Object[] { 1 + offset }))); + } + + @Test + public void containsId_withTableQueryAndNonexistingId_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.containsId(new RowId( + new Object[] { 1337 + offset }))); + } + + @Test + public void getContainerProperty_tableExistingItemIdAndPropertyId_returnsProperty() + throws SQLException { + TableQuery t = new TableQuery("people", connectionPool, AllTests.sqlGen); + SQLContainer container = new SQLContainer(t); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + "Ville", + container + .getContainerProperty( + new RowId(new Object[] { new BigDecimal( + 0 + offset) }), "NAME").getValue()); + } else { + Assert.assertEquals( + "Ville", + container.getContainerProperty( + new RowId(new Object[] { 0 + offset }), "NAME") + .getValue()); + } + } + + @Test + public void getContainerProperty_tableExistingItemIdAndNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1 + offset }), "asdf")); + } + + @Test + public void getContainerProperty_tableNonexistingItemId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1337 + offset }), "NAME")); + } + + @Test + public void getContainerPropertyIds_table_returnsIDAndNAME() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> propertyIds = container.getContainerPropertyIds(); + Assert.assertEquals(3, propertyIds.size()); + Assert.assertArrayEquals(new String[] { "ID", "NAME", "AGE" }, + propertyIds.toArray()); + } + + @Test + public void getItem_tableExistingItemId_returnsItem() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 0 + offset) })); + } else { + item = container.getItem(new RowId(new Object[] { 0 + offset })); + } + Assert.assertNotNull(item); + Assert.assertEquals("Ville", item.getItemProperty("NAME").getValue()); + } + + @Test + public void getItem_commitedModifiedAndRefreshed() throws SQLException { + String OLD_VALUE = "SomeValue"; //$NON-NLS-1$ + String NEW_VALUE = "OtherValue"; //$NON-NLS-1$ + + SQLContainer container = new SQLContainer(new TableQuery("people", //$NON-NLS-1$ + connectionPool, AllTests.sqlGen)); + Object itemID = container.addItem(); + Item item = container.getItem(itemID); + item.getItemProperty("NAME").setValue(OLD_VALUE); //$NON-NLS-1$ + container.commit(); + + itemID = container.getIdByIndex(container.size() - 1); + item = container.getItem(itemID); + Assert.assertEquals(OLD_VALUE, item.getItemProperty("NAME") //$NON-NLS-1$ + .getValue()); + item.getItemProperty("NAME").setValue(NEW_VALUE); //$NON-NLS-1$ + + // refresh the container which free's the caches + // and the modified cache keeps untouched which is a really powerful + // feature + container.refresh(); + + // access the item again will use the item from the modified cache. + item = container.getItem(itemID); + Assert.assertEquals(NEW_VALUE, item.getItemProperty("NAME") //$NON-NLS-1$ + .getValue()); + } + + @Test + public void getItem_table5000RowsWithParameter1337_returnsItemWithId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertNotNull(item); + Assert.assertEquals(new BigDecimal(1337 + offset), item + .getItemProperty("ID").getValue()); + } else { + item = container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertNotNull(item); + Assert.assertEquals(1337 + offset, item.getItemProperty("ID") + .getValue()); + } + Assert.assertEquals("Person 1337", item.getItemProperty("NAME") + .getValue()); + } + + @Test + public void getItemIds_table_returnsItemIdsWithKeys0through3() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> itemIds = container.getItemIds(); + Assert.assertEquals(4, itemIds.size()); + RowId zero = new RowId(new Object[] { 0 + offset }); + RowId one = new RowId(new Object[] { 1 + offset }); + RowId two = new RowId(new Object[] { 2 + offset }); + RowId three = new RowId(new Object[] { 3 + offset }); + if (AllTests.db == DB.ORACLE) { + String[] correct = new String[] { "1", "2", "3", "4" }; + List<String> oracle = new ArrayList<String>(); + for (Object o : itemIds) { + oracle.add(o.toString()); + } + Assert.assertArrayEquals(correct, oracle.toArray()); + } else { + Assert.assertArrayEquals(new Object[] { zero, one, two, three }, + itemIds.toArray()); + } + } + + @Test + public void getType_tableNAMEPropertyId_returnsString() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(String.class, container.getType("NAME")); + } + + @Test + public void getType_tableIDPropertyId_returnsInteger() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(BigDecimal.class, container.getType("ID")); + } else { + Assert.assertEquals(Integer.class, container.getType("ID")); + } + } + + @Test + public void getType_tableNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertNull(container.getType("asdf")); + } + + @Test + public void size_table_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + } + + @Test + public void size_tableOneAddedItem_returnsFive() throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(5, container.size()); + } + + @Test + public void indexOfId_tableWithParameterThree_returnsThree() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(3, container.indexOfId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertEquals(3, + container.indexOfId(new RowId(new Object[] { 3 + offset }))); + } + } + + @Test + public void indexOfId_table5000RowsWithParameter1337_returns1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery q = new TableQuery("people", connectionPool, AllTests.sqlGen); + SQLContainer container = new SQLContainer(q); + if (AllTests.db == DB.ORACLE) { + container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { new BigDecimal(1337 + offset) }))); + } else { + container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { 1337 + offset }))); + } + } + + @Test + public void getIdByIndex_table5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void getIdByIndex_tableWithPaging5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void nextItemId_tableCurrentItem1337_returnsItem1338() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1338 + offset }).toString(), + container.nextItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1338 + offset }), + container.nextItemId(itemId)); + } + } + + @Test + public void prevItemId_tableCurrentItem1337_returns1336() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1336 + offset }).toString(), + container.prevItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1336 + offset }), + container.prevItemId(itemId)); + } + } + + @Test + public void firstItemId_table_returnsItemId0() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 0 + offset }).toString(), + container.firstItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 0 + offset }), + container.firstItemId()); + } + } + + @Test + public void lastItemId_table5000Rows_returnsItemId4999() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 4999 + offset }).toString(), + container.lastItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 4999 + offset }), + container.lastItemId()); + } + } + + @Test + public void isFirstId_tableActualFirstId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { new BigDecimal(0 + offset) }))); + } else { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { 0 + offset }))); + } + } + + @Test + public void isFirstId_tableSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_tableSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_tableLastId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 3 + offset }))); + } + } + + @Test + public void isLastId_table5000RowsLastId_returnsTrue() throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(4999 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 4999 + offset }))); + } + } + + @Test + public void allIdsFound_table5000RowsLastId_shouldSucceed() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + } + } + + @Test + public void allIdsFound_table5000RowsLastId_autoCommit_shouldSucceed() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setAutoCommit(true); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(container.containsId(container.getIdByIndex(i))); + } + } + + @Test + public void refresh_table_sizeShouldUpdate() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + container.refresh(); + Assert.assertEquals(5000, container.size()); + } + + @Test + public void refresh_tableWithoutCallingRefresh_sizeShouldNotUpdate() + throws SQLException { + // Yeah, this is a weird one. We're testing that the size doesn't update + // after adding lots of items unless we call refresh inbetween. This to + // make sure that the refresh method actually refreshes stuff and isn't + // a NOP. + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + Assert.assertEquals(4, container.size()); + } + + @Test + public void setAutoCommit_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setAutoCommit(true); + Assert.assertTrue(container.isAutoCommit()); + container.setAutoCommit(false); + Assert.assertFalse(container.isAutoCommit()); + } + + @Test + public void getPageLength_table_returnsDefault100() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertEquals(100, container.getPageLength()); + } + + @Test + public void setPageLength_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.setPageLength(20); + Assert.assertEquals(20, container.getPageLength()); + container.setPageLength(200); + Assert.assertEquals(200, container.getPageLength()); + } + + @Test(expected = UnsupportedOperationException.class) + public void addContainerProperty_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addContainerProperty("asdf", String.class, ""); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeContainerProperty_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.removeContainerProperty("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObjectObject_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAfter("asdf", "foo"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtIntObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAt(2, "asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtInt_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAt(2); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItemAfter("asdf"); + } + + @Test + public void addItem_tableAddOneNewItem_returnsItemId() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + } + + @Test + public void addItem_tableAddOneNewItem_autoCommit_returnsFinalItemId() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + container.setAutoCommit(true); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + Assert.assertTrue(itemId instanceof RowId); + Assert.assertFalse(itemId instanceof TemporaryRowId); + } + + @Test + public void addItem_tableAddOneNewItem_autoCommit_sizeIsIncreased() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + container.setAutoCommit(true); + int originalSize = container.size(); + container.addItem(); + Assert.assertEquals(originalSize + 1, container.size()); + } + + @Test + public void addItem_tableAddOneNewItem_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + container.addItem(); + Assert.assertEquals(size + 1, container.size()); + } + + @Test + public void addItem_tableAddTwoNewItems_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(size + 2, container.size()); + Assert.assertNotSame(id1, id2); + Assert.assertFalse(id1.equals(id2)); + } + + @Test + public void nextItemId_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.nextItemId(lastId)); + } + + @Test + public void lastItemId_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.lastItemId()); + Assert.assertNotSame(lastId, container.lastItemId()); + } + + @Test + public void indexOfId_tableNewlyAddedItem_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertEquals(4, container.indexOfId(id)); + } + + @Test + public void getItem_tableNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + } + + @Test + public void getItemIds_tableNewlyAddedItem_containsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + } + + @Test + public void getContainerProperty_tableNewlyAddedItem_returnsPropertyOfNewlyAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Item item = container.getItem(id); + item.getItemProperty("NAME").setValue("asdf"); + Assert.assertEquals("asdf", container.getContainerProperty(id, "NAME") + .getValue()); + } + + @Test + public void containsId_tableNewlyAddedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + } + + @Test + public void prevItemId_tableTwoNewlyAddedItems_returnsFirstAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(id1, container.prevItemId(id2)); + } + + @Test + public void firstItemId_tableEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertSame(id, container.firstItemId()); + } + + @Test + public void isFirstId_tableEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.isFirstId(id)); + } + + @Test + public void isLastId_tableOneItemAdded_returnsTrueForAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.isLastId(id)); + } + + @Test + public void isLastId_tableTwoItemsAdded_returnsTrueForLastAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem(); + Object id2 = container.addItem(); + Assert.assertTrue(container.isLastId(id2)); + } + + @Test + public void getIdByIndex_tableOneItemAddedLastIndexInContainer_returnsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertEquals(id, container.getIdByIndex(container.size() - 1)); + } + + @Test + public void removeItem_tableNoAddedItems_removesItemFromContainer() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.firstItemId()); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void containsId_tableRemovedItem_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void removeItem_tableOneAddedItem_removesTheAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + int size = container.size(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void getItem_tableItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItem_tableAddedItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemIds_tableItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void getItemIds_tableAddedItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void containsId_tableItemRemoved_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.firstItemId(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_tableAddedItemRemoved_returnsFalse() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void nextItemId_tableItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void nextItemId_tableAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void prevItemId_tableItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void prevItemId_tableAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void firstItemId_tableFirstItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertNotSame(first, container.firstItemId()); + } + + @Test + public void firstItemId_tableNewlyAddedFirstItemRemoved_resultChanges() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object first = container.addItem(); + Object second = container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertSame(second, container.firstItemId()); + } + + @Test + public void lastItemId_tableLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void lastItemId_tableAddedLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void isFirstId_tableFirstItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isFirstId_tableAddedFirstItemRemoved_returnsFalse() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new TableQuery("garbage", + connectionPool, AllTests.sqlGen)); + Object first = container.addItem(); + container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isLastId_tableLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void isLastId_tableAddedLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void indexOfId_tableItemRemoved_returnsNegOne() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void indexOfId_tableAddedItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + Assert.assertTrue(container.indexOfId(id) != -1); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void getIdByIndex_tableItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(2)); + } + + @Test + public void getIdByIndex_tableAddedItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object id = container.addItem(); + container.addItem(); + int index = container.indexOfId(id); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(index)); + } + + @Test + public void removeAllItems_table_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void removeAllItems_tableAddedItems_shouldSucceed() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addItem(); + container.addItem(); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void commit_tableAddedItem_shouldBeWrittenToDB() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("New Name"); + Assert.assertTrue(id instanceof TemporaryRowId); + Assert.assertSame(id, container.lastItemId()); + container.commit(); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("New Name", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void commit_tableTwoAddedItems_shouldBeWrittenToDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Object id2 = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("Herbert"); + container.getContainerProperty(id2, "NAME").setValue("Larry"); + Assert.assertTrue(id2 instanceof TemporaryRowId); + Assert.assertSame(id2, container.lastItemId()); + container.commit(); + Object nextToLast = container.getIdByIndex(container.size() - 2); + Assert.assertFalse(nextToLast instanceof TemporaryRowId); + Assert.assertEquals("Herbert", + container.getContainerProperty(nextToLast, "NAME").getValue()); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("Larry", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void commit_tableRemovedItem_shouldBeRemovedFromDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.removeItem(last); + container.commit(); + Assert.assertFalse(last.equals(container.lastItemId())); + } + + @Test + public void commit_tableLastItemUpdated_shouldUpdateRowInDB() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("Donald"); + container.commit(); + Assert.assertEquals("Donald", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void rollback_tableItemAdded_discardsAddedItem() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("foo"); + Assert.assertEquals(size + 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void rollback_tableItemRemoved_restoresRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + int size = container.size(); + Object last = container.lastItemId(); + container.removeItem(last); + Assert.assertEquals(size - 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertEquals(last, container.lastItemId()); + } + + @Test + public void rollback_tableItemChanged_discardsChanges() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("foo"); + container.rollback(); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void itemChangeNotification_table_isModifiedReturnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + RowItem last = (RowItem) container.getItem(container.lastItemId()); + container.itemChangeNotification(last); + Assert.assertTrue(container.isModified()); + } + + @Test + public void itemSetChangeListeners_table_shouldFire() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.replay(listener); + + container.addListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void itemSetChangeListeners_tableItemRemoved_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeItem(container.lastItemId()); + + EasyMock.verify(listener); + } + + @Test + public void removeListener_table_shouldNotFire() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void isModified_tableRemovedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.removeItem(container.lastItemId()); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_tableAddedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.addItem(); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_tableChangedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Assert.assertFalse(container.isModified()); + container.getContainerProperty(container.lastItemId(), "NAME") + .setValue("foo"); + Assert.assertTrue(container.isModified()); + } + + @Test + public void getSortableContainerPropertyIds_table_returnsAllPropertyIds() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + Collection<?> sortableIds = container.getSortableContainerPropertyIds(); + Assert.assertTrue(sortableIds.contains("ID")); + Assert.assertTrue(sortableIds.contains("NAME")); + Assert.assertTrue(sortableIds.contains("AGE")); + Assert.assertEquals(3, sortableIds.size()); + if (AllTests.db == DB.MSSQL || AllTests.db == DB.ORACLE) { + Assert.assertFalse(sortableIds.contains("rownum")); + } + } + + @Test + public void addOrderBy_table_shouldReorderResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addOrderBy(new OrderBy("NAME", true)); + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test(expected = IllegalArgumentException.class) + public void addOrderBy_tableIllegalColumn_shouldFail() throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + container.addOrderBy(new OrderBy("asdf", true)); + } + + @Test + public void sort_table_sortsByName() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addFilter_table_filtersResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Like("NAME", "%lle")); + // Ville, Kalle, Pelle + Assert.assertEquals(3, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addContainerFilter_filtersResults() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addContainerFilter_ignoreCase_filtersResults() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "vi", true, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void removeAllContainerFilters_table_noFiltering() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeAllContainerFilters(); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void removeContainerFilters_table_noFiltering() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeContainerFilters("NAME"); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + + @Test + public void addFilter_tableBufferedItems_alsoFiltersBufferedItems() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Palle"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Bengt"); + + container.addContainerFilter(new Like("NAME", "%lle")); + + // Ville, Kalle, Pelle, Palle + Assert.assertEquals(4, container.size()); + Assert.assertEquals( + "Ville", + container.getContainerProperty(container.getIdByIndex(0), + "NAME").getValue()); + Assert.assertEquals( + "Kalle", + container.getContainerProperty(container.getIdByIndex(1), + "NAME").getValue()); + Assert.assertEquals( + "Pelle", + container.getContainerProperty(container.getIdByIndex(2), + "NAME").getValue()); + Assert.assertEquals( + "Palle", + container.getContainerProperty(container.getIdByIndex(3), + "NAME").getValue()); + + Assert.assertNull(container.getIdByIndex(4)); + Assert.assertNull(container.nextItemId(container.getIdByIndex(3))); + + Assert.assertFalse(container.containsId(id2)); + Assert.assertFalse(container.getItemIds().contains(id2)); + + Assert.assertNull(container.getItem(id2)); + Assert.assertEquals(-1, container.indexOfId(id2)); + + Assert.assertNotSame(id2, container.lastItemId()); + Assert.assertSame(id1, container.lastItemId()); + } + + @Test + public void sort_tableBufferedItems_sortsBufferedItemsLastInOrderAdded() + throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Wilbert"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Albert"); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville, Wilbert, Albert + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals( + "Wilbert", + container.getContainerProperty( + container.getIdByIndex(container.size() - 2), "NAME") + .getValue()); + Assert.assertEquals("Albert", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java new file mode 100644 index 0000000000..6649bc16e8 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java @@ -0,0 +1,2458 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryDelegate; +import com.vaadin.data.util.sqlcontainer.query.FreeformStatementDelegate; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; + +public class SQLContainerTest { + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void constructor_withFreeformQuery_shouldSucceed() + throws SQLException { + new SQLContainer(new FreeformQuery("SELECT * FROM people", + connectionPool, "ID")); + } + + @Test(expected = SQLException.class) + public void constructor_withIllegalFreeformQuery_shouldFail() + throws SQLException { + SQLContainer c = new SQLContainer(new FreeformQuery( + "SELECT * FROM asdf", connectionPool, "ID")); + c.getItem(c.firstItemId()); + } + + @Test + public void containsId_withFreeformQueryAndExistingId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertTrue(container.containsId(new RowId(new Object[] { 1 }))); + } + + @Test + public void containsId_withFreeformQueryAndNonexistingId_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container + .containsId(new RowId(new Object[] { 1337 }))); + } + + @Test + public void getContainerProperty_freeformExistingItemIdAndPropertyId_returnsProperty() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + "Ville", + container + .getContainerProperty( + new RowId(new Object[] { new BigDecimal( + 0 + offset) }), "NAME").getValue()); + } else { + Assert.assertEquals( + "Ville", + container.getContainerProperty( + new RowId(new Object[] { 0 + offset }), "NAME") + .getValue()); + } + } + + @Test + public void getContainerProperty_freeformExistingItemIdAndNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1 + offset }), "asdf")); + } + + @Test + public void getContainerProperty_freeformNonexistingItemId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getContainerProperty(new RowId( + new Object[] { 1337 + offset }), "NAME")); + } + + @Test + public void getContainerPropertyIds_freeform_returnsIDAndNAME() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> propertyIds = container.getContainerPropertyIds(); + Assert.assertEquals(3, propertyIds.size()); + Assert.assertArrayEquals(new String[] { "ID", "NAME", "AGE" }, + propertyIds.toArray()); + } + + @Test + public void getItem_freeformExistingItemId_returnsItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 0 + offset) })); + } else { + item = container.getItem(new RowId(new Object[] { 0 + offset })); + } + Assert.assertNotNull(item); + Assert.assertEquals("Ville", item.getItemProperty("NAME").getValue()); + } + + @Test + public void getItem_freeform5000RowsWithParameter1337_returnsItemWithId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Item item; + if (AllTests.db == DB.ORACLE) { + item = container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertNotNull(item); + Assert.assertEquals(new BigDecimal(1337 + offset), item + .getItemProperty("ID").getValue()); + } else { + item = container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertNotNull(item); + Assert.assertEquals(1337 + offset, item.getItemProperty("ID") + .getValue()); + } + Assert.assertEquals("Person 1337", item.getItemProperty("NAME") + .getValue()); + } + + @Test + public void getItemIds_freeform_returnsItemIdsWithKeys0through3() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> itemIds = container.getItemIds(); + Assert.assertEquals(4, itemIds.size()); + RowId zero = new RowId(new Object[] { 0 + offset }); + RowId one = new RowId(new Object[] { 1 + offset }); + RowId two = new RowId(new Object[] { 2 + offset }); + RowId three = new RowId(new Object[] { 3 + offset }); + if (AllTests.db == DB.ORACLE) { + String[] correct = new String[] { "1", "2", "3", "4" }; + List<String> oracle = new ArrayList<String>(); + for (Object o : itemIds) { + oracle.add(o.toString()); + } + Assert.assertArrayEquals(correct, oracle.toArray()); + } else { + Assert.assertArrayEquals(new Object[] { zero, one, two, three }, + itemIds.toArray()); + } + } + + @Test + public void getType_freeformNAMEPropertyId_returnsString() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(String.class, container.getType("NAME")); + } + + @Test + public void getType_freeformIDPropertyId_returnsInteger() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(BigDecimal.class, container.getType("ID")); + } else { + Assert.assertEquals(Integer.class, container.getType("ID")); + } + } + + @Test + public void getType_freeformNonexistingPropertyId_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertNull(container.getType("asdf")); + } + + @Test + public void size_freeform_returnsFour() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + } + + @Test + public void size_freeformOneAddedItem_returnsFive() throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', '42')"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', '42')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(5, container.size()); + } + + @Test + public void indexOfId_freeformWithParameterThree_returnsThree() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(3, container.indexOfId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertEquals(3, + container.indexOfId(new RowId(new Object[] { 3 + offset }))); + } + } + + @Test + public void indexOfId_freeform5000RowsWithParameter1337_returns1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + container.getItem(new RowId(new Object[] { new BigDecimal( + 1337 + offset) })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { new BigDecimal(1337 + offset) }))); + } else { + container.getItem(new RowId(new Object[] { 1337 + offset })); + Assert.assertEquals(1337, container.indexOfId(new RowId( + new Object[] { 1337 + offset }))); + } + } + + @Test + public void getIdByIndex_freeform5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new RowId(new Object[] { new BigDecimal( + 1337 + offset) }), itemId); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @SuppressWarnings("unchecked") + @Test + public void getIdByIndex_freeformWithPaging5000rowsIndex1337_returnsRowId1337() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1337 + offset }).toString(), + itemId.toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1337 + offset }), + itemId); + } + } + + @Test + public void nextItemId_freeformCurrentItem1337_returnsItem1338() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1338 + offset }).toString(), + container.nextItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1338 + offset }), + container.nextItemId(itemId)); + } + } + + @Test + public void prevItemId_freeformCurrentItem1337_returns1336() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + Object itemId = container.getIdByIndex(1337); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 1336 + offset }).toString(), + container.prevItemId(itemId).toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 1336 + offset }), + container.prevItemId(itemId)); + } + } + + @Test + public void firstItemId_freeform_returnsItemId0() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 0 + offset }).toString(), + container.firstItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 0 + offset }), + container.firstItemId()); + } + } + + @Test + public void lastItemId_freeform5000Rows_returnsItemId4999() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals( + new RowId(new Object[] { 4999 + offset }).toString(), + container.lastItemId().toString()); + } else { + Assert.assertEquals(new RowId(new Object[] { 4999 + offset }), + container.lastItemId()); + } + } + + @Test + public void isFirstId_freeformActualFirstId_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { new BigDecimal(0 + offset) }))); + } else { + Assert.assertTrue(container.isFirstId(new RowId( + new Object[] { 0 + offset }))); + } + } + + @Test + public void isFirstId_freeformSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isFirstId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_freeformSecondId_returnsFalse() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { new BigDecimal(1 + offset) }))); + } else { + Assert.assertFalse(container.isLastId(new RowId( + new Object[] { 1 + offset }))); + } + } + + @Test + public void isLastId_freeformLastId_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(3 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 3 + offset }))); + } + } + + @Test + public void isLastId_freeform5000RowsLastId_returnsTrue() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people ORDER BY \"ID\" ASC", connectionPool, + "ID")); + if (AllTests.db == DB.ORACLE) { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { new BigDecimal(4999 + offset) }))); + } else { + Assert.assertTrue(container.isLastId(new RowId( + new Object[] { 4999 + offset }))); + } + } + + @Test + public void refresh_freeform_sizeShouldUpdate() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + container.refresh(); + Assert.assertEquals(5000, container.size()); + } + + @Test + public void refresh_freeformWithoutCallingRefresh_sizeShouldNotUpdate() + throws SQLException { + // Yeah, this is a weird one. We're testing that the size doesn't update + // after adding lots of items unless we call refresh inbetween. This to + // make sure that the refresh method actually refreshes stuff and isn't + // a NOP. + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(4, container.size()); + DataGenerator.addFiveThousandPeople(connectionPool); + Assert.assertEquals(4, container.size()); + } + + @Test + public void setAutoCommit_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.setAutoCommit(true); + Assert.assertTrue(container.isAutoCommit()); + container.setAutoCommit(false); + Assert.assertFalse(container.isAutoCommit()); + } + + @Test + public void getPageLength_freeform_returnsDefault100() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertEquals(100, container.getPageLength()); + } + + @Test + public void setPageLength_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.setPageLength(20); + Assert.assertEquals(20, container.getPageLength()); + container.setPageLength(200); + Assert.assertEquals(200, container.getPageLength()); + } + + @Test(expected = UnsupportedOperationException.class) + public void addContainerProperty_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerProperty("asdf", String.class, ""); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeContainerProperty_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.removeContainerProperty("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem("asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObjectObject_normal_isUnsupported() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAfter("asdf", "foo"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtIntObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAt(2, "asdf"); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAtInt_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAt(2); + } + + @Test(expected = UnsupportedOperationException.class) + public void addItemAfterObject_normal_isUnsupported() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItemAfter("asdf"); + } + + @Test + public void addItem_freeformAddOneNewItem_returnsItemId() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object itemId = container.addItem(); + Assert.assertNotNull(itemId); + } + + @Test + public void addItem_freeformAddOneNewItem_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + container.addItem(); + Assert.assertEquals(size + 1, container.size()); + } + + @Test + public void addItem_freeformAddTwoNewItems_shouldChangeSize() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(size + 2, container.size()); + Assert.assertNotSame(id1, id2); + Assert.assertFalse(id1.equals(id2)); + } + + @Test + public void nextItemId_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.nextItemId(lastId)); + } + + @Test + public void lastItemId_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object lastId = container.lastItemId(); + Object id = container.addItem(); + Assert.assertEquals(id, container.lastItemId()); + Assert.assertNotSame(lastId, container.lastItemId()); + } + + @Test + public void indexOfId_freeformNewlyAddedItem_returnsFour() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertEquals(4, container.indexOfId(id)); + } + + @Test + public void getItem_freeformNewlyAddedItem_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + } + + @Test + public void getItem_freeformNewlyAddedItemAndFiltered_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerFilter(new Equal("NAME", "asdf")); + Object id = container.addItem(); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemUnfiltered_freeformNewlyAddedItemAndFiltered_returnsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addContainerFilter(new Equal("NAME", "asdf")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItemUnfiltered(id)); + } + + @Test + public void getItemIds_freeformNewlyAddedItem_containsNewlyAdded() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + } + + @Test + public void getContainerProperty_freeformNewlyAddedItem_returnsPropertyOfNewlyAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Item item = container.getItem(id); + item.getItemProperty("NAME").setValue("asdf"); + Assert.assertEquals("asdf", container.getContainerProperty(id, "NAME") + .getValue()); + } + + @Test + public void containsId_freeformNewlyAddedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + } + + @Test + public void prevItemId_freeformTwoNewlyAddedItems_returnsFirstAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id1 = container.addItem(); + Object id2 = container.addItem(); + Assert.assertEquals(id1, container.prevItemId(id2)); + } + + @Test + public void firstItemId_freeformEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertSame(id, container.firstItemId()); + } + + @Test + public void isFirstId_freeformEmptyResultSet_returnsFirstAddedItem() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.isFirstId(id)); + } + + @Test + public void isLastId_freeformOneItemAdded_returnsTrueForAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.isLastId(id)); + } + + @Test + public void isLastId_freeformTwoItemsAdded_returnsTrueForLastAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem(); + Object id2 = container.addItem(); + Assert.assertTrue(container.isLastId(id2)); + } + + @Test + public void getIdByIndex_freeformOneItemAddedLastIndexInContainer_returnsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertEquals(id, container.getIdByIndex(container.size() - 1)); + } + + @Test + public void removeItem_freeformNoAddedItems_removesItemFromContainer() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.firstItemId()); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void containsId_freeformRemovedItem_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_unknownObject() throws SQLException { + + Handler ensureNoLogging = new Handler() { + + @Override + public void publish(LogRecord record) { + Assert.fail("No messages should be logged"); + + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }; + + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Logger logger = Logger.getLogger(SQLContainer.class.getName()); + + logger.addHandler(ensureNoLogging); + try { + Assert.assertFalse(container.containsId(new Object())); + } finally { + logger.removeHandler(ensureNoLogging); + } + } + + @Test + public void removeItem_freeformOneAddedItem_removesTheAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + int size = container.size(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + Assert.assertEquals(size - 1, container.size()); + } + + @Test + public void getItem_freeformItemRemoved_returnsNull() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItem_freeformAddedItemRemoved_returnsNull() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertNotNull(container.getItem(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNull(container.getItem(id)); + } + + @Test + public void getItemIds_freeformItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void getItemIds_freeformAddedItemRemoved_shouldNotContainRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.getItemIds().contains(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.getItemIds().contains(id)); + } + + @Test + public void containsId_freeformItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.firstItemId(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void containsId_freeformAddedItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + Assert.assertTrue(container.removeItem(id)); + Assert.assertFalse(container.containsId(id)); + } + + @Test + public void nextItemId_freeformItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void nextItemId_freeformAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(third, container.nextItemId(first)); + } + + @Test + public void prevItemId_freeformItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.getIdByIndex(0); + Object second = container.getIdByIndex(1); + Object third = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void prevItemId_freeformAddedItemRemoved_skipsRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.lastItemId(); + Object second = container.addItem(); + Object third = container.addItem(); + Assert.assertTrue(container.removeItem(second)); + Assert.assertEquals(first, container.prevItemId(third)); + } + + @Test + public void firstItemId_freeformFirstItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertNotSame(first, container.firstItemId()); + } + + @Test + public void firstItemId_freeformNewlyAddedFirstItemRemoved_resultChanges() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object first = container.addItem(); + Object second = container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertSame(second, container.firstItemId()); + } + + @Test + public void lastItemId_freeformLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void lastItemId_freeformAddedLastItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertNotSame(last, container.lastItemId()); + } + + @Test + public void isFirstId_freeformFirstItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object first = container.firstItemId(); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isFirstId_freeformAddedFirstItemRemoved_returnsFalse() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM GARBAGE", connectionPool, "ID")); + Object first = container.addItem(); + container.addItem(); + Assert.assertSame(first, container.firstItemId()); + Assert.assertTrue(container.removeItem(first)); + Assert.assertFalse(container.isFirstId(first)); + } + + @Test + public void isLastId_freeformLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void isLastId_freeformAddedLastItemRemoved_returnsFalse() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.addItem(); + Assert.assertSame(last, container.lastItemId()); + Assert.assertTrue(container.removeItem(last)); + Assert.assertFalse(container.isLastId(last)); + } + + @Test + public void indexOfId_freeformItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void indexOfId_freeformAddedItemRemoved_returnsNegOne() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + Assert.assertTrue(container.indexOfId(id) != -1); + Assert.assertTrue(container.removeItem(id)); + Assert.assertEquals(-1, container.indexOfId(id)); + } + + @Test + public void getIdByIndex_freeformItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.getIdByIndex(2); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(2)); + } + + @Test + public void getIdByIndex_freeformAddedItemRemoved_resultChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object id = container.addItem(); + container.addItem(); + int index = container.indexOfId(id); + Assert.assertTrue(container.removeItem(id)); + Assert.assertNotSame(id, container.getIdByIndex(index)); + } + + @Test + public void removeAllItems_freeform_shouldSucceed() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @Test + public void removeAllItems_freeformAddedItems_shouldSucceed() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addItem(); + container.addItem(); + Assert.assertTrue(container.removeAllItems()); + Assert.assertEquals(0, container.size()); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformAddedItem_shouldBeWrittenToDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into people values('" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } else { + statement + .executeUpdate("insert into people values(default, '" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("New Name"); + container.getContainerProperty(id, "AGE").setValue(30); + Assert.assertTrue(id instanceof TemporaryRowId); + Assert.assertSame(id, container.lastItemId()); + container.commit(); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("New Name", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformTwoAddedItems_shouldBeWrittenToDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement + .executeUpdate("insert into people values('" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } else { + statement + .executeUpdate("insert into people values(default, '" + + item.getItemProperty("NAME") + .getValue() + + "', '" + + item.getItemProperty("AGE") + .getValue() + "')"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object id = container.addItem(); + Object id2 = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("Herbert"); + container.getContainerProperty(id, "AGE").setValue(30); + container.getContainerProperty(id2, "NAME").setValue("Larry"); + container.getContainerProperty(id2, "AGE").setValue(50); + Assert.assertTrue(id2 instanceof TemporaryRowId); + Assert.assertSame(id2, container.lastItemId()); + container.commit(); + Object nextToLast = container.getIdByIndex(container.size() - 2); + Assert.assertFalse(nextToLast instanceof TemporaryRowId); + Assert.assertEquals("Herbert", + container.getContainerProperty(nextToLast, "NAME").getValue()); + Assert.assertFalse(container.lastItemId() instanceof TemporaryRowId); + Assert.assertEquals("Larry", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformRemovedItem_shouldBeRemovedFromDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Boolean>() { + @Override + public Boolean answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + statement + .executeUpdate("DELETE FROM people WHERE \"ID\"=" + + item.getItemProperty("ID").getValue()); + statement.close(); + return true; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.removeItem(last); + container.commit(); + Assert.assertFalse(last.equals(container.lastItemId())); + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void commit_freeformLastItemUpdated_shouldUpdateRowInDB() + throws SQLException { + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))) + .andAnswer(new IAnswer<Integer>() { + @Override + public Integer answer() throws Throwable { + Connection conn = (Connection) EasyMock + .getCurrentArguments()[0]; + RowItem item = (RowItem) EasyMock.getCurrentArguments()[1]; + Statement statement = conn.createStatement(); + statement.executeUpdate("UPDATE people SET \"NAME\"='" + + item.getItemProperty("NAME").getValue() + + "' WHERE \"ID\"=" + + item.getItemProperty("ID").getValue()); + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + return 1; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT row_number() OVER" + + " ( ORDER BY \"ID\" ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN " + + start + + " AND " + end; + return q; + } else if (AllTests.db == DB.ORACLE) { + int start = offset + 1; + int end = offset + limit + 1; + String q = "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY \"ID\" ASC) x) " + + " WHERE r BETWEEN " + + start + + " AND " + + end; + return q; + } else { + return "SELECT * FROM people LIMIT " + limit + + " OFFSET " + offset; + } + } + }).anyTimes(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + query.setDelegate(delegate); + EasyMock.replay(delegate); + SQLContainer container = new SQLContainer(query); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("Donald"); + container.commit(); + Assert.assertEquals("Donald", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + EasyMock.verify(delegate); + } + + @Test + public void rollback_freeformItemAdded_discardsAddedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object id = container.addItem(); + container.getContainerProperty(id, "NAME").setValue("foo"); + Assert.assertEquals(size + 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void rollback_freeformItemRemoved_restoresRemovedItem() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + int size = container.size(); + Object last = container.lastItemId(); + container.removeItem(last); + Assert.assertEquals(size - 1, container.size()); + container.rollback(); + Assert.assertEquals(size, container.size()); + Assert.assertEquals(last, container.lastItemId()); + } + + @Test + public void rollback_freeformItemChanged_discardsChanges() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Object last = container.lastItemId(); + container.getContainerProperty(last, "NAME").setValue("foo"); + container.rollback(); + Assert.assertFalse("foo".equals(container.getContainerProperty( + container.lastItemId(), "NAME").getValue())); + } + + @Test + public void itemChangeNotification_freeform_isModifiedReturnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + RowItem last = (RowItem) container.getItem(container.lastItemId()); + container.itemChangeNotification(last); + Assert.assertTrue(container.isModified()); + } + + @Test + public void itemSetChangeListeners_freeform_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.replay(listener); + + container.addListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void itemSetChangeListeners_freeformItemRemoved_shouldFire() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + listener.containerItemSetChange(EasyMock.isA(ItemSetChangeEvent.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeItem(container.lastItemId()); + + EasyMock.verify(listener); + } + + @Test + public void removeListener_freeform_shouldNotFire() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + ItemSetChangeListener listener = EasyMock + .createMock(ItemSetChangeListener.class); + EasyMock.replay(listener); + + container.addListener(listener); + container.removeListener(listener); + container.addItem(); + + EasyMock.verify(listener); + } + + @Test + public void isModified_freeformRemovedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.removeItem(container.lastItemId()); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_freeformAddedItem_returnsTrue() throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.addItem(); + Assert.assertTrue(container.isModified()); + } + + @Test + public void isModified_freeformChangedItem_returnsTrue() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Assert.assertFalse(container.isModified()); + container.getContainerProperty(container.lastItemId(), "NAME") + .setValue("foo"); + Assert.assertTrue(container.isModified()); + } + + @Test + public void getSortableContainerPropertyIds_freeform_returnsAllPropertyIds() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + Collection<?> sortableIds = container.getSortableContainerPropertyIds(); + Assert.assertTrue(sortableIds.contains("ID")); + Assert.assertTrue(sortableIds.contains("NAME")); + Assert.assertTrue(sortableIds.contains("AGE")); + Assert.assertEquals(3, sortableIds.size()); + } + + @SuppressWarnings("unchecked") + @Test + public void addOrderBy_freeform_shouldReorderResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addOrderBy(new OrderBy("NAME", true)); + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @Test(expected = IllegalArgumentException.class) + public void addOrderBy_freeformIllegalColumn_shouldFail() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", connectionPool, "ID")); + container.addOrderBy(new OrderBy("asdf", true)); + } + + @SuppressWarnings("unchecked") + @Test + public void sort_freeform_sortsByName() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addFilter_freeform_filtersResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Like("NAME", "%lle")); + // Ville, Kalle, Pelle + Assert.assertEquals(3, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addContainerFilter_filtersResults() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addContainerFilter_ignoreCase_filtersResults() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + // FIXME LIKE %asdf% doesn't match a string that begins with asdf + container.addContainerFilter("NAME", "vi", true, true); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void removeAllContainerFilters_freeform_noFiltering() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, false); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeAllContainerFilters(); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void removeContainerFilters_freeform_noFiltering() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter("NAME", "Vi", false, true); + + // Ville + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Ville", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.removeContainerFilters("NAME"); + + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void addFilter_freeformBufferedItems_alsoFiltersBufferedItems() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Palle"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Bengt"); + + container.addContainerFilter(new Like("NAME", "%lle")); + + // Ville, Kalle, Pelle, Palle + Assert.assertEquals(4, container.size()); + Assert.assertEquals( + "Ville", + container.getContainerProperty(container.getIdByIndex(0), + "NAME").getValue()); + Assert.assertEquals( + "Kalle", + container.getContainerProperty(container.getIdByIndex(1), + "NAME").getValue()); + Assert.assertEquals( + "Pelle", + container.getContainerProperty(container.getIdByIndex(2), + "NAME").getValue()); + Assert.assertEquals( + "Palle", + container.getContainerProperty(container.getIdByIndex(3), + "NAME").getValue()); + + Assert.assertNull(container.getIdByIndex(4)); + Assert.assertNull(container.nextItemId(container.getIdByIndex(3))); + + Assert.assertFalse(container.containsId(id2)); + Assert.assertFalse(container.getItemIds().contains(id2)); + + Assert.assertNull(container.getItem(id2)); + Assert.assertEquals(-1, container.indexOfId(id2)); + + Assert.assertNotSame(id2, container.lastItemId()); + Assert.assertSame(id1, container.lastItemId()); + + EasyMock.verify(delegate); + } + + @SuppressWarnings("unchecked") + @Test + public void sort_freeformBufferedItems_sortsBufferedItemsLastInOrderAdded() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + connectionPool, "ID"); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + final ArrayList<OrderBy> orderBys = new ArrayList<OrderBy>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<OrderBy> orders = (List<OrderBy>) EasyMock + .getCurrentArguments()[0]; + orderBys.clear(); + orderBys.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryString(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<String>() { + @Override + public String answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + if (AllTests.db == DB.MSSQL) { + SQLGenerator gen = new MSSQLGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else if (AllTests.db == DB.ORACLE) { + SQLGenerator gen = new OracleGenerator(); + if (orderBys == null || orderBys.isEmpty()) { + List<OrderBy> ob = new ArrayList<OrderBy>(); + ob.add(new OrderBy("ID", true)); + return gen.generateSelectQuery("people", null, + ob, offset, limit, null) + .getQueryString(); + } else { + return gen.generateSelectQuery("people", null, + orderBys, offset, limit, null) + .getQueryString(); + } + } else { + StringBuffer query = new StringBuffer( + "SELECT * FROM people"); + if (!orderBys.isEmpty()) { + query.append(" ORDER BY "); + for (OrderBy orderBy : orderBys) { + query.append("\"" + orderBy.getColumn() + + "\""); + if (orderBy.isAscending()) { + query.append(" ASC"); + } else { + query.append(" DESC"); + } + } + } + query.append(" LIMIT ").append(limit) + .append(" OFFSET ").append(offset); + return query.toString(); + } + } + }).anyTimes(); + EasyMock.expect(delegate.getCountQuery()) + .andThrow(new UnsupportedOperationException()).anyTimes(); + EasyMock.replay(delegate); + + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals("Ville", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + Object id1 = container.addItem(); + container.getContainerProperty(id1, "NAME").setValue("Wilbert"); + Object id2 = container.addItem(); + container.getContainerProperty(id2, "NAME").setValue("Albert"); + + container.sort(new Object[] { "NAME" }, new boolean[] { true }); + + // Börje, Kalle, Pelle, Ville, Wilbert, Albert + Assert.assertEquals("Börje", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + Assert.assertEquals( + "Wilbert", + container.getContainerProperty( + container.getIdByIndex(container.size() - 2), "NAME") + .getValue()); + Assert.assertEquals("Albert", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + EasyMock.verify(delegate); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java new file mode 100644 index 0000000000..a12786f13a --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java @@ -0,0 +1,186 @@ +package com.vaadin.data.util.sqlcontainer; + +import java.math.BigDecimal; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformStatementDelegate; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; +import com.vaadin.ui.Table; +import com.vaadin.ui.Window; + +public class TicketTests { + + private SimpleJDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @Test + public void ticket5867_throwsIllegalState_transactionAlreadyActive() + throws SQLException { + SQLContainer container = new SQLContainer(new FreeformQuery( + "SELECT * FROM people", Arrays.asList("ID"), connectionPool)); + Table table = new Table(); + Window w = new Window(); + w.addComponent(table); + table.setContainerDataSource(container); + } + + @SuppressWarnings("unchecked") + @Test + public void ticket6136_freeform_ageIs18() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformStatementDelegate delegate = EasyMock + .createMock(FreeformStatementDelegate.class); + final ArrayList<Filter> filters = new ArrayList<Filter>(); + delegate.setFilters(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(EasyMock.isA(List.class)); + EasyMock.expectLastCall().anyTimes(); + delegate.setOrderBy(null); + EasyMock.expectLastCall().anyTimes(); + delegate.setFilters(EasyMock.isA(List.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + List<Filter> orders = (List<Filter>) EasyMock + .getCurrentArguments()[0]; + filters.clear(); + filters.addAll(orders); + return null; + } + }).anyTimes(); + EasyMock.expect( + delegate.getQueryStatement(EasyMock.anyInt(), EasyMock.anyInt())) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + public StatementHelper answer() throws Throwable { + Object[] args = EasyMock.getCurrentArguments(); + int offset = (Integer) (args[0]); + int limit = (Integer) (args[1]); + return FreeformQueryUtil.getQueryWithFilters(filters, + offset, limit); + } + }).anyTimes(); + EasyMock.expect(delegate.getCountStatement()) + .andAnswer(new IAnswer<StatementHelper>() { + @Override + @SuppressWarnings("deprecation") + public StatementHelper answer() throws Throwable { + StatementHelper sh = new StatementHelper(); + StringBuffer query = new StringBuffer( + "SELECT COUNT(*) FROM people"); + if (!filters.isEmpty()) { + query.append(QueryBuilder.getWhereStringForFilters( + filters, sh)); + } + sh.setQueryString(query.toString()); + return sh; + } + }).anyTimes(); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + Assert.assertEquals("Börje", + container.getContainerProperty(container.lastItemId(), "NAME") + .getValue()); + + container.addContainerFilter(new Equal("AGE", 18)); + // Pelle + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new BigDecimal(18), container + .getContainerProperty(container.firstItemId(), "AGE") + .getValue()); + } else { + Assert.assertEquals( + 18, + container.getContainerProperty(container.firstItemId(), + "AGE").getValue()); + } + + EasyMock.verify(delegate); + } + + @Test + public void ticket6136_table_ageIs18() throws SQLException { + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + // Ville, Kalle, Pelle, Börje + Assert.assertEquals(4, container.size()); + + container.addContainerFilter(new Equal("AGE", 18)); + + // Pelle + Assert.assertEquals(1, container.size()); + Assert.assertEquals("Pelle", + container.getContainerProperty(container.firstItemId(), "NAME") + .getValue()); + if (AllTests.db == DB.ORACLE) { + Assert.assertEquals(new BigDecimal(18), container + .getContainerProperty(container.firstItemId(), "AGE") + .getValue()); + } else { + Assert.assertEquals( + 18, + container.getContainerProperty(container.firstItemId(), + "AGE").getValue()); + } + } + + @Test + public void ticket7434_getItem_Modified_Changed_Unchanged() + throws SQLException { + SQLContainer container = new SQLContainer(new TableQuery("people", + connectionPool, AllTests.sqlGen)); + + Object id = container.firstItemId(); + Item item = container.getItem(id); + String name = (String) item.getItemProperty("NAME").getValue(); + + // set a different name + item.getItemProperty("NAME").setValue("otherName"); + Assert.assertEquals("otherName", item.getItemProperty("NAME") + .getValue()); + + // access the item and reset the name to its old value + Item item2 = container.getItem(id); + item2.getItemProperty("NAME").setValue(name); + Assert.assertEquals(name, item2.getItemProperty("NAME").getValue()); + + Item item3 = container.getItem(id); + String name3 = (String) item3.getItemProperty("NAME").getValue(); + + Assert.assertEquals(name, name3); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java new file mode 100644 index 0000000000..31bdf2b81b --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/UtilTest.java @@ -0,0 +1,53 @@ +package com.vaadin.data.util.sqlcontainer; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.SQLUtil; + +public class UtilTest { + + @Test + public void escapeSQL_noQuotes_returnsSameString() { + Assert.assertEquals("asdf", SQLUtil.escapeSQL("asdf")); + } + + @Test + public void escapeSQL_singleQuotes_returnsEscapedString() { + Assert.assertEquals("O''Brien", SQLUtil.escapeSQL("O'Brien")); + } + + @Test + public void escapeSQL_severalQuotes_returnsEscapedString() { + Assert.assertEquals("asdf''ghjk''qwerty", + SQLUtil.escapeSQL("asdf'ghjk'qwerty")); + } + + @Test + public void escapeSQL_doubleQuotes_returnsEscapedString() { + Assert.assertEquals("asdf\\\"foo", SQLUtil.escapeSQL("asdf\"foo")); + } + + @Test + public void escapeSQL_multipleDoubleQuotes_returnsEscapedString() { + Assert.assertEquals("asdf\\\"foo\\\"bar", + SQLUtil.escapeSQL("asdf\"foo\"bar")); + } + + @Test + public void escapeSQL_backslashes_returnsEscapedString() { + Assert.assertEquals("foo\\\\nbar\\\\r", + SQLUtil.escapeSQL("foo\\nbar\\r")); + } + + @Test + public void escapeSQL_x00_removesX00() { + Assert.assertEquals("foobar", SQLUtil.escapeSQL("foo\\x00bar")); + } + + @Test + public void escapeSQL_x1a_removesX1a() { + Assert.assertEquals("foobar", SQLUtil.escapeSQL("foo\\x1abar")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java new file mode 100644 index 0000000000..65a995120e --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPoolTest.java @@ -0,0 +1,108 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.sql.DataSource; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +public class J2EEConnectionPoolTest { + + @Test + public void reserveConnection_dataSourceSpecified_shouldReturnValidConnection() + throws SQLException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + EasyMock.replay(connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + EasyMock.verify(connection, ds); + } + + @Test + public void releaseConnection_shouldCloseConnection() throws SQLException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + connection.close(); + EasyMock.expectLastCall(); + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + EasyMock.replay(connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + pool.releaseConnection(c); + EasyMock.verify(connection, ds); + } + + @Test + public void reserveConnection_dataSourceLookedUp_shouldReturnValidConnection() + throws SQLException, NamingException { + Connection connection = EasyMock.createMock(Connection.class); + connection.setAutoCommit(false); + EasyMock.expectLastCall(); + connection.close(); + EasyMock.expectLastCall(); + + DataSource ds = EasyMock.createMock(DataSource.class); + ds.getConnection(); + EasyMock.expectLastCall().andReturn(connection); + + System.setProperty("java.naming.factory.initial", + "com.vaadin.data.util.sqlcontainer.connection.MockInitialContextFactory"); + Context context = EasyMock.createMock(Context.class); + context.lookup("testDataSource"); + EasyMock.expectLastCall().andReturn(ds); + MockInitialContextFactory.setMockContext(context); + + EasyMock.replay(context, connection, ds); + + J2EEConnectionPool pool = new J2EEConnectionPool("testDataSource"); + Connection c = pool.reserveConnection(); + Assert.assertEquals(connection, c); + pool.releaseConnection(c); + EasyMock.verify(context, connection, ds); + } + + @Test(expected = SQLException.class) + public void reserveConnection_nonExistantDataSourceLookedUp_shouldFail() + throws SQLException, NamingException { + System.setProperty("java.naming.factory.initial", + "com.vaadin.addon.sqlcontainer.connection.MockInitialContextFactory"); + Context context = EasyMock.createMock(Context.class); + context.lookup("foo"); + EasyMock.expectLastCall().andThrow(new NamingException("fail")); + MockInitialContextFactory.setMockContext(context); + + EasyMock.replay(context); + + J2EEConnectionPool pool = new J2EEConnectionPool("foo"); + pool.reserveConnection(); + EasyMock.verify(context); + } + + @Test + public void releaseConnection_null_shouldSucceed() throws SQLException { + DataSource ds = EasyMock.createMock(DataSource.class); + EasyMock.replay(ds); + + J2EEConnectionPool pool = new J2EEConnectionPool(ds); + pool.releaseConnection(null); + EasyMock.verify(ds); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java new file mode 100644 index 0000000000..324899e373 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/MockInitialContextFactory.java @@ -0,0 +1,33 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + +import org.junit.Test; + +/** + * Provides a JNDI initial context factory for the MockContext. + */ +public class MockInitialContextFactory implements InitialContextFactory { + private static Context mockCtx = null; + + @Test + public void testDummy() { + // Added dummy test so JUnit will not complain about + // "No runnable methods". + } + + public static void setMockContext(Context ctx) { + mockCtx = ctx; + } + + @Override + public Context getInitialContext(java.util.Hashtable<?, ?> environment) + throws NamingException { + if (mockCtx == null) { + throw new IllegalStateException("mock context was not set."); + } + return mockCtx; + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java new file mode 100644 index 0000000000..147319643d --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/connection/SimpleJDBCConnectionPoolTest.java @@ -0,0 +1,172 @@ +package com.vaadin.data.util.sqlcontainer.connection; + +import java.sql.Connection; +import java.sql.SQLException; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; + +public class SimpleJDBCConnectionPoolTest { + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } + + @Test + public void reserveConnection_reserveNewConnection_returnsConnection() + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + Assert.assertNotNull(conn); + } + + @Test + public void releaseConnection_releaseUnused_shouldNotThrowException() + throws SQLException { + Connection conn = connectionPool.reserveConnection(); + connectionPool.releaseConnection(conn); + Assert.assertFalse(conn.isClosed()); + } + + @Test(expected = SQLException.class) + public void reserveConnection_noConnectionsLeft_shouldFail() + throws SQLException { + try { + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + connectionPool.reserveConnection(); + Assert.fail("Reserving connection didn't fail even though no connections are available!"); + } + + @Test + public void reserveConnection_oneConnectionLeft_returnsConnection() + throws SQLException { + try { + connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + Connection conn = connectionPool.reserveConnection(); + Assert.assertNotNull(conn); + } + + @Test + public void reserveConnection_oneConnectionJustReleased_returnsConnection() + throws SQLException { + Connection conn2 = null; + try { + connectionPool.reserveConnection(); + conn2 = connectionPool.reserveConnection(); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail("Exception before all connections used! " + + e.getMessage()); + } + + connectionPool.releaseConnection(conn2); + + connectionPool.reserveConnection(); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_allParametersNull_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool(null, null, + null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameGiven_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, null, null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameAndUrlGiven_shouldFail() + throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, AllTests.dbURL, null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construct_onlyDriverNameAndUrlAndUserGiven_shouldFail() + throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool( + AllTests.dbDriver, AllTests.dbURL, AllTests.dbUser, null); + } + + @Test(expected = RuntimeException.class) + public void construct_nonExistingDriver_shouldFail() throws SQLException { + SimpleJDBCConnectionPool cp = new SimpleJDBCConnectionPool("foo", + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd); + } + + @Test + public void reserveConnection_newConnectionOpened_shouldSucceed() + throws SQLException { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 0, 2); + Connection c = connectionPool.reserveConnection(); + Assert.assertNotNull(c); + } + + @Test + public void releaseConnection_nullConnection_shouldDoNothing() { + connectionPool.releaseConnection(null); + } + + @Test + public void releaseConnection_failingRollback_shouldCallClose() + throws SQLException { + Connection c = EasyMock.createMock(Connection.class); + c.getAutoCommit(); + EasyMock.expectLastCall().andReturn(false); + c.rollback(); + EasyMock.expectLastCall().andThrow(new SQLException("Rollback failed")); + c.close(); + EasyMock.expectLastCall().atLeastOnce(); + EasyMock.replay(c); + // make sure the connection pool is initialized + connectionPool.reserveConnection(); + connectionPool.releaseConnection(c); + EasyMock.verify(c); + } + + @Test + public void destroy_shouldCloseAllConnections() throws SQLException { + Connection c1 = connectionPool.reserveConnection(); + Connection c2 = connectionPool.reserveConnection(); + connectionPool.destroy(); + Assert.assertTrue(c1.isClosed()); + Assert.assertTrue(c2.isClosed()); + } + + @Test + public void destroy_shouldCloseAllConnections2() throws SQLException { + Connection c1 = connectionPool.reserveConnection(); + Connection c2 = connectionPool.reserveConnection(); + connectionPool.releaseConnection(c1); + connectionPool.releaseConnection(c2); + connectionPool.destroy(); + Assert.assertTrue(c1.isClosed()); + Assert.assertTrue(c2.isClosed()); + } + +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java new file mode 100644 index 0000000000..da4cfe4522 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/BetweenTest.java @@ -0,0 +1,122 @@ +package com.vaadin.data.util.sqlcontainer.filters; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.filter.Between; + +public class BetweenTest { + + private Item itemWithPropertyValue(Object propertyId, Object value) { + Property<?> property = EasyMock.createMock(Property.class); + property.getValue(); + EasyMock.expectLastCall().andReturn(value).anyTimes(); + EasyMock.replay(property); + + Item item = EasyMock.createMock(Item.class); + item.getItemProperty(propertyId); + EasyMock.expectLastCall().andReturn(property).anyTimes(); + EasyMock.replay(item); + return item; + } + + @Test + public void passesFilter_valueIsInRange_shouldBeTrue() { + Item item = itemWithPropertyValue("foo", 15); + Between between = new Between("foo", 1, 30); + Assert.assertTrue(between.passesFilter("foo", item)); + } + + @Test + public void passesFilter_valueIsOutOfRange_shouldBeFalse() { + Item item = itemWithPropertyValue("foo", 15); + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.passesFilter("foo", item)); + } + + @Test + public void passesFilter_valueNotComparable_shouldBeFalse() { + Item item = itemWithPropertyValue("foo", new Object()); + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.passesFilter("foo", item)); + } + + @Test + public void appliesToProperty_differentProperties_shoudlBeFalse() { + Between between = new Between("foo", 0, 2); + Assert.assertFalse(between.appliesToProperty("bar")); + } + + @Test + public void appliesToProperty_sameProperties_shouldBeTrue() { + Between between = new Between("foo", 0, 2); + Assert.assertTrue(between.appliesToProperty("foo")); + } + + @Test + public void hashCode_equalInstances_shouldBeEqual() { + Between b1 = new Between("foo", 0, 2); + Between b2 = new Between("foo", 0, 2); + Assert.assertEquals(b1.hashCode(), b2.hashCode()); + } + + @Test + public void equals_differentObjects_shouldBeFalse() { + Between b1 = new Between("foo", 0, 2); + Object obj = new Object(); + Assert.assertFalse(b1.equals(obj)); + } + + @Test + public void equals_sameInstance_shouldBeTrue() { + Between b1 = new Between("foo", 0, 2); + Between b2 = b1; + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_equalInstances_shouldBeTrue() { + Between b1 = new Between("foo", 0, 2); + Between b2 = new Between("foo", 0, 2); + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_equalInstances2_shouldBeTrue() { + Between b1 = new Between(null, null, null); + Between b2 = new Between(null, null, null); + Assert.assertTrue(b1.equals(b2)); + } + + @Test + public void equals_secondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", 0, 1); + Between b2 = new Between("foo", 0, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_firstAndSecondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", 0, null); + Between b2 = new Between("foo", 1, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_propertyAndFirstAndSecondValueDiffers_shouldBeFalse() { + Between b1 = new Between("foo", null, 1); + Between b2 = new Between("bar", 1, 2); + Assert.assertFalse(b1.equals(b2)); + } + + @Test + public void equals_propertiesDiffer_shouldBeFalse() { + Between b1 = new Between(null, 0, 1); + Between b2 = new Between("bar", 0, 1); + Assert.assertFalse(b1.equals(b2)); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java new file mode 100644 index 0000000000..f1130aad80 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/LikeTest.java @@ -0,0 +1,229 @@ +package com.vaadin.data.util.sqlcontainer.filters; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.data.util.filter.Like; + +public class LikeTest { + + @Test + public void passesFilter_valueIsNotStringType_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<Integer>(5)); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValue_shouldSucceed() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfooghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValueCaseInsensitive_shouldSucceed() { + Like like = new Like("test", "%foo%"); + like.setCaseSensitive(false); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfOOghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringContainingValueConstructedCaseInsensitive_shouldSucceed() { + Like like = new Like("test", "%foo%", false); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdfOOghij")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringNotContainingValue_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("asdbarghij")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringExactlyEqualToValue_shouldSucceed() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foo")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_containsLikeQueryOnStringEqualToValueMinusOneCharAtTheEnd_shouldFail() { + Like like = new Like("test", "%foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("fo")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_beginsWithLikeQueryOnStringBeginningWithValue_shouldSucceed() { + Like like = new Like("test", "foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foobar")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_beginsWithLikeQueryOnStringNotBeginningWithValue_shouldFail() { + Like like = new Like("test", "foo%"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("barfoo")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_endsWithLikeQueryOnStringEndingWithValue_shouldSucceed() { + Like like = new Like("test", "%foo"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("barfoo")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_endsWithLikeQueryOnStringNotEndingWithValue_shouldFail() { + Like like = new Like("test", "%foo"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("foobar")); + + Assert.assertFalse(like.passesFilter("id", item)); + } + + @Test + public void passesFilter_startsWithAndEndsWithOnMatchingValue_shouldSucceed() { + Like like = new Like("test", "foo%bar"); + + Item item = new PropertysetItem(); + item.addItemProperty("test", new ObjectProperty<String>("fooASDFbar")); + + Assert.assertTrue(like.passesFilter("id", item)); + } + + @Test + public void appliesToProperty_valueIsProperty_shouldBeTrue() { + Like like = new Like("test", "%foo"); + Assert.assertTrue(like.appliesToProperty("test")); + } + + @Test + public void appliesToProperty_valueIsNotProperty_shouldBeFalse() { + Like like = new Like("test", "%foo"); + Assert.assertFalse(like.appliesToProperty("bar")); + } + + @Test + public void equals_sameInstances_shouldBeTrue() { + Like like1 = new Like("test", "%foo"); + Like like2 = like1; + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_twoEqualInstances_shouldBeTrue() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "foo"); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_differentValues_shouldBeFalse() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "bar"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentProperties_shouldBeFalse() { + Like like1 = new Like("foo", "test"); + Like like2 = new Like("bar", "test"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentPropertiesAndValues_shouldBeFalse() { + Like like1 = new Like("foo", "bar"); + Like like2 = new Like("baz", "zomg"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_differentClasses_shouldBeFalse() { + Like like1 = new Like("foo", "bar"); + Object obj = new Object(); + Assert.assertFalse(like1.equals(obj)); + } + + @Test + public void equals_bothHaveNullProperties_shouldBeTrue() { + Like like1 = new Like(null, "foo"); + Like like2 = new Like(null, "foo"); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_bothHaveNullValues_shouldBeTrue() { + Like like1 = new Like("foo", null); + Like like2 = new Like("foo", null); + Assert.assertTrue(like1.equals(like2)); + } + + @Test + public void equals_onePropertyIsNull_shouldBeFalse() { + Like like1 = new Like(null, "bar"); + Like like2 = new Like("foo", "baz"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void equals_oneValueIsNull_shouldBeFalse() { + Like like1 = new Like("foo", null); + Like like2 = new Like("baz", "bar"); + Assert.assertFalse(like1.equals(like2)); + } + + @Test + public void hashCode_equalInstances_shouldBeEqual() { + Like like1 = new Like("test", "foo"); + Like like2 = new Like("test", "foo"); + Assert.assertEquals(like1.hashCode(), like2.hashCode()); + } + + @Test + public void hashCode_differentPropertiesAndValues_shouldNotEqual() { + Like like1 = new Like("foo", "bar"); + Like like2 = new Like("baz", "zomg"); + Assert.assertTrue(like1.hashCode() != like2.hashCode()); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java new file mode 100644 index 0000000000..e62a06e6e1 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/generator/SQLGeneratorsTest.java @@ -0,0 +1,241 @@ +package com.vaadin.data.util.sqlcontainer.generator; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.filter.Or; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; +import com.vaadin.data.util.sqlcontainer.query.TableQuery; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.MSSQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.SQLGenerator; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; + +public class SQLGeneratorsTest { + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void generateSelectQuery_basicQuery_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + StatementHelper sh = sg.generateSelectQuery("TABLE", null, null, 0, 0, + null); + Assert.assertEquals(sh.getQueryString(), "SELECT * FROM TABLE"); + } + + @Test + public void generateSelectQuery_pagingAndColumnsSet_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + StatementHelper sh = sg.generateSelectQuery("TABLE", null, null, 4, 8, + "COL1, COL2, COL3"); + Assert.assertEquals(sh.getQueryString(), + "SELECT COL1, COL2, COL3 FROM TABLE LIMIT 8 OFFSET 4"); + } + + /** + * Note: Only tests one kind of filter and ordering. + */ + @Test + public void generateSelectQuery_filtersAndOrderingSet_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + List<com.vaadin.data.Container.Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 0, 0, null); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM TABLE WHERE \"name\" LIKE ? ORDER BY \"name\" ASC"); + } + + @Test + public void generateSelectQuery_filtersAndOrderingSet_exclusiveFilteringMode_shouldSucceed() { + SQLGenerator sg = new DefaultSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 0, 0, null); + // TODO + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM TABLE WHERE (\"name\" LIKE ? " + + "OR \"name\" LIKE ?) ORDER BY \"name\" ASC"); + } + + @Test + public void generateDeleteQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = AllTests.sqlGen; + TableQuery query = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(query); + + StatementHelper sh = sg.generateDeleteQuery( + "people", + query.getPrimaryKeyColumns(), + null, + (RowItem) container.getItem(container.getItemIds().iterator() + .next())); + Assert.assertEquals("DELETE FROM people WHERE \"ID\" = ?", + sh.getQueryString()); + } + + @Test + public void generateUpdateQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = new DefaultSQLGenerator(); + TableQuery query = new TableQuery("people", connectionPool); + SQLContainer container = new SQLContainer(query); + + RowItem ri = (RowItem) container.getItem(container.getItemIds() + .iterator().next()); + ri.getItemProperty("NAME").setValue("Viljami"); + + StatementHelper sh = sg.generateUpdateQuery("people", ri); + Assert.assertTrue("UPDATE people SET \"NAME\" = ?, \"AGE\" = ? WHERE \"ID\" = ?" + .equals(sh.getQueryString()) + || "UPDATE people SET \"AGE\" = ?, \"NAME\" = ? WHERE \"ID\" = ?" + .equals(sh.getQueryString())); + } + + @Test + public void generateInsertQuery_basicQuery_shouldSucceed() + throws SQLException { + /* + * No need to run this for Oracle/MSSQL generators since the + * DefaultSQLGenerator method would be called anyway. + */ + if (AllTests.sqlGen instanceof MSSQLGenerator + || AllTests.sqlGen instanceof OracleGenerator) { + return; + } + SQLGenerator sg = new DefaultSQLGenerator(); + TableQuery query = new TableQuery("people", connectionPool); + SQLContainer container = new SQLContainer(query); + + RowItem ri = (RowItem) container.getItem(container.addItem()); + ri.getItemProperty("NAME").setValue("Viljami"); + + StatementHelper sh = sg.generateInsertQuery("people", ri); + + Assert.assertTrue("INSERT INTO people (\"NAME\", \"AGE\") VALUES (?, ?)" + .equals(sh.getQueryString()) + || "INSERT INTO people (\"AGE\", \"NAME\") VALUES (?, ?)" + .equals(sh.getQueryString())); + } + + @Test + public void generateComplexSelectQuery_forOracle_shouldSucceed() + throws SQLException { + SQLGenerator sg = new OracleGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals( + "SELECT * FROM (SELECT x.*, ROWNUM AS \"rownum\" FROM" + + " (SELECT NAME, ID FROM TABLE WHERE \"name\" LIKE ?" + + " ORDER BY \"name\" ASC) x) WHERE \"rownum\" BETWEEN 5 AND 12", + sh.getQueryString()); + } + + @Test + public void generateComplexSelectQuery_forMSSQL_shouldSucceed() + throws SQLException { + SQLGenerator sg = new MSSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Like("name", "%lle")); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM (SELECT row_number() OVER " + + "( ORDER BY \"name\" ASC) AS rownum, NAME, ID " + + "FROM TABLE WHERE \"name\" LIKE ?) " + + "AS a WHERE a.rownum BETWEEN 5 AND 12"); + } + + @Test + public void generateComplexSelectQuery_forOracle_exclusiveFilteringMode_shouldSucceed() + throws SQLException { + SQLGenerator sg = new OracleGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals( + sh.getQueryString(), + "SELECT * FROM (SELECT x.*, ROWNUM AS \"rownum\" FROM" + + " (SELECT NAME, ID FROM TABLE WHERE (\"name\" LIKE ?" + + " OR \"name\" LIKE ?) " + + "ORDER BY \"name\" ASC) x) WHERE \"rownum\" BETWEEN 5 AND 12"); + } + + @Test + public void generateComplexSelectQuery_forMSSQL_exclusiveFilteringMode_shouldSucceed() + throws SQLException { + SQLGenerator sg = new MSSQLGenerator(); + List<Filter> f = new ArrayList<Filter>(); + f.add(new Or(new Like("name", "%lle"), new Like("name", "vi%"))); + List<OrderBy> ob = Arrays.asList(new OrderBy("name", true)); + StatementHelper sh = sg.generateSelectQuery("TABLE", f, ob, 4, 8, + "NAME, ID"); + Assert.assertEquals(sh.getQueryString(), + "SELECT * FROM (SELECT row_number() OVER " + + "( ORDER BY \"name\" ASC) AS rownum, NAME, ID " + + "FROM TABLE WHERE (\"name\" LIKE ? " + + "OR \"name\" LIKE ?)) " + + "AS a WHERE a.rownum BETWEEN 5 AND 12"); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java new file mode 100644 index 0000000000..9b38655186 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/FreeformQueryTest.java @@ -0,0 +1,897 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.RowId; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.FreeformQuery; +import com.vaadin.data.util.sqlcontainer.query.FreeformQueryDelegate; +import com.vaadin.data.util.sqlcontainer.query.OrderBy; + +public class FreeformQueryTest { + + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + @Test + public void construction_legalParameters_shouldSucceed() { + FreeformQuery ffQuery = new FreeformQuery("SELECT * FROM foo", + Arrays.asList("ID"), connectionPool); + Assert.assertArrayEquals(new Object[] { "ID" }, ffQuery + .getPrimaryKeyColumns().toArray()); + + Assert.assertEquals("SELECT * FROM foo", ffQuery.getQueryString()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyQueryString_shouldFail() { + new FreeformQuery("", Arrays.asList("ID"), connectionPool); + } + + @Test + public void construction_nullPrimaryKeys_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", null, connectionPool); + } + + @Test + public void construction_nullPrimaryKeys2_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", connectionPool); + } + + @Test + public void construction_emptyPrimaryKeys_shouldSucceed() { + new FreeformQuery("SELECT * FROM foo", connectionPool); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyStringsInPrimaryKeys_shouldFail() { + new FreeformQuery("SELECT * FROM foo", Arrays.asList(""), + connectionPool); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullConnectionPool_shouldFail() { + new FreeformQuery("SELECT * FROM foo", Arrays.asList("ID"), null); + } + + @Test + public void getCount_simpleQuery_returnsFour() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertEquals(4, query.getCount()); + } + + @Test(expected = SQLException.class) + public void getCount_illegalQuery_shouldThrowSQLException() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM asdf", + Arrays.asList("ID"), connectionPool); + query.getResults(0, 50); + } + + @Test + public void getCount_simpleQueryTwoMorePeopleAdded_returnsSix() + throws SQLException { + // Add some people + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + statement.executeUpdate("insert into people values('Ingvar', 50)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + statement + .executeUpdate("insert into people values(default, 'Ingvar', 50)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + + Assert.assertEquals(6, query.getCount()); + } + + @Test + public void getCount_moreComplexQuery_returnsThree() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + connectionPool, new String[] { "ID" }); + Assert.assertEquals(3, query.getCount()); + } + + @Test + public void getCount_normalState_releasesConnection() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + connectionPool, "ID"); + query.getCount(); + query.getCount(); + Assert.assertNotNull(connectionPool.reserveConnection()); + } + + @Test + public void getCount_delegateRegistered_shouldUseDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getCountQuery()).andReturn( + "SELECT COUNT(*) FROM people WHERE \"NAME\" LIKE '%lle'"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + Assert.assertEquals(3, query.getCount()); + EasyMock.verify(delegate); + } + + @Test + public void getCount_delegateRegisteredZeroRows_returnsZero() + throws SQLException { + DataGenerator.createGarbage(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM GARBAGE", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getCountQuery()).andReturn( + "SELECT COUNT(*) FROM GARBAGE"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + Assert.assertEquals(0, query.getCount()); + EasyMock.verify(delegate); + } + + @Test + public void getResults_simpleQuery_returnsFourRecords() throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT \"ID\",\"NAME\" FROM people", Arrays.asList("ID"), + connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void getResults_moreComplexQuery_returnsThreeRecords() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void getResults_noDelegate5000Rows_returns5000rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + ResultSet rs = query.getResults(0, 0); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(rs.next()); + } + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test(expected = UnsupportedOperationException.class) + public void setFilters_noDelegate_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + query.setFilters(filters); + } + + @Test(expected = UnsupportedOperationException.class) + public void setOrderBy_noDelegate_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setOrderBy(Arrays.asList(new OrderBy("name", true))); + } + + @Test(expected = IllegalStateException.class) + public void storeRow_noDelegateNoTransactionActive_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.storeRow(new RowItem(new SQLContainer(query), new RowId( + new Object[] { 1 }), null)); + } + + @Test(expected = UnsupportedOperationException.class) + public void storeRow_noDelegate_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(container); + query.beginTransaction(); + query.storeRow(new RowItem(container, new RowId(new Object[] { 1 }), + null)); + query.commit(); + EasyMock.verify(container); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeRow_noDelegate_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(container); + query.beginTransaction(); + query.removeRow(new RowItem(container, new RowId(new Object[] { 1 }), + null)); + query.commit(); + EasyMock.verify(container); + } + + @Test + public void beginTransaction_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + } + + @Test + public void commit_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + query.commit(); + } + + @Test + public void rollback_readOnly_shouldSucceed() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.beginTransaction(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_noActiveTransaction_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_noActiveTransaction_shouldFail() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.rollback(); + } + + @Test + public void containsRowWithKeys_simpleQueryWithExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_simpleQueryWithNonexistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertFalse(query.containsRowWithKey(1337)); + } + + // (expected = SQLException.class) + @Test + public void containsRowWithKeys_simpleQueryWithInvalidKeys_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + Assert.assertFalse(query.containsRowWithKey(38796)); + } + + @Test + public void containsRowWithKeys_queryContainingWhereClauseAndExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_queryContainingLowercaseWhereClauseAndExistingKeys_returnsTrue() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "select * from people where \"NAME\" like '%lle'", + Arrays.asList("ID"), connectionPool); + Assert.assertTrue(query.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_nullKeys_shouldFailAndReleaseConnections() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "select * from people where \"NAME\" like '%lle'", + Arrays.asList("ID"), connectionPool); + try { + query.containsRowWithKey(new Object[] { null }); + } catch (SQLException e) { + // We should now be able to reserve two connections + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } + } + + /* + * -------- Tests with a delegate --------- + */ + + @Test + public void setDelegate_noExistingDelegate_shouldRegisterNewDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + query.setDelegate(delegate); + Assert.assertEquals(delegate, query.getDelegate()); + } + + @Test + public void getResults_hasDelegate_shouldCallDelegate() throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 0 AND 2"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people) x) WHERE r BETWEEN 1 AND 2"); + } else { + EasyMock.expect(delegate.getQueryString(0, 2)).andReturn( + "SELECT * FROM people LIMIT 2 OFFSET 0"); + } + EasyMock.replay(delegate); + + query.setDelegate(delegate); + query.beginTransaction(); + query.getResults(0, 2); + EasyMock.verify(delegate); + query.commit(); + } + + @Test + public void getResults_delegateImplementsGetQueryString_shouldHonorOffsetAndPagelength() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 0 AND 2"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(0, 2)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people) x) WHERE r BETWEEN 1 AND 2"); + } else { + EasyMock.expect(delegate.getQueryString(0, 2)).andReturn( + "SELECT * FROM people LIMIT 2 OFFSET 0"); + } + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + ResultSet rs = query.getResults(0, 2); + int rsoffset = 0; + if (AllTests.db == DB.MSSQL) { + rsoffset++; + } + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1 + rsoffset)); + Assert.assertEquals("Ville", rs.getString(2 + rsoffset)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1 + rsoffset)); + Assert.assertEquals("Kalle", rs.getString(2 + rsoffset)); + + Assert.assertFalse(rs.next()); + + EasyMock.verify(delegate); + query.commit(); + } + + @Test + public void getResults_delegateRegistered5000Rows_returns100rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + if (AllTests.db == DB.MSSQL) { + EasyMock.expect(delegate.getQueryString(200, 100)) + .andReturn( + "SELECT * FROM (SELECT row_number()" + + "OVER (ORDER BY id ASC) AS rownum, * FROM people)" + + " AS a WHERE a.rownum BETWEEN 201 AND 300"); + } else if (AllTests.db == DB.ORACLE) { + EasyMock.expect(delegate.getQueryString(200, 100)) + .andReturn( + "SELECT * FROM (SELECT x.*, ROWNUM AS r FROM" + + " (SELECT * FROM people ORDER BY ID ASC) x) WHERE r BETWEEN 201 AND 300"); + } else { + EasyMock.expect(delegate.getQueryString(200, 100)).andReturn( + "SELECT * FROM people LIMIT 100 OFFSET 200"); + } + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + ResultSet rs = query.getResults(200, 100); + for (int i = 0; i < 100; i++) { + Assert.assertTrue(rs.next()); + Assert.assertEquals(200 + i + offset, rs.getInt("ID")); + } + Assert.assertFalse(rs.next()); + query.commit(); + } + + @Test + public void setFilters_delegateImplementsSetFilters_shouldPassFiltersToDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + delegate.setFilters(filters); + + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setFilters(filters); + + EasyMock.verify(delegate); + } + + @Test(expected = UnsupportedOperationException.class) + public void setFilters_delegateDoesNotImplementSetFilters_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("name", "%lle")); + delegate.setFilters(filters); + EasyMock.expectLastCall().andThrow(new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setFilters(filters); + + EasyMock.verify(delegate); + } + + @Test + public void setOrderBy_delegateImplementsSetOrderBy_shouldPassArgumentsToDelegate() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<OrderBy> orderBys = Arrays.asList(new OrderBy("name", false)); + delegate.setOrderBy(orderBys); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setOrderBy(orderBys); + + EasyMock.verify(delegate); + } + + @Test(expected = UnsupportedOperationException.class) + public void setOrderBy_delegateDoesNotImplementSetOrderBy_shouldFail() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + List<OrderBy> orderBys = Arrays.asList(new OrderBy("name", false)); + delegate.setOrderBy(orderBys); + EasyMock.expectLastCall().andThrow(new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.setOrderBy(orderBys); + + EasyMock.verify(delegate); + } + + @Test + public void setFilters_noDelegateAndNullParameter_shouldSucceed() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setFilters(null); + } + + @Test + public void setOrderBy_noDelegateAndNullParameter_shouldSucceed() { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + query.setOrderBy(null); + } + + @Test + public void storeRow_delegateImplementsStoreRow_shouldPassToDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andReturn(1); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.storeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test(expected = UnsupportedOperationException.class) + public void storeRow_delegateDoesNotImplementStoreRow_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.storeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andThrow( + new UnsupportedOperationException()); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.storeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test + public void removeRow_delegateImplementsRemoveRow_shouldPassToDelegate() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andReturn(true); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.removeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test(expected = UnsupportedOperationException.class) + public void removeRow_delegateDoesNotImplementRemoveRow_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect( + delegate.removeRow(EasyMock.isA(Connection.class), + EasyMock.isA(RowItem.class))).andThrow( + new UnsupportedOperationException()); + SQLContainer container = EasyMock.createNiceMock(SQLContainer.class); + EasyMock.replay(delegate, container); + query.setDelegate(delegate); + + query.beginTransaction(); + RowItem row = new RowItem(container, new RowId(new Object[] { 1 }), + null); + query.removeRow(row); + query.commit(); + + EasyMock.verify(delegate, container); + } + + @Test + public void beginTransaction_delegateRegistered_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + } + + @Test(expected = IllegalStateException.class) + public void beginTransaction_transactionAlreadyActive_shouldFail() + throws SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + + query.beginTransaction(); + query.beginTransaction(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredNoActiveTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.commit(); + } + + @Test + public void commit_delegateRegisteredActiveTransaction_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredActiveTransactionDoubleCommit_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredNoActiveTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.rollback(); + } + + @Test + public void rollback_delegateRegisteredActiveTransaction_shouldSucceed() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredActiveTransactionDoubleRollback_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void rollback_delegateRegisteredCommittedTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.commit(); + query.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_delegateRegisteredRollbackedTransaction_shouldFail() + throws UnsupportedOperationException, SQLException { + FreeformQuery query = new FreeformQuery("SELECT * FROM people", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.beginTransaction(); + query.rollback(); + query.commit(); + } + + @Test(expected = SQLException.class) + public void containsRowWithKeys_delegateRegistered_shouldCallGetContainsRowQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE name LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getContainsRowQueryString(1)).andReturn(""); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + query.containsRowWithKey(1); + + EasyMock.verify(delegate); + } + + @Test + public void containsRowWithKeys_delegateRegistered_shouldUseResultFromGetContainsRowQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + // In order to test that this is the query that is actually used, we use + // a non-existing id in place of the existing one. + EasyMock.expect(delegate.getContainsRowQueryString(1)) + .andReturn( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle' AND \"ID\" = 1337"); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + // The id (key) used should be 1337 as above, for the call with key = 1 + Assert.assertFalse(query.containsRowWithKey(1)); + + EasyMock.verify(delegate); + } + + @Test + public void containsRowWithKeys_delegateRegisteredGetContainsRowQueryStringNotImplemented_shouldBuildQueryString() + throws SQLException { + FreeformQuery query = new FreeformQuery( + "SELECT * FROM people WHERE \"NAME\" LIKE '%lle'", + Arrays.asList("ID"), connectionPool); + FreeformQueryDelegate delegate = EasyMock + .createMock(FreeformQueryDelegate.class); + EasyMock.expect(delegate.getContainsRowQueryString(1)).andThrow( + new UnsupportedOperationException()); + EasyMock.replay(delegate); + query.setDelegate(delegate); + + Assert.assertTrue(query.containsRowWithKey(1)); + + EasyMock.verify(delegate); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java new file mode 100644 index 0000000000..f635b23ebd --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/QueryBuilderTest.java @@ -0,0 +1,311 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.util.ArrayList; + +import junit.framework.Assert; + +import org.easymock.EasyMock; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.And; +import com.vaadin.data.util.filter.Between; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Compare.Greater; +import com.vaadin.data.util.filter.Compare.GreaterOrEqual; +import com.vaadin.data.util.filter.Compare.Less; +import com.vaadin.data.util.filter.Compare.LessOrEqual; +import com.vaadin.data.util.filter.IsNull; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.filter.Not; +import com.vaadin.data.util.filter.Or; +import com.vaadin.data.util.filter.SimpleStringFilter; +import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.QueryBuilder; +import com.vaadin.data.util.sqlcontainer.query.generator.filter.StringDecorator; + +public class QueryBuilderTest { + + private StatementHelper mockedStatementHelper(Object... values) { + StatementHelper sh = EasyMock.createMock(StatementHelper.class); + for (Object val : values) { + sh.addParameterValue(val); + EasyMock.expectLastCall(); + } + EasyMock.replay(sh); + return sh; + } + + // escape bad characters and wildcards + + @Test + public void getWhereStringForFilter_equals() { + StatementHelper sh = mockedStatementHelper("Fido"); + Equal f = new Equal("NAME", "Fido"); + Assert.assertEquals("\"NAME\" = ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_greater() { + StatementHelper sh = mockedStatementHelper(18); + Greater f = new Greater("AGE", 18); + Assert.assertEquals("\"AGE\" > ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_less() { + StatementHelper sh = mockedStatementHelper(65); + Less f = new Less("AGE", 65); + Assert.assertEquals("\"AGE\" < ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_greaterOrEqual() { + StatementHelper sh = mockedStatementHelper(18); + GreaterOrEqual f = new GreaterOrEqual("AGE", 18); + Assert.assertEquals("\"AGE\" >= ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_lessOrEqual() { + StatementHelper sh = mockedStatementHelper(65); + LessOrEqual f = new LessOrEqual("AGE", 65); + Assert.assertEquals("\"AGE\" <= ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilter() { + StatementHelper sh = mockedStatementHelper("Vi%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", false, true); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilterMatchAnywhere() { + StatementHelper sh = mockedStatementHelper("%Vi%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", false, + false); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_simpleStringFilterMatchAnywhereIgnoreCase() { + StatementHelper sh = mockedStatementHelper("%VI%"); + SimpleStringFilter f = new SimpleStringFilter("NAME", "Vi", true, false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_startsWith() { + StatementHelper sh = mockedStatementHelper("Vi%"); + Like f = new Like("NAME", "Vi%"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_startsWithNumber() { + StatementHelper sh = mockedStatementHelper("1%"); + Like f = new Like("AGE", "1%"); + Assert.assertEquals("\"AGE\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_endsWith() { + StatementHelper sh = mockedStatementHelper("%lle"); + Like f = new Like("NAME", "%lle"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_contains() { + StatementHelper sh = mockedStatementHelper("%ill%"); + Like f = new Like("NAME", "%ill%"); + Assert.assertEquals("\"NAME\" LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_between() { + StatementHelper sh = mockedStatementHelper(18, 65); + Between f = new Between("AGE", 18, 65); + Assert.assertEquals("\"AGE\" BETWEEN ? AND ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_equals() { + StatementHelper sh = mockedStatementHelper("FIDO"); + Like f = new Like("NAME", "Fido"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_startsWith() { + StatementHelper sh = mockedStatementHelper("VI%"); + Like f = new Like("NAME", "Vi%"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_endsWith() { + StatementHelper sh = mockedStatementHelper("%LLE"); + Like f = new Like("NAME", "%lle"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilter_caseInsensitive_contains() { + StatementHelper sh = mockedStatementHelper("%ILL%"); + Like f = new Like("NAME", "%ill%"); + f.setCaseSensitive(false); + Assert.assertEquals("UPPER(\"NAME\") LIKE ?", + QueryBuilder.getWhereStringForFilter(f, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_listOfFilters() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("NAME", "%lle")); + filters.add(new Greater("AGE", 18)); + Assert.assertEquals(" WHERE \"NAME\" LIKE ? AND \"AGE\" > ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_oneAndFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new And(new Like("NAME", "%lle"), new Greater("AGE", 18))); + Assert.assertEquals(" WHERE (\"NAME\" LIKE ? AND \"AGE\" > ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_oneOrFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new Like("NAME", "%lle"), new Greater("AGE", 18))); + Assert.assertEquals(" WHERE (\"NAME\" LIKE ? OR \"AGE\" > ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexCompoundFilters() { + StatementHelper sh = mockedStatementHelper("%lle", 18, 65, "Pelle"); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new And(new Like("NAME", "%lle"), new Or(new Less( + "AGE", 18), new Greater("AGE", 65))), + new Equal("NAME", "Pelle"))); + Assert.assertEquals( + " WHERE ((\"NAME\" LIKE ? AND (\"AGE\" < ? OR \"AGE\" > ?)) OR \"NAME\" = ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexCompoundFiltersAndSingleFilter() { + StatementHelper sh = mockedStatementHelper("%lle", 18, 65, "Pelle", + "Virtanen"); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Or(new And(new Like("NAME", "%lle"), new Or(new Less( + "AGE", 18), new Greater("AGE", 65))), + new Equal("NAME", "Pelle"))); + filters.add(new Equal("LASTNAME", "Virtanen")); + Assert.assertEquals( + " WHERE ((\"NAME\" LIKE ? AND (\"AGE\" < ? OR \"AGE\" > ?)) OR \"NAME\" = ?) AND \"LASTNAME\" = ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_emptyList_shouldReturnEmptyString() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + Assert.assertEquals("", QueryBuilder.getWhereStringForFilters(filters, + new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_NotFilter() { + StatementHelper sh = mockedStatementHelper(18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new Equal("AGE", 18))); + Assert.assertEquals(" WHERE NOT \"AGE\" = ?", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_complexNegatedFilter() { + StatementHelper sh = mockedStatementHelper(65, 18); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new Or(new Equal("AGE", 65), new Equal("AGE", 18)))); + Assert.assertEquals(" WHERE NOT (\"AGE\" = ? OR \"AGE\" = ?)", + QueryBuilder.getWhereStringForFilters(filters, sh)); + EasyMock.verify(sh); + } + + @Test + public void getWhereStringForFilters_isNull() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new IsNull("NAME")); + Assert.assertEquals(" WHERE \"NAME\" IS NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_isNotNull() { + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new IsNull("NAME"))); + Assert.assertEquals(" WHERE \"NAME\" IS NOT NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + } + + @Test + public void getWhereStringForFilters_customStringDecorator() { + QueryBuilder.setStringDecorator(new StringDecorator("[", "]")); + ArrayList<Filter> filters = new ArrayList<Filter>(); + filters.add(new Not(new IsNull("NAME"))); + Assert.assertEquals(" WHERE [NAME] IS NOT NULL", QueryBuilder + .getWhereStringForFilters(filters, new StatementHelper())); + // Reset the default string decorator + QueryBuilder.setStringDecorator(new StringDecorator("\"", "\"")); + } +} diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java new file mode 100644 index 0000000000..e135894013 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/query/TableQueryTest.java @@ -0,0 +1,663 @@ +package com.vaadin.data.util.sqlcontainer.query; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.util.filter.Compare.Equal; +import com.vaadin.data.util.filter.Like; +import com.vaadin.data.util.sqlcontainer.AllTests; +import com.vaadin.data.util.sqlcontainer.AllTests.DB; +import com.vaadin.data.util.sqlcontainer.DataGenerator; +import com.vaadin.data.util.sqlcontainer.OptimisticLockException; +import com.vaadin.data.util.sqlcontainer.RowItem; +import com.vaadin.data.util.sqlcontainer.SQLContainer; +import com.vaadin.data.util.sqlcontainer.connection.JDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.connection.SimpleJDBCConnectionPool; +import com.vaadin.data.util.sqlcontainer.query.generator.DefaultSQLGenerator; + +public class TableQueryTest { + private static final int offset = AllTests.offset; + private JDBCConnectionPool connectionPool; + + @Before + public void setUp() throws SQLException { + + try { + connectionPool = new SimpleJDBCConnectionPool(AllTests.dbDriver, + AllTests.dbURL, AllTests.dbUser, AllTests.dbPwd, 2, 2); + } catch (SQLException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + DataGenerator.addPeopleToDatabase(connectionPool); + } + + @After + public void tearDown() { + if (connectionPool != null) { + connectionPool.destroy(); + } + } + + /********************************************************************** + * TableQuery construction tests + **********************************************************************/ + @Test + public void construction_legalParameters_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + new DefaultSQLGenerator()); + Assert.assertArrayEquals(new Object[] { "ID" }, tQuery + .getPrimaryKeyColumns().toArray()); + boolean correctTableName = "people".equalsIgnoreCase(tQuery + .getTableName()); + Assert.assertTrue(correctTableName); + } + + @Test + public void construction_legalParameters_defaultGenerator_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertArrayEquals(new Object[] { "ID" }, tQuery + .getPrimaryKeyColumns().toArray()); + boolean correctTableName = "people".equalsIgnoreCase(tQuery + .getTableName()); + Assert.assertTrue(correctTableName); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nonExistingTableName_shouldFail() { + new TableQuery("skgwaguhsd", connectionPool, new DefaultSQLGenerator()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_emptyTableName_shouldFail() { + new TableQuery("", connectionPool, new DefaultSQLGenerator()); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullSqlGenerator_shouldFail() { + new TableQuery("people", connectionPool, null); + } + + @Test(expected = IllegalArgumentException.class) + public void construction_nullConnectionPool_shouldFail() { + new TableQuery("people", null, new DefaultSQLGenerator()); + } + + /********************************************************************** + * TableQuery row count tests + **********************************************************************/ + @Test + public void getCount_simpleQuery_returnsFour() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertEquals(4, tQuery.getCount()); + } + + @Test + public void getCount_simpleQueryTwoMorePeopleAdded_returnsSix() + throws SQLException { + // Add some people + Connection conn = connectionPool.reserveConnection(); + Statement statement = conn.createStatement(); + if (AllTests.db == DB.MSSQL) { + statement.executeUpdate("insert into people values('Bengt', 30)"); + statement.executeUpdate("insert into people values('Ingvar', 50)"); + } else { + statement + .executeUpdate("insert into people values(default, 'Bengt', 30)"); + statement + .executeUpdate("insert into people values(default, 'Ingvar', 50)"); + } + statement.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + Assert.assertEquals(6, tQuery.getCount()); + } + + @Test + public void getCount_normalState_releasesConnection() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.getCount(); + tQuery.getCount(); + Assert.assertNotNull(connectionPool.reserveConnection()); + } + + /********************************************************************** + * TableQuery get results tests + **********************************************************************/ + @Test + public void getResults_simpleQuery_returnsFourRecords() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + ResultSet rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void getResults_noDelegate5000Rows_returns5000rows() + throws SQLException { + DataGenerator.addFiveThousandPeople(connectionPool); + + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + tQuery.beginTransaction(); + ResultSet rs = tQuery.getResults(0, 0); + for (int i = 0; i < 5000; i++) { + Assert.assertTrue(rs.next()); + } + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + /********************************************************************** + * TableQuery transaction management tests + **********************************************************************/ + @Test + public void beginTransaction_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + } + + @Test(expected = IllegalStateException.class) + public void beginTransaction_transactionAlreadyActive_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + tQuery.beginTransaction(); + tQuery.beginTransaction(); + } + + @Test + public void commit_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + tQuery.commit(); + } + + @Test + public void rollback_readOnly_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.beginTransaction(); + tQuery.rollback(); + } + + @Test(expected = SQLException.class) + public void commit_noActiveTransaction_shouldFail() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.commit(); + } + + @Test(expected = SQLException.class) + public void rollback_noActiveTransaction_shouldFail() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.rollback(); + } + + /********************************************************************** + * TableQuery row query with given keys tests + **********************************************************************/ + @Test + public void containsRowWithKeys_existingKeys_returnsTrue() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + Assert.assertTrue(tQuery.containsRowWithKey(1)); + } + + @Test + public void containsRowWithKeys_nonexistingKeys_returnsTrue() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + Assert.assertFalse(tQuery.containsRowWithKey(1337)); + } + + @Test + public void containsRowWithKeys_invalidKeys_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + boolean b = true; + try { + b = tQuery.containsRowWithKey("foo"); + } catch (SQLException se) { + return; + } + Assert.assertFalse(b); + } + + @Test + public void containsRowWithKeys_nullKeys_shouldFailAndReleaseConnections() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + try { + tQuery.containsRowWithKey(new Object[] { null }); + org.junit.Assert + .fail("null should throw an IllegalArgumentException from StatementHelper"); + } catch (IllegalArgumentException e) { + // We should now be able to reserve two connections + connectionPool.reserveConnection(); + connectionPool.reserveConnection(); + } + } + + /********************************************************************** + * TableQuery filtering and ordering tests + **********************************************************************/ + @Test + public void setFilters_shouldReturnCorrectCount() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Like("NAME", "%lle")); + tQuery.setFilters(filters); + Assert.assertEquals(3, tQuery.getCount()); + } + + @Test + public void setOrderByNameAscending_shouldReturnCorrectOrder() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + List<OrderBy> orderBys = Arrays.asList(new OrderBy("NAME", true)); + tQuery.setOrderBy(orderBys); + + tQuery.beginTransaction(); + ResultSet rs; + rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void setOrderByNameDescending_shouldReturnCorrectOrder() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + List<OrderBy> orderBys = Arrays.asList(new OrderBy("NAME", false)); + tQuery.setOrderBy(orderBys); + + tQuery.beginTransaction(); + ResultSet rs; + rs = tQuery.getResults(0, 0); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(0 + offset, rs.getInt(1)); + Assert.assertEquals("Ville", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(2 + offset, rs.getInt(1)); + Assert.assertEquals("Pelle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(1 + offset, rs.getInt(1)); + Assert.assertEquals("Kalle", rs.getString(2)); + + Assert.assertTrue(rs.next()); + Assert.assertEquals(3 + offset, rs.getInt(1)); + Assert.assertEquals("Börje", rs.getString(2)); + + Assert.assertFalse(rs.next()); + tQuery.commit(); + } + + @Test + public void setFilters_nullParameter_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setFilters(null); + } + + @Test + public void setOrderBy_nullParameter_shouldSucceed() { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setOrderBy(null); + } + + /********************************************************************** + * TableQuery row removal tests + **********************************************************************/ + @Test + public void removeRowThroughContainer_legalRowItem_shouldSucceed() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + Assert.assertTrue(container.removeItem(container.getItemIds() + .iterator().next())); + + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(3, container.size()); + container.commit(); + + Assert.assertEquals(3, tQuery.getCount()); + Assert.assertEquals(3, container.size()); + } + + @Test + public void removeRowThroughContainer_nonexistingRowId_shouldFail() + throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(true); + Assert.assertFalse(container.removeItem("foo")); + } + + /********************************************************************** + * TableQuery row adding / modification tests + **********************************************************************/ + @Test + public void insertRowThroughContainer_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("ID"); + + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + + Object item = container.addItem(); + Assert.assertNotNull(item); + + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(5, container.size()); + container.commit(); + + Assert.assertEquals(5, tQuery.getCount()); + Assert.assertEquals(5, container.size()); + } + + @Test + public void modifyRowThroughContainer_shouldSucceed() throws SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + + // In this test the primary key is used as a version column + tQuery.setVersionColumn("ID"); + SQLContainer container = new SQLContainer(tQuery); + container.setAutoCommit(false); + + /* Check that the container size is correct and there is no 'Viljami' */ + Assert.assertEquals(4, container.size()); + List<Filter> filters = new ArrayList<Filter>(); + filters.add(new Equal("NAME", "Viljami")); + tQuery.setFilters(filters); + Assert.assertEquals(0, tQuery.getCount()); + tQuery.setFilters(null); + + /* Fetch first item, modify and commit */ + Object item = container.getItem(container.getItemIds().iterator() + .next()); + Assert.assertNotNull(item); + + RowItem ri = (RowItem) item; + Assert.assertNotNull(ri.getItemProperty("NAME")); + ri.getItemProperty("NAME").setValue("Viljami"); + + container.commit(); + + // Check that the size is still correct and only 1 'Viljami' is found + Assert.assertEquals(4, tQuery.getCount()); + Assert.assertEquals(4, container.size()); + tQuery.setFilters(filters); + Assert.assertEquals(1, tQuery.getCount()); + } + + @Test + public void storeRow_noVersionColumn_shouldSucceed() + throws UnsupportedOperationException, SQLException { + TableQuery tQuery = new TableQuery("people", connectionPool, + AllTests.sqlGen); + SQLContainer container = new SQLContainer(tQuery); + Object id = container.addItem(); + RowItem row = (RowItem) container.getItem(id); + row.getItemProperty("NAME").setValue("R2D2"); + row.getItemProperty("AGE").setValue(123); + tQuery.beginTransaction(); + tQuery.storeRow(row); + tQuery.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM PEOPLE WHERE \"NAME\" = ?"); + stmt.setString(1, "R2D2"); + ResultSet rs = stmt.executeQuery(); + Assert.assertTrue(rs.next()); + rs.close(); + stmt.close(); + connectionPool.releaseConnection(conn); + } + + @Test + public void storeRow_versionSetAndEqualToDBValue_shouldSucceed() + throws SQLException { + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + row.getItemProperty("TEXT").setValue("asdf"); + container.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM VERSIONED WHERE \"TEXT\" = ?"); + stmt.setString(1, "asdf"); + ResultSet rs = stmt.executeQuery(); + Assert.assertTrue(rs.next()); + rs.close(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + @Test(expected = OptimisticLockException.class) + public void storeRow_versionSetAndLessThanDBValue_shouldThrowException() + throws SQLException { + if (AllTests.db == DB.HSQLDB) { + throw new OptimisticLockException( + "HSQLDB doesn't support row versioning for optimistic locking - don't run this test.", + null); + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + row.getItemProperty("TEXT").setValue("asdf"); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "foo"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + container.commit(); + } + + @Test + public void removeRow_versionSetAndEqualToDBValue_shouldSucceed() + throws SQLException { + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + container.removeItem(container.firstItemId()); + container.commit(); + + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("SELECT * FROM VERSIONED WHERE \"TEXT\" = ?"); + stmt.setString(1, "Junk"); + ResultSet rs = stmt.executeQuery(); + Assert.assertFalse(rs.next()); + rs.close(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + } + + @Test(expected = OptimisticLockException.class) + public void removeRow_versionSetAndLessThanDBValue_shouldThrowException() + throws SQLException { + if (AllTests.db == AllTests.DB.HSQLDB) { + // HSQLDB doesn't support versioning, so this is to make the test + // green. + throw new OptimisticLockException(null); + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "asdf"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + container.removeItem(container.firstItemId()); + container.commit(); + } + + @Test + public void removeRow_throwsOptimisticLockException_shouldStillWork() + throws SQLException { + if (AllTests.db == AllTests.DB.HSQLDB) { + // HSQLDB doesn't support versioning, so this is to make the test + // green. + return; + } + DataGenerator.addVersionedData(connectionPool); + + TableQuery tQuery = new TableQuery("versioned", connectionPool, + AllTests.sqlGen); + tQuery.setVersionColumn("VERSION"); + SQLContainer container = new SQLContainer(tQuery); + RowItem row = (RowItem) container.getItem(container.firstItemId()); + Assert.assertEquals("Junk", row.getItemProperty("TEXT").getValue()); + + // Update the version using another connection. + Connection conn = connectionPool.reserveConnection(); + PreparedStatement stmt = conn + .prepareStatement("UPDATE VERSIONED SET \"TEXT\" = ? WHERE \"ID\" = ?"); + stmt.setString(1, "asdf"); + stmt.setObject(2, row.getItemProperty("ID").getValue()); + stmt.executeUpdate(); + stmt.close(); + conn.commit(); + connectionPool.releaseConnection(conn); + + Object itemToRemove = container.firstItemId(); + try { + container.removeItem(itemToRemove); + container.commit(); + } catch (OptimisticLockException e) { + // This is expected, refresh and try again. + container.rollback(); + container.removeItem(itemToRemove); + container.commit(); + } + Object id = container.addItem(); + RowItem item = (RowItem) container.getItem(id); + item.getItemProperty("TEXT").setValue("foo"); + container.commit(); + } + +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/server/JSONSerializerTest.java b/server/tests/src/com/vaadin/server/JSONSerializerTest.java new file mode 100644 index 0000000000..05139e6f1a --- /dev/null +++ b/server/tests/src/com/vaadin/server/JSONSerializerTest.java @@ -0,0 +1,140 @@ +package com.vaadin.server; + +/* + * Copyright 2011 Vaadin Ltd. + * + * 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. + */ +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import com.vaadin.server.JsonCodec.BeanProperty; +import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState; + +/** + * Tests for {@link JsonCodec} + * + * @author Vaadin Ltd + * @since 7.0 + * + */ +public class JSONSerializerTest extends TestCase { + HashMap<String, AbstractSplitPanelState> stringToStateMap; + HashMap<AbstractSplitPanelState, String> stateToStringMap; + + public void testStringToBeanMapSerialization() throws Exception { + Type mapType = getClass().getDeclaredField("stringToStateMap") + .getGenericType(); + stringToStateMap = new HashMap<String, AbstractSplitPanelState>(); + AbstractSplitPanelState s = new AbstractSplitPanelState(); + AbstractSplitPanelState s2 = new AbstractSplitPanelState(); + s.setCaption("State 1"); + s.setId("foo"); + s2.setCaption("State 2"); + s2.setId("bar"); + stringToStateMap.put("string - state 1", s); + stringToStateMap.put("String - state 2", s2); + + Object encodedMap = JsonCodec.encode(stringToStateMap, null, mapType, + null).getEncodedValue(); + + ensureDecodedCorrectly(stringToStateMap, encodedMap, mapType); + } + + public void testBeanToStringMapSerialization() throws Exception { + Type mapType = getClass().getDeclaredField("stateToStringMap") + .getGenericType(); + stateToStringMap = new HashMap<AbstractSplitPanelState, String>(); + AbstractSplitPanelState s = new AbstractSplitPanelState(); + AbstractSplitPanelState s2 = new AbstractSplitPanelState(); + s.setCaption("State 1"); + s2.setCaption("State 2"); + stateToStringMap.put(s, "string - state 1"); + stateToStringMap.put(s2, "String - state 2"); + + Object encodedMap = JsonCodec.encode(stateToStringMap, null, mapType, + null).getEncodedValue(); + + ensureDecodedCorrectly(stateToStringMap, encodedMap, mapType); + } + + private void ensureDecodedCorrectly(Object original, Object encoded, + Type type) throws Exception { + Object serverSideDecoded = JsonCodec.decodeInternalOrCustomType(type, + encoded, null); + assertTrue("Server decoded", equals(original, serverSideDecoded)); + + } + + private boolean equals(Object o1, Object o2) throws Exception { + if (o1 == null) { + return (o2 == null); + } + if (o2 == null) { + return false; + } + + if (o1 instanceof Map) { + if (!(o2 instanceof Map)) { + return false; + } + return equalsMap((Map) o1, (Map) o2); + } + + if (o1.getClass() != o2.getClass()) { + return false; + } + + if (o1 instanceof Collection || o1 instanceof Number + || o1 instanceof String) { + return o1.equals(o2); + } + + return equalsBean(o1, o2); + } + + private boolean equalsBean(Object o1, Object o2) throws Exception { + for (BeanProperty property : JsonCodec.getProperties(o1.getClass())) { + Object c1 = property.getValue(o1); + Object c2 = property.getValue(o2); + if (!equals(c1, c2)) { + return false; + } + } + return true; + } + + private boolean equalsMap(Map o1, Map o2) throws Exception { + for (Object key1 : o1.keySet()) { + Object key2 = key1; + if (!(o2.containsKey(key2))) { + // Try to fins a key that is equal + for (Object k2 : o2.keySet()) { + if (equals(key1, k2)) { + key2 = k2; + break; + } + } + } + if (!equals(o1.get(key1), o2.get(key2))) { + return false; + } + + } + return true; + } +} diff --git a/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java new file mode 100644 index 0000000000..df16e98bba --- /dev/null +++ b/server/tests/src/com/vaadin/server/TestAbstractApplicationServletStaticFilesLocation.java @@ -0,0 +1,205 @@ +package com.vaadin.server; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Properties; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + +import com.vaadin.server.AbstractApplicationServlet; +import com.vaadin.server.ApplicationServlet; + +import junit.framework.TestCase; + +public class TestAbstractApplicationServletStaticFilesLocation extends TestCase { + + ApplicationServlet servlet; + + private Method getStaticFilesLocationMethod; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + servlet = new ApplicationServlet(); + + // Workaround to avoid calling init and creating servlet config + Field f = AbstractApplicationServlet.class + .getDeclaredField("applicationProperties"); + f.setAccessible(true); + f.set(servlet, new Properties()); + + getStaticFilesLocationMethod = AbstractApplicationServlet.class + .getDeclaredMethod( + "getStaticFilesLocation", + new Class[] { javax.servlet.http.HttpServletRequest.class }); + getStaticFilesLocationMethod.setAccessible(true); + + } + + public class DummyServletConfig implements ServletConfig { + + // public DummyServletConfig(Map<String,String> initParameters, ) + @Override + public String getInitParameter(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration<Object> getInitParameterNames() { + return new Enumeration<Object>() { + + @Override + public boolean hasMoreElements() { + return false; + } + + @Override + public Object nextElement() { + return null; + } + }; + } + + @Override + public ServletContext getServletContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletName() { + // TODO Auto-generated method stub + return null; + } + + } + + public void testWidgetSetLocation() throws Exception { + String location; + + /* SERVLETS */ + // http://dummy.host:8080/contextpath/servlet + // should return /contextpath + location = testLocation("http://dummy.host:8080", "/contextpath", + "/servlet", ""); + assertEquals("/contextpath", location); + + // http://dummy.host:8080/servlet + // should return "" + location = testLocation("http://dummy.host:8080", "", "/servlet", ""); + assertEquals("", location); + + // http://dummy.host/contextpath/servlet/extra/stuff + // should return /contextpath + location = testLocation("http://dummy.host", "/contextpath", + "/servlet", "/extra/stuff"); + assertEquals("/contextpath", location); + + // http://dummy.host/context/path/servlet/extra/stuff + // should return /context/path + location = testLocation("http://dummy.host", "/context/path", + "/servlet", "/extra/stuff"); + assertEquals("/context/path", location); + + /* Include requests */ + location = testIncludedLocation("http://my.portlet.server", "/user", + "/tmpservletlocation1", ""); + assertEquals("Wrong widgetset location", "/user", location); + + } + + private String testLocation(String base, String contextPath, + String servletPath, String pathInfo) throws Exception { + + HttpServletRequest request = createNonIncludeRequest(base, contextPath, + servletPath, pathInfo); + // Set request into replay mode + replay(request); + + String location = (String) getStaticFilesLocationMethod.invoke(servlet, + request); + return location; + } + + private String testIncludedLocation(String base, String portletContextPath, + String servletPath, String pathInfo) throws Exception { + + HttpServletRequest request = createIncludeRequest(base, + portletContextPath, servletPath, pathInfo); + // Set request into replay mode + replay(request); + + String location = (String) getStaticFilesLocationMethod.invoke(servlet, + request); + return location; + } + + private HttpServletRequest createIncludeRequest(String base, + String realContextPath, String realServletPath, String pathInfo) + throws Exception { + HttpServletRequest request = createRequest(base, "", "", pathInfo); + expect(request.getAttribute("javax.servlet.include.context_path")) + .andReturn(realContextPath).anyTimes(); + expect(request.getAttribute("javax.servlet.include.servlet_path")) + .andReturn(realServletPath).anyTimes(); + + return request; + } + + private HttpServletRequest createNonIncludeRequest(String base, + String realContextPath, String realServletPath, String pathInfo) + throws Exception { + HttpServletRequest request = createRequest(base, realContextPath, + realServletPath, pathInfo); + expect(request.getAttribute("javax.servlet.include.context_path")) + .andReturn(null).anyTimes(); + expect(request.getAttribute("javax.servlet.include.servlet_path")) + .andReturn(null).anyTimes(); + + return request; + } + + /** + * Creates a HttpServletRequest mock using the supplied parameters. + * + * @param base + * The base url, e.g. http://localhost:8080 + * @param contextPath + * The context path where the application is deployed, e.g. + * /mycontext + * @param servletPath + * The servlet path to the servlet we are testing, e.g. /myapp + * @param pathInfo + * Any text following the servlet path in the request, not + * including query parameters, e.g. /UIDL/ + * @return A mock HttpServletRequest object useful for testing + * @throws MalformedURLException + */ + private HttpServletRequest createRequest(String base, String contextPath, + String servletPath, String pathInfo) throws MalformedURLException { + URL url = new URL(base + contextPath + pathInfo); + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.isSecure()).andReturn( + url.getProtocol().equalsIgnoreCase("https")).anyTimes(); + expect(request.getServerName()).andReturn(url.getHost()).anyTimes(); + expect(request.getServerPort()).andReturn(url.getPort()).anyTimes(); + expect(request.getRequestURI()).andReturn(url.getPath()).anyTimes(); + expect(request.getContextPath()).andReturn(contextPath).anyTimes(); + expect(request.getPathInfo()).andReturn(pathInfo).anyTimes(); + expect(request.getServletPath()).andReturn(servletPath).anyTimes(); + + return request; + } + +} diff --git a/server/tests/src/com/vaadin/tests/VaadinClasses.java b/server/tests/src/com/vaadin/tests/VaadinClasses.java new file mode 100644 index 0000000000..15e1283e47 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/VaadinClasses.java @@ -0,0 +1,257 @@ +package com.vaadin.tests; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.JarURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; + +import com.vaadin.Application; +import com.vaadin.ui.Component; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.Field; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.LoginForm; +import com.vaadin.ui.PopupView; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalSplitPanel; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.BaseTheme; + +import org.junit.Test; + +@SuppressWarnings("deprecation") +public class VaadinClasses { + + public static void main(String[] args) { + System.out.println("ComponentContainers"); + System.out.println("==================="); + for (Class<? extends ComponentContainer> c : getComponentContainers()) { + System.out.println(c.getName()); + } + System.out.println(); + System.out.println("Components"); + System.out.println("=========="); + for (Class<? extends Component> c : getComponents()) { + System.out.println(c.getName()); + } + System.out.println(); + System.out.println("Server side classes"); + System.out.println("==================="); + for (Class<?> c : getAllServerSideClasses()) { + System.out.println(c.getName()); + } + } + + public static List<Class<? extends Component>> getComponents() { + try { + return findClasses(Component.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends Field>> getFields() { + try { + return findClasses(Field.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends BaseTheme>> getThemeClasses() { + try { + return findClasses(BaseTheme.class, "com.vaadin.ui.themes"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends Object>> getAllServerSideClasses() { + try { + return findClassesNoTests(Object.class, "com.vaadin", new String[] { + "com.vaadin.tests", "com.vaadin.client" }); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends ComponentContainer>> getComponentContainers() { + try { + return findClasses(ComponentContainer.class, "com.vaadin.ui"); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingAddRemoveComponent() { + List<Class<? extends ComponentContainer>> classes = getComponentContainers(); + classes.remove(PopupView.class); + classes.remove(CustomComponent.class); + classes.remove(DragAndDropWrapper.class); + classes.remove(CustomComponent.class); + classes.remove(LoginForm.class); + classes.remove(UI.class); + + return classes; + } + + public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingUnlimitedNumberOfComponents() { + List<Class<? extends ComponentContainer>> classes = getComponentContainersSupportingAddRemoveComponent(); + classes.remove(VerticalSplitPanel.class); + classes.remove(HorizontalSplitPanel.class); + classes.remove(Window.class); + + return classes; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static List<Class<?>> getBasicComponentTests() { + try { + // Given as name to avoid dependencies on testbench source folder + return (List) findClasses( + Class.forName("com.vaadin.tests.components.AbstractComponentTest"), + "com.vaadin.tests.components"); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass, + String basePackage) throws IOException { + return findClasses(baseClass, basePackage, new String[] {}); + } + + private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass, + String basePackage, String[] ignoredPackages) throws IOException { + List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>(); + String basePackageDirName = "/" + basePackage.replace('.', '/'); + URL location = Application.class.getResource(basePackageDirName); + if (location.getProtocol().equals("file")) { + try { + File f = new File(location.toURI()); + if (!f.exists()) { + throw new IOException("Directory " + f.toString() + + " does not exist"); + } + findPackages(f, basePackage, baseClass, classes, + ignoredPackages); + } catch (URISyntaxException e) { + throw new IOException(e.getMessage()); + } + } else if (location.getProtocol().equals("jar")) { + JarURLConnection juc = (JarURLConnection) location.openConnection(); + findPackages(juc, basePackage, baseClass, classes); + } + + Collections.sort(classes, new Comparator<Class<? extends T>>() { + + @Override + public int compare(Class<? extends T> o1, Class<? extends T> o2) { + return o1.getName().compareTo(o2.getName()); + } + + }); + return classes; + } + + private static <T> List<Class<? extends T>> findClassesNoTests( + Class<T> baseClass, String basePackage, String[] ignoredPackages) + throws IOException { + List<Class<? extends T>> classes = findClasses(baseClass, basePackage, + ignoredPackages); + List<Class<? extends T>> classesNoTests = new ArrayList<Class<? extends T>>(); + for (Class<? extends T> clazz : classes) { + if (!clazz.getName().contains("Test")) { + boolean testPresent = false; + for (Method method : clazz.getMethods()) { + if (method.isAnnotationPresent(Test.class)) { + testPresent = true; + break; + } + } + if (!testPresent) { + classesNoTests.add(clazz); + } + } + } + return classesNoTests; + } + + private static <T> void findPackages(JarURLConnection juc, + String javaPackage, Class<T> baseClass, + Collection<Class<? extends T>> result) throws IOException { + String prefix = "com/vaadin/ui"; + Enumeration<JarEntry> ent = juc.getJarFile().entries(); + while (ent.hasMoreElements()) { + JarEntry e = ent.nextElement(); + if (e.getName().endsWith(".class") + && e.getName().startsWith(prefix)) { + String fullyQualifiedClassName = e.getName().replace('/', '.') + .replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + } + + private static <T> void findPackages(File parent, String javaPackage, + Class<T> baseClass, Collection<Class<? extends T>> result, + String[] ignoredPackages) { + for (String ignoredPackage : ignoredPackages) { + if (javaPackage.equals(ignoredPackage)) { + return; + } + } + + for (File file : parent.listFiles()) { + if (file.isDirectory()) { + findPackages(file, javaPackage + "." + file.getName(), + baseClass, result, ignoredPackages); + } else if (file.getName().endsWith(".class")) { + String fullyQualifiedClassName = javaPackage + "." + + file.getName().replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + + } + + @SuppressWarnings("unchecked") + private static <T> void addClassIfMatches( + Collection<Class<? extends T>> result, + String fullyQualifiedClassName, Class<T> baseClass) { + try { + // Try to load the class + + Class<?> c = Class.forName(fullyQualifiedClassName); + if (baseClass.isAssignableFrom(c) + && !Modifier.isAbstract(c.getModifiers())) { + result.add((Class<? extends T>) c); + } + } catch (Exception e) { + // Could ignore that class cannot be loaded + e.printStackTrace(); + } catch (LinkageError e) { + // Ignore. Client side classes will at least throw LinkageErrors + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Address.java b/server/tests/src/com/vaadin/tests/data/bean/Address.java new file mode 100644 index 0000000000..15cdf34ae5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Address.java @@ -0,0 +1,63 @@ +package com.vaadin.tests.data.bean; + +import java.io.Serializable; + +@SuppressWarnings("serial") +public class Address implements Serializable { + + private String streetAddress = ""; + private Integer postalCode = null; + private String city = ""; + private Country country = null; + + public Address() { + + } + + public Address(String streetAddress, int postalCode, String city, + Country country) { + setStreetAddress(streetAddress); + setPostalCode(postalCode); + setCity(city); + setCountry(country); + } + + @Override + public String toString() { + return "Address [streetAddress=" + streetAddress + ", postalCode=" + + postalCode + ", city=" + city + ", country=" + country + "]"; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public Integer getPostalCode() { + return postalCode; + } + + public void setPostalCode(Integer postalCode) { + this.postalCode = postalCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Country getCountry() { + return country; + } + + public void setCountry(Country country) { + this.country = country; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java b/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java new file mode 100644 index 0000000000..416563baba --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/BeanToValidate.java @@ -0,0 +1,56 @@ +package com.vaadin.tests.data.bean; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class BeanToValidate { + @NotNull + @Size(min = 3, max = 16) + private String firstname; + + @NotNull(message = "Last name must not be empty") + private String lastname; + + @Min(value = 18, message = "Must be 18 or above") + @Max(150) + private int age; + + @Digits(integer = 3, fraction = 2) + private String decimals; + + public String getFirstname() { + return firstname; + } + + public void setFirstname(String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(String lastname) { + this.lastname = lastname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getDecimals() { + return decimals; + } + + public void setDecimals(String decimals) { + this.decimals = decimals; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Country.java b/server/tests/src/com/vaadin/tests/data/bean/Country.java new file mode 100644 index 0000000000..afdf8dcfa1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Country.java @@ -0,0 +1,18 @@ +package com.vaadin.tests.data.bean; + +public enum Country { + + FINLAND("Finland"), SWEDEN("Sweden"), USA("USA"), RUSSIA("Russia"), NETHERLANDS( + "Netherlands"), SOUTH_AFRICA("South Africa"); + + private String name; + + private Country(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Person.java b/server/tests/src/com/vaadin/tests/data/bean/Person.java new file mode 100644 index 0000000000..f7bad31d0e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Person.java @@ -0,0 +1,143 @@ +package com.vaadin.tests.data.bean; + +import java.math.BigDecimal; +import java.util.Date; + +public class Person { + private String firstName; + private String lastName; + private String email; + private int age; + private Sex sex; + private Address address; + private boolean deceased; + private Date birthDate; + + private Integer salary; // null if unknown + private Double salaryDouble; // null if unknown + + private BigDecimal rent; + + public Person() { + + } + + @Override + public String toString() { + return "Person [firstName=" + firstName + ", lastName=" + lastName + + ", email=" + email + ", age=" + age + ", sex=" + sex + + ", address=" + address + ", deceased=" + deceased + + ", salary=" + salary + ", salaryDouble=" + salaryDouble + + ", rent=" + rent + "]"; + } + + public Person(String firstName, String lastName, String email, int age, + Sex sex, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean getDeceased() { + return deceased; + } + + public void setDeceased(boolean deceased) { + this.deceased = deceased; + } + + public Integer getSalary() { + return salary; + } + + public void setSalary(Integer salary) { + this.salary = salary; + } + + public BigDecimal getRent() { + return rent; + } + + public void setRent(BigDecimal rent) { + this.rent = rent; + } + + public Double getSalaryDouble() { + return salaryDouble; + } + + public void setSalaryDouble(Double salaryDouble) { + this.salaryDouble = salaryDouble; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public static Person createTestPerson1() { + return new Person("Foo", "Bar", "yeah@cool.com", 46, Sex.MALE, + new Address("Street", 1123, "Turku", Country.FINLAND)); + } + + public static Person createTestPerson2() { + return new Person("Maya", "Dinkelstein", "maya@foo.bar", 18, + Sex.FEMALE, new Address("Red street", 12, "Amsterdam", + Country.NETHERLANDS)); + } +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java b/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java new file mode 100644 index 0000000000..93b2273263 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/PersonWithBeanValidationAnnotations.java @@ -0,0 +1,156 @@ +package com.vaadin.tests.data.bean; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; +import javax.validation.constraints.Size; + +public class PersonWithBeanValidationAnnotations { + @NotNull + @Size(min = 5, max = 20) + private String firstName; + @NotNull + private String lastName; + + private String email; + + @Min(0) + @Max(100) + private int age; + + @NotNull + private Sex sex; + + private Address address; + private boolean deceased; + + @NotNull + @Past + private Date birthDate; + + @Min(0) + private Integer salary; // null if unknown + + @Digits(integer = 6, fraction = 2) + private Double salaryDouble; // null if unknown + + private BigDecimal rent; + + public PersonWithBeanValidationAnnotations() { + + } + + @Override + public String toString() { + return "Person [firstName=" + firstName + ", lastName=" + lastName + + ", email=" + email + ", age=" + age + ", sex=" + sex + + ", address=" + address + ", deceased=" + deceased + + ", salary=" + salary + ", salaryDouble=" + salaryDouble + + ", rent=" + rent + "]"; + } + + public PersonWithBeanValidationAnnotations(String firstName, + String lastName, String email, int age, Sex sex, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.age = age; + this.sex = sex; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Sex getSex() { + return sex; + } + + public void setSex(Sex sex) { + this.sex = sex; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean getDeceased() { + return deceased; + } + + public void setDeceased(boolean deceased) { + this.deceased = deceased; + } + + public Integer getSalary() { + return salary; + } + + public void setSalary(Integer salary) { + this.salary = salary; + } + + public BigDecimal getRent() { + return rent; + } + + public void setRent(BigDecimal rent) { + this.rent = rent; + } + + public Double getSalaryDouble() { + return salaryDouble; + } + + public void setSalaryDouble(Double salaryDouble) { + this.salaryDouble = salaryDouble; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + +} diff --git a/server/tests/src/com/vaadin/tests/data/bean/Sex.java b/server/tests/src/com/vaadin/tests/data/bean/Sex.java new file mode 100644 index 0000000000..a4e3f20a11 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/bean/Sex.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.data.bean; + +public enum Sex { + MALE("Male"), FEMALE("Female"), UNKNOWN("Unknown"); + + private String stringRepresentation; + + private Sex(String stringRepresentation) { + this.stringRepresentation = stringRepresentation; + } + + public String getStringRepresentation() { + return stringRepresentation; + } + + @Override + public String toString() { + return getStringRepresentation(); + } +} diff --git a/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java new file mode 100644 index 0000000000..6393d61981 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/data/converter/ConverterFactory.java @@ -0,0 +1,116 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.data.converter; + +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.DefaultConverterFactory; +import com.vaadin.ui.TextField; + +public class ConverterFactory extends TestCase { + + public static class ConvertTo42 implements Converter<String, Integer> { + + @Override + public Integer convertToModel(String value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return 42; + } + + @Override + public String convertToPresentation(Integer value, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return "42"; + } + + @Override + public Class<Integer> getModelType() { + return Integer.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + + } + + public static class ConverterFactory42 extends DefaultConverterFactory { + @Override + public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter( + Class<PRESENTATION> presentationType, Class<MODEL> modelType) { + if (modelType == Integer.class) { + return (Converter<PRESENTATION, MODEL>) new ConvertTo42(); + } + + return super.createConverter(presentationType, modelType); + } + } + + public void testApplicationConverterFactoryInBackgroundThread() { + Application.setCurrent(null); + final Application appWithCustomIntegerConverter = new Application(); + appWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + + TextField tf = new TextField("", "123") { + @Override + public Application getApplication() { + return appWithCustomIntegerConverter; + }; + }; + tf.setConverter(Integer.class); + // The application converter always returns 42. Current application is + // null + assertEquals(42, tf.getConvertedValue()); + } + + public void testApplicationConverterFactoryForDetachedComponent() { + final Application appWithCustomIntegerConverter = new Application(); + appWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + Application.setCurrent(appWithCustomIntegerConverter); + + TextField tf = new TextField("", "123"); + tf.setConverter(Integer.class); + // The application converter always returns 42. Current application is + // null + assertEquals(42, tf.getConvertedValue()); + } + + public void testApplicationConverterFactoryForDifferentThanCurrentApplication() { + final Application fieldAppWithCustomIntegerConverter = new Application(); + fieldAppWithCustomIntegerConverter + .setConverterFactory(new ConverterFactory42()); + Application.setCurrent(new Application()); + + TextField tf = new TextField("", "123") { + @Override + public Application getApplication() { + return fieldAppWithCustomIntegerConverter; + } + }; + tf.setConverter(Integer.class); + + // The application converter always returns 42. Application.getCurrent() + // should not be used + assertEquals(42, tf.getConvertedValue()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java b/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java new file mode 100644 index 0000000000..8334c7f183 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/IndexedContainerListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class IndexedContainerListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ValueChangeEvent.class, ValueChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java b/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java new file mode 100644 index 0000000000..d493f22779 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/PropertysetItemListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Item.PropertySetChangeEvent; +import com.vaadin.data.Item.PropertySetChangeListener; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class PropertysetItemListeners extends AbstractListenerMethodsTest { + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(PropertysetItem.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java b/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java new file mode 100644 index 0000000000..1ab742427d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/SourceFileChecker.java @@ -0,0 +1,217 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.commons.io.IOUtils; + +public class SourceFileChecker extends TestCase { + + /** + * The tests are run in the build directory. + */ + public static String baseDirectory = null; + public static final String SRC_DIR = getBaseDir() + "src"; + public static final String TESTBENCH_SRC_DIR = getBaseDir() + + "tests/testbench"; + public static final String SERVERSIDE_SRC_DIR = getBaseDir() + + "tests/server-side"; + public static final String CLIENTSIDE_SRC_DIR = getBaseDir() + + "tests/client-side"; + private String externalJavaFiles = "com/vaadin/external"; + private String buildFiles = "build"; + private Set<String> alwaysIgnore = new HashSet<String>(); + { + alwaysIgnore.add(".settings"); + alwaysIgnore.add("eclipse"); + } + + public static String getBaseDir() { + if (baseDirectory != null) { + return baseDirectory; + } + // Run in the "build" directory by build, in the project root by Eclipse + for (File f : new File(".").listFiles()) { + if (f.getName().equals("buildhelpers")) { + // We are in "build" + baseDirectory = "../"; + return baseDirectory; + } + } + + baseDirectory = "./"; + return baseDirectory; + } + + private static final String[] ALL_SRC_DIRS = new String[] { SRC_DIR, + TESTBENCH_SRC_DIR, SERVERSIDE_SRC_DIR, CLIENTSIDE_SRC_DIR }; + + public void testJavaFilesContainsLicense() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + validateFiles(SRC_DIR, new LicenseChecker(), ignore, + "The following files are missing license information:\n{0}", + ".java"); + } + + public void testNonJavaFilesUseUnixNewline() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(buildFiles); + + for (String suffix : new String[] { ".html", ".css", ".xml" }) { + validateFiles(getBaseDir(), new DosNewlineDetector(), ignore, + "The following files contain CRLF instead of LF:\n{0}", + suffix); + } + } + + public void testJavaFilesUseUnixNewline() throws IOException { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + for (String dir : ALL_SRC_DIRS) { + validateFiles(dir, new DosNewlineDetector(), ignore, + "The following files contain CRLF instead of LF:\n{0}", + ".java"); + } + } + + public void testGwtFilesUsingEntry() { + Set<String> ignore = new HashSet<String>(alwaysIgnore); + ignore.add(externalJavaFiles); + validateFiles( + SRC_DIR, + new GwtEntryChecker(), + ignore, + "The following files might export javscript callbacks without $entry:\n{0}", + ".java"); + } + + public interface FileValidator { + void validateFile(File f) throws Exception; + } + + private void validateFiles(String directory, FileValidator validator, + Set<String> ignore, String errorMessage, String ending) { + File srcDir = new File(directory); + HashSet<String> missing = new HashSet<String>(); + validateFiles(directory, srcDir, missing, validator, ending, ignore); + if (!missing.isEmpty()) { + throw new RuntimeException(errorMessage.replace("{0}", missing + .toString().replace(',', '\n'))); + } + + } + + private void validateFiles(String baseDirectory, File directory, + HashSet<String> missing, FileValidator validator, String suffix, + Set<String> ignores) { + Assert.assertTrue("Directory " + directory + " does not exist", + directory.exists()); + + File[] files = directory.listFiles(); + if (files == null) { + throw new RuntimeException("Listing of directory " + + directory.getPath() + " failed"); + } + for (File f : files) { + boolean ignoreThis = false; + for (String ignore : ignores) { + if (new File(baseDirectory, ignore).equals(f)) { + ignoreThis = true; + continue; + } + } + + if (ignoreThis) { + continue; + } + + if (f.isDirectory()) { + validateFiles(baseDirectory, f, missing, validator, suffix, + ignores); + } else if (f.getName().endsWith(suffix)) { + try { + validator.validateFile(f); + } catch (Throwable t) { + missing.add(f.getPath()); + } + } + } + } + + abstract class FileContentsValidator implements FileValidator { + @Override + public void validateFile(File f) throws Exception { + FileInputStream fis = new FileInputStream(f); + String contents = IOUtils.toString(fis); + fis.close(); + validateContents(f, contents); + } + + protected abstract void validateContents(File f, String contents) + throws Exception; + + } + + class DosNewlineDetector extends FileContentsValidator { + + @Override + protected void validateContents(File f, String contents) + throws Exception { + if (contents.contains("\r\n")) { + throw new IllegalArgumentException(); + } + + } + + } + + class LicenseChecker extends FileContentsValidator { + + @Override + protected void validateContents(File f, String contents) + throws Exception { + if (!contents.contains("@" + "VaadinApache2LicenseForJavaFiles" + + "@")) { + throw new IllegalArgumentException(); + } + } + } + + class GwtEntryChecker extends FileContentsValidator { + // Matches e.g. + // @com.vaadin.client.HistoryImplIEVaadin::escapeHtml( + private final Matcher matcher = Pattern.compile("@[\\w.]+::\\w+\\(") + .matcher(""); + + @Override + protected void validateContents(File f, String contents) + throws Exception { + matcher.reset(contents); + while (matcher.find()) { + int start = matcher.start(); + + // Search backwards to find index of native block start + int nativeBlockStart = contents.lastIndexOf("/*-{", start); + + // Get contents between block start and our match + String beforeMatchInBlock = contents.substring( + nativeBlockStart, start); + + // Fail if there's no $entry + if (!beforeMatchInBlock.contains("$entry")) { + throw new IllegalArgumentException(); + } + } + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java new file mode 100644 index 0000000000..0d8433d1c6 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractBeanContainerListeners.java @@ -0,0 +1,16 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractBeanContainerListeners extends + AbstractListenerMethodsTest { + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(BeanItemContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class, + new BeanItemContainer<PropertySetChangeListener>( + PropertySetChangeListener.class)); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java new file mode 100644 index 0000000000..b63e4f809a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractContainerListeners.java @@ -0,0 +1,21 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractContainerListeners extends AbstractListenerMethodsTest { + + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ItemSetChangeEvent.class, ItemSetChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + PropertySetChangeEvent.class, PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java new file mode 100644 index 0000000000..a8e2a4aa2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractInMemoryContainerListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractInMemoryContainerListeners extends + AbstractListenerMethodsTest { + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(IndexedContainer.class, + ItemSetChangeEvent.class, ItemSetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java b/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java new file mode 100644 index 0000000000..a1d01d1930 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestAbstractPropertyListeners.java @@ -0,0 +1,24 @@ +package com.vaadin.tests.server; + +import com.vaadin.data.Property.ReadOnlyStatusChangeEvent; +import com.vaadin.data.Property.ReadOnlyStatusChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.AbstractProperty; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; + +public class TestAbstractPropertyListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbstractProperty.class, + ValueChangeEvent.class, ValueChangeListener.class, + new ObjectProperty<String>("")); + } + + public void testReadOnlyStatusChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbstractProperty.class, + ReadOnlyStatusChangeEvent.class, + ReadOnlyStatusChangeListener.class, new ObjectProperty<String>( + "")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java new file mode 100644 index 0000000000..e98be99cbc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -0,0 +1,271 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import junit.framework.TestCase; + +import org.junit.Test; + +public class TestClassesSerializable extends TestCase { + + /** + * JARs that will be scanned for classes to test, in addition to classpath + * directories. + */ + private static String JAR_PATTERN = ".*vaadin.*\\.jar"; + + private static String[] BASE_PACKAGES = { "com.vaadin" }; + + private static String[] EXCLUDED_PATTERNS = { + "com\\.vaadin\\.demo\\..*", // + "com\\.vaadin\\.external\\.org\\.apache\\.commons\\.fileupload\\..*", // + "com\\.vaadin\\.launcher\\..*", // + "com\\.vaadin\\.client\\..*", // + "com\\.vaadin\\.server\\.widgetsetutils\\..*", // + "com\\.vaadin\\.tests\\..*", // exclude automated tests + "com\\.vaadin\\.tools\\..*", // + "com\\.vaadin\\.ui\\.themes\\..*", // + // exact class level filtering + "com\\.vaadin\\.event\\.FieldEvents", // + "com\\.vaadin\\.event\\.LayoutEvents", // + "com\\.vaadin\\.event\\.MouseEvents", // + "com\\.vaadin\\.server\\.AbstractApplicationPortlet", // + "com\\.vaadin\\.server\\.ApplicationPortlet2", // + "com\\.vaadin\\.server\\.Constants", // + "com\\.vaadin\\.util\\.SerializerHelper", // fully static + // class level filtering, also affecting nested classes and + // interfaces + "com\\.vaadin\\.server\\.AbstractCommunicationManager.*", // + "com\\.vaadin\\.server\\.CommunicationManager.*", // + "com\\.vaadin\\.server\\.PortletCommunicationManager.*", // + }; + + /** + * Tests that all the relevant classes and interfaces under + * {@link #BASE_PACKAGES} implement Serializable. + * + * @throws Exception + */ + public void testClassesSerializable() throws Exception { + List<String> rawClasspathEntries = getRawClasspathEntries(); + + List<String> classes = new ArrayList<String>(); + for (String location : rawClasspathEntries) { + classes.addAll(findServerClasses(location)); + } + + ArrayList<Class<?>> nonSerializableClasses = new ArrayList<Class<?>>(); + for (String className : classes) { + Class<?> cls = Class.forName(className); + // skip annotations and synthetic classes + if (cls.isAnnotation() || cls.isSynthetic()) { + continue; + } + // Don't add classes that have a @Test annotation on any methods + boolean testPresent = false; + for (Method method : cls.getMethods()) { + if (method.isAnnotationPresent(Test.class)) { + testPresent = true; + break; + } + } + if (testPresent) { + continue; + } + + // report non-serializable classes and interfaces + if (!Serializable.class.isAssignableFrom(cls)) { + nonSerializableClasses.add(cls); + // TODO easier to read when testing + // System.err.println(cls); + } + } + + // useful failure message including all non-serializable classes and + // interfaces + if (!nonSerializableClasses.isEmpty()) { + String nonSerializableString = ""; + Iterator<Class<?>> it = nonSerializableClasses.iterator(); + while (it.hasNext()) { + Class c = it.next(); + nonSerializableString += ", " + c.getName(); + if (c.isAnonymousClass()) { + nonSerializableString += "(super: "; + nonSerializableString += c.getSuperclass().getName(); + nonSerializableString += ", interfaces: "; + for (Class i : c.getInterfaces()) { + nonSerializableString += i.getName(); + nonSerializableString += ","; + } + nonSerializableString += ")"; + } + } + fail("Serializable not implemented by the following classes and interfaces: " + + nonSerializableString); + } + } + + /** + * Lists all class path entries by splitting the class path string. + * + * Adapted from ClassPathExplorer.getRawClasspathEntries(), but without + * filtering. + * + * @return List of class path segment strings + */ + // + private final static List<String> getRawClasspathEntries() { + // try to keep the order of the classpath + List<String> locations = new ArrayList<String>(); + + String pathSep = System.getProperty("path.separator"); + String classpath = System.getProperty("java.class.path"); + + if (classpath.startsWith("\"")) { + classpath = classpath.substring(1); + } + if (classpath.endsWith("\"")) { + classpath = classpath.substring(0, classpath.length() - 1); + } + + String[] split = classpath.split(pathSep); + for (int i = 0; i < split.length; i++) { + String classpathEntry = split[i]; + locations.add(classpathEntry); + } + + return locations; + } + + /** + * Finds the server side classes/interfaces under a class path entry - + * either a directory or a JAR that matches {@link #JAR_PATTERN}. + * + * Only classes under {@link #BASE_PACKAGES} are considered, and those + * matching {@link #EXCLUDED_PATTERNS} are filtered out. + * + * @param classpathEntry + * @return + * @throws IOException + */ + private List<String> findServerClasses(String classpathEntry) + throws IOException { + Collection<String> classes = new ArrayList<String>(); + + File file = new File(classpathEntry); + if (file.isDirectory()) { + classes = findClassesInDirectory(null, file); + } else if (file.getName().matches(JAR_PATTERN)) { + classes = findClassesInJar(file); + } else { + System.out.println("Ignoring " + classpathEntry); + return Collections.emptyList(); + } + + List<String> filteredClasses = new ArrayList<String>(); + for (String className : classes) { + boolean ok = false; + for (String basePackage : BASE_PACKAGES) { + if (className.startsWith(basePackage + ".")) { + ok = true; + break; + } + } + for (String excludedPrefix : EXCLUDED_PATTERNS) { + if (className.matches(excludedPrefix)) { + ok = false; + break; + } + } + + // Don't add test classes + if (className.contains("Test")) { + ok = false; + } + + if (ok) { + filteredClasses.add(className); + } + } + + return filteredClasses; + } + + /** + * Lists class names (based on .class files) in a JAR file. + * + * @param file + * a valid JAR file + * @return collection of fully qualified class names in the JAR + * @throws IOException + */ + private Collection<String> findClassesInJar(File file) throws IOException { + Collection<String> classes = new ArrayList<String>(); + + JarFile jar = new JarFile(file); + Enumeration<JarEntry> e = jar.entries(); + while (e.hasMoreElements()) { + JarEntry entry = e.nextElement(); + if (entry.getName().endsWith(".class")) { + String nameWithoutExtension = entry.getName().replaceAll( + "\\.class", ""); + String className = nameWithoutExtension.replace('/', '.'); + classes.add(className); + } + } + return classes; + } + + /** + * Lists class names (based on .class files) in a directory (a package path + * root). + * + * @param parentPackage + * parent package name or null at root of hierarchy, used by + * recursion + * @param parent + * File representing the directory to scan + * @return collection of fully qualified class names in the directory + */ + private final static Collection<String> findClassesInDirectory( + String parentPackage, File parent) { + if (parent.isHidden() + || parent.getPath().contains(File.separator + ".")) { + return Collections.emptyList(); + } + + if (parentPackage == null) { + parentPackage = ""; + } else { + parentPackage += "."; + } + + Collection<String> classNames = new ArrayList<String>(); + + // add all directories recursively + File[] files = parent.listFiles(); + for (File child : files) { + if (child.isDirectory()) { + classNames.addAll(findClassesInDirectory( + parentPackage + child.getName(), child)); + } else if (child.getName().endsWith(".class")) { + classNames.add(parentPackage.replace(File.separatorChar, '.') + + child.getName().replaceAll("\\.class", "")); + } + } + + return classNames; + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestEventRouter.java b/server/tests/src/com/vaadin/tests/server/TestEventRouter.java new file mode 100644 index 0000000000..a8f5039042 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestEventRouter.java @@ -0,0 +1,39 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.ui.TextField; + +public class TestEventRouter extends TestCase { + + int innerListenerCalls = 0; + + public void testAddInEventListener() { + final TextField tf = new TextField(); + + final ValueChangeListener outer = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + ValueChangeListener inner = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + innerListenerCalls++; + System.out.println("The inner listener was called"); + } + }; + + tf.addListener(inner); + } + }; + + tf.addListener(outer); + tf.setValue("abc"); // No inner listener calls, adds one inner + tf.setValue("def"); // One inner listener call, adds one inner + tf.setValue("ghi"); // Two inner listener calls, adds one inner + assert (innerListenerCalls == 3); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java b/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java new file mode 100644 index 0000000000..8a368ead53 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestFileTypeResolver.java @@ -0,0 +1,79 @@ +package com.vaadin.tests.server; + +import java.io.File; + +import junit.framework.TestCase; + +import com.vaadin.service.FileTypeResolver; + +public class TestFileTypeResolver extends TestCase { + + private static final String FLASH_MIME_TYPE = "application/x-shockwave-flash"; + private static final String TEXT_MIME_TYPE = "text/plain"; + private static final String HTML_MIME_TYPE = "text/html"; + + public void testMimeTypes() { + File plainFlash = new File("MyFlash.swf"); + File plainText = new File("/a/b/MyFlash.txt"); + File plainHtml = new File("c:\\MyFlash.html"); + + // Flash + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath()), + FLASH_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath() + + "?param1=value1"), FLASH_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainFlash.getAbsolutePath() + + "?param1=value1¶m2=value2"), FLASH_MIME_TYPE); + + // Plain text + assertEquals(FileTypeResolver.getMIMEType(plainText.getAbsolutePath()), + TEXT_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainText.getAbsolutePath() + + "?param1=value1"), TEXT_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainText.getAbsolutePath() + + "?param1=value1¶m2=value2"), TEXT_MIME_TYPE); + + // Plain text + assertEquals(FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath()), + HTML_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath() + + "?param1=value1"), HTML_MIME_TYPE); + assertEquals( + FileTypeResolver.getMIMEType(plainHtml.getAbsolutePath() + + "?param1=value1¶m2=value2"), HTML_MIME_TYPE); + + // Filename missing + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("")); + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("?param1")); + + } + + public void testExtensionCase() { + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.jpg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.jPg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPG")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPEG")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.Jpeg")); + assertEquals("image/jpeg", FileTypeResolver.getMIMEType("abc.JPE")); + } + + public void testCustomMimeType() { + assertEquals(FileTypeResolver.DEFAULT_MIME_TYPE, + FileTypeResolver.getMIMEType("vaadin.foo")); + + FileTypeResolver.addExtension("foo", "Vaadin Foo/Bar"); + FileTypeResolver.addExtension("FOO2", "Vaadin Foo/Bar2"); + assertEquals("Vaadin Foo/Bar", + FileTypeResolver.getMIMEType("vaadin.foo")); + assertEquals("Vaadin Foo/Bar2", + FileTypeResolver.getMIMEType("vaadin.Foo2")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java b/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java new file mode 100644 index 0000000000..1c1f9624c8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestKeyMapper.java @@ -0,0 +1,102 @@ +package com.vaadin.tests.server; + +import java.lang.reflect.Field; +import java.util.HashMap; + +import junit.framework.TestCase; + +import com.vaadin.server.KeyMapper; + +public class TestKeyMapper extends TestCase { + + public void testAdd() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + String key1 = mapper.key(o1); + String key2 = mapper.key(o2); + String key3 = mapper.key(o3); + + assertEquals(mapper.get(key1), o1); + assertEquals(mapper.get(key2), o2); + assertEquals(mapper.get(key3), o3); + assertNotSame(key1, key2); + assertNotSame(key1, key3); + assertNotSame(key2, key3); + + assertSize(mapper, 3); + + // Key should not add if there already is a mapping + assertEquals(mapper.key(o3), key3); + assertSize(mapper, 3); + + // Remove -> add should return a new key + mapper.remove(o1); + String newkey1 = mapper.key(o1); + assertNotSame(key1, newkey1); + + } + + public void testRemoveAll() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + mapper.key(o1); + mapper.key(o2); + mapper.key(o3); + + assertSize(mapper, 3); + mapper.removeAll(); + assertSize(mapper, 0); + + } + + public void testRemove() { + KeyMapper<Object> mapper = new KeyMapper<Object>(); + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + + // Create new ids + mapper.key(o1); + mapper.key(o2); + mapper.key(o3); + + assertSize(mapper, 3); + mapper.remove(o1); + assertSize(mapper, 2); + mapper.key(o1); + assertSize(mapper, 3); + mapper.remove(o1); + assertSize(mapper, 2); + + mapper.remove(o2); + mapper.remove(o3); + assertSize(mapper, 0); + + } + + private void assertSize(KeyMapper<?> mapper, int i) { + try { + Field f1 = KeyMapper.class.getDeclaredField("objectKeyMap"); + Field f2 = KeyMapper.class.getDeclaredField("keyObjectMap"); + f1.setAccessible(true); + f2.setAccessible(true); + + HashMap<?, ?> h1 = (HashMap<?, ?>) f1.get(mapper); + HashMap<?, ?> h2 = (HashMap<?, ?>) f2.get(mapper); + + assertEquals(i, h1.size()); + assertEquals(i, h2.size()); + } catch (Throwable t) { + t.printStackTrace(); + fail(); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java new file mode 100644 index 0000000000..dc730f6cc4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestMimeTypes.java @@ -0,0 +1,26 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.server.ClassResource; +import com.vaadin.ui.Embedded; + +public class TestMimeTypes extends TestCase { + + public void testEmbeddedPDF() { + Application app = new Application() { + + @Override + public void init() { + // TODO Auto-generated method stub + + } + }; + Embedded e = new Embedded("A pdf", new ClassResource("file.pddf")); + assertEquals("Invalid mimetype", "application/octet-stream", + e.getMimeType()); + e = new Embedded("A pdf", new ClassResource("file.pdf")); + assertEquals("Invalid mimetype", "application/pdf", e.getMimeType()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java b/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java new file mode 100644 index 0000000000..48c60c83c4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestPropertyFormatter.java @@ -0,0 +1,75 @@ +package com.vaadin.tests.server; + +import java.util.Date; + +import junit.framework.TestCase; + +import org.junit.Test; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertyFormatter; + +@SuppressWarnings("unchecked") +public class TestPropertyFormatter extends TestCase { + + class TestFormatter extends PropertyFormatter { + + @Override + public String format(Object value) { + boolean isCorrectType = getExpectedClass().isAssignableFrom( + value.getClass()); + assertTrue(isCorrectType); + return "FOO"; + } + + @Override + public Object parse(String formattedValue) throws Exception { + return getExpectedClass().newInstance(); + } + }; + + @SuppressWarnings("rawtypes") + private Class expectedClass; + + @SuppressWarnings("rawtypes") + private Class getExpectedClass() { + return expectedClass; + } + + /** + * The object passed to format should be same as property's type. + * + * @throws IllegalAccessException + * @throws InstantiationException + */ + @Test + @SuppressWarnings({ "rawtypes" }) + public void testCorrectTypeForFormat() throws InstantiationException, + IllegalAccessException { + Class[] testedTypes = new Class[] { Integer.class, Boolean.class, + Double.class, String.class, Date.class }; + Object[] testValues = new Object[] { new Integer(3), Boolean.FALSE, + new Double(3.3), "bar", new Date() }; + + int i = 0; + for (Class class1 : testedTypes) { + expectedClass = class1; + + TestFormatter formatter = new TestFormatter(); + + // Should just return null, without formatting + Object value = formatter.getValue(); + + // test with property which value is null + formatter.setPropertyDataSource(new ObjectProperty(null, + expectedClass)); + formatter.getValue(); // calls format + + // test with a value + formatter.setPropertyDataSource(new ObjectProperty(testValues[i++], + expectedClass)); + formatter.getValue(); // calls format + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestSerialization.java b/server/tests/src/com/vaadin/tests/server/TestSerialization.java new file mode 100644 index 0000000000..84ff5ad6fa --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestSerialization.java @@ -0,0 +1,126 @@ +package com.vaadin.tests.server; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import junit.framework.TestCase; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.data.validator.RegexpValidator; +import com.vaadin.ui.Form; + +public class TestSerialization extends TestCase { + + public void testValidators() throws Exception { + RegexpValidator validator = new RegexpValidator(".*", "Error"); + validator.validate("aaa"); + RegexpValidator validator2 = (RegexpValidator) serializeAndDeserialize(validator); + validator2.validate("aaa"); + } + + public void testForm() throws Exception { + Form f = new Form(); + String propertyId = "My property"; + f.addItemProperty(propertyId, new MethodProperty<Object>(new Data(), + "dummyGetterAndSetter")); + f.replaceWithSelect(propertyId, new Object[] { "a", "b", null }, + new String[] { "Item a", "ITem b", "Null item" }); + + serializeAndDeserialize(f); + + } + + public void testIndedexContainerItemIds() throws Exception { + IndexedContainer ic = new IndexedContainer(); + ic.addContainerProperty("prop1", String.class, null); + Object id = ic.addItem(); + ic.getItem(id).getItemProperty("prop1").setValue("1"); + + Item item2 = ic.addItem("item2"); + item2.getItemProperty("prop1").setValue("2"); + + serializeAndDeserialize(ic); + } + + public void testMethodPropertyGetter() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyGetter"); + serializeAndDeserialize(mp); + } + + public void testMethodPropertyGetterAndSetter() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyGetterAndSetter"); + serializeAndDeserialize(mp); + } + + public void testMethodPropertyInt() throws Exception { + MethodProperty<?> mp = new MethodProperty<Object>(new Data(), + "dummyInt"); + serializeAndDeserialize(mp); + } + + private static Serializable serializeAndDeserialize(Serializable s) + throws IOException, ClassNotFoundException { + // Serialize and deserialize + + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bs); + out.writeObject(s); + byte[] data = bs.toByteArray(); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream( + data)); + Serializable s2 = (Serializable) in.readObject(); + + // using special toString(Object) method to avoid calling + // Property.toString(), which will be temporarily disabled + if (s.equals(s2)) { + System.out.println(toString(s) + " equals " + toString(s2)); + } else { + System.out.println(toString(s) + " does NOT equal " + toString(s2)); + } + + return s2; + } + + private static String toString(Object o) { + if (o instanceof Property) { + return String.valueOf(((Property<?>) o).getValue()); + } else { + return String.valueOf(o); + } + } + + public static class Data implements Serializable { + private String dummyGetter; + private String dummyGetterAndSetter; + private int dummyInt; + + public String getDummyGetterAndSetter() { + return dummyGetterAndSetter; + } + + public void setDummyGetterAndSetter(String dummyGetterAndSetter) { + this.dummyGetterAndSetter = dummyGetterAndSetter; + } + + public int getDummyInt() { + return dummyInt; + } + + public void setDummyInt(int dummyInt) { + this.dummyInt = dummyInt; + } + + public String getDummyGetter() { + return dummyGetter; + } + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java b/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java new file mode 100644 index 0000000000..84247c81c1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestSimpleMultiPartInputStream.java @@ -0,0 +1,138 @@ +package com.vaadin.tests.server; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import junit.framework.TestCase; + +import com.vaadin.server.AbstractCommunicationManager.SimpleMultiPartInputStream; + +public class TestSimpleMultiPartInputStream extends TestCase { + + /** + * Check that the output for a given stream until boundary is as expected. + * + * @param input + * @param boundary + * @param expected + * @throws Exception + */ + protected void checkBoundaryDetection(byte[] input, String boundary, + byte[] expected) throws Exception { + ByteArrayInputStream bais = new ByteArrayInputStream(input); + SimpleMultiPartInputStream smpis = new SimpleMultiPartInputStream(bais, + boundary); + ByteArrayOutputStream resultStream = new ByteArrayOutputStream(); + int outbyte; + try { + while ((outbyte = smpis.read()) != -1) { + resultStream.write(outbyte); + } + } catch (IOException e) { + throw new IOException(e.getMessage() + "; expected " + + new String(expected) + " but got " + + resultStream.toString()); + } + if (!Arrays.equals(expected, resultStream.toByteArray())) { + throw new Exception("Mismatch: expected " + new String(expected) + + " but got " + resultStream.toString()); + } + } + + protected void checkBoundaryDetection(String input, String boundary, + String expected) throws Exception { + checkBoundaryDetection(input.getBytes(), boundary, expected.getBytes()); + } + + public void testSingleByteBoundaryAtEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("a"), "a", "xyz123"); + } + + public void testSingleByteBoundaryInMiddle() throws Exception { + checkBoundaryDetection("xyz" + getFullBoundary("a") + "123", "a", "xyz"); + } + + public void testCorrectBoundaryAtEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("abc"), "abc", + "xyz123"); + } + + public void testCorrectBoundaryNearEnd() throws Exception { + checkBoundaryDetection("xyz123" + getFullBoundary("abc") + "de", "abc", + "xyz123"); + } + + public void testCorrectBoundaryAtBeginning() throws Exception { + checkBoundaryDetection(getFullBoundary("abc") + "xyz123", "abc", ""); + } + + public void testRepeatingCharacterBoundary() throws Exception { + checkBoundaryDetection(getFullBoundary("aa") + "xyz123", "aa", ""); + checkBoundaryDetection("axyz" + getFullBoundary("aa") + "123", "aa", + "axyz"); + checkBoundaryDetection("xyz123" + getFullBoundary("aa"), "aa", "xyz123"); + } + + /** + * Note, the boundary in this test is invalid. Boundary strings don't + * contain CR/LF. + * + */ + // public void testRepeatingNewlineBoundary() throws Exception { + // checkBoundaryDetection("1234567890" + getFullBoundary("\n\n") + // + "1234567890", "\n\n", ""); + // } + + public void testRepeatingStringBoundary() throws Exception { + checkBoundaryDetection(getFullBoundary("abab") + "xyz123", "abab", ""); + checkBoundaryDetection("abaxyz" + getFullBoundary("abab") + "123", + "abab", "abaxyz"); + checkBoundaryDetection("xyz123" + getFullBoundary("abab"), "abab", + "xyz123"); + } + + public void testOverlappingBoundary() throws Exception { + checkBoundaryDetection("abc" + getFullBoundary("abcabd") + "xyz123", + "abcabd", "abc"); + checkBoundaryDetection("xyzabc" + getFullBoundary("abcabd") + "123", + "abcabd", "xyzabc"); + checkBoundaryDetection("xyz123abc" + getFullBoundary("abcabd"), + "abcabd", "xyz123abc"); + } + + /* + * TODO fix these tests, they don't do what their method name says. + */ + + // public void testNoBoundaryInInput() throws Exception { + // try { + // checkBoundaryDetection("xyz123", "abc", "xyz123"); + // fail(); + // } catch (IOException e) { + // } + // } + // + // public void testPartialBoundaryAtInputEnd() throws Exception { + // try { + // // This should lead to IOException (stream end), not AIOOBE + // checkBoundaryDetection("xyz123ab", "abc", "xyz123ab"); + // fail(); + // } catch (IOException e) { + // } + // } + // + // public void testPartialBoundaryAtInputBeginning() throws Exception { + // try { + // checkBoundaryDetection("abxyz123", "abc", "abxyz123"); + // fail(); + // } catch (IOException e) { + // } + // } + + public static String getFullBoundary(String str) { + return "\r\n--" + str + "--"; + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java new file mode 100644 index 0000000000..f3b367483a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java @@ -0,0 +1,77 @@ +package com.vaadin.tests.server; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.Application; +import com.vaadin.server.CommunicationManager; +import com.vaadin.server.StreamVariable; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.UI; +import com.vaadin.ui.Upload; + +public class TestStreamVariableMapping extends TestCase { + private static final String variableName = "myName"; + + private Upload owner; + private StreamVariable streamVariable; + + private CommunicationManager cm; + + @Override + protected void setUp() throws Exception { + final Application application = new Application(); + final UI uI = new UI() { + @Override + protected void init(WrappedRequest request) { + // TODO Auto-generated method stub + + } + + @Override + public Application getApplication() { + return application; + } + }; + owner = new Upload() { + @Override + public UI getUI() { + return uI; + } + }; + streamVariable = EasyMock.createMock(StreamVariable.class); + cm = createCommunicationManager(); + + super.setUp(); + } + + public void testAddStreamVariable() { + String targetUrl = cm.getStreamVariableTargetUrl(owner, variableName, + streamVariable); + assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/1/myName/")); + + StreamVariable streamVariable2 = cm.getStreamVariable( + owner.getConnectorId(), variableName); + assertSame(streamVariable, streamVariable2); + } + + public void testRemoverVariable() { + cm.getStreamVariableTargetUrl(owner, variableName, streamVariable); + assertNotNull(cm + .getStreamVariable(owner.getConnectorId(), variableName)); + + cm.cleanStreamVariable(owner, variableName); + assertNull(cm.getStreamVariable(owner.getConnectorId(), variableName)); + } + + private CommunicationManager createCommunicationManager() { + return new CommunicationManager(new Application() { + @Override + public void init() { + // TODO Auto-generated method stub + } + }); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TestThemeNames.java b/server/tests/src/com/vaadin/tests/server/TestThemeNames.java new file mode 100644 index 0000000000..22fe315730 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TestThemeNames.java @@ -0,0 +1,38 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.themes.BaseTheme; + +public class TestThemeNames extends TestCase { + public void testThemeNames() { + File baseDir = new File(SourceFileChecker.getBaseDir() + + "WebContent/VAADIN/themes/"); + + List<Class<? extends BaseTheme>> themeClasses = VaadinClasses + .getThemeClasses(); + for (Class<? extends BaseTheme> themeClass : themeClasses) { + try { + Field field = themeClass.getField("THEME_NAME"); + String themeName = (String) field.get(null); + + File themeDir = new File(baseDir, themeName); + File styleFile = new File(themeDir, "styles.css"); + + assertTrue("Can't find " + styleFile + " for theme " + + themeClass.getName(), styleFile.exists()); + + // Test that casing matches + assertEquals(themeDir.getCanonicalFile().getName(), themeName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java b/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java new file mode 100644 index 0000000000..0cacccd08a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/TransactionListenersConcurrency.java @@ -0,0 +1,201 @@ +package com.vaadin.tests.server; + +import static org.easymock.EasyMock.createMock; + +import java.lang.Thread.UncaughtExceptionHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Random; + +import javax.servlet.http.HttpSession; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.Application.ApplicationStartEvent; +import com.vaadin.server.AbstractWebApplicationContext; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.WebApplicationContext; +import com.vaadin.service.ApplicationContext.TransactionListener; + +import org.easymock.EasyMock; + +public class TransactionListenersConcurrency extends TestCase { + + /** + * This test starts N threads concurrently. Each thread creates an + * application which adds a transaction listener to the context. A + * transaction is then started for each application. Some semi-random delays + * are included so that calls to addTransactionListener and + * WebApplicationContext.startTransaction are mixed. + * + */ + public void testTransactionListeners() throws Exception { + final List<Throwable> exceptions = new ArrayList<Throwable>(); + + HttpSession session = createSession(); + final WebApplicationContext context = WebApplicationContext + .getApplicationContext(session); + List<Thread> threads = new ArrayList<Thread>(); + + for (int i = 0; i < 5; i++) { + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + Application app = new Application() { + + @Override + public void init() { + // Sleep 0-1000ms so another transaction has time to + // start before we add the transaction listener. + try { + Thread.sleep((long) (1000 * new Random() + .nextDouble())); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + getContext().addTransactionListener( + new DelayTransactionListener(2000)); + } + + }; + + // Start the application so the transaction listener is + // called later on. + try { + DeploymentConfiguration dc = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(dc.isProductionMode()).andReturn(true); + EasyMock.expect(dc.getInitParameters()).andReturn( + new Properties()); + EasyMock.replay(dc); + + app.start(new ApplicationStartEvent(new URL( + "http://localhost/"), dc, context)); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + try { + // Call the transaction listener using reflection as + // startTransaction is protected. + + Method m = AbstractWebApplicationContext.class + .getDeclaredMethod("startTransaction", + Application.class, Object.class); + m.setAccessible(true); + m.invoke(context, app, null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + }); + + threads.add(t); + t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + + @Override + public void uncaughtException(Thread t, Throwable e) { + if (e.getCause() != null) { + e = e.getCause(); + } + exceptions.add(e); + } + }); + } + + // Start the threads and wait for all of them to finish + for (Thread t : threads) { + t.start(); + } + int running = threads.size(); + + while (running > 0) { + for (Iterator<Thread> i = threads.iterator(); i.hasNext();) { + Thread t = i.next(); + if (!t.isAlive()) { + running--; + i.remove(); + } + } + } + + for (Throwable t : exceptions) { + if (t instanceof InvocationTargetException) { + t = t.getCause(); + } + if (t != null) { + t.printStackTrace(System.err); + fail(t.getClass().getName()); + } + } + + System.out.println("Done, all ok"); + + } + + /** + * Creates a HttpSession mock + * + */ + private static HttpSession createSession() { + HttpSession session = createMock(HttpSession.class); + EasyMock.expect( + session.getAttribute(WebApplicationContext.class.getName())) + .andReturn(null).anyTimes(); + session.setAttribute( + EasyMock.eq(WebApplicationContext.class.getName()), + EasyMock.anyObject()); + + EasyMock.replay(session); + return session; + } + + /** + * A transaction listener that just sleeps for the given amount of time in + * transactionStart and transactionEnd. + * + */ + public static class DelayTransactionListener implements TransactionListener { + + private int delay; + + public DelayTransactionListener(int delay) { + this.delay = delay; + } + + @Override + public void transactionStart(Application application, + Object transactionData) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + + @Override + public void transactionEnd(Application application, + Object transactionData) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java b/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java new file mode 100644 index 0000000000..e189ffc77d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/AbstractListenerMethodsTest.java @@ -0,0 +1,173 @@ +package com.vaadin.tests.server.component; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.junit.Assert; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.Component; + +public abstract class AbstractListenerMethodsTest extends TestCase { + + public static void main(String[] args) { + findAllListenerMethods(); + } + + private static void findAllListenerMethods() { + Set<Class<?>> classes = new HashSet<Class<?>>(); + for (Class<?> c : VaadinClasses.getAllServerSideClasses()) { + while (c != null && c.getName().startsWith("com.vaadin.")) { + classes.add(c); + c = c.getSuperclass(); + } + } + + for (Class<?> c : classes) { + boolean found = false; + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals("addListener")) { + if (m.getParameterTypes().length != 1) { + continue; + } + String packageName = "com.vaadin.tests.server"; + if (Component.class.isAssignableFrom(c)) { + packageName += ".component." + + c.getSimpleName().toLowerCase(); + continue; + } + + if (!found) { + found = true; + System.out.println("package " + packageName + ";"); + + System.out.println("import " + + AbstractListenerMethodsTest.class.getName() + + ";"); + System.out.println("import " + c.getName() + ";"); + System.out.println("public class " + + c.getSimpleName() + + "Listeners extends " + + AbstractListenerMethodsTest.class + .getSimpleName() + " {"); + } + + String listenerClassName = m.getParameterTypes()[0] + .getSimpleName(); + String eventClassName = listenerClassName.replaceFirst( + "Listener$", "Event"); + System.out.println("public void test" + listenerClassName + + "() throws Exception {"); + System.out.println(" testListener(" + c.getSimpleName() + + ".class, " + eventClassName + ".class, " + + listenerClassName + ".class);"); + System.out.println("}"); + } + } + if (found) { + System.out.println("}"); + System.out.println(); + } + } + } + + protected void testListenerAddGetRemove(Class<?> testClass, + Class<?> eventClass, Class<?> listenerClass) throws Exception { + // Create a component for testing + Object c = testClass.newInstance(); + testListenerAddGetRemove(testClass, eventClass, listenerClass, c); + + } + + protected void testListenerAddGetRemove(Class<?> cls, Class<?> eventClass, + Class<?> listenerClass, Object c) throws Exception { + + Object mockListener1 = EasyMock.createMock(listenerClass); + Object mockListener2 = EasyMock.createMock(listenerClass); + + // Verify we start from no listeners + verifyListeners(c, eventClass); + + // Add one listener and verify + addListener(c, mockListener1, listenerClass); + verifyListeners(c, eventClass, mockListener1); + + // Add another listener and verify + addListener(c, mockListener2, listenerClass); + verifyListeners(c, eventClass, mockListener1, mockListener2); + + // Ensure we can fetch using parent class also + if (eventClass.getSuperclass() != null) { + verifyListeners(c, eventClass.getSuperclass(), mockListener1, + mockListener2); + } + + // Remove the first and verify + removeListener(c, mockListener1, listenerClass); + verifyListeners(c, eventClass, mockListener2); + + // Remove the remaining and verify + removeListener(c, mockListener2, listenerClass); + verifyListeners(c, eventClass); + + } + + private void removeListener(Object c, Object listener, + Class<?> listenerClass) throws IllegalArgumentException, + IllegalAccessException, InvocationTargetException, + SecurityException, NoSuchMethodException { + Method method = getRemoveListenerMethod(c.getClass(), listenerClass); + method.invoke(c, listener); + + } + + private void addListener(Object c, Object listener1, Class<?> listenerClass) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, SecurityException, NoSuchMethodException { + Method method = getAddListenerMethod(c.getClass(), listenerClass); + method.invoke(c, listener1); + } + + private Collection<?> getListeners(Object c, Class<?> eventType) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, SecurityException, NoSuchMethodException { + Method method = getGetListenersMethod(c.getClass()); + return (Collection<?>) method.invoke(c, eventType); + } + + private Method getGetListenersMethod(Class<? extends Object> cls) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("getListeners", Class.class); + } + + private Method getAddListenerMethod(Class<?> cls, Class<?> listenerClass) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("addListener", listenerClass); + + } + + private Method getRemoveListenerMethod(Class<?> cls, Class<?> listenerClass) + throws SecurityException, NoSuchMethodException { + return cls.getMethod("removeListener", listenerClass); + + } + + private void verifyListeners(Object c, Class<?> eventClass, + Object... expectedListeners) throws IllegalArgumentException, + SecurityException, IllegalAccessException, + InvocationTargetException, NoSuchMethodException { + Collection<?> registeredListeners = getListeners(c, eventClass); + assertEquals("Number of listeners", expectedListeners.length, + registeredListeners.size()); + + Assert.assertArrayEquals(expectedListeners, + registeredListeners.toArray()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java b/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java new file mode 100644 index 0000000000..ad80007882 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/FinalMethodTest.java @@ -0,0 +1,68 @@ +package com.vaadin.tests.server.component; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashSet; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.Component; + +public class FinalMethodTest extends TestCase { + + // public void testThatContainersHaveNoFinalMethods() { + // HashSet<Class<?>> tested = new HashSet<Class<?>>(); + // for (Class<?> c : VaadinClasses.getAllServerSideClasses()) { + // if (Container.class.isAssignableFrom(c)) { + // ensureNoFinalMethods(c, tested); + // } + // } + // } + + public void testThatComponentsHaveNoFinalMethods() { + HashSet<Class<?>> tested = new HashSet<Class<?>>(); + for (Class<? extends Component> c : VaadinClasses.getComponents()) { + ensureNoFinalMethods(c, tested); + } + } + + private void ensureNoFinalMethods(Class<?> c, HashSet<Class<?>> tested) { + if (tested.contains(c)) { + return; + } + + tested.add(c); + + if (c == Object.class) { + return; + } + System.out.println("Checking " + c.getName()); + for (Method m : c.getDeclaredMethods()) { + if (isPrivate(m)) { + continue; + } + if (isFinal(m)) { + String error = "Class " + c.getName() + " contains a " + + (isPublic(m) ? "public" : "non-public") + + " final method: " + m.getName(); + // System.err.println(error); + throw new RuntimeException(error); + } + } + ensureNoFinalMethods(c.getSuperclass(), tested); + + } + + private boolean isFinal(Method m) { + return Modifier.isFinal(m.getModifiers()); + } + + private boolean isPrivate(Method m) { + return Modifier.isPrivate(m.getModifiers()); + } + + private boolean isPublic(Method m) { + return Modifier.isPublic(m.getModifiers()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java new file mode 100644 index 0000000000..7d6db42d1a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.absolutelayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.AbsoluteLayout; + +public class AbsoluteLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(AbsoluteLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java new file mode 100644 index 0000000000..d76dcffa2f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ComponentPosition.java @@ -0,0 +1,204 @@ +package com.vaadin.tests.server.component.absolutelayout; + +import junit.framework.TestCase; + +import com.vaadin.server.Sizeable; +import com.vaadin.server.Sizeable.Unit; +import com.vaadin.ui.AbsoluteLayout; +import com.vaadin.ui.Button; + +public class ComponentPosition extends TestCase { + + private static final String CSS = "top:7.0px;right:7.0%;bottom:7.0pc;left:7.0em;z-index:7;"; + private static final String PARTIAL_CSS = "top:7.0px;left:7.0em;"; + private static final Float CSS_VALUE = Float.valueOf(7); + + private static final Unit UNIT_UNSET = Sizeable.Unit.PIXELS; + + /** + * Add component w/o giving positions, assert that everything is unset + */ + public void testNoPosition() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + assertNull(layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertNull(layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(UNIT_UNSET, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals("", layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, setting all attributes using CSS, assert getter agree + */ + public void testFullCss() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.PICAS, layout.getPosition(b) + .getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(Sizeable.Unit.PERCENTAGE, layout.getPosition(b) + .getRightUnits()); + + assertEquals(7, layout.getPosition(b).getZIndex()); + + assertEquals(CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, setting some attributes using CSS, assert getters agree + */ + public void testPartialCss() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, PARTIAL_CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals(PARTIAL_CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component setting all attributes using CSS, then reset using partial + * CSS; assert getters agree and the appropriate attributes are unset. + */ + public void testPartialCssReset() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + layout.getPosition(b).setCSSString(PARTIAL_CSS); + + assertEquals(CSS_VALUE, layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertEquals(CSS_VALUE, layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals(Sizeable.Unit.PIXELS, layout.getPosition(b).getTopUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.EM, layout.getPosition(b).getLeftUnits()); + assertEquals(UNIT_UNSET, layout.getPosition(b).getRightUnits()); + + assertEquals(-1, layout.getPosition(b).getZIndex()); + + assertEquals(PARTIAL_CSS, layout.getPosition(b).getCSSString()); + + } + + /** + * Add component, then set all position attributes with individual setters + * for value and units; assert getters agree. + */ + public void testSetPosition() { + final Float SIZE = Float.valueOf(12); + + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + layout.getPosition(b).setTopValue(SIZE); + layout.getPosition(b).setRightValue(SIZE); + layout.getPosition(b).setBottomValue(SIZE); + layout.getPosition(b).setLeftValue(SIZE); + + layout.getPosition(b).setTopUnits(Sizeable.Unit.CM); + layout.getPosition(b).setRightUnits(Sizeable.Unit.EX); + layout.getPosition(b).setBottomUnits(Sizeable.Unit.INCH); + layout.getPosition(b).setLeftUnits(Sizeable.Unit.MM); + + assertEquals(SIZE, layout.getPosition(b).getTopValue()); + assertEquals(SIZE, layout.getPosition(b).getRightValue()); + assertEquals(SIZE, layout.getPosition(b).getBottomValue()); + assertEquals(SIZE, layout.getPosition(b).getLeftValue()); + + assertEquals(Sizeable.Unit.CM, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.EX, layout.getPosition(b).getRightUnits()); + assertEquals(Sizeable.Unit.INCH, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.MM, layout.getPosition(b).getLeftUnits()); + + } + + /** + * Add component, then set all position attributes with combined setters for + * value and units; assert getters agree. + */ + public void testSetPosition2() { + final Float SIZE = Float.valueOf(12); + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b); + + layout.getPosition(b).setTop(SIZE, Sizeable.Unit.CM); + layout.getPosition(b).setRight(SIZE, Sizeable.Unit.EX); + layout.getPosition(b).setBottom(SIZE, Sizeable.Unit.INCH); + layout.getPosition(b).setLeft(SIZE, Sizeable.Unit.MM); + + assertEquals(SIZE, layout.getPosition(b).getTopValue()); + assertEquals(SIZE, layout.getPosition(b).getRightValue()); + assertEquals(SIZE, layout.getPosition(b).getBottomValue()); + assertEquals(SIZE, layout.getPosition(b).getLeftValue()); + + assertEquals(Sizeable.Unit.CM, layout.getPosition(b).getTopUnits()); + assertEquals(Sizeable.Unit.EX, layout.getPosition(b).getRightUnits()); + assertEquals(Sizeable.Unit.INCH, layout.getPosition(b).getBottomUnits()); + assertEquals(Sizeable.Unit.MM, layout.getPosition(b).getLeftUnits()); + + } + + /** + * Add component, set all attributes using CSS, unset some using method + * calls, assert getters agree. + */ + public void testUnsetPosition() { + AbsoluteLayout layout = new AbsoluteLayout(); + Button b = new Button(); + layout.addComponent(b, CSS); + + layout.getPosition(b).setTopValue(null); + layout.getPosition(b).setRightValue(null); + layout.getPosition(b).setBottomValue(null); + layout.getPosition(b).setLeftValue(null); + + layout.getPosition(b).setZIndex(-1); + + assertNull(layout.getPosition(b).getTopValue()); + assertNull(layout.getPosition(b).getBottomValue()); + assertNull(layout.getPosition(b).getLeftValue()); + assertNull(layout.getPosition(b).getRightValue()); + + assertEquals("", layout.getPosition(b).getCSSString()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java new file mode 100644 index 0000000000..1903e66f92 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java @@ -0,0 +1,61 @@ +package com.vaadin.tests.server.component.abstractcomponent; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbstractComponent; + +public class TestAbstractComponentStyleNames extends TestCase { + + public void testSetMultiple() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testSetAdd() { + AbstractComponent component = getComponent(); + component.setStyleName("style1"); + component.addStyleName("style2"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testAddSame() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + component.addStyleName("style1"); + assertEquals(component.getStyleName(), "style1 style2"); + } + + public void testSetRemove() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2"); + component.removeStyleName("style1"); + assertEquals(component.getStyleName(), "style2"); + } + + public void testAddRemove() { + AbstractComponent component = getComponent(); + component.addStyleName("style1"); + component.addStyleName("style2"); + component.removeStyleName("style1"); + assertEquals(component.getStyleName(), "style2"); + } + + public void testRemoveMultipleWithExtraSpaces() { + AbstractComponent component = getComponent(); + component.setStyleName("style1 style2 style3"); + component.removeStyleName(" style1 style3 "); + assertEquals(component.getStyleName(), "style2"); + } + + public void testSetWithExtraSpaces() { + AbstractComponent component = getComponent(); + component.setStyleName(" style1 style2 "); + assertEquals(component.getStyleName(), "style1 style2"); + } + + private AbstractComponent getComponent() { + return new AbstractComponent() { + }; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java new file mode 100644 index 0000000000..f9f170eb2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractcomponentcontainer/TestAbstractComponentContainerListeners.java @@ -0,0 +1,22 @@ +package com.vaadin.tests.server.component.abstractcomponentcontainer; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.ComponentContainer.ComponentAttachEvent; +import com.vaadin.ui.ComponentContainer.ComponentAttachListener; +import com.vaadin.ui.ComponentContainer.ComponentDetachEvent; +import com.vaadin.ui.ComponentContainer.ComponentDetachListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.VerticalLayout; + +public class TestAbstractComponentContainerListeners extends + AbstractListenerMethodsTest { + public void testComponentDetachListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(HorizontalLayout.class, + ComponentDetachEvent.class, ComponentDetachListener.class); + } + + public void testComponentAttachListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(VerticalLayout.class, + ComponentAttachEvent.class, ComponentAttachListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java new file mode 100644 index 0000000000..57af748247 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java @@ -0,0 +1,216 @@ +package com.vaadin.tests.server.component.abstractfield; + +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.data.util.converter.Converter; +import com.vaadin.data.util.converter.StringToIntegerConverter; +import com.vaadin.tests.data.bean.Address; +import com.vaadin.tests.data.bean.Country; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.data.bean.Sex; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.TextField; + +public class AbstractFieldValueConversions extends TestCase { + + Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", + 34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", + Country.FINLAND)); + + public void testWithoutConversion() { + TextField tf = new TextField(); + tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, + "firstName")); + assertEquals("Paula", tf.getValue()); + assertEquals("Paula", tf.getPropertyDataSource().getValue()); + tf.setValue("abc"); + assertEquals("abc", tf.getValue()); + assertEquals("abc", tf.getPropertyDataSource().getValue()); + assertEquals("abc", paulaBean.getFirstName()); + } + + public void testStringIdentityConversion() { + TextField tf = new TextField(); + tf.setConverter(new Converter<String, String>() { + + @Override + public String convertToModel(String value, Locale locale) { + return value; + } + + @Override + public String convertToPresentation(String value, Locale locale) { + return value; + } + + @Override + public Class<String> getModelType() { + return String.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + }); + tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, + "firstName")); + assertEquals("Paula", tf.getValue()); + assertEquals("Paula", tf.getPropertyDataSource().getValue()); + tf.setValue("abc"); + assertEquals("abc", tf.getValue()); + assertEquals("abc", tf.getPropertyDataSource().getValue()); + assertEquals("abc", paulaBean.getFirstName()); + } + + public void testFailingConversion() { + TextField tf = new TextField(); + tf.setConverter(new Converter<String, Integer>() { + + @Override + public Integer convertToModel(String value, Locale locale) { + throw new ConversionException("Failed"); + } + + @Override + public String convertToPresentation(Integer value, Locale locale) { + throw new ConversionException("Failed"); + } + + @Override + public Class<Integer> getModelType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Class<String> getPresentationType() { + // TODO Auto-generated method stub + return null; + } + }); + try { + tf.setValue(1); + fail("setValue(Integer) should throw an exception"); + } catch (Converter.ConversionException e) { + // OK, expected + } + } + + public void testIntegerStringConversion() { + TextField tf = new TextField(); + + tf.setConverter(new StringToIntegerConverter()); + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, "age")); + assertEquals(34, tf.getPropertyDataSource().getValue()); + assertEquals("34", tf.getValue()); + tf.setValue("12"); + assertEquals(12, tf.getPropertyDataSource().getValue()); + assertEquals("12", tf.getValue()); + tf.getPropertyDataSource().setValue(42); + assertEquals(42, tf.getPropertyDataSource().getValue()); + assertEquals("42", tf.getValue()); + } + + public void testBooleanNullConversion() { + CheckBox cb = new CheckBox(); + cb.setConverter(new Converter<Boolean, Boolean>() { + + @Override + public Boolean convertToModel(Boolean value, Locale locale) { + // value from a CheckBox should never be null as long as it is + // not set to null (handled by conversion below). + assertNotNull(value); + return value; + } + + @Override + public Boolean convertToPresentation(Boolean value, Locale locale) { + // Datamodel -> field + if (value == null) { + return false; + } + + return value; + } + + @Override + public Class<Boolean> getModelType() { + return Boolean.class; + } + + @Override + public Class<Boolean> getPresentationType() { + return Boolean.class; + } + + }); + MethodProperty<Boolean> property = new MethodProperty<Boolean>( + paulaBean, "deceased"); + cb.setPropertyDataSource(property); + assertEquals(Boolean.FALSE, property.getValue()); + assertEquals(Boolean.FALSE, cb.getValue()); + Boolean newDmValue = cb.getConverter().convertToPresentation( + cb.getValue(), new Locale("fi", "FI")); + assertEquals(Boolean.FALSE, newDmValue); + + // FIXME: Should be able to set to false here to cause datamodel to be + // set to false but the change will not be propagated to the Property + // (field value is already false) + + cb.setValue(true); + assertEquals(Boolean.TRUE, cb.getValue()); + assertEquals(Boolean.TRUE, property.getValue()); + + cb.setValue(false); + assertEquals(Boolean.FALSE, cb.getValue()); + assertEquals(Boolean.FALSE, property.getValue()); + + } + + public static class NumberBean { + private Number number; + + public Number getNumber() { + return number; + } + + public void setNumber(Number number) { + this.number = number; + } + + } + + public void testNumberDoubleConverterChange() { + final Application a = new Application(); + Application.setCurrent(a); + TextField tf = new TextField() { + @Override + public Application getApplication() { + return a; + } + }; + NumberBean nb = new NumberBean(); + nb.setNumber(490); + + tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number")); + assertEquals(490, tf.getPropertyDataSource().getValue()); + assertEquals("490", tf.getValue()); + + Converter c1 = tf.getConverter(); + + tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number")); + Converter c2 = tf.getConverter(); + assertTrue( + "StringToNumber converter is ok for integer types and should stay even though property is changed", + c1 == c2); + assertEquals(490, tf.getPropertyDataSource().getValue()); + assertEquals("490", tf.getValue()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java new file mode 100644 index 0000000000..25430fc9a5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java @@ -0,0 +1,48 @@ +package com.vaadin.tests.server.component.abstractfield; + +import java.math.BigDecimal; +import java.util.Locale; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.tests.data.bean.Address; +import com.vaadin.tests.data.bean.Country; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.tests.data.bean.Sex; +import com.vaadin.ui.TextField; + +public class DefaultConverterFactory extends TestCase { + + Person paulaBean = new Person("Paula", "Brilliant", "paula@brilliant.com", + 34, Sex.FEMALE, new Address("Paula street 1", 12345, "P-town", + Country.FINLAND)); + { + paulaBean.setSalary(49000); + BigDecimal rent = new BigDecimal(57223); + rent = rent.scaleByPowerOfTen(-2); + paulaBean.setRent(rent); + } + + public void testDefaultNumberConversion() { + Application app = new Application(); + Application.setCurrent(app); + TextField tf = new TextField(); + tf.setLocale(new Locale("en", "US")); + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, + "salary")); + assertEquals("49,000", tf.getValue()); + + tf.setLocale(new Locale("fi", "FI")); + // FIXME: The following line should not be necessary and should be + // removed + tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean, + "salary")); + String value = tf.getValue(); + // Java uses a non-breaking space (ascii 160) instead of space when + // formatting + String expected = "49" + (char) 160 + "000"; + assertEquals(expected, value); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java new file mode 100644 index 0000000000..5dbab8467e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java @@ -0,0 +1,101 @@ +package com.vaadin.tests.server.component.abstractfield; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.data.Property; +import com.vaadin.data.util.AbstractProperty; +import com.vaadin.data.util.converter.Converter.ConversionException; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.UI; + +public class RemoveListenersOnDetach { + + int numValueChanges = 0; + int numReadOnlyChanges = 0; + + AbstractField field = new AbstractField() { + private UI uI = new UI() { + + @Override + protected void init(WrappedRequest request) { + + } + + }; + private Application application = new Application() { + + }; + + @Override + public Class<?> getType() { + return String.class; + } + + @Override + public void valueChange(Property.ValueChangeEvent event) { + super.valueChange(event); + numValueChanges++; + } + + @Override + public void readOnlyStatusChange( + Property.ReadOnlyStatusChangeEvent event) { + super.readOnlyStatusChange(event); + numReadOnlyChanges++; + } + + @Override + public com.vaadin.ui.UI getUI() { + return uI; + }; + + @Override + public Application getApplication() { + return application; + }; + }; + + Property property = new AbstractProperty() { + @Override + public Object getValue() { + return null; + } + + @Override + public void setValue(Object newValue) throws ReadOnlyException, + ConversionException { + fireValueChange(); + } + + @Override + public Class<?> getType() { + return String.class; + } + }; + + @Test + public void testAttachDetach() { + field.setPropertyDataSource(property); + + property.setValue(null); + property.setReadOnly(true); + assertEquals(1, numValueChanges); + assertEquals(1, numReadOnlyChanges); + + field.attach(); + property.setValue(null); + property.setReadOnly(false); + assertEquals(2, numValueChanges); + assertEquals(2, numReadOnlyChanges); + + field.detach(); + property.setValue(null); + property.setReadOnly(true); + assertEquals(2, numValueChanges); + assertEquals(2, numReadOnlyChanges); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java new file mode 100644 index 0000000000..9937bf92d5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/TestAbstractFieldListeners.java @@ -0,0 +1,21 @@ +package com.vaadin.tests.server.component.abstractfield; + +import com.vaadin.data.Property.ReadOnlyStatusChangeEvent; +import com.vaadin.data.Property.ReadOnlyStatusChangeListener; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.CheckBox; + +public class TestAbstractFieldListeners extends AbstractListenerMethodsTest { + public void testReadOnlyStatusChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CheckBox.class, + ReadOnlyStatusChangeEvent.class, + ReadOnlyStatusChangeListener.class); + } + + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CheckBox.class, ValueChangeEvent.class, + ValueChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java new file mode 100644 index 0000000000..1971fb6d0e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/AddComponentsTest.java @@ -0,0 +1,115 @@ +package com.vaadin.tests.server.component.abstractorderedlayout; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; +import com.vaadin.ui.VerticalLayout; + +public class AddComponentsTest { + + Component[] children = new Component[] { new Label("A"), new Label("B"), + new Label("C"), new Label("D") }; + + @Test + public void moveComponentsBetweenLayouts() { + AbstractOrderedLayout layout1 = new HorizontalLayout(); + AbstractOrderedLayout layout2 = new VerticalLayout(); + + layout1.addComponent(children[0]); + layout1.addComponent(children[1]); + + layout2.addComponent(children[2]); + layout2.addComponent(children[3]); + + layout2.addComponent(children[1], 1); + assertOrder(layout1, new int[] { 0 }); + assertOrder(layout2, new int[] { 2, 1, 3 }); + + layout1.addComponent(children[3], 0); + assertOrder(layout1, new int[] { 3, 0 }); + assertOrder(layout2, new int[] { 2, 1 }); + + layout2.addComponent(children[0]); + assertOrder(layout1, new int[] { 3 }); + assertOrder(layout2, new int[] { 2, 1, 0 }); + + layout1.addComponentAsFirst(children[1]); + assertOrder(layout1, new int[] { 1, 3 }); + assertOrder(layout2, new int[] { 2, 0 }); + } + + @Test + public void shuffleChildComponents() { + shuffleChildComponents(new HorizontalLayout()); + shuffleChildComponents(new VerticalLayout()); + } + + private void shuffleChildComponents(AbstractOrderedLayout layout) { + + for (int i = 0; i < children.length; ++i) { + layout.addComponent(children[i], i); + } + + assertOrder(layout, new int[] { 0, 1, 2, 3 }); + + // Move C from #2 to #1 + // Exhibits defect #7668 + layout.addComponent(children[2], 1); + assertOrder(layout, new int[] { 0, 2, 1, 3 }); + + // Move C from #1 to #4 (which becomes #3 when #1 is erased) + layout.addComponent(children[2], 4); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Keep everything in place + layout.addComponent(children[1], 1); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Move D from #2 to #0 + layout.addComponent(children[3], 0); + assertOrder(layout, new int[] { 3, 0, 1, 2 }); + + // Move A from #1 to end (#4 which becomes #3) + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Keep everything in place + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Move C from #2 to #0 + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + + // Keep everything in place + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + } + + /** + * Asserts that layout has the components in children in the order specified + * by indices. + */ + private void assertOrder(Layout layout, int[] indices) { + Iterator<?> i = layout.getComponentIterator(); + try { + for (int index : indices) { + assertSame(children[index], i.next()); + } + assertFalse("Too many components in layout", i.hasNext()); + } catch (NoSuchElementException e) { + fail("Too few components in layout"); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java new file mode 100644 index 0000000000..a0b34aca78 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/TestAbstractOrderedLayoutListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.abstractorderedlayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.VerticalLayout; + +public class TestAbstractOrderedLayoutListeners extends + AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(VerticalLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java new file mode 100644 index 0000000000..75c19b0517 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestAbstractSelectListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.abstractselect; + +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.ComboBox; + +public class TestAbstractSelectListeners extends AbstractListenerMethodsTest { + public void testItemSetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(ComboBox.class, ItemSetChangeEvent.class, + ItemSetChangeListener.class); + } + + public void testPropertySetChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(ComboBox.class, PropertySetChangeEvent.class, + PropertySetChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java new file mode 100644 index 0000000000..2b6cdaa6cc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestAbstractSplitPanelListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.abstractsplitpanel; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.AbstractSplitPanel.SplitterClickEvent; +import com.vaadin.ui.AbstractSplitPanel.SplitterClickListener; +import com.vaadin.ui.HorizontalSplitPanel; + +public class TestAbstractSplitPanelListeners extends + AbstractListenerMethodsTest { + public void testSplitterClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(HorizontalSplitPanel.class, + SplitterClickEvent.class, SplitterClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java new file mode 100644 index 0000000000..9868d6ebfd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstracttextfield/TestAbstractTextFieldListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.abstracttextfield; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.event.FieldEvents.TextChangeEvent; +import com.vaadin.event.FieldEvents.TextChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.TextField; + +public class TestAbstractTextFieldListeners extends AbstractListenerMethodsTest { + public void testTextChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, TextChangeEvent.class, + TextChangeListener.class); + } + + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TextField.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java new file mode 100644 index 0000000000..4fe499a0a0 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java @@ -0,0 +1,48 @@ +package com.vaadin.tests.server.component.button; + +import static org.junit.Assert.assertEquals; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; + +import org.junit.Test; + +/** + * Tests the public click() method. + */ +public class ButtonClick { + private boolean clicked = false; + + @Test + public void testClick() { + getButton().click(); + assertEquals(clicked, true); + } + + @Test + public void testClickDisabled() { + Button b = getButton(); + b.setEnabled(false); + b.click(); + assertEquals(clicked, false); + } + + @Test + public void testClickReadOnly() { + Button b = getButton(); + b.setReadOnly(true); + b.click(); + assertEquals(clicked, false); + } + + private Button getButton() { + Button b = new Button(); + b.addListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent ev) { + clicked = true; + } + }); + return b; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java b/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java new file mode 100644 index 0000000000..dc37312eea --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/button/ButtonListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.button; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; + +public class ButtonListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, BlurEvent.class, + BlurListener.class); + } + + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Button.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java b/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java new file mode 100644 index 0000000000..c0d739b597 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/csslayout/AddComponentsTest.java @@ -0,0 +1,109 @@ +package com.vaadin.tests.server.component.csslayout; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; + +public class AddComponentsTest { + + private Component[] children = new Component[] { new Label("A"), + new Label("B"), new Label("C"), new Label("D") }; + + @Test + public void moveComponentsBetweenLayouts() { + CssLayout layout1 = new CssLayout(); + CssLayout layout2 = new CssLayout(); + + layout1.addComponent(children[0]); + layout1.addComponent(children[1]); + + layout2.addComponent(children[2]); + layout2.addComponent(children[3]); + + layout2.addComponent(children[1], 1); + assertOrder(layout1, new int[] { 0 }); + assertOrder(layout2, new int[] { 2, 1, 3 }); + + layout1.addComponent(children[3], 0); + assertOrder(layout1, new int[] { 3, 0 }); + assertOrder(layout2, new int[] { 2, 1 }); + + layout2.addComponent(children[0]); + assertOrder(layout1, new int[] { 3 }); + assertOrder(layout2, new int[] { 2, 1, 0 }); + + layout1.addComponentAsFirst(children[1]); + assertOrder(layout1, new int[] { 1, 3 }); + assertOrder(layout2, new int[] { 2, 0 }); + } + + @Test + public void shuffleChildComponents() { + CssLayout layout = new CssLayout(); + + for (int i = 0; i < children.length; ++i) { + layout.addComponent(children[i], i); + } + + assertOrder(layout, new int[] { 0, 1, 2, 3 }); + + // Move C from #2 to #1 + // Exhibits defect #7668 + layout.addComponent(children[2], 1); + assertOrder(layout, new int[] { 0, 2, 1, 3 }); + + // Move C from #1 to #4 (which becomes #3 when #1 is erased) + layout.addComponent(children[2], 4); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Keep everything in place + layout.addComponent(children[1], 1); + assertOrder(layout, new int[] { 0, 1, 3, 2 }); + + // Move D from #2 to #0 + layout.addComponent(children[3], 0); + assertOrder(layout, new int[] { 3, 0, 1, 2 }); + + // Move A from #1 to end (#4 which becomes #3) + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Keep everything in place + layout.addComponent(children[0]); + assertOrder(layout, new int[] { 3, 1, 2, 0 }); + + // Move C from #2 to #0 + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + + // Keep everything in place + layout.addComponentAsFirst(children[2]); + assertOrder(layout, new int[] { 2, 3, 1, 0 }); + } + + /** + * Asserts that layout has the components in children in the order specified + * by indices. + */ + private void assertOrder(Layout layout, int[] indices) { + Iterator<?> i = layout.getComponentIterator(); + try { + for (int index : indices) { + assertSame(children[index], i.next()); + } + assertFalse("Too many components in layout", i.hasNext()); + } catch (NoSuchElementException e) { + fail("Too few components in layout"); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java new file mode 100644 index 0000000000..21a48888d6 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/csslayout/CssLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.csslayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.CssLayout; + +public class CssLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(CssLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java b/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java new file mode 100644 index 0000000000..0f4aee35c7 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/datefield/DateFieldListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.datefield; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.DateField; + +public class DateFieldListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(DateField.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(DateField.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java b/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java new file mode 100644 index 0000000000..00b5c60dad --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/datefield/ResolutionTest.java @@ -0,0 +1,61 @@ +package com.vaadin.tests.server.component.datefield; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import com.vaadin.tests.util.TestUtil; +import com.vaadin.ui.DateField.Resolution; + +public class ResolutionTest extends TestCase { + + public void testResolutionHigherOrEqualToYear() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsHigherOrEqualTo(Resolution.YEAR); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.YEAR); + TestUtil.assertIterableEquals(expected, higherOrEqual); + } + + public void testResolutionHigherOrEqualToDay() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsHigherOrEqualTo(Resolution.DAY); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.DAY); + expected.add(Resolution.MONTH); + expected.add(Resolution.YEAR); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } + + public void testResolutionLowerThanDay() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.DAY); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.HOUR); + expected.add(Resolution.MINUTE); + expected.add(Resolution.SECOND); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } + + public void testResolutionLowerThanSecond() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.SECOND); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + TestUtil.assertIterableEquals(expected, higherOrEqual); + } + + public void testResolutionLowerThanYear() { + Iterable<Resolution> higherOrEqual = Resolution + .getResolutionsLowerThan(Resolution.YEAR); + ArrayList<Resolution> expected = new ArrayList<Resolution>(); + expected.add(Resolution.MONTH); + expected.add(Resolution.DAY); + expected.add(Resolution.HOUR); + expected.add(Resolution.MINUTE); + expected.add(Resolution.SECOND); + TestUtil.assertIterableEquals(expected, higherOrEqual); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java b/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java new file mode 100644 index 0000000000..7512f0f499 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/embedded/EmbeddedListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.embedded; + +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Embedded; + +public class EmbeddedListeners extends AbstractListenerMethodsTest { + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Embedded.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java new file mode 100644 index 0000000000..ce3a9faa65 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.gridlayout; + +import com.vaadin.event.LayoutEvents.LayoutClickEvent; +import com.vaadin.event.LayoutEvents.LayoutClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.GridLayout; + +public class GridLayoutListeners extends AbstractListenerMethodsTest { + public void testLayoutClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(GridLayout.class, LayoutClickEvent.class, + LayoutClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java new file mode 100644 index 0000000000..48279c7c88 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/label/LabelConverters.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.server.component.label; + +import junit.framework.TestCase; + +import com.vaadin.Application; +import com.vaadin.data.Property; +import com.vaadin.data.util.MethodProperty; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.ui.Label; + +public class LabelConverters extends TestCase { + + public void testLabelSetDataSourceLaterOn() { + Person p = Person.createTestPerson1(); + Label l = new Label("My label"); + assertEquals("My label", l.getValue()); + assertNull(l.getConverter()); + l.setPropertyDataSource(new MethodProperty<String>(p, "firstName")); + assertEquals(p.getFirstName(), l.getValue()); + p.setFirstName("123"); + assertEquals("123", l.getValue()); + } + + public void testIntegerDataSource() { + Application.setCurrent(new Application()); + Label l = new Label("Foo"); + Property ds = new MethodProperty<Integer>(Person.createTestPerson1(), + "age"); + l.setPropertyDataSource(ds); + assertEquals(String.valueOf(Person.createTestPerson1().getAge()), + l.getValue()); + } + + public void testSetValueWithDataSource() { + try { + MethodProperty<String> property = new MethodProperty<String>( + Person.createTestPerson1(), "firstName"); + Label l = new Label(property); + l.setValue("Foo"); + fail("setValue should throw an exception when a data source is set"); + } catch (Exception e) { + } + + } + + public void testLabelWithoutDataSource() { + Label l = new Label("My label"); + assertEquals("My label", l.getValue()); + assertNull(l.getConverter()); + assertNull(l.getPropertyDataSource()); + l.setValue("New value"); + assertEquals("New value", l.getValue()); + assertNull(l.getConverter()); + assertNull(l.getPropertyDataSource()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java b/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java new file mode 100644 index 0000000000..3ed79f5010 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/label/LabelListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.label; + +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Label; +import com.vaadin.ui.Label.ValueChangeEvent; + +public class LabelListeners extends AbstractListenerMethodsTest { + public void testValueChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Label.class, ValueChangeEvent.class, + ValueChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java b/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java new file mode 100644 index 0000000000..fd3e02994c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/loginform/LoginFormListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.loginform; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.LoginForm; +import com.vaadin.ui.LoginForm.LoginEvent; +import com.vaadin.ui.LoginForm.LoginListener; + +public class LoginFormListeners extends AbstractListenerMethodsTest { + public void testLoginListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(LoginForm.class, LoginEvent.class, + LoginListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java b/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java new file mode 100644 index 0000000000..f304315ebc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/menubar/MenuBarIds.java @@ -0,0 +1,98 @@ +package com.vaadin.tests.server.component.menubar; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.Command; +import com.vaadin.ui.MenuBar.MenuItem; + +public class MenuBarIds extends TestCase implements Command { + + private MenuItem lastSelectedItem; + private MenuItem menuFile; + private MenuItem menuEdit; + private MenuItem menuEditCopy; + private MenuItem menuEditCut; + private MenuItem menuEditPaste; + private MenuItem menuEditFind; + private MenuItem menuFileOpen; + private MenuItem menuFileSave; + private MenuItem menuFileExit; + private Set<MenuItem> menuItems = new HashSet<MenuItem>(); + + private MenuBar menuBar; + + @Override + public void setUp() { + menuBar = new MenuBar(); + menuFile = menuBar.addItem("File", this); + menuEdit = menuBar.addItem("Edit", this); + menuEditCopy = menuEdit.addItem("Copy", this); + menuEditCut = menuEdit.addItem("Cut", this); + menuEditPaste = menuEdit.addItem("Paste", this); + menuEdit.addSeparator(); + menuEditFind = menuEdit.addItem("Find...", this); + menuFileOpen = menuFile.addItem("Open", this); + menuFileSave = menuFile.addItem("Save", this); + menuFile.addSeparator(); + menuFileExit = menuFile.addItem("Exit", this); + + menuItems.add(menuFile); + menuItems.add(menuEdit); + menuItems.add(menuEditCopy); + menuItems.add(menuEditCut); + menuItems.add(menuEditPaste); + menuItems.add(menuEditFind); + menuItems.add(menuFileOpen); + menuItems.add(menuFileSave); + menuItems.add(menuFileExit); + } + + public void testMenubarIdUniqueness() { + // Ids within a menubar must be unique + assertUniqueIds(menuBar); + + menuBar.removeItem(menuFile); + MenuItem file2 = menuBar.addItem("File2", this); + MenuItem file3 = menuBar.addItem("File3", this); + MenuItem file2sub = file2.addItem("File2 sub menu", this); + menuItems.add(file2); + menuItems.add(file2sub); + menuItems.add(file3); + + assertUniqueIds(menuBar); + } + + private static void assertUniqueIds(MenuBar menuBar) { + + Set<Object> ids = new HashSet<Object>(); + + for (MenuItem item : menuBar.getItems()) { + assertUniqueIds(ids, item); + } + } + + private static void assertUniqueIds(Set<Object> ids, MenuItem item) { + int id = item.getId(); + System.out.println("Item " + item.getText() + ", id: " + id); + assertFalse(ids.contains(id)); + ids.add(id); + if (item.getChildren() != null) { + for (MenuItem subItem : item.getChildren()) { + assertUniqueIds(ids, subItem); + } + } + } + + @Override + public void menuSelected(MenuItem selectedItem) { + assertNull("lastSelectedItem was not cleared before selecting an item", + lastSelectedItem); + + lastSelectedItem = selectedItem; + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java b/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java new file mode 100644 index 0000000000..7eb35c3882 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/optiongroup/OptionGroupListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.optiongroup; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.OptionGroup; + +public class OptionGroupListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(OptionGroup.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(OptionGroup.class, BlurEvent.class, + BlurListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java b/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java new file mode 100644 index 0000000000..6a9d55d7e4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/orderedlayout/TestOrderedLayout.java @@ -0,0 +1,49 @@ +package com.vaadin.tests.server.component.orderedlayout; + +import java.util.Iterator; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +public class TestOrderedLayout extends TestCase { + + public void testVLIteration() { + testIndexing(new VerticalLayout(), 10); + } + + public void testHLIteration() { + testIndexing(new HorizontalLayout(), 12); + } + + public void testIndexing(AbstractOrderedLayout aol, int nrComponents) { + Component[] components = generateComponents(nrComponents); + for (Component c : components) { + aol.addComponent(c); + } + for (int i = 0; i < nrComponents; i++) { + assert (aol.getComponent(i) == components[i]); + assert (aol.getComponentIndex(components[i]) == i); + } + + // Iteration should be in indexed order + int idx = 0; + for (Iterator<Component> i = aol.getComponentIterator(); i.hasNext();) { + Component c = i.next(); + assert (aol.getComponentIndex(c) == idx++); + } + } + + private Component[] generateComponents(int nr) { + Component[] components = new Component[nr]; + for (int i = 0; i < nr; i++) { + components[i] = new Label("" + i); + } + + return components; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java b/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java new file mode 100644 index 0000000000..275e90f5d1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/panel/PanelListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.panel; + +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Panel; + +public class PanelListeners extends AbstractListenerMethodsTest { + public void testClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Panel.class, ClickEvent.class, + ClickListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java b/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java new file mode 100644 index 0000000000..12a5a0f520 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/popupview/PopupViewListeners.java @@ -0,0 +1,14 @@ +package com.vaadin.tests.server.component.popupview; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Label; +import com.vaadin.ui.PopupView; +import com.vaadin.ui.PopupView.PopupVisibilityEvent; +import com.vaadin.ui.PopupView.PopupVisibilityListener; + +public class PopupViewListeners extends AbstractListenerMethodsTest { + public void testPopupVisibilityListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(PopupView.class, PopupVisibilityEvent.class, + PopupVisibilityListener.class, new PopupView("", new Label())); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java new file mode 100644 index 0000000000..906d6ccebd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/root/CustomUIClassLoader.java @@ -0,0 +1,137 @@ +package com.vaadin.tests.server.component.root; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.Application; +import com.vaadin.Application.ApplicationStartEvent; +import com.vaadin.UIRequiresMoreInformationException; +import com.vaadin.server.DefaultUIProvider; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.UI; + +public class CustomUIClassLoader extends TestCase { + + /** + * Stub root + */ + public static class MyUI extends UI { + @Override + protected void init(WrappedRequest request) { + // Nothing to see here + } + } + + /** + * Dummy ClassLoader that just saves the name of the requested class before + * delegating to the default implementation. + */ + public class LoggingClassLoader extends ClassLoader { + + private List<String> requestedClasses = new ArrayList<String>(); + + @Override + protected synchronized Class<?> loadClass(String name, boolean resolve) + throws ClassNotFoundException { + requestedClasses.add(name); + return super.loadClass(name, resolve); + } + } + + /** + * Tests that a UI class can be loaded even if no classloader has been + * provided. + * + * @throws Exception + * if thrown + */ + public void testWithNullClassLoader() throws Exception { + Application application = createStubApplication(); + application.start(new ApplicationStartEvent(null, + createConfigurationMock(), null)); + + UI uI = application.getUIForRequest(createRequestMock(null)); + assertTrue(uI instanceof MyUI); + } + + private static DeploymentConfiguration createConfigurationMock() { + DeploymentConfiguration configurationMock = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(configurationMock.isProductionMode()).andReturn(false); + EasyMock.expect(configurationMock.getInitParameters()).andReturn( + new Properties()); + + EasyMock.replay(configurationMock); + return configurationMock; + } + + private static WrappedRequest createRequestMock(ClassLoader classloader) { + // Mock a DeploymentConfiguration to give the passed classloader + DeploymentConfiguration configurationMock = EasyMock + .createMock(DeploymentConfiguration.class); + EasyMock.expect(configurationMock.getClassLoader()).andReturn( + classloader); + + // Mock a WrappedRequest to give the mocked deployment configuration + WrappedRequest requestMock = EasyMock.createMock(WrappedRequest.class); + EasyMock.expect(requestMock.getDeploymentConfiguration()).andReturn( + configurationMock); + + EasyMock.replay(configurationMock, requestMock); + return requestMock; + } + + /** + * Tests that the ClassLoader passed in the ApplicationStartEvent is used to + * load UI classes. + * + * @throws Exception + * if thrown + */ + public void testWithClassLoader() throws Exception { + LoggingClassLoader loggingClassLoader = new LoggingClassLoader(); + + Application application = createStubApplication(); + application.start(new ApplicationStartEvent(null, + createConfigurationMock(), null)); + + UI uI = application + .getUIForRequest(createRequestMock(loggingClassLoader)); + assertTrue(uI instanceof MyUI); + assertEquals(1, loggingClassLoader.requestedClasses.size()); + assertEquals(MyUI.class.getName(), + loggingClassLoader.requestedClasses.get(0)); + + } + + private Application createStubApplication() { + return new Application() { + { + addUIProvider(new DefaultUIProvider()); + } + + @Override + public String getProperty(String name) { + if (name.equals(UI_PARAMETER)) { + return MyUI.class.getName(); + } else { + return super.getProperty(name); + } + } + + @Override + public UI getUIForRequest(WrappedRequest request) + throws UIRequiresMoreInformationException { + // Always create a new root for testing (can't directly use + // getRoot as it's protected) + return getUI(request); + } + }; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java b/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java new file mode 100644 index 0000000000..c7703303d3 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/select/SelectListeners.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.server.component.select; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Select; + +public class SelectListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Select.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Select.class, BlurEvent.class, + BlurListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java b/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java new file mode 100644 index 0000000000..b969bf5e53 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/slider/SliderTest.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.slider; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.ui.Slider; +import com.vaadin.ui.Slider.ValueOutOfBoundsException; + +public class SliderTest extends TestCase { + + public void testOutOfBounds() { + Slider s = new Slider(0, 10); + s.setValue(0); + Assert.assertEquals(0.0, s.getValue()); + s.setValue(10); + Assert.assertEquals(10.0, s.getValue()); + try { + s.setValue(20); + fail("Should throw out of bounds exception"); + } catch (ValueOutOfBoundsException e) { + // TODO: handle exception + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java b/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java new file mode 100644 index 0000000000..299f9c79d4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableColumnAlignments.java @@ -0,0 +1,143 @@ +package com.vaadin.tests.server.component.table; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.Align; + +public class TableColumnAlignments { + + @Test + public void defaultColumnAlignments() { + for (int properties = 0; properties < 10; properties++) { + Table t = TableGenerator.createTableWithDefaultContainer( + properties, 10); + Object[] expected = new Object[properties]; + for (int i = 0; i < properties; i++) { + expected[i] = Align.LEFT; + } + org.junit.Assert.assertArrayEquals("getColumnAlignments", expected, + t.getColumnAlignments()); + } + } + + @Test + public void explicitColumnAlignments() { + int properties = 5; + Table t = TableGenerator + .createTableWithDefaultContainer(properties, 10); + Align[] explicitAlignments = new Align[] { Align.CENTER, Align.LEFT, + Align.RIGHT, Align.RIGHT, Align.LEFT }; + + t.setColumnAlignments(explicitAlignments); + + assertArrayEquals("Explicit visible columns, 5 properties", + explicitAlignments, t.getColumnAlignments()); + } + + @Test + public void invalidColumnAlignmentStrings() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT }; + try { + t.setColumnAlignments(new Align[] { Align.RIGHT, Align.RIGHT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + } + + @Test + public void columnAlignmentForPropertyNotInContainer() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT }; + try { + t.setColumnAlignment("Property 1200", Align.LEFT); + // FIXME: Uncomment as there should be an exception (#6475) + // junit.framework.Assert + // .fail("No exception thrown for property not in container"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + // FIXME: Uncomment as null should be returned (#6474) + // junit.framework.Assert.assertEquals( + // "Column alignment for property not in container returned", + // null, t.getColumnAlignment("Property 1200")); + + } + + @Test + public void invalidColumnAlignmentsLength() { + Table t = TableGenerator.createTableWithDefaultContainer(7, 7); + Align[] defaultAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT }; + + try { + t.setColumnAlignments(new Align[] { Align.LEFT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + try { + t.setColumnAlignments(new Align[] {}); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + try { + t.setColumnAlignments(new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, Align.LEFT, + Align.LEFT }); + junit.framework.Assert + .fail("No exception thrown for invalid array length"); + } catch (IllegalArgumentException e) { + // Ok, expected + } + assertArrayEquals("Invalid change affected alignments", + defaultAlignments, t.getColumnAlignments()); + + } + + @Test + public void explicitColumnAlignmentOneByOne() { + int properties = 5; + Table t = TableGenerator + .createTableWithDefaultContainer(properties, 10); + Align[] explicitAlignments = new Align[] { Align.CENTER, Align.LEFT, + Align.RIGHT, Align.RIGHT, Align.LEFT }; + + Align[] currentAlignments = new Align[] { Align.LEFT, Align.LEFT, + Align.LEFT, Align.LEFT, Align.LEFT }; + + for (int i = 0; i < properties; i++) { + t.setColumnAlignment("Property " + i, explicitAlignments[i]); + currentAlignments[i] = explicitAlignments[i]; + + assertArrayEquals("Explicit visible columns, " + i + + " alignments set", currentAlignments, + t.getColumnAlignments()); + } + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java b/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java new file mode 100644 index 0000000000..0e63049944 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableGenerator.java @@ -0,0 +1,42 @@ +package com.vaadin.tests.server.component.table; + +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.ui.Table; + +public class TableGenerator { + public static Table createTableWithDefaultContainer(int properties, + int items) { + Table t = new Table(); + + for (int i = 0; i < properties; i++) { + t.addContainerProperty("Property " + i, String.class, null); + } + + for (int j = 0; j < items; j++) { + Item item = t.addItem("Item " + j); + for (int i = 0; i < properties; i++) { + item.getItemProperty("Property " + i).setValue( + "Item " + j + "/Property " + i); + } + } + + return t; + } + + @Test + public void testTableGenerator() { + Table t = createTableWithDefaultContainer(1, 1); + junit.framework.Assert.assertEquals(t.size(), 1); + junit.framework.Assert.assertEquals(t.getContainerPropertyIds().size(), + 1); + + t = createTableWithDefaultContainer(100, 50); + junit.framework.Assert.assertEquals(t.size(), 50); + junit.framework.Assert.assertEquals(t.getContainerPropertyIds().size(), + 100); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java b/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java new file mode 100644 index 0000000000..6cc522f8c7 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableListeners.java @@ -0,0 +1,41 @@ +package com.vaadin.tests.server.component.table; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnReorderEvent; +import com.vaadin.ui.Table.ColumnReorderListener; +import com.vaadin.ui.Table.ColumnResizeEvent; +import com.vaadin.ui.Table.ColumnResizeListener; +import com.vaadin.ui.Table.FooterClickEvent; +import com.vaadin.ui.Table.FooterClickListener; +import com.vaadin.ui.Table.HeaderClickEvent; +import com.vaadin.ui.Table.HeaderClickListener; + +public class TableListeners extends AbstractListenerMethodsTest { + public void testColumnResizeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ColumnResizeEvent.class, + ColumnResizeListener.class); + } + + public void testItemClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ItemClickEvent.class, + ItemClickListener.class); + } + + public void testFooterClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, FooterClickEvent.class, + FooterClickListener.class); + } + + public void testHeaderClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, HeaderClickEvent.class, + HeaderClickListener.class); + } + + public void testColumnReorderListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Table.class, ColumnReorderEvent.class, + ColumnReorderListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java b/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java new file mode 100644 index 0000000000..ee6349093c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableSerialization.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.table; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.Table; + +public class TableSerialization extends TestCase { + + public void testSerialization() { + Table t = new Table(); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + + } + + public void testSerializationWithRowHeaders() { + Table t = new Table(); + t.setRowHeaderMode(Table.ROW_HEADER_MODE_EXPLICIT); + t.setColumnWidth(null, 100); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java b/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java new file mode 100644 index 0000000000..be312044db --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableVisibleColumns.java @@ -0,0 +1,75 @@ +package com.vaadin.tests.server.component.table; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +import com.vaadin.ui.Table; + +public class TableVisibleColumns { + + String[] defaultColumns3 = new String[] { "Property 0", "Property 1", + "Property 2" }; + + @Test + public void defaultVisibleColumns() { + for (int properties = 0; properties < 10; properties++) { + Table t = TableGenerator.createTableWithDefaultContainer( + properties, 10); + Object[] expected = new Object[properties]; + for (int i = 0; i < properties; i++) { + expected[i] = "Property " + i; + } + org.junit.Assert.assertArrayEquals("getVisibleColumns", expected, + t.getVisibleColumns()); + } + } + + @Test + public void explicitVisibleColumns() { + Table t = TableGenerator.createTableWithDefaultContainer(5, 10); + Object[] newVisibleColumns = new Object[] { "Property 1", "Property 2" }; + t.setVisibleColumns(newVisibleColumns); + assertArrayEquals("Explicit visible columns, 5 properties", + newVisibleColumns, t.getVisibleColumns()); + + } + + @Test + public void invalidVisibleColumnIds() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + + try { + t.setVisibleColumns(new Object[] { "a", "Property 2", "Property 3" }); + junit.framework.Assert.fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // OK, expected + } + assertArrayEquals(defaultColumns3, t.getVisibleColumns()); + } + + @Test + public void duplicateVisibleColumnIds() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + try { + t.setVisibleColumns(new Object[] { "Property 0", "Property 1", + "Property 2", "Property 1" }); + // FIXME: Multiple properties in the Object array should be detected + // (#6476) + // junit.framework.Assert.fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { + // OK, expected + } + // FIXME: Multiple properties in the Object array should be detected + // (#6476) + // assertArrayEquals(defaultColumns3, t.getVisibleColumns()); + } + + @Test + public void noVisibleColumns() { + Table t = TableGenerator.createTableWithDefaultContainer(3, 10); + t.setVisibleColumns(new Object[] {}); + assertArrayEquals(new Object[] {}, t.getVisibleColumns()); + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java b/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java new file mode 100644 index 0000000000..647d13855b --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TestFooter.java @@ -0,0 +1,94 @@ +package com.vaadin.tests.server.component.table; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.Table; + +/** + * Test case for testing the footer API + * + */ +public class TestFooter extends TestCase { + + /** + * Tests if setting the footer visibility works properly + */ + public void testFooterVisibility() { + Table table = new Table("Test table", createContainer()); + + // The footer should by default be hidden + assertFalse(table.isFooterVisible()); + + // Set footer visibility to tru should be reflected in the + // isFooterVisible() method + table.setFooterVisible(true); + assertTrue(table.isFooterVisible()); + } + + /** + * Tests adding footers to the columns + */ + public void testAddingFooters() { + Table table = new Table("Test table", createContainer()); + + // Table should not contain any footers at initialization + assertNull(table.getColumnFooter("col1")); + assertNull(table.getColumnFooter("col2")); + assertNull(table.getColumnFooter("col3")); + + // Adding column footer + table.setColumnFooter("col1", "Footer1"); + assertEquals("Footer1", table.getColumnFooter("col1")); + + // Add another footer + table.setColumnFooter("col2", "Footer2"); + assertEquals("Footer2", table.getColumnFooter("col2")); + + // Add footer for a non-existing column + table.setColumnFooter("fail", "FooterFail"); + } + + /** + * Test removing footers + */ + public void testRemovingFooters() { + Table table = new Table("Test table", createContainer()); + table.setColumnFooter("col1", "Footer1"); + table.setColumnFooter("col2", "Footer2"); + + // Test removing footer + assertNotNull(table.getColumnFooter("col1")); + table.setColumnFooter("col1", null); + assertNull(table.getColumnFooter("col1")); + + // The other footer should still be there + assertNotNull(table.getColumnFooter("col2")); + + // Remove non-existing footer + table.setColumnFooter("fail", null); + } + + /** + * Creates a container with three properties "col1,col2,col3" with 100 items + * + * @return Returns the created table + */ + private static Container createContainer() { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty("col1", String.class, ""); + container.addContainerProperty("col2", String.class, ""); + container.addContainerProperty("col3", String.class, ""); + + for (int i = 0; i < 100; i++) { + Item item = container.addItem("item " + i); + item.getItemProperty("col1").setValue("first" + i); + item.getItemProperty("col2").setValue("middle" + i); + item.getItemProperty("col3").setValue("last" + i); + } + + return container; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java b/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java new file mode 100644 index 0000000000..767b651b68 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/table/TestMultipleSelection.java @@ -0,0 +1,57 @@ +package com.vaadin.tests.server.component.table; + +import java.util.Arrays; +import java.util.Set; + +import junit.framework.TestCase; + +import com.vaadin.data.Container; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.AbstractSelect.MultiSelectMode; +import com.vaadin.ui.Table; + +public class TestMultipleSelection extends TestCase { + + /** + * Tests weather the multiple select mode is set when using Table.set + */ + @SuppressWarnings("unchecked") + public void testSetMultipleItems() { + Table table = new Table("", createTestContainer()); + + // Tests if multiple selection is set + table.setMultiSelect(true); + assertTrue(table.isMultiSelect()); + + // Test multiselect by setting several items at once + + table.setValue(Arrays.asList("1", new String[] { "3" })); + assertEquals(2, ((Set<String>) table.getValue()).size()); + } + + /** + * Tests setting the multiselect mode of the Table. The multiselect mode + * affects how mouse selection is made in the table by the user. + */ + public void testSetMultiSelectMode() { + Table table = new Table("", createTestContainer()); + + // Default multiselect mode should be MultiSelectMode.DEFAULT + assertEquals(MultiSelectMode.DEFAULT, table.getMultiSelectMode()); + + // Tests if multiselectmode is set + table.setMultiSelectMode(MultiSelectMode.SIMPLE); + assertEquals(MultiSelectMode.SIMPLE, table.getMultiSelectMode()); + } + + /** + * Creates a testing container for the tests + * + * @return A new container with test items + */ + private Container createTestContainer() { + IndexedContainer container = new IndexedContainer(Arrays.asList("1", + new String[] { "2", "3", "4" })); + return container; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java new file mode 100644 index 0000000000..5c01a1c99f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TabSheetListeners.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.tabsheet; + +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +public class TabSheetListeners extends AbstractListenerMethodsTest { + public void testSelectedTabChangeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(TabSheet.class, SelectedTabChangeEvent.class, + SelectedTabChangeListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java new file mode 100644 index 0000000000..0ef8ae5a76 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java @@ -0,0 +1,224 @@ +package com.vaadin.tests.server.component.tabsheet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import java.util.Iterator; + +import org.junit.Test; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.Tab; + +public class TestTabSheet { + + @Test + public void addExistingComponent() { + Component c = new Label("abc"); + TabSheet tabSheet = new TabSheet(); + tabSheet.addComponent(c); + tabSheet.addComponent(c); + + Iterator<Component> iter = tabSheet.getComponentIterator(); + + assertEquals(c, iter.next()); + assertEquals(false, iter.hasNext()); + assertNotNull(tabSheet.getTab(c)); + } + + @Test + public void getComponentFromTab() { + Component c = new Label("abc"); + TabSheet tabSheet = new TabSheet(); + Tab tab = tabSheet.addTab(c); + assertEquals(c, tab.getComponent()); + } + + @Test + public void addTabWithComponentOnly() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + // Check right order of tabs + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab2)); + assertEquals(2, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent()); + + // Check right order of tabs + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab2)); + assertEquals(2, tabSheet.getTabPosition(tab3)); + } + + @Test + public void addTabWithComponentAndIndex() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + Tab tab4 = tabSheet.addTab(new Label("ddd"), 1); + Tab tab5 = tabSheet.addTab(new Label("eee"), 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent(), 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + } + + @Test + public void addTabWithAllParameters() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + Tab tab4 = tabSheet.addTab(new Label("ddd"), "ddd", null, 1); + Tab tab5 = tabSheet.addTab(new Label("eee"), "eee", null, 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + + // Calling addTab with existing component does not move tab + tabSheet.addTab(tab1.getComponent(), "xxx", null, 3); + + assertEquals(0, tabSheet.getTabPosition(tab1)); + assertEquals(1, tabSheet.getTabPosition(tab4)); + assertEquals(2, tabSheet.getTabPosition(tab2)); + assertEquals(3, tabSheet.getTabPosition(tab5)); + assertEquals(4, tabSheet.getTabPosition(tab3)); + } + + @Test + public void getTabByPosition() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + + assertEquals(tab1, tabSheet.getTab(0)); + assertEquals(tab2, tabSheet.getTab(1)); + assertEquals(tab3, tabSheet.getTab(2)); + + assertEquals(null, tabSheet.getTab(3)); + } + + @Test + public void selectTab() { + TabSheet tabSheet = new TabSheet(); + Tab tab1 = tabSheet.addTab(new Label("aaa")); + Tab tab2 = tabSheet.addTab(new Label("bbb")); + Tab tab3 = tabSheet.addTab(new Label("ccc")); + Label componentNotInSheet = new Label("ddd"); + Tab tabNotInSheet = new TabSheet().addTab(new Label("eee")); + + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // Select tab by component... + tabSheet.setSelectedTab(tab2.getComponent()); + assertEquals(tab2.getComponent(), tabSheet.getSelectedTab()); + + // by tab instance + tabSheet.setSelectedTab(tab3); + assertEquals(tab3.getComponent(), tabSheet.getSelectedTab()); + + // by index + tabSheet.setSelectedTab(0); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // Should be no-op... + tabSheet.setSelectedTab(componentNotInSheet); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // this as well + tabSheet.setSelectedTab(tabNotInSheet); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + + // and this + tabSheet.setSelectedTab(123); + assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); + } + + @Test + public void replaceComponent() { + TabSheet tabSheet = new TabSheet(); + Label lbl1 = new Label("aaa"); + Label lbl2 = new Label("bbb"); + Label lbl3 = new Label("ccc"); + Label lbl4 = new Label("ddd"); + + Tab tab1 = tabSheet.addTab(lbl1); + tab1.setCaption("tab1"); + tab1.setClosable(true); + Tab tab2 = tabSheet.addTab(lbl2); + tab2.setDescription("description"); + tab2.setEnabled(false); + + // Replace component not in tabsheet with one already in tabsheet - + // should be no-op + tabSheet.replaceComponent(lbl3, lbl2); + assertEquals(2, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertNull(tabSheet.getTab(lbl3)); + + // Replace component not in tabsheet with one not in tabsheet either + // should add lbl4 as last tab + tabSheet.replaceComponent(lbl3, lbl4); + assertEquals(3, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(2, tabSheet.getTabPosition(tabSheet.getTab(lbl4))); + + // Replace component in tabsheet with another + // should swap places, tab association should stay the same but tabs + // should swap metadata + tabSheet.replaceComponent(lbl1, lbl2); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(false, tab1.isClosable()); + assertEquals(true, tab2.isClosable()); + assertEquals(false, tab1.isEnabled()); + assertEquals(true, tab2.isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(null, tab2.getDescription()); + assertEquals(3, tabSheet.getComponentCount()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl1))); + assertEquals(0, tabSheet.getTabPosition(tabSheet.getTab(lbl2))); + + // Replace component in tabsheet with one not in tabsheet + // should create a new tab instance for the new component, old tab + // instance should become unattached + // tab metadata should be copied from old to new + tabSheet.replaceComponent(lbl1, lbl3); + assertEquals(3, tabSheet.getComponentCount()); + assertNull(tabSheet.getTab(lbl1)); + assertNull(tab1.getComponent()); + assertNotNull(tabSheet.getTab(lbl3)); + assertEquals(false, tabSheet.getTab(lbl3).isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl3))); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java b/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java new file mode 100644 index 0000000000..4bb0177a18 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java @@ -0,0 +1,108 @@ +package com.vaadin.tests.server.component.textfield; + +import java.util.Collections; + +import junit.framework.TestCase; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertyFormatter; +import com.vaadin.ui.TextField; + +public class TextFieldWithPropertyFormatter extends TestCase { + + private static final String INPUT_VALUE = "foo"; + private static final String PARSED_VALUE = "BAR"; + private static final String FORMATTED_VALUE = "FOOBAR"; + private static final String ORIGINAL_VALUE = "Original"; + private TextField field; + private PropertyFormatter<String> formatter; + private ObjectProperty<String> property; + private ValueChangeListener listener; + private int listenerCalled; + private int repainted; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + field = new TextField() { + @Override + public void markAsDirty() { + repainted++; + super.markAsDirty(); + } + }; + + formatter = new PropertyFormatter<String>() { + + @Override + public String parse(String formattedValue) throws Exception { + assertEquals(INPUT_VALUE, formattedValue); + return PARSED_VALUE; + } + + @Override + public String format(String value) { + return FORMATTED_VALUE; + } + }; + + property = new ObjectProperty<String>(ORIGINAL_VALUE); + + formatter.setPropertyDataSource(property); + field.setPropertyDataSource(formatter); + + listener = new Property.ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + listenerCalled++; + assertEquals(1, listenerCalled); + assertEquals(FORMATTED_VALUE, event.getProperty().getValue()); + } + }; + + field.addListener(listener); + listenerCalled = 0; + repainted = 0; + } + + public void testWithServerApi() { + checkInitialState(); + + field.setValue(INPUT_VALUE); + + checkEndState(); + + } + + private void checkEndState() { + assertEquals(1, listenerCalled); + // setModified triggers repaint, this is done 2 times. A + // ValueChangeEvent triggers the third + assertEquals(3, repainted); + assertEquals(FORMATTED_VALUE, field.getValue()); + assertEquals(FORMATTED_VALUE, formatter.getValue()); + assertEquals(PARSED_VALUE, property.getValue()); + } + + private void checkInitialState() { + assertEquals(ORIGINAL_VALUE, property.getValue()); + assertEquals(FORMATTED_VALUE, formatter.getValue()); + assertEquals(FORMATTED_VALUE, field.getValue()); + } + + public void testWithSimulatedClientSideChange() { + checkInitialState(); + + field.changeVariables(null, + Collections.singletonMap("text", (Object) INPUT_VALUE)); + + checkEndState(); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java b/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java new file mode 100644 index 0000000000..66535d3ffb --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TestHasChildren.java @@ -0,0 +1,25 @@ +package com.vaadin.tests.server.component.tree; + +import junit.framework.TestCase; + +import com.vaadin.ui.Tree; + +public class TestHasChildren extends TestCase { + + private Tree tree; + + @Override + protected void setUp() { + tree = new Tree(); + tree.addItem("parent"); + tree.addItem("child"); + tree.setChildrenAllowed("parent", true); + tree.setParent("child", "parent"); + } + + public void testRemoveChildren() { + assertTrue(tree.hasChildren("parent")); + tree.removeItem("child"); + assertFalse(tree.hasChildren("parent")); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java b/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java new file mode 100644 index 0000000000..4984cf161b --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TestListeners.java @@ -0,0 +1,137 @@ +package com.vaadin.tests.server.component.tree; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.ui.Tree; +import com.vaadin.ui.Tree.CollapseEvent; +import com.vaadin.ui.Tree.CollapseListener; +import com.vaadin.ui.Tree.ExpandEvent; +import com.vaadin.ui.Tree.ExpandListener; + +public class TestListeners extends TestCase implements ExpandListener, + CollapseListener { + private int expandCalled; + private int collapseCalled; + private Object lastExpanded; + private Object lastCollapsed; + + @Override + protected void setUp() { + expandCalled = 0; + } + + public void testExpandListener() { + Tree tree = createTree(10, 20, false); + tree.addListener((ExpandListener) this); + List<Object> rootIds = new ArrayList<Object>(tree.rootItemIds()); + + assertEquals(10, rootIds.size()); + assertEquals(10 + 10 * 20 + 10, tree.size()); + + // Expanding should send one expand event for the root item id + tree.expandItem(rootIds.get(0)); + assertEquals(1, expandCalled); + assertEquals(rootIds.get(0), lastExpanded); + + // Expand should send one event for each expanded item id. + // In this case root + child 4 + expandCalled = 0; + tree.expandItemsRecursively(rootIds.get(1)); + assertEquals(2, expandCalled); + List<Object> c = new ArrayList<Object>(tree.getChildren(rootIds.get(1))); + + assertEquals(c.get(4), lastExpanded); + + // Expanding an already expanded item should send no expand event + expandCalled = 0; + tree.expandItem(rootIds.get(0)); + assertEquals(0, expandCalled); + } + + /** + * Creates a tree with "rootItems" roots, each with "children" children, + * each with 1 child. + * + * @param rootItems + * @param children + * @param expand + * @return + */ + private Tree createTree(int rootItems, int children, boolean expand) { + Tree tree = new Tree(); + for (int i = 0; i < rootItems; i++) { + String rootId = "root " + i; + tree.addItem(rootId); + if (expand) { + tree.expandItemsRecursively(rootId); + } else { + tree.collapseItemsRecursively(rootId); + + } + for (int j = 0; j < children; j++) { + String childId = "child " + i + "/" + j; + tree.addItem(childId); + tree.setParent(childId, rootId); + tree.setChildrenAllowed(childId, false); + if (j == 4) { + tree.setChildrenAllowed(childId, true); + Object grandChildId = tree.addItem(); + tree.setParent(grandChildId, childId); + tree.setChildrenAllowed(grandChildId, false); + if (expand) { + tree.expandItemsRecursively(childId); + } else { + tree.collapseItemsRecursively(childId); + } + } + } + } + + return tree; + } + + public void testCollapseListener() { + Tree tree = createTree(7, 15, true); + tree.addListener((CollapseListener) this); + + List<Object> rootIds = new ArrayList<Object>(tree.rootItemIds()); + + assertEquals(7, rootIds.size()); + assertEquals(7 + 7 * 15 + 7, tree.size()); + + // Expanding should send one expand event for the root item id + tree.collapseItem(rootIds.get(0)); + assertEquals(1, collapseCalled); + assertEquals(rootIds.get(0), lastCollapsed); + + // Collapse sends one event for each collapsed node. + // In this case root + child 4 + collapseCalled = 0; + tree.collapseItemsRecursively(rootIds.get(1)); + assertEquals(2, collapseCalled); + List<Object> c = new ArrayList<Object>(tree.getChildren(rootIds.get(1))); + assertEquals(c.get(4), lastCollapsed); + + // Collapsing an already expanded item should send no expand event + collapseCalled = 0; + tree.collapseItem(rootIds.get(0)); + assertEquals(0, collapseCalled); + } + + @Override + public void nodeExpand(ExpandEvent event) { + lastExpanded = event.getItemId(); + expandCalled++; + + } + + @Override + public void nodeCollapse(CollapseEvent event) { + lastCollapsed = event.getItemId(); + collapseCalled++; + + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java b/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java new file mode 100644 index 0000000000..e14ebe739d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/tree/TreeListeners.java @@ -0,0 +1,27 @@ +package com.vaadin.tests.server.component.tree; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Tree; +import com.vaadin.ui.Tree.CollapseEvent; +import com.vaadin.ui.Tree.CollapseListener; +import com.vaadin.ui.Tree.ExpandEvent; +import com.vaadin.ui.Tree.ExpandListener; + +public class TreeListeners extends AbstractListenerMethodsTest { + public void testExpandListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, ExpandEvent.class, + ExpandListener.class); + } + + public void testItemClickListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, ItemClickEvent.class, + ItemClickListener.class); + } + + public void testCollapseListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Tree.class, CollapseEvent.class, + CollapseListener.class); + } +}
\ No newline at end of file diff --git a/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java b/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java new file mode 100644 index 0000000000..535ed8e860 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/treetable/EmptyTreeTable.java @@ -0,0 +1,13 @@ +package com.vaadin.tests.server.component.treetable; + +import junit.framework.TestCase; + +import com.vaadin.ui.TreeTable; + +public class EmptyTreeTable extends TestCase { + public void testLastId() { + TreeTable treeTable = new TreeTable(); + + assertFalse(treeTable.isLastId(treeTable.getValue())); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java b/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java new file mode 100644 index 0000000000..265e5382d4 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/upload/UploadListeners.java @@ -0,0 +1,41 @@ +package com.vaadin.tests.server.component.upload; + +import com.vaadin.server.StreamVariable.StreamingProgressEvent; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Upload; +import com.vaadin.ui.Upload.FailedEvent; +import com.vaadin.ui.Upload.FailedListener; +import com.vaadin.ui.Upload.FinishedEvent; +import com.vaadin.ui.Upload.FinishedListener; +import com.vaadin.ui.Upload.ProgressListener; +import com.vaadin.ui.Upload.StartedEvent; +import com.vaadin.ui.Upload.StartedListener; +import com.vaadin.ui.Upload.SucceededEvent; +import com.vaadin.ui.Upload.SucceededListener; + +public class UploadListeners extends AbstractListenerMethodsTest { + public void testProgressListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, StreamingProgressEvent.class, + ProgressListener.class); + } + + public void testSucceededListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, SucceededEvent.class, + SucceededListener.class); + } + + public void testStartedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, StartedEvent.class, + StartedListener.class); + } + + public void testFailedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, FailedEvent.class, + FailedListener.class); + } + + public void testFinishedListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Upload.class, FinishedEvent.class, + FinishedListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java new file mode 100644 index 0000000000..88bc28bbc8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/AddRemoveSubWindow.java @@ -0,0 +1,79 @@ +package com.vaadin.tests.server.component.window; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.ui.UI; +import com.vaadin.ui.UI.LegacyWindow; +import com.vaadin.ui.Window; + +public class AddRemoveSubWindow { + + public class TestApp extends Application.LegacyApplication { + + @Override + public void init() { + LegacyWindow w = new LegacyWindow("Main window"); + setMainWindow(w); + } + } + + @Test + public void addSubWindow() { + TestApp app = new TestApp(); + app.init(); + Window subWindow = new Window("Sub window"); + UI mainWindow = app.getMainWindow(); + + mainWindow.addWindow(subWindow); + // Added to main window so the parent of the sub window should be the + // main window + assertEquals(subWindow.getParent(), mainWindow); + + try { + mainWindow.addWindow(subWindow); + assertTrue("Window.addWindow did not throw the expected exception", + false); + } catch (IllegalArgumentException e) { + // Should throw an exception as it has already been added to the + // main window + } + + // Try to add the same sub window to another window + try { + LegacyWindow w = new LegacyWindow(); + w.addWindow(subWindow); + assertTrue("Window.addWindow did not throw the expected exception", + false); + } catch (IllegalArgumentException e) { + // Should throw an exception as it has already been added to the + // main window + } + + } + + @Test + public void removeSubWindow() { + TestApp app = new TestApp(); + app.init(); + Window subWindow = new Window("Sub window"); + UI mainWindow = app.getMainWindow(); + mainWindow.addWindow(subWindow); + + // Added to main window so the parent of the sub window should be the + // main window + assertEquals(subWindow.getParent(), mainWindow); + + // Parent should still be set + assertEquals(subWindow.getParent(), mainWindow); + + // Remove from the main window and assert it has been removed + boolean removed = mainWindow.removeWindow(subWindow); + assertTrue("Window was not removed correctly", removed); + assertNull(subWindow.getParent()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java new file mode 100644 index 0000000000..0fb0765c9f --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/AttachDetachWindow.java @@ -0,0 +1,254 @@ +package com.vaadin.tests.server.component.window; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.Application; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.Label; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class AttachDetachWindow { + + private Application testApp = new Application(); + + private interface TestContainer { + public boolean attachCalled(); + + public boolean detachCalled(); + + public TestContent getTestContent(); + + public Application getApplication(); + } + + private class TestWindow extends Window implements TestContainer { + boolean windowAttachCalled = false; + boolean windowDetachCalled = false; + private TestContent testContent = new TestContent();; + + TestWindow() { + setContent(testContent); + } + + @Override + public void attach() { + super.attach(); + windowAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + windowDetachCalled = true; + } + + @Override + public boolean attachCalled() { + return windowAttachCalled; + } + + @Override + public boolean detachCalled() { + return windowDetachCalled; + } + + @Override + public TestContent getTestContent() { + return testContent; + } + } + + private class TestContent extends VerticalLayout { + boolean contentDetachCalled = false; + boolean childDetachCalled = false; + boolean contentAttachCalled = false; + boolean childAttachCalled = false; + + private Label child = new Label() { + @Override + public void attach() { + super.attach(); + childAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + childDetachCalled = true; + } + }; + + public TestContent() { + addComponent(child); + } + + @Override + public void attach() { + super.attach(); + contentAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + contentDetachCalled = true; + } + } + + private class TestUI extends UI implements TestContainer { + boolean rootAttachCalled = false; + boolean rootDetachCalled = false; + private TestContent testContent = new TestContent();; + + public TestUI() { + setContent(testContent); + } + + @Override + protected void init(WrappedRequest request) { + // Do nothing + } + + @Override + public boolean attachCalled() { + return rootAttachCalled; + } + + @Override + public boolean detachCalled() { + return rootDetachCalled; + } + + @Override + public TestContent getTestContent() { + return testContent; + } + + @Override + public void attach() { + super.attach(); + rootAttachCalled = true; + } + + @Override + public void detach() { + super.detach(); + rootDetachCalled = true; + } + } + + TestUI main = new TestUI(); + TestWindow sub = new TestWindow(); + + @Test + public void addSubWindowBeforeAttachingMainWindow() { + assertUnattached(main); + assertUnattached(sub); + + main.addWindow(sub); + assertUnattached(main); + assertUnattached(sub); + + // attaching main should recurse to sub + main.setApplication(testApp); + assertAttached(main); + assertAttached(sub); + } + + @Test + public void addSubWindowAfterAttachingMainWindow() { + assertUnattached(main); + assertUnattached(sub); + + main.setApplication(testApp); + assertAttached(main); + assertUnattached(sub); + + // main is already attached, so attach should be called for sub + main.addWindow(sub); + assertAttached(main); + assertAttached(sub); + } + + @Test + public void removeSubWindowBeforeDetachingMainWindow() { + main.setApplication(testApp); + main.addWindow(sub); + + // sub should be detached when removing from attached main + main.removeWindow(sub); + assertAttached(main); + assertDetached(sub); + + // main detach should recurse to sub + main.setApplication(null); + assertDetached(main); + assertDetached(sub); + } + + @Test + public void removeSubWindowAfterDetachingMainWindow() { + main.setApplication(testApp); + main.addWindow(sub); + + // main detach should recurse to sub + main.setApplication(null); + assertDetached(main); + assertDetached(sub); + + main.removeWindow(sub); + assertDetached(main); + assertDetached(sub); + } + + /** + * Asserts that win and its children are attached to testApp and their + * attach() methods have been called. + */ + private void assertAttached(TestContainer win) { + TestContent testContent = win.getTestContent(); + + assertTrue("window attach not called", win.attachCalled()); + assertTrue("window content attach not called", + testContent.contentAttachCalled); + assertTrue("window child attach not called", + testContent.childAttachCalled); + + assertSame("window not attached", win.getApplication(), testApp); + assertSame("window content not attached", testContent.getApplication(), + testApp); + assertSame("window children not attached", + testContent.child.getApplication(), testApp); + } + + /** + * Asserts that win and its children are not attached. + */ + private void assertUnattached(TestContainer win) { + assertSame("window not detached", win.getApplication(), null); + assertSame("window content not detached", win.getTestContent() + .getApplication(), null); + assertSame("window children not detached", + win.getTestContent().child.getApplication(), null); + } + + /** + * Asserts that win and its children are unattached and their detach() + * methods have been been called. + * + * @param win + */ + private void assertDetached(TestContainer win) { + assertUnattached(win); + assertTrue("window detach not called", win.detachCalled()); + assertTrue("window content detach not called", + win.getTestContent().contentDetachCalled); + assertTrue("window child detach not called", + win.getTestContent().childDetachCalled); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java b/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java new file mode 100644 index 0000000000..c33871cbd8 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/window/WindowListeners.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.component.window; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.tests.server.component.AbstractListenerMethodsTest; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.CloseEvent; +import com.vaadin.ui.Window.CloseListener; +import com.vaadin.ui.Window.ResizeEvent; +import com.vaadin.ui.Window.ResizeListener; + +public class WindowListeners extends AbstractListenerMethodsTest { + public void testFocusListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, FocusEvent.class, + FocusListener.class); + } + + public void testBlurListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, BlurEvent.class, + BlurListener.class); + } + + public void testResizeListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, ResizeEvent.class, + ResizeListener.class); + } + + public void testCloseListenerAddGetRemove() throws Exception { + testListenerAddGetRemove(Window.class, CloseEvent.class, + CloseListener.class); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java new file mode 100644 index 0000000000..e3e743d02a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/AbstractIndexedLayoutTest.java @@ -0,0 +1,84 @@ +package com.vaadin.tests.server.componentcontainer; + +import junit.framework.TestCase; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; + +public abstract class AbstractIndexedLayoutTest extends TestCase { + + private Layout layout; + + protected abstract Layout createLayout(); + + @Override + protected void setUp() throws Exception { + layout = createLayout(); + } + + public Layout getLayout() { + return layout; + } + + public void testAddRemoveComponent() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + + assertEquals(c1, getComponent(0)); + assertEquals(1, getComponentCount()); + layout.addComponent(c2); + assertEquals(c1, getComponent(0)); + assertEquals(c2, getComponent(1)); + assertEquals(2, getComponentCount()); + layout.removeComponent(c1); + assertEquals(c2, getComponent(0)); + assertEquals(1, getComponentCount()); + layout.removeComponent(c2); + assertEquals(0, getComponentCount()); + } + + protected abstract int getComponentCount(); + + protected abstract Component getComponent(int index); + + protected abstract int getComponentIndex(Component c); + + public void testGetComponentIndex() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + assertEquals(0, getComponentIndex(c1)); + layout.addComponent(c2); + assertEquals(0, getComponentIndex(c1)); + assertEquals(1, getComponentIndex(c2)); + layout.removeComponent(c1); + assertEquals(0, getComponentIndex(c2)); + layout.removeComponent(c2); + assertEquals(-1, getComponentIndex(c2)); + assertEquals(-1, getComponentIndex(c1)); + } + + public void testGetComponent() { + Label c1 = new Label(); + Label c2 = new Label(); + + layout.addComponent(c1); + assertEquals(c1, getComponent(0)); + layout.addComponent(c2); + assertEquals(c1, getComponent(0)); + assertEquals(c2, getComponent(1)); + layout.removeComponent(c1); + assertEquals(c2, getComponent(0)); + layout.removeComponent(c2); + try { + getComponent(0); + fail(); + } catch (IndexOutOfBoundsException e) { + // Expected + } + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java new file mode 100644 index 0000000000..828404bd5a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java @@ -0,0 +1,40 @@ +package com.vaadin.tests.server.componentcontainer; + +import java.util.List; + +import junit.framework.TestCase; + +import com.vaadin.tests.VaadinClasses; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; + +public class AddRemoveComponentTest extends TestCase { + + public void testRemoveComponentFromWrongContainer() + throws InstantiationException, IllegalAccessException { + List<Class<? extends ComponentContainer>> containerClasses = VaadinClasses + .getComponentContainersSupportingAddRemoveComponent(); + + // No default constructor, special case + containerClasses.remove(CustomLayout.class); + testRemoveComponentFromWrongContainer(new CustomLayout("dummy")); + + for (Class<? extends ComponentContainer> c : containerClasses) { + testRemoveComponentFromWrongContainer(c.newInstance()); + } + } + + private void testRemoveComponentFromWrongContainer( + ComponentContainer componentContainer) { + HorizontalLayout hl = new HorizontalLayout(); + Label label = new Label(); + hl.addComponent(label); + + componentContainer.removeComponent(label); + assertEquals( + "Parent no longer correct for " + componentContainer.getClass(), + hl, label.getParent()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java new file mode 100644 index 0000000000..dc9667c38e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/CssLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Layout; + +public class CssLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new CssLayout(); + } + + @Override + public CssLayout getLayout() { + return (CssLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java new file mode 100644 index 0000000000..71a813d423 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/FormLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.Layout; + +public class FormLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new FormLayout(); + } + + @Override + public FormLayout getLayout() { + return (FormLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java b/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java new file mode 100644 index 0000000000..0e3a1d5734 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/componentcontainer/VerticalLayoutTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.server.componentcontainer; + +import com.vaadin.ui.Component; +import com.vaadin.ui.Layout; +import com.vaadin.ui.VerticalLayout; + +public class VerticalLayoutTest extends AbstractIndexedLayoutTest { + + @Override + protected Layout createLayout() { + return new VerticalLayout(); + } + + @Override + public VerticalLayout getLayout() { + return (VerticalLayout) super.getLayout(); + } + + @Override + protected Component getComponent(int index) { + return getLayout().getComponent(index); + } + + @Override + protected int getComponentIndex(Component c) { + return getLayout().getComponentIndex(c); + } + + @Override + protected int getComponentCount() { + return getLayout().getComponentCount(); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java b/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java new file mode 100644 index 0000000000..f2de4f3c04 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/AbstractTestFieldValueChange.java @@ -0,0 +1,129 @@ +package com.vaadin.tests.server.components; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.Property.ValueChangeNotifier; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.ui.AbstractField; + +/** + * Base class for tests for checking that value change listeners for fields are + * not called exactly once when they should be, and not at other times. + * + * Does not check all cases (e.g. properties that do not implement + * {@link ValueChangeNotifier}). + * + * Subclasses should implement {@link #setValue()} and call + * <code>super.setValue(AbstractField)</code>. Also, subclasses should typically + * override {@link #setValue(AbstractField)} to set the field value via + * <code>changeVariables()</code>. + */ +public abstract class AbstractTestFieldValueChange<T> extends TestCase { + + private AbstractField<T> field; + private ValueChangeListener listener; + + protected void setUp(AbstractField<T> field) throws Exception { + this.field = field; + listener = EasyMock.createStrictMock(ValueChangeListener.class); + + } + + protected ValueChangeListener getListener() { + return listener; + } + + /** + * Test that listeners are not called when they have been unregistered. + */ + public void testRemoveListener() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(false); + + // Expectations and start test + listener.valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(listener); + + // Add listener and set the value -> should end up in listener once + getField().addListener(listener); + setValue(getField()); + + // Ensure listener was called once + EasyMock.verify(listener); + + // Remove the listener and set the value -> should not end up in + // listener + getField().removeListener(listener); + setValue(getField()); + + // Ensure listener still has been called only once + EasyMock.verify(listener); + } + + /** + * Common unbuffered case: both writeThrough (auto-commit) and readThrough + * are on. Calling commit() should not cause notifications. + * + * Using the readThrough mode allows changes made to the property value to + * be seen in some cases also when there is no notification of value change + * from the property. + * + * Field value change notifications closely mirror value changes of the data + * source behind the field. + */ + public void testNonBuffered() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(false); + + expectValueChangeFromSetValueNotCommit(); + } + + /** + * Fully buffered use where the data source is neither read nor modified + * during editing, and is updated at commit(). + * + * Field value change notifications reflect the buffered value in the field, + * not the original data source value changes. + */ + public void testBuffered() { + getField().setPropertyDataSource(new ObjectProperty<String>("")); + getField().setBuffered(true); + + expectValueChangeFromSetValueNotCommit(); + } + + protected void expectValueChangeFromSetValueNotCommit() { + // Expectations and start test + listener.valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(listener); + + // Add listener and set the value -> should end up in listener once + getField().addListener(listener); + setValue(getField()); + + // Ensure listener was called once + EasyMock.verify(listener); + + // commit + getField().commit(); + + // Ensure listener was not called again + EasyMock.verify(listener); + } + + protected AbstractField<T> getField() { + return field; + } + + /** + * Override in subclasses to set value with changeVariables(). + */ + protected void setValue(AbstractField<T> field) { + field.setValue("newValue"); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java new file mode 100644 index 0000000000..3ba1c4c7f1 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/ComponentAttachDetachListenerTest.java @@ -0,0 +1,345 @@ +package com.vaadin.tests.server.components; + +import java.util.Iterator; + +import junit.framework.TestCase; + +import com.vaadin.ui.AbsoluteLayout; +import com.vaadin.ui.AbsoluteLayout.ComponentPosition; +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.ComponentContainer.ComponentAttachEvent; +import com.vaadin.ui.ComponentContainer.ComponentAttachListener; +import com.vaadin.ui.ComponentContainer.ComponentDetachEvent; +import com.vaadin.ui.ComponentContainer.ComponentDetachListener; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.GridLayout.Area; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; + +public class ComponentAttachDetachListenerTest extends TestCase { + + private AbstractOrderedLayout olayout; + private GridLayout gridlayout; + private AbsoluteLayout absolutelayout; + private CssLayout csslayout; + + // General variables + private int attachCounter = 0; + private Component attachedComponent = null; + private ComponentContainer attachTarget = null; + private boolean foundInContainer = false; + + private int detachCounter = 0; + private Component detachedComponent = null; + private ComponentContainer detachedTarget = null; + + // Ordered layout specific variables + private int indexOfComponent = -1; + + // Grid layout specific variables + private Area componentArea = null; + + // Absolute layout specific variables + private ComponentPosition componentPosition = null; + + private class MyAttachListener implements ComponentAttachListener { + @Override + public void componentAttachedToContainer(ComponentAttachEvent event) { + attachCounter++; + attachedComponent = event.getAttachedComponent(); + attachTarget = event.getContainer(); + + // Search for component in container (should be found) + Iterator<Component> iter = attachTarget.getComponentIterator(); + while (iter.hasNext()) { + if (iter.next() == attachedComponent) { + foundInContainer = true; + break; + } + } + + // Get layout specific variables + if (attachTarget instanceof AbstractOrderedLayout) { + indexOfComponent = ((AbstractOrderedLayout) attachTarget) + .getComponentIndex(attachedComponent); + } else if (attachTarget instanceof GridLayout) { + componentArea = ((GridLayout) attachTarget) + .getComponentArea(attachedComponent); + } else if (attachTarget instanceof AbsoluteLayout) { + componentPosition = ((AbsoluteLayout) attachTarget) + .getPosition(attachedComponent); + } + } + } + + private class MyDetachListener implements ComponentDetachListener { + @Override + public void componentDetachedFromContainer(ComponentDetachEvent event) { + detachCounter++; + detachedComponent = event.getDetachedComponent(); + detachedTarget = event.getContainer(); + + // Search for component in container (should NOT be found) + Iterator<Component> iter = detachedTarget.getComponentIterator(); + while (iter.hasNext()) { + if (iter.next() == detachedComponent) { + foundInContainer = true; + break; + } + } + + // Get layout specific variables + if (detachedTarget instanceof AbstractOrderedLayout) { + indexOfComponent = ((AbstractOrderedLayout) detachedTarget) + .getComponentIndex(detachedComponent); + } else if (detachedTarget instanceof GridLayout) { + componentArea = ((GridLayout) detachedTarget) + .getComponentArea(detachedComponent); + } else if (detachedTarget instanceof AbsoluteLayout) { + componentPosition = ((AbsoluteLayout) detachedTarget) + .getPosition(detachedComponent); + } + + } + } + + private void resetVariables() { + // Attach + attachCounter = 0; + attachedComponent = null; + attachTarget = null; + foundInContainer = false; + + // Detach + detachCounter = 0; + detachedComponent = null; + detachedTarget = null; + + // Common + indexOfComponent = -1; + componentArea = null; + componentPosition = null; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + olayout = new HorizontalLayout(); + olayout.addListener(new MyAttachListener()); + olayout.addListener(new MyDetachListener()); + + gridlayout = new GridLayout(); + gridlayout.addListener(new MyAttachListener()); + gridlayout.addListener(new MyDetachListener()); + + absolutelayout = new AbsoluteLayout(); + absolutelayout.addListener(new MyAttachListener()); + absolutelayout.addListener(new MyDetachListener()); + + csslayout = new CssLayout(); + csslayout.addListener(new MyAttachListener()); + csslayout.addListener(new MyDetachListener()); + } + + public void testOrderedLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + olayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(olayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The index of the component should not be -1 + assertFalse(indexOfComponent == -1); + } + + public void testOrderedLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + olayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + olayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(olayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The index of the component should be -1 + assertEquals(-1, indexOfComponent); + } + + public void testGridLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + gridlayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(gridlayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The grid area should not be null + assertNotNull(componentArea); + } + + public void testGridLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + gridlayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + gridlayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(gridlayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The grid area should be null + assertNull(componentArea); + } + + public void testAbsoluteLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + absolutelayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(absolutelayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + + // The component position should not be null + assertNotNull(componentPosition); + } + + public void testAbsoluteLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + absolutelayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + absolutelayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(absolutelayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + + // The component position should be null + assertNull(componentPosition); + } + + public void testCSSLayoutAttachListener() { + // Reset state variables + resetVariables(); + + // Add component -> Should trigger attach listener + Component comp = new Label(); + csslayout.addComponent(comp); + + // Attach counter should get incremented + assertEquals(1, attachCounter); + + // The attached component should be the label + assertSame(comp, attachedComponent); + + // The attached target should be the layout + assertSame(csslayout, attachTarget); + + // The attached component should be found in the container + assertTrue(foundInContainer); + } + + public void testCSSLayoutDetachListener() { + // Add a component to detach + Component comp = new Label(); + csslayout.addComponent(comp); + + // Reset state variables (since they are set by the attach listener) + resetVariables(); + + // Detach the component -> triggers the detach listener + csslayout.removeComponent(comp); + + // Detach counter should get incremented + assertEquals(1, detachCounter); + + // The detached component should be the label + assertSame(comp, detachedComponent); + + // The detached target should be the layout + assertSame(csslayout, detachedTarget); + + // The detached component should not be found in the container + assertFalse(foundInContainer); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java b/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java new file mode 100644 index 0000000000..308889fa33 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestComboBoxValueChange.java @@ -0,0 +1,31 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.ComboBox; + +/** + * Check that the value change listener for a combo box is triggered exactly + * once when setting the value, at the correct time. + * + * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. + */ +public class TestComboBoxValueChange extends + AbstractTestFieldValueChange<Object> { + @Override + protected void setUp() throws Exception { + ComboBox combo = new ComboBox(); + combo.addItem("myvalue"); + super.setUp(combo); + } + + @Override + protected void setValue(AbstractField<Object> field) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("selected", new String[] { "myvalue" }); + ((ComboBox) field).changeVariables(field, variables); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java b/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java new file mode 100644 index 0000000000..92664917fd --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestGridLayoutLastRowRemoval.java @@ -0,0 +1,40 @@ +package com.vaadin.tests.server.components; + +import junit.framework.TestCase; + +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; + +public class TestGridLayoutLastRowRemoval extends TestCase { + + public void testRemovingLastRow() { + GridLayout grid = new GridLayout(2, 1); + grid.addComponent(new Label("Col1")); + grid.addComponent(new Label("Col2")); + + try { + // Removing the last row in the grid + grid.removeRow(0); + } catch (IllegalArgumentException iae) { + // Removing the last row should not throw an + // IllegalArgumentException + fail("removeRow(0) threw an IllegalArgumentExcetion when removing the last row"); + } + + // The column amount should be preserved + assertEquals(2, grid.getColumns()); + + // There should be one row left + assertEquals(1, grid.getRows()); + + // There should be no component left in the grid layout + assertNull("A component should not be left in the layout", + grid.getComponent(0, 0)); + assertNull("A component should not be left in the layout", + grid.getComponent(1, 0)); + + // The cursor should be in the first cell + assertEquals(0, grid.getCursorX()); + assertEquals(0, grid.getCursorY()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java b/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java new file mode 100644 index 0000000000..de838e339c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestTextFieldValueChange.java @@ -0,0 +1,126 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; + +import org.easymock.EasyMock; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.ui.AbstractField; +import com.vaadin.ui.TextField; + +/** + * Check that the value change listener for a text field is triggered exactly + * once when setting the value, at the correct time. + * + * See <a href="http://dev.vaadin.com/ticket/4394">Ticket 4394</a>. + */ +public class TestTextFieldValueChange extends + AbstractTestFieldValueChange<String> { + + @Override + protected void setUp() throws Exception { + super.setUp(new TextField()); + } + + /** + * Case where the text field only uses its internal buffer, no external + * property data source. + */ + public void testNoDataSource() { + getField().setPropertyDataSource(null); + + expectValueChangeFromSetValueNotCommit(); + } + + @Override + protected void setValue(AbstractField<String> field) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("text", "newValue"); + ((TextField) field).changeVariables(field, variables); + } + + /** + * Test that field propagates value change events originating from property, + * but don't fire value change events twice if value has only changed once. + * + * + * TODO make test field type agnostic (eg. combobox) + */ + public void testValueChangeEventPropagationWithReadThrough() { + ObjectProperty<String> property = new ObjectProperty<String>(""); + getField().setPropertyDataSource(property); + + // defaults, buffering off + getField().setBuffered(false); + + // Expectations and start test + getListener().valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(getListener()); + + // Add listener and set the value -> should end up in listener once + getField().addListener(getListener()); + + property.setValue("Foo"); + + // Ensure listener was called once + EasyMock.verify(getListener()); + + // get value should not fire value change again + Object value = getField().getValue(); + Assert.assertEquals("Foo", value); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + } + + /** + * Value change events from property should not propagate if read through is + * false. Execpt when the property is being set. + * + * TODO make test field type agnostic (eg. combobox) + */ + public void testValueChangePropagationWithReadThroughOff() { + final String initialValue = "initial"; + ObjectProperty<String> property = new ObjectProperty<String>( + initialValue); + + // set buffering + getField().setBuffered(true); + + // Value change should only happen once, when setting the property, + // further changes via property should not cause value change listener + // in field to be notified + getListener().valueChange(EasyMock.isA(ValueChangeEvent.class)); + EasyMock.replay(getListener()); + + getField().addListener(getListener()); + getField().setPropertyDataSource(property); + + // Ensure listener was called once + EasyMock.verify(getListener()); + + // modify property value, should not fire value change in field as the + // read buffering is on (read through == false) + property.setValue("Foo"); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + + // get value should not fire value change again + Object value = getField().getValue(); + + // field value should be different from the original value and current + // proeprty value + boolean isValueEqualToInitial = value.equals(initialValue); + Assert.assertTrue(isValueEqualToInitial); + + // Ensure listener still has been called only once + EasyMock.verify(getListener()); + + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/components/TestWindow.java b/server/tests/src/com/vaadin/tests/server/components/TestWindow.java new file mode 100644 index 0000000000..12d3a3c8f5 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/components/TestWindow.java @@ -0,0 +1,92 @@ +package com.vaadin.tests.server.components; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import com.vaadin.ui.UI.LegacyWindow; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.CloseEvent; +import com.vaadin.ui.Window.CloseListener; +import com.vaadin.ui.Window.ResizeEvent; +import com.vaadin.ui.Window.ResizeListener; + +public class TestWindow extends TestCase { + + private Window window; + + @Override + protected void setUp() throws Exception { + window = new Window(); + new LegacyWindow().addWindow(window); + } + + public void testCloseListener() { + CloseListener cl = EasyMock.createMock(Window.CloseListener.class); + + // Expectations + cl.windowClose(EasyMock.isA(CloseEvent.class)); + + // Start actual test + EasyMock.replay(cl); + + // Add listener and send a close event -> should end up in listener once + window.addListener(cl); + sendClose(window); + + // Ensure listener was called once + EasyMock.verify(cl); + + // Remove the listener and send close event -> should not end up in + // listener + window.removeListener(cl); + sendClose(window); + + // Ensure listener still has been called only once + EasyMock.verify(cl); + + } + + public void testResizeListener() { + ResizeListener rl = EasyMock.createMock(Window.ResizeListener.class); + + // Expectations + rl.windowResized(EasyMock.isA(ResizeEvent.class)); + + // Start actual test + EasyMock.replay(rl); + + // Add listener and send a resize event -> should end up in listener + // once + window.addListener(rl); + sendResize(window); + + // Ensure listener was called once + EasyMock.verify(rl); + + // Remove the listener and send close event -> should not end up in + // listener + window.removeListener(rl); + sendResize(window); + + // Ensure listener still has been called only once + EasyMock.verify(rl); + + } + + private void sendResize(Window window2) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("height", 1234); + window.changeVariables(window, variables); + + } + + private static void sendClose(Window window) { + Map<String, Object> variables = new HashMap<String, Object>(); + variables.put("close", true); + window.changeVariables(window, variables); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java b/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java new file mode 100644 index 0000000000..5db0df4280 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import com.vaadin.navigator.Navigator.ClassBasedViewProvider; +import com.vaadin.navigator.View; +import com.vaadin.ui.Label; + +public class ClassBasedViewProviderTest extends TestCase { + + public static class TestView extends Label implements View { + public String parameters = null; + + @Override + public void navigateTo(String parameters) { + this.parameters = parameters; + } + + } + + public static class TestView2 extends TestView { + + } + + public void testCreateProviderWithNullName() throws Exception { + try { + new ClassBasedViewProvider(null, TestView.class); + fail("Should not be able to create view provider with null name"); + } catch (IllegalArgumentException e) { + } + } + + public void testCreateProviderWithEmptyStringName() throws Exception { + new ClassBasedViewProvider("", TestView.class); + } + + public void testCreateProviderNullViewClass() throws Exception { + try { + new ClassBasedViewProvider("test", null); + fail("Should not be able to create view provider with null view class"); + } catch (IllegalArgumentException e) { + } + } + + public void testViewNameGetter() throws Exception { + ClassBasedViewProvider provider1 = new ClassBasedViewProvider("", + TestView.class); + assertEquals("View name should be empty", "", provider1.getViewName()); + + ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("View name does not match", "test", + provider2.getViewName()); + } + + public void testViewClassGetter() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("Incorrect view class returned by getter", TestView.class, + provider.getViewClass()); + } + + public void testGetViewNameForNullString() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertNull("Received view name for null view string", + provider.getViewName((String) null)); + } + + public void testGetViewNameForEmptyString() throws Exception { + ClassBasedViewProvider provider1 = new ClassBasedViewProvider("", + TestView.class); + assertEquals( + "Did not find view name for empty view string in a provider with empty string registered", + "", provider1.getViewName("")); + + ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test", + TestView.class); + assertNull( + "Found view name for empty view string when none registered", + provider2.getViewName("")); + } + + public void testGetViewNameWithParameters() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + assertEquals("Incorrect view name found for view string", "test", + provider.getViewName("test")); + assertEquals( + "Incorrect view name found for view string ending with slash", + "test", provider.getViewName("test/")); + assertEquals( + "Incorrect view name found for view string with parameters", + "test", provider.getViewName("test/params/are/here")); + } + + public void testGetView() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + + View view = provider.getView("test"); + assertNotNull("Did not get view from a provider", view); + assertEquals("Incorrect view type", TestView.class, view.getClass()); + } + + public void testGetViewIncorrectViewName() throws Exception { + ClassBasedViewProvider provider = new ClassBasedViewProvider("test", + TestView.class); + + View view = provider.getView("test2"); + assertNull("Got view from a provider for incorrect view name", view); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java new file mode 100644 index 0000000000..595ddb95db --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/NavigatorTest.java @@ -0,0 +1,575 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.server.navigator; + +import java.util.LinkedList; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.FragmentManager; +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.navigator.ViewProvider; +import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView; +import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView2; + +public class NavigatorTest extends TestCase { + + // TODO test internal parameters (and absence of them) + // TODO test listeners blocking navigation, multiple listeners + + public static class NullDisplay implements ViewDisplay { + @Override + public void showView(View view) { + // do nothing + } + } + + public static class NullFragmentManager implements FragmentManager { + @Override + public String getFragment() { + return null; + } + + @Override + public void setFragment(String fragment) { + // do nothing + } + } + + public static class TestDisplay implements ViewDisplay { + private View currentView; + + @Override + public void showView(View view) { + currentView = view; + } + + public View getCurrentView() { + return currentView; + } + } + + public static class TestNavigator extends Navigator { + public TestNavigator() { + super(new NullFragmentManager(), new TestDisplay()); + } + + public View getView(String viewAndParameters) { + navigateTo(viewAndParameters); + return ((TestDisplay) getDisplay()).getCurrentView(); + } + } + + public static class ViewChangeTestListener implements ViewChangeListener { + private final LinkedList<ViewChangeEvent> referenceEvents = new LinkedList<ViewChangeListener.ViewChangeEvent>(); + private final LinkedList<Boolean> referenceIsCheck = new LinkedList<Boolean>(); + private final LinkedList<Boolean> checkReturnValues = new LinkedList<Boolean>(); + + public void addExpectedIsViewChangeAllowed(ViewChangeEvent event, + boolean returnValue) { + referenceIsCheck.add(true); + referenceEvents.add(event); + checkReturnValues.add(returnValue); + } + + public void addExpectedNavigatorViewChange(ViewChangeEvent event) { + referenceIsCheck.add(false); + referenceEvents.add(event); + } + + public boolean isReady() { + return referenceEvents.isEmpty(); + } + + public boolean equalsReferenceEvent(ViewChangeEvent event, + ViewChangeEvent reference) { + if (event == null) { + return false; + } + if (reference.getNavigator() != event.getNavigator()) { + return false; + } + if (reference.getOldView() != event.getOldView()) { + return false; + } + if (reference.getNewView() != event.getNewView()) { + return false; + } + if (!stringEquals(reference.getViewName(), event.getViewName())) { + return false; + } + if (!stringEquals(reference.getFragmentParameters(), + event.getFragmentParameters())) { + return false; + } + return true; + } + + private static boolean stringEquals(String string1, String string2) { + if (string1 == null) { + return string2 == null; + } else { + return string1.equals(string2); + } + } + + @Override + public boolean isViewChangeAllowed(ViewChangeEvent event) { + if (referenceEvents.isEmpty()) { + fail("Unexpected call to isViewChangeAllowed()"); + } + ViewChangeEvent reference = referenceEvents.remove(); + Boolean isCheck = referenceIsCheck.remove(); + if (!isCheck) { + fail("Expected navigatorViewChanged(), received isViewChangeAllowed()"); + } + // here to make sure exactly the correct values are removed from + // each queue + Boolean returnValue = checkReturnValues.remove(); + if (!equalsReferenceEvent(event, reference)) { + fail("View change event does not match reference event"); + } + return returnValue; + } + + @Override + public void navigatorViewChanged(ViewChangeEvent event) { + if (referenceEvents.isEmpty()) { + fail("Unexpected call to navigatorViewChanged()"); + } + ViewChangeEvent reference = referenceEvents.remove(); + Boolean isCheck = referenceIsCheck.remove(); + if (isCheck) { + fail("Expected isViewChangeAllowed(), received navigatorViewChanged()"); + } + if (!equalsReferenceEvent(event, reference)) { + fail("View change event does not match reference event"); + } + } + } + + public void testBasicNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test2/")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.addProvider(provider); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2/"); + navigator.navigateTo("test1/params"); + } + + public void testMainView() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.addProvider(provider); + + navigator.navigateTo("test2"); + navigator.navigateTo(""); + navigator.navigateTo("test1/params"); + } + + public void testListeners() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeTestListener listener = new ViewChangeTestListener(); + + // create navigator to test + Navigator navigator = new Navigator(manager, display); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1, + "test1", ""); + listener.addExpectedIsViewChangeAllowed(event1, true); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(""); + display.showView(view1); + manager.setFragment("test1"); + listener.addExpectedNavigatorViewChange(event1); + + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + ViewChangeEvent event2 = new ViewChangeEvent(navigator, view1, view2, + "test2", ""); + listener.addExpectedIsViewChangeAllowed(event2, true); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + listener.addExpectedNavigatorViewChange(event2); + + control.replay(); + + // test navigator + navigator.addProvider(provider); + navigator.addListener(listener); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2"); + + if (!listener.isReady()) { + fail("Missing listener calls"); + } + } + + public void testBlockNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeTestListener listener1 = new ViewChangeTestListener(); + ViewChangeTestListener listener2 = new ViewChangeTestListener(); + + Navigator navigator = new Navigator(manager, display); + + // prepare mocks: what to expect + // first listener blocks first view change + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1, + "test1", ""); + listener1.addExpectedIsViewChangeAllowed(event1, false); + + // second listener blocks second view change + EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event2 = new ViewChangeEvent(navigator, null, view1, + "test1", "test"); + listener1.addExpectedIsViewChangeAllowed(event2, true); + listener2.addExpectedIsViewChangeAllowed(event2, false); + + // both listeners allow view change + EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + EasyMock.expect(manager.getFragment()).andReturn(""); + ViewChangeEvent event3 = new ViewChangeEvent(navigator, null, view1, + "test1", "bar"); + listener1.addExpectedIsViewChangeAllowed(event3, true); + listener2.addExpectedIsViewChangeAllowed(event3, true); + view1.navigateTo("bar"); + display.showView(view1); + manager.setFragment("test1/bar"); + listener1.addExpectedNavigatorViewChange(event3); + listener2.addExpectedNavigatorViewChange(event3); + + // both listeners allow view change from non-null view + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + ViewChangeEvent event4 = new ViewChangeEvent(navigator, view1, view2, + "test2", ""); + listener1.addExpectedIsViewChangeAllowed(event4, true); + listener2.addExpectedIsViewChangeAllowed(event4, true); + view2.navigateTo(""); + display.showView(view2); + manager.setFragment("test2"); + listener1.addExpectedNavigatorViewChange(event4); + listener2.addExpectedNavigatorViewChange(event4); + + control.replay(); + + // test navigator + navigator.addProvider(provider); + navigator.addListener(listener1); + navigator.addListener(listener2); + + navigator.navigateTo("test1"); + navigator.navigateTo("test1/test"); + navigator.navigateTo("test1/bar"); + navigator.navigateTo("test2"); + + if (!listener1.isReady()) { + fail("Missing listener calls for listener1"); + } + if (!listener2.isReady()) { + fail("Missing listener calls for listener2"); + } + } + + public void testAddViewInstance() throws Exception { + View view = new TestView(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + + assertEquals("Registered view instance not returned by navigator", + view, navigator.getView("test")); + } + + public void testAddViewInstanceSameName() throws Exception { + View view1 = new TestView(); + View view2 = new TestView2(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view1); + navigator.addView("test", view2); + + assertEquals( + "Adding second view with same name should override previous view", + view2, navigator.getView("test")); + } + + public void testAddViewClass() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + + View view = navigator.getView("test"); + assertNotNull("Received null view", view); + assertEquals("Received incorrect type of view", TestView.class, + view.getClass()); + } + + public void testAddViewClassSameName() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.addView("test", TestView2.class); + + assertEquals( + "Adding second view class with same name should override previous view", + TestView2.class, navigator.getView("test").getClass()); + } + + public void testAddViewInstanceAndClassSameName() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + TestView2 view2 = new TestView2(); + navigator.addView("test", view2); + + assertEquals( + "Adding second view class with same name should override previous view", + view2, navigator.getView("test")); + + navigator.addView("test", TestView.class); + + assertEquals( + "Adding second view class with same name should override previous view", + TestView.class, navigator.getView("test").getClass()); + } + + public void testAddViewWithNullName() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView(null, new TestView()); + fail("addView() accepted null view name"); + } catch (IllegalArgumentException e) { + } + try { + navigator.addView(null, TestView.class); + fail("addView() accepted null view name"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewWithNullInstance() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView("test", (View) null); + fail("addView() accepted null view instance"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewWithNullClass() throws Exception { + Navigator navigator = new Navigator(new NullFragmentManager(), + new NullDisplay()); + + try { + navigator.addView("test", (Class<View>) null); + fail("addView() accepted null view class"); + } catch (IllegalArgumentException e) { + } + } + + public void testRemoveViewInstance() throws Exception { + View view = new TestView(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + navigator.removeView("test"); + + assertNull("View not removed", navigator.getView("test")); + } + + public void testRemoveViewInstanceNothingElse() throws Exception { + View view = new TestView(); + View view2 = new TestView2(); + + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", view); + navigator.addView("test2", view2); + navigator.removeView("test"); + + assertEquals("Removed extra views", view2, navigator.getView("test2")); + } + + public void testRemoveViewClass() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.removeView("test"); + + assertNull("View not removed", navigator.getView("test")); + } + + public void testRemoveViewClassNothingElse() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test", TestView.class); + navigator.addView("test2", TestView2.class); + navigator.removeView("test"); + + assertEquals("Removed extra views", TestView2.class, + navigator.getView("test2").getClass()); + } + + public void testGetViewNestedNames() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test/subview", TestView2.class); + navigator.addView("test", TestView.class); + + assertEquals("Incorrect view name found for subview string", + TestView2.class, navigator.getView("test/subview").getClass()); + assertEquals( + "Incorrect view name found for subview string with empty parameters", + TestView2.class, navigator.getView("test/subview/").getClass()); + assertEquals( + "Incorrect view name found for subview string with parameters", + TestView2.class, navigator.getView("test/subview/parameters") + .getClass()); + assertEquals("Incorrect view name found for top level view string", + TestView.class, navigator.getView("test").getClass()); + assertEquals( + "Incorrect view name found for top level view string with empty parameters", + TestView.class, navigator.getView("test/").getClass()); + assertEquals( + "Incorrect view name found for top level view string with parameters starting like subview name", + TestView.class, navigator.getView("test/subviewnothere") + .getClass()); + } + + public void testGetViewLongestPrefixOrder() throws Exception { + TestNavigator navigator = new TestNavigator(); + + navigator.addView("test/subview", TestView2.class); + navigator.addView("test", TestView.class); + + assertEquals("Incorrect view name found", TestView.class, navigator + .getView("test").getClass()); + + // other order + + TestNavigator navigator2 = new TestNavigator(); + + navigator2.addView("test", TestView.class); + navigator2.addView("test/subview", TestView2.class); + + assertEquals("Incorrect view name found", TestView.class, navigator2 + .getView("test").getClass()); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java new file mode 100644 index 0000000000..18ed52cc2a --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.Navigator.UriFragmentManager; +import com.vaadin.server.Page; +import com.vaadin.server.Page.FragmentChangedEvent; + +public class UriFragmentManagerTest extends TestCase { + + public void testGetSetFragment() { + Page page = EasyMock.createMock(Page.class); + UriFragmentManager manager = new UriFragmentManager(page, null); + + // prepare mock + EasyMock.expect(page.getFragment()).andReturn(""); + page.setFragment("test", false); + EasyMock.expect(page.getFragment()).andReturn("test"); + EasyMock.replay(page); + + // test manager using the mock + assertEquals("Incorrect fragment value", "", manager.getFragment()); + manager.setFragment("test"); + assertEquals("Incorrect fragment value", "test", manager.getFragment()); + } + + public void testListener() { + // create mocks + IMocksControl control = EasyMock.createControl(); + Navigator navigator = control.createMock(Navigator.class); + Page page = control.createMock(Page.class); + + UriFragmentManager manager = new UriFragmentManager(page, navigator); + + EasyMock.expect(page.getFragment()).andReturn("test"); + navigator.navigateTo("test"); + control.replay(); + + FragmentChangedEvent event = page.new FragmentChangedEvent(page, + "oldtest"); + manager.fragmentChanged(event); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java b/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java new file mode 100644 index 0000000000..e3320b8699 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/RangeValidatorTest.java @@ -0,0 +1,52 @@ +package com.vaadin.tests.server.validation; + +import junit.framework.TestCase; + +import com.vaadin.data.validator.IntegerRangeValidator; + +public class RangeValidatorTest extends TestCase { + + // This test uses IntegerRangeValidator for simplicity. + // IntegerRangeValidator contains no code so we really are testing + // RangeValidator + public void testMinValueNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMinValueIncluded(false); + assertFalse(iv.isValid(0)); + assertTrue(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMinMaxValuesInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + assertTrue(iv.isValid(0)); + assertTrue(iv.isValid(1)); + assertTrue(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMaxValueNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMaxValueIncluded(false); + assertTrue(iv.isValid(0)); + assertTrue(iv.isValid(9)); + assertFalse(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } + + public void testMinMaxValuesNonInclusive() { + IntegerRangeValidator iv = new IntegerRangeValidator("Failed", 0, 10); + iv.setMinValueIncluded(false); + iv.setMaxValueIncluded(false); + + assertFalse(iv.isValid(0)); + assertTrue(iv.isValid(1)); + assertTrue(iv.isValid(9)); + assertFalse(iv.isValid(10)); + assertFalse(iv.isValid(11)); + assertFalse(iv.isValid(-1)); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java b/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java new file mode 100644 index 0000000000..8f6928fc35 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/TestBeanValidation.java @@ -0,0 +1,57 @@ +package com.vaadin.tests.server.validation; + +import org.junit.Test; + +import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.data.validator.BeanValidator; +import com.vaadin.tests.data.bean.BeanToValidate; + +public class TestBeanValidation { + @Test(expected = InvalidValueException.class) + public void testBeanValidationNull() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate(null); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationStringTooShort() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate("aa"); + } + + @Test + public void testBeanValidationStringOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "firstname"); + validator.validate("aaa"); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationIntegerTooSmall() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, "age"); + validator.validate(17); + } + + @Test + public void testBeanValidationIntegerOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, "age"); + validator.validate(18); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationTooManyDigits() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "decimals"); + validator.validate("1234.567"); + } + + @Test + public void testBeanValidationDigitsOk() { + BeanValidator validator = new BeanValidator(BeanToValidate.class, + "decimals"); + validator.validate("123.45"); + } + +} diff --git a/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java b/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java new file mode 100644 index 0000000000..e37b97e02c --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/validation/TestReadOnlyValidation.java @@ -0,0 +1,17 @@ +package com.vaadin.tests.server.validation; + +import org.junit.Test; + +import com.vaadin.data.validator.IntegerValidator; +import com.vaadin.ui.TextField; + +public class TestReadOnlyValidation { + + @Test + public void testIntegerValidation() { + TextField field = new TextField(); + field.addValidator(new IntegerValidator("Enter a Valid Number")); + field.setValue(String.valueOf(10)); + field.validate(); + } +} diff --git a/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java b/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java new file mode 100644 index 0000000000..9e791500b0 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/GraphVizClassHierarchyCreator.java @@ -0,0 +1,149 @@ +package com.vaadin.tests.util; + +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.vaadin.tests.VaadinClasses; + +public class GraphVizClassHierarchyCreator { + + public static void main(String[] args) { + String gv = getGraphVizHierarchy((List) VaadinClasses.getComponents(), + "com.vaadin"); + System.out.println(gv); + } + + private static String getGraphVizHierarchy(List<Class> classes, + String packageToInclude) { + boolean includeInterfaces = false; + + StringBuilder header = new StringBuilder(); + header.append("digraph finite_state_machine {\n" + + " rankdir=BT;\n" + " dpi=\"150\";\n" + + " ratio=\"0.25\";\n"); + + StringBuilder sb = new StringBuilder(); + + Set<Class> classesAndParents = new HashSet<Class>(); + for (Class<?> cls : classes) { + addClassAndParents(classesAndParents, cls, packageToInclude); + } + + Set<Class> interfaces = new HashSet<Class>(); + for (Object cls : classesAndParents.toArray()) { + for (Class<?> c : ((Class) cls).getInterfaces()) { + addClassAndParentInterfaces(classesAndParents, c, + packageToInclude); + } + } + + for (Class<?> c : classesAndParents) { + appendClass(sb, c, c.getSuperclass(), packageToInclude, + includeInterfaces); + for (Class ci : c.getInterfaces()) { + appendClass(sb, c, ci, packageToInclude, includeInterfaces); + } + } + + header.append(" node [shape = ellipse, style=\"dotted\"] "); + for (Class c : classesAndParents) { + if (!c.isInterface() && Modifier.isAbstract(c.getModifiers())) { + header.append(c.getSimpleName() + " "); + } + } + if (includeInterfaces) { + System.out.print(" node [shape = ellipse, style=\"solid\"] "); + for (Class c : classesAndParents) { + if (c.isInterface()) { + header.append(c.getSimpleName() + " "); + } + } + header.append(";\n"); + } + header.append(";\n"); + header.append(" node [shape = rectangle, style=\"solid\"];\n"); + return header.toString() + sb.toString() + "}"; + } + + private static void addClassAndParents(Set<Class> classesAndParents, + Class<?> cls, String packageToInclude) { + + if (cls == null) { + return; + } + + if (classesAndParents.contains(cls)) { + return; + } + + if (!cls.getPackage().getName().startsWith(packageToInclude)) { + return; + } + + classesAndParents.add(cls); + addClassAndParents(classesAndParents, cls.getSuperclass(), + packageToInclude); + + } + + private static void addClassAndParentInterfaces( + Set<Class> classesAndParents, Class<?> cls, String packageToInclude) { + + if (cls == null) { + return; + } + + if (classesAndParents.contains(cls)) { + return; + } + + if (!cls.getPackage().getName().startsWith(packageToInclude)) { + return; + } + + classesAndParents.add(cls); + for (Class iClass : cls.getInterfaces()) { + addClassAndParentInterfaces(classesAndParents, iClass, + packageToInclude); + } + + } + + private static void appendClass(StringBuilder sb, Class<?> c, + Class<?> superClass, String packageToInclude, + boolean includeInterfaces) { + if (superClass == null) { + return; + } + if (!c.getPackage().getName().startsWith(packageToInclude)) { + return; + } + if (!superClass.getPackage().getName().startsWith(packageToInclude)) { + return; + } + if (!includeInterfaces && (c.isInterface() || superClass.isInterface())) { + return; + } + + sb.append(c.getSimpleName()).append(" -> ") + .append(superClass.getSimpleName()).append("\n"); + + } + + private static void addInterfaces(Set<Class> interfaces, Class<?> cls) { + if (interfaces.contains(cls)) { + return; + } + + if (cls.isInterface()) { + interfaces.add(cls); + } + + for (Class c : cls.getInterfaces()) { + addInterfaces(interfaces, c); + } + } + +} diff --git a/server/tests/src/com/vaadin/tests/util/TestUtil.java b/server/tests/src/com/vaadin/tests/util/TestUtil.java new file mode 100644 index 0000000000..e84f9dd8b9 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/TestUtil.java @@ -0,0 +1,43 @@ +package com.vaadin.tests.util; + +import java.util.Iterator; + +import junit.framework.Assert; + +public class TestUtil { + public static void assertArrays(Object[] actualObjects, + Object[] expectedObjects) { + Assert.assertEquals( + "Actual contains a different number of values than was expected", + expectedObjects.length, actualObjects.length); + + for (int i = 0; i < actualObjects.length; i++) { + Object actual = actualObjects[i]; + Object expected = expectedObjects[i]; + + Assert.assertEquals("Item[" + i + "] does not match", expected, + actual); + } + + } + + public static void assertIterableEquals(Iterable<?> iterable1, + Iterable<?> iterable2) { + Iterator<?> i1 = iterable1.iterator(); + Iterator<?> i2 = iterable2.iterator(); + + while (i1.hasNext()) { + Object o1 = i1.next(); + if (!i2.hasNext()) { + Assert.fail("The second iterable contains fewer items than the first. The object " + + o1 + " has no match in the second iterable."); + } + Object o2 = i2.next(); + Assert.assertEquals(o1, o2); + } + if (i2.hasNext()) { + Assert.fail("The second iterable contains more items than the first. The object " + + i2.next() + " has no match in the first iterable."); + } + } +} diff --git a/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java b/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java new file mode 100644 index 0000000000..d62f0df332 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/util/UniqueSerializableTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2011 Vaadin Ltd. + * + * 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.vaadin.tests.util; + +import java.io.Serializable; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.UniqueSerializable; + +public class UniqueSerializableTest extends TestCase implements Serializable { + + public void testUniqueness() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable o2 = new UniqueSerializable() { + }; + assertFalse(o1 == o2); + assertFalse(o1.equals(o2)); + } + + public void testSerialization() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable d1 = (UniqueSerializable) SerializationUtils + .deserialize(SerializationUtils.serialize(o1)); + assertTrue(d1.equals(o1)); + } + +} |