2 * Copyright (C) 2009, 2010, 2011 Openismus GmbH
4 * This file is part of gwt-glom
6 * gwt-glom is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
11 * gwt-glom is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with gwt-glom. If not, see <http://www.gnu.org/licenses/>.
20 package org.glom.web.server.libglom;
22 import static org.hamcrest.CoreMatchers.is;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertThat;
25 import static org.junit.Assert.assertTrue;
28 import java.util.ArrayList;
29 import java.util.List;
31 import org.apache.commons.lang3.StringUtils;
32 import org.glom.web.shared.libglom.Field;
33 import org.glom.web.shared.libglom.NumericFormat;
34 import org.glom.web.shared.libglom.Relationship;
35 import org.glom.web.shared.libglom.Report;
36 import org.glom.web.shared.libglom.layout.LayoutGroup;
37 import org.glom.web.shared.libglom.layout.LayoutItem;
38 import org.glom.web.shared.libglom.layout.LayoutItemField;
39 import org.glom.web.shared.libglom.layout.LayoutItemNotebook;
40 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
41 import org.glom.web.shared.libglom.layout.SortClause;
42 import org.glom.web.shared.libglom.layout.reportparts.LayoutItemGroupBy;
43 import org.junit.AfterClass;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
48 * Simple test to ensure that the generated bindings are working.
50 public class DocumentTest {
52 private static Document document;
53 private static String locale = ""; // This means the original locale.
54 static String testUriMusicCollection = "";
55 static String testUriFilmManager = "";
58 static public void setUp() {
59 URL url = DocumentTest.class.getResource("example_music_collection.glom");
60 assertTrue(url != null);
61 testUriMusicCollection = url.toString();
62 assertTrue(!StringUtils.isEmpty(testUriMusicCollection));
64 url = DocumentTest.class.getResource("example_film_manager.glom");
65 assertTrue(url != null);
66 testUriFilmManager = url.toString();
67 assertTrue(!StringUtils.isEmpty(testUriMusicCollection));
69 document = new Document();
70 document.setFileURI(testUriMusicCollection);
71 final boolean retval = document.load();
76 static public void tearDown() {
80 public void testDocumentInfo() {
81 assertThat(document.getDatabaseTitleOriginal(), is("Music Collection"));
82 assertThat(document.getDefaultTable(), is("artists"));
86 public void testReadTableNames() {
87 final List<String> tableNames = document.getTableNames();
88 assertEquals(4, tableNames.size());
90 String tables = tableNames.get(0);
91 for (int i = 1; i < tableNames.size(); i++) {
92 tables += ", " + tableNames.get(i);
94 assertThat(tables, is("artists, albums, songs, publishers"));
98 public void testReadTableFieldSizes() {
100 List<Field> fields = document.getTableFields("albums");
101 assertEquals(6, fields.size());
103 Field field = fields.get(0);
104 String titles = field.getTitleOrName(locale);
105 for (int i = 1; i < fields.size(); i++) {
106 field = fields.get(i);
107 titles += ", " + field.getTitleOrName(locale);
110 // TODO: The sequence is not important. It's only important that they are all there.
111 assertThat(titles, is("Publisher ID, Artist ID, Album ID, Name, Year, Comments"));
113 fields = document.getTableFields("artists");
114 assertEquals(4, fields.size());
116 field = fields.get(0);
117 titles = field.getTitleOrName(locale);
118 for (int i = 1; i < fields.size(); i++) {
119 field = fields.get(i);
120 titles += ", " + field.getTitleOrName(locale);
123 // TODO: The sequence is not important. It's only important that they are all there.
124 assertThat(titles, is("Artist ID, Name, Description, Comments"));
126 fields = document.getTableFields("publishers");
127 assertEquals(3, fields.size());
129 field = fields.get(0);
130 titles = field.getTitleOrName(locale);
131 for (int i = 1; i < fields.size(); i++) {
132 field = fields.get(i);
133 titles += ", " + field.getTitleOrName(locale);
136 // TODO: The sequence is not important. It's only important that they are all there.
137 assertThat(titles, is("Name, Publisher ID, Comments"));
139 fields = document.getTableFields("songs");
140 assertEquals(4, fields.size());
142 field = fields.get(0);
143 titles = field.getTitleOrName(locale);
144 for (int i = 1; i < fields.size(); i++) {
145 field = fields.get(i);
146 titles += ", " + field.getTitleOrName(locale);
149 // TODO: The sequence is not important. It's only important that they are all there.
150 assertThat(titles, is("Song ID, Album ID, Name, Comments"));
154 public void testReadLayoutListInfo() {
155 final String[] tables = { "albums", "artists", "publishers", "songs" };
156 final int[] sortClauseSizes = { 0, 1, 1, 1 };
157 final int[] layoutFieldSizes = { 7, 4, 3, 4 };
159 for (int i = 0; i < tables.length; i++) {
160 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", tables[i]);
161 assertTrue(!layoutList.isEmpty());
162 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
163 final List<LayoutItemField> layoutFields = new ArrayList<LayoutItemField>();
164 final SortClause sortClause = new SortClause(); // TODO: Why use a SortClause instead of a List?
165 final int numItems = safeLongToInt(layoutItems.size());
166 for (int j = 0; j < numItems; j++) {
167 final LayoutItem item = layoutItems.get(j);
169 if (item instanceof LayoutItemField) {
170 final LayoutItemField field = (LayoutItemField) item;
171 layoutFields.add(field);
172 final Field details = field.getFullFieldDetails();
173 if (details != null && details.getPrimaryKey()) {
174 sortClause.add(new SortClause.SortField(field, true)); // ascending
178 assertEquals(sortClauseSizes[i], sortClause.size());
179 assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
184 * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when
185 * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting.
188 public void testGetNumericFormat() {
189 final List<String> tableNames = document.getTableNames();
191 for (int i = 0; i < tableNames.size(); i++) {
192 final String table = tableNames.get(i);
193 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
194 assertTrue(!layoutList.isEmpty());
195 LayoutGroup firstgroup = layoutList.get(0);
196 assertTrue(firstgroup != null);
197 final List<LayoutItem> layoutItems = firstgroup.getItems();
198 final int numItems = safeLongToInt(layoutItems.size());
199 for (int j = 0; j < numItems; j++) {
200 final LayoutItem item = layoutItems.get(j);
201 assertTrue(item != null);
203 if (item instanceof LayoutItemField) {
204 final LayoutItemField itemField = (LayoutItemField) item;
205 // don't keep a reference to the FeildFormatting object
206 final NumericFormat numFormat = itemField.getFormattingUsed().getNumericFormat();
207 assertTrue(numFormat != null);
210 final boolean altForegroundColorForNegatives = numFormat.getUseAltForegroundColorForNegatives();
211 final String currencySymbol = numFormat.getCurrencySymbol();
212 final long decimalPlaces = numFormat.getDecimalPlaces();
213 final boolean decimalPlacesRestricted = numFormat.getDecimalPlacesRestricted();
214 final boolean useThousandsSepator = numFormat.getUseThousandsSeparator();
215 final String alternativeColorForNegatives = NumericFormat.getAlternativeColorForNegatives();
216 final long defaultPrecision = NumericFormat.getDefaultPrecision();
218 // Simulate a garbage collection
220 System.runFinalization();
222 // re-get the values and test
223 assertEquals(altForegroundColorForNegatives, numFormat.getUseAltForegroundColorForNegatives());
224 assertEquals(currencySymbol, numFormat.getCurrencySymbol());
225 assertEquals(decimalPlaces, numFormat.getDecimalPlaces());
226 assertEquals(decimalPlacesRestricted, numFormat.getDecimalPlacesRestricted());
227 assertEquals(useThousandsSepator, numFormat.getUseThousandsSeparator());
228 assertEquals(alternativeColorForNegatives, NumericFormat.getAlternativeColorForNegatives());
229 assertEquals(defaultPrecision, NumericFormat.getDefaultPrecision());
237 * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship.
240 public void testUsesRelationshipMethods() {
241 final String table = "albums";
242 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
243 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
245 String names = null, hasRelationshipNames = null, tablesUsed = null;
246 final LayoutItem firstItem = layoutItems.get(0);
248 if (firstItem instanceof LayoutItemField) {
249 final LayoutItemField firstItemField = (LayoutItemField) firstItem;
250 names = firstItemField.getName();
251 hasRelationshipNames = "" + firstItemField.getHasRelationshipName();
252 tablesUsed = firstItemField.getTableUsed(table);
254 final int numItems = safeLongToInt(layoutItems.size());
255 for (int j = 1; j < numItems; j++) {
256 final LayoutItem item = layoutItems.get(j);
258 if (item instanceof LayoutItemField) {
259 final LayoutItemField itemField = (LayoutItemField) item;
260 names += ", " + itemField.getName();
261 hasRelationshipNames += ", " + itemField.getHasRelationshipName();
262 tablesUsed += ", " + itemField.getTableUsed(table);
265 assertEquals("name, year, artist_id, name, publisher_id, name, comments", names);
266 assertEquals("false, false, false, true, false, true, false", hasRelationshipNames);
267 assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed);
271 public void testGetSuitableTableToViewDetails() {
273 // Create a new document for the film manager
274 final Document filmManagerDocument = new Document();
275 filmManagerDocument.setFileURI(testUriFilmManager);
276 final boolean retval = filmManagerDocument.load();
279 // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details
280 // view layout. I've included safety checks that will fail if the layout changes.
281 final List<LayoutGroup> detailsLayout = filmManagerDocument.getDataLayoutGroups("details", "scenes");
282 assertEquals(3, detailsLayout.size());
284 LayoutGroup layoutGroup = detailsLayout.get(1);
285 assertEquals("details", layoutGroup.getName());
287 layoutGroup = detailsLayout.get(2);
288 assertEquals("details_lower", layoutGroup.getName());
290 List<LayoutItem> items = layoutGroup.getItems();
291 assertEquals(2, items.size());
293 final LayoutItem notebookItem = items.get(0);
294 assertEquals("notebook", notebookItem.getName());
295 assertTrue(notebookItem instanceof LayoutItemNotebook);
296 final LayoutItemNotebook notebook = (LayoutItemNotebook) notebookItem;
297 items = notebook.getItems();
298 assertEquals(7, items.size());
299 final LayoutItem portalItem = items.get(0);
300 assertTrue(portalItem instanceof LayoutItemPortal);
301 final LayoutItemPortal portal = (LayoutItemPortal) portalItem;
302 assertTrue(portal != null);
304 assertEquals(portal.getRelationshipNameUsed(), "scene_cast");
306 // call getSuitableTableToCiewDetails
307 final Document.TableToViewDetails viewDetails = filmManagerDocument.getPortalSuitableTableToViewDetails(portal);
308 assertTrue(viewDetails != null);
310 // Simulate a garbage collection
312 System.runFinalization();
314 // Check if things are working like we expect
315 assertEquals("characters", viewDetails.tableName);
316 assertTrue(viewDetails.usesRelationship != null);
317 final Relationship relationship = viewDetails.usesRelationship.getRelationship();
318 assertTrue(relationship != null);
319 assertEquals("cast", relationship.getName());
320 assertTrue(viewDetails.usesRelationship.getRelatedRelationship() == null);
325 public void testReadReportNames() {
326 final List<String> reportNames = document.getReportNames("albums");
327 assertEquals(1, reportNames.size()); // TODO: Test something with more reports.
329 String reports = reportNames.get(0);
330 for (int i = 1; i < reportNames.size(); i++) {
331 reports += ", " + reportNames.get(i);
333 assertThat(reports, is("albums_by_artist"));
337 public void testReadReportStructure() {
338 final Report report = document.getReport("albums", "albums_by_artist");
339 assertTrue(report != null);
340 final LayoutGroup layoutGroup = report.getLayoutGroup();
341 assertTrue(layoutGroup != null);
342 final List<LayoutItem> layoutItems = layoutGroup.getItems();
343 final int numItems = safeLongToInt(layoutItems.size());
344 assertEquals(1, numItems);
346 LayoutItem layoutItem = layoutItems.get(0);
347 assertTrue(layoutItem != null);
348 final LayoutGroup asGroup = (LayoutGroup) layoutItem;
349 assertTrue(asGroup != null);
350 final LayoutItemGroupBy groupby = (LayoutItemGroupBy) layoutItem;
351 assertTrue(groupby != null);
353 assertTrue(groupby.getHasFieldGroupBy());
354 final LayoutItemField fieldGroupBy = groupby.getFieldGroupBy();
355 assertTrue(fieldGroupBy != null);
356 assertThat(fieldGroupBy.getName(), is("artist_id"));
358 final LayoutGroup groupSecondaries = groupby.getSecondaryFields();
359 assertTrue(groupSecondaries != null);
361 final List<LayoutItem> innerItems = groupby.getItems();
362 assertTrue(innerItems != null);
363 final int numInnerItems = safeLongToInt(innerItems.size());
364 assertEquals(2, numInnerItems);
366 layoutItem = innerItems.get(0);
367 assertTrue(layoutItem != null);
368 assertTrue(layoutItem instanceof LayoutItemField);
369 LayoutItemField field = (LayoutItemField) layoutItem;
370 assertTrue(field != null);
371 assertThat(field.getName(), is("name"));
372 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_TEXT));
374 layoutItem = innerItems.get(1);
375 assertTrue(layoutItem != null);
376 assertTrue(layoutItem instanceof LayoutItemField);
377 field = (LayoutItemField) layoutItem;
378 assertTrue(field != null);
379 assertThat(field.getName(), is("year"));
380 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_NUMERIC));
383 // Test thread class that runs all the tests.
384 private class TestThread implements Runnable {
388 for (int i = 0; i < 20; i++) {
390 testGetNumericFormat();
391 testGetSuitableTableToViewDetails();
392 testReadLayoutListInfo();
393 testReadTableFieldSizes();
394 testReadTableNames();
395 testUsesRelationshipMethods();
401 * Tests threaded access.
404 public void testThreadedAccess() throws InterruptedException {
405 // create the threads
406 final Thread thread1 = new Thread(new TestThread());
407 final Thread thread2 = new Thread(new TestThread());
408 final Thread thread3 = new Thread(new TestThread());
409 final Thread thread4 = new Thread(new TestThread());
417 // wait for the treads to finish
420 } catch (final InterruptedException e) {
421 System.out.println("Thread 1 had a problem finishing. " + e);
427 } catch (final InterruptedException e) {
428 System.out.println("Thread 2 had a problem finishing. " + e);
434 } catch (final InterruptedException e) {
435 System.out.println("Thread 3 had a problem finishing. " + e);
441 } catch (final InterruptedException e) {
442 System.out.println("Thread 4 had a problem finishing. " + e);
448 * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
450 * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
452 private static int safeLongToInt(final long l) {
453 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
454 throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");