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.assertFalse;
25 import static org.junit.Assert.assertThat;
26 import static org.junit.Assert.assertTrue;
29 import java.util.ArrayList;
30 import java.util.List;
33 import org.apache.commons.lang3.StringUtils;
34 import org.glom.web.shared.DataItem;
35 import org.glom.web.shared.libglom.Field;
36 import org.glom.web.shared.libglom.NumericFormat;
37 import org.glom.web.shared.libglom.Relationship;
38 import org.glom.web.shared.libglom.Report;
39 import org.glom.web.shared.libglom.Translatable;
40 import org.glom.web.shared.libglom.layout.LayoutGroup;
41 import org.glom.web.shared.libglom.layout.LayoutItem;
42 import org.glom.web.shared.libglom.layout.LayoutItemField;
43 import org.glom.web.shared.libglom.layout.LayoutItemNotebook;
44 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
45 import org.glom.web.shared.libglom.layout.SortClause;
46 import org.glom.web.shared.libglom.layout.TableToViewDetails;
47 import org.glom.web.shared.libglom.layout.reportparts.LayoutItemGroupBy;
48 import org.junit.AfterClass;
49 import org.junit.BeforeClass;
50 import org.junit.Test;
53 * Simple test to ensure that the generated bindings are working.
55 public class DocumentTest {
57 private static Document document;
58 private static String defaultLocale = "";
59 private static String germanLocale = "de";
60 static String testUriMusicCollection = "";
61 static String testUriFilmManager = "";
64 static public void setUp() {
65 URL url = DocumentTest.class.getResource("example_music_collection.glom");
66 assertTrue(url != null);
67 testUriMusicCollection = url.toString();
68 assertTrue(!StringUtils.isEmpty(testUriMusicCollection));
70 url = DocumentTest.class.getResource("example_film_manager.glom");
71 assertTrue(url != null);
72 testUriFilmManager = url.toString();
73 assertTrue(!StringUtils.isEmpty(testUriFilmManager));
75 document = new Document();
76 document.setFileURI(testUriMusicCollection);
77 final boolean retval = document.load();
82 static public void tearDown() {
86 public void testDocumentInfo() {
87 assertThat(document.getDatabaseTitleOriginal(), is("Music Collection"));
88 assertThat(document.getDatabaseTitle(defaultLocale), is("Music Collection"));
89 assertThat(document.getDatabaseTitle(germanLocale), is("Musiksammlung"));
90 assertThat(document.getDefaultTable(), is("artists"));
94 public void testLocales() {
95 final List<String> localeIDs = document.getTranslationAvailableLocales();
96 assertEquals(8, localeIDs.size());
98 String tables = localeIDs.get(0);
99 for (int i = 1; i < localeIDs.size(); i++) {
100 tables += ", " + localeIDs.get(i);
102 assertThat(tables, is("cs, de, es, fr, gl, pt_BR, sl, en"));
106 public void testReadTableNames() {
107 final List<String> tableNames = document.getTableNames();
108 assertEquals(4, tableNames.size());
110 String tables = tableNames.get(0);
111 for (int i = 1; i < tableNames.size(); i++) {
112 tables += ", " + tableNames.get(i);
114 assertThat(tables, is("artists, albums, songs, publishers"));
117 String getTitles(final List<Field> list, final String locale) {
119 for (int i = 0; i < list.size(); i++) {
120 final Translatable item = list.get(i);
126 result += item.getTitleOrName(locale);
133 public void testReadTableFieldSizes() {
135 List<Field> fields = document.getTableFields("albums");
136 assertEquals(6, fields.size());
138 // TODO: The sequence is not important. It's only important that they are all there.
139 assertThat(getTitles(fields, defaultLocale), is("Publisher ID, Artist ID, Album ID, Name, Year, Comments"));
140 assertThat(getTitles(fields, germanLocale), is("Herausgeber-Kennung, Künstlerkennung, Albenkennung, Name, Jahr, Kommentare"));
142 fields = document.getTableFields("artists");
143 assertEquals(4, fields.size());
145 // TODO: The sequence is not important. It's only important that they are all there.
146 assertThat(getTitles(fields, defaultLocale), is("Artist ID, Name, Description, Comments"));
147 assertThat(getTitles(fields, germanLocale), is("Künstlerkennung, Name, Beschreibung, Kommentare"));
149 fields = document.getTableFields("publishers");
150 assertEquals(3, fields.size());
152 // TODO: The sequence is not important. It's only important that they are all there.
153 assertThat(getTitles(fields, defaultLocale), is("Name, Publisher ID, Comments"));
154 assertThat(getTitles(fields, germanLocale), is("Name, Herausgeber-Kennung, Kommentare"));
157 fields = document.getTableFields("songs");
158 assertEquals(4, fields.size());
160 // TODO: The sequence is not important. It's only important that they are all there.
161 assertThat(getTitles(fields, defaultLocale), is("Song ID, Album ID, Name, Comments"));
162 assertThat(getTitles(fields, germanLocale), is("Lied-Kennung, Albenkennung, Name, Kommentare"));
166 public void testReadTableExampleRows() {
167 final List<Map<String, DataItem>> exampleRows = document.getExampleRows("albums");
168 assertFalse(exampleRows.isEmpty());
170 final Map<String, DataItem> row = exampleRows.get(0);
171 assertFalse(row.isEmpty());
175 public void testReadLayoutListInfo() {
176 final String[] tables = { "albums", "artists", "publishers", "songs" };
177 final int[] sortClauseSizes = { 0, 1, 1, 1 };
178 final int[] layoutFieldSizes = { 7, 4, 3, 4 };
180 for (int i = 0; i < tables.length; i++) {
181 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", tables[i]);
182 assertTrue(!layoutList.isEmpty());
183 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
184 final List<LayoutItemField> layoutFields = new ArrayList<LayoutItemField>();
185 final SortClause sortClause = new SortClause(); // TODO: Why use a SortClause instead of a List?
186 final int numItems = safeLongToInt(layoutItems.size());
187 for (int j = 0; j < numItems; j++) {
188 final LayoutItem item = layoutItems.get(j);
190 if (item instanceof LayoutItemField) {
191 final LayoutItemField field = (LayoutItemField) item;
192 layoutFields.add(field);
193 final Field details = field.getFullFieldDetails();
194 if (details != null && details.getPrimaryKey()) {
195 sortClause.add(new SortClause.SortField(field, true)); // ascending
199 assertEquals(sortClauseSizes[i], sortClause.size());
200 assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
205 * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when
206 * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting.
209 public void testGetNumericFormat() {
210 final List<String> tableNames = document.getTableNames();
212 for (int i = 0; i < tableNames.size(); i++) {
213 final String table = tableNames.get(i);
214 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
215 assertTrue(!layoutList.isEmpty());
216 final LayoutGroup firstgroup = layoutList.get(0);
217 assertTrue(firstgroup != null);
218 final List<LayoutItem> layoutItems = firstgroup.getItems();
219 final int numItems = safeLongToInt(layoutItems.size());
220 for (int j = 0; j < numItems; j++) {
221 final LayoutItem item = layoutItems.get(j);
222 assertTrue(item != null);
224 if (item instanceof LayoutItemField) {
225 final LayoutItemField itemField = (LayoutItemField) item;
226 // don't keep a reference to the FeildFormatting object
227 final NumericFormat numFormat = itemField.getFormattingUsed().getNumericFormat();
228 assertTrue(numFormat != null);
231 final boolean altForegroundColorForNegatives = numFormat.getUseAltForegroundColorForNegatives();
232 final String currencySymbol = numFormat.getCurrencySymbol();
233 final long decimalPlaces = numFormat.getDecimalPlaces();
234 final boolean decimalPlacesRestricted = numFormat.getDecimalPlacesRestricted();
235 final boolean useThousandsSepator = numFormat.getUseThousandsSeparator();
236 final String alternativeColorForNegatives = NumericFormat
237 .getAlternativeColorForNegativesAsHTMLColor();
238 final long defaultPrecision = NumericFormat.getDefaultPrecision();
240 // Simulate a garbage collection
242 System.runFinalization();
244 // re-get the values and test
245 assertEquals(altForegroundColorForNegatives, numFormat.getUseAltForegroundColorForNegatives());
246 assertEquals(currencySymbol, numFormat.getCurrencySymbol());
247 assertEquals(decimalPlaces, numFormat.getDecimalPlaces());
248 assertEquals(decimalPlacesRestricted, numFormat.getDecimalPlacesRestricted());
249 assertEquals(useThousandsSepator, numFormat.getUseThousandsSeparator());
250 assertEquals(alternativeColorForNegatives,
251 NumericFormat.getAlternativeColorForNegativesAsHTMLColor());
252 assertEquals(defaultPrecision, NumericFormat.getDefaultPrecision());
260 * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship.
263 public void testUsesRelationshipMethods() {
264 final String table = "albums";
265 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
266 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
268 String names = null, hasRelationshipNames = null, tablesUsed = null;
269 final LayoutItem firstItem = layoutItems.get(0);
271 if (firstItem instanceof LayoutItemField) {
272 final LayoutItemField firstItemField = (LayoutItemField) firstItem;
273 names = firstItemField.getName();
274 hasRelationshipNames = "" + firstItemField.getHasRelationshipName();
275 tablesUsed = firstItemField.getTableUsed(table);
277 final int numItems = safeLongToInt(layoutItems.size());
278 for (int j = 1; j < numItems; j++) {
279 final LayoutItem item = layoutItems.get(j);
281 if (item instanceof LayoutItemField) {
282 final LayoutItemField itemField = (LayoutItemField) item;
283 names += ", " + itemField.getName();
284 hasRelationshipNames += ", " + itemField.getHasRelationshipName();
285 tablesUsed += ", " + itemField.getTableUsed(table);
288 assertEquals("name, year, artist_id, name, publisher_id, name, comments", names);
289 assertEquals("false, false, false, true, false, true, false", hasRelationshipNames);
290 assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed);
294 public void testGetSuitableTableToViewDetails() {
296 // Create a new document for the film manager
297 final Document filmManagerDocument = new Document();
298 filmManagerDocument.setFileURI(testUriFilmManager);
299 final boolean retval = filmManagerDocument.load();
302 // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details
303 // view layout. I've included safety checks that will fail if the layout changes.
304 final List<LayoutGroup> detailsLayout = filmManagerDocument.getDataLayoutGroups("details", "scenes");
305 assertEquals(3, detailsLayout.size());
307 LayoutGroup layoutGroup = detailsLayout.get(1);
308 assertEquals("details", layoutGroup.getName());
309 assertEquals("Details", layoutGroup.getTitle(defaultLocale));
310 assertEquals("Details", layoutGroup.getTitle(germanLocale));
312 layoutGroup = detailsLayout.get(2);
313 assertEquals("details_lower", layoutGroup.getName());
315 List<LayoutItem> items = layoutGroup.getItems();
316 assertEquals(2, items.size());
318 final LayoutItem notebookItem = items.get(0);
319 assertEquals("notebook", notebookItem.getName());
320 assertTrue(notebookItem instanceof LayoutItemNotebook);
321 final LayoutItemNotebook notebook = (LayoutItemNotebook) notebookItem;
322 items = notebook.getItems();
323 assertEquals(7, items.size());
324 final LayoutItem portalItem = items.get(0);
325 assertTrue(portalItem instanceof LayoutItemPortal);
326 final LayoutItemPortal portal = (LayoutItemPortal) portalItem;
327 assertTrue(portal != null);
329 assertEquals("scene_cast", portal.getRelationshipNameUsed());
330 assertEquals("Cast", portal.getTitle(defaultLocale));
331 assertEquals("Szene Besetzung", portal.getTitle(germanLocale));
333 // call getSuitableTableToCiewDetails
334 final TableToViewDetails viewDetails = filmManagerDocument.getPortalSuitableTableToViewDetails(portal);
335 assertTrue(viewDetails != null);
337 // Simulate a garbage collection
339 System.runFinalization();
341 // Check if things are working like we expect
342 assertEquals("characters", viewDetails.tableName);
343 assertTrue(viewDetails.usesRelationship != null);
344 final Relationship relationship = viewDetails.usesRelationship.getRelationship();
345 assertTrue(relationship != null);
346 assertEquals("cast", relationship.getName());
347 assertTrue(viewDetails.usesRelationship.getRelatedRelationship() == null);
352 public void testReadReportNames() {
353 final List<String> reportNames = document.getReportNames("albums");
354 assertEquals(1, reportNames.size()); // TODO: Test something with more reports.
356 String reports = reportNames.get(0);
357 for (int i = 1; i < reportNames.size(); i++) {
358 reports += ", " + reportNames.get(i);
360 assertThat(reports, is("albums_by_artist"));
364 public void testReadReportStructure() {
365 final Report report = document.getReport("albums", "albums_by_artist");
366 assertTrue(report != null);
368 assertThat(report.getTitle(defaultLocale), is("Albums By Artist"));
369 assertThat(report.getTitle(germanLocale), is("Alben nach Künstler"));
371 final LayoutGroup layoutGroup = report.getLayoutGroup();
372 assertTrue(layoutGroup != null);
373 final List<LayoutItem> layoutItems = layoutGroup.getItems();
374 final int numItems = safeLongToInt(layoutItems.size());
375 assertEquals(1, numItems);
377 LayoutItem layoutItem = layoutItems.get(0);
378 assertTrue(layoutItem != null);
379 final LayoutGroup asGroup = (LayoutGroup) layoutItem;
380 assertTrue(asGroup != null);
381 final LayoutItemGroupBy groupby = (LayoutItemGroupBy) layoutItem;
382 assertTrue(groupby != null);
384 assertTrue(groupby.getHasFieldGroupBy());
385 final LayoutItemField fieldGroupBy = groupby.getFieldGroupBy();
386 assertTrue(fieldGroupBy != null);
387 assertThat(fieldGroupBy.getName(), is("artist_id"));
389 final LayoutGroup groupSecondaries = groupby.getSecondaryFields();
390 assertTrue(groupSecondaries != null);
392 final List<LayoutItem> innerItems = groupby.getItems();
393 assertTrue(innerItems != null);
394 final int numInnerItems = safeLongToInt(innerItems.size());
395 assertEquals(2, numInnerItems);
397 layoutItem = innerItems.get(0);
398 assertTrue(layoutItem != null);
399 assertTrue(layoutItem instanceof LayoutItemField);
400 LayoutItemField field = (LayoutItemField) layoutItem;
401 assertTrue(field != null);
402 assertThat(field.getName(), is("name"));
403 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_TEXT));
405 layoutItem = innerItems.get(1);
406 assertTrue(layoutItem != null);
407 assertTrue(layoutItem instanceof LayoutItemField);
408 field = (LayoutItemField) layoutItem;
409 assertTrue(field != null);
410 assertThat(field.getName(), is("year"));
411 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_NUMERIC));
414 // Test thread class that runs all the tests.
415 private class TestThread implements Runnable {
419 for (int i = 0; i < 20; i++) {
421 testGetNumericFormat();
422 testGetSuitableTableToViewDetails();
423 testReadLayoutListInfo();
424 testReadTableFieldSizes();
425 testReadTableNames();
426 testUsesRelationshipMethods();
432 * Tests threaded access.
435 public void testThreadedAccess() throws InterruptedException {
436 // create the threads
437 final Thread thread1 = new Thread(new TestThread());
438 final Thread thread2 = new Thread(new TestThread());
439 final Thread thread3 = new Thread(new TestThread());
440 final Thread thread4 = new Thread(new TestThread());
448 // wait for the treads to finish
451 } catch (final InterruptedException e) {
452 System.out.println("Thread 1 had a problem finishing. " + e);
458 } catch (final InterruptedException e) {
459 System.out.println("Thread 2 had a problem finishing. " + e);
465 } catch (final InterruptedException e) {
466 System.out.println("Thread 3 had a problem finishing. " + e);
472 } catch (final InterruptedException e) {
473 System.out.println("Thread 4 had a problem finishing. " + e);
479 * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
481 * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
483 private static int safeLongToInt(final long l) {
484 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
485 throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");