2 * Copyright (C) 2009, 2010, 2011 Openismus GmbH
4 * This file is part of Java-libglom.
6 * Java-libglom 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 * Java-libglom 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 Java-libglom. 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;
27 import java.util.ArrayList;
28 import java.util.List;
30 import org.glom.web.shared.libglom.Field;
31 import org.glom.web.shared.libglom.NumericFormat;
32 import org.glom.web.shared.libglom.Relationship;
33 import org.glom.web.shared.libglom.Report;
34 import org.glom.web.shared.libglom.layout.LayoutGroup;
35 import org.glom.web.shared.libglom.layout.LayoutItem;
36 import org.glom.web.shared.libglom.layout.LayoutItemField;
37 import org.glom.web.shared.libglom.layout.LayoutItemNotebook;
38 import org.glom.web.shared.libglom.layout.LayoutItemPortal;
39 import org.glom.web.shared.libglom.layout.SortClause;
40 import org.glom.web.shared.libglom.layout.reportparts.LayoutItemGroupBy;
41 import org.junit.AfterClass;
42 import org.junit.BeforeClass;
43 import org.junit.Test;
46 * Simple test to ensure that the generated bindings are working.
48 public class DocumentTest {
50 private static Document document;
51 private static String locale = ""; // This means the original locale.
52 final static String testUriMusicCollection = "src/test/java/org/glom/web/shared/libglom/example_music_collection.glom";
53 final static String testUriFilmManager = "src/test/java/org/glom/web/shared/libglom/example_film_manager.glom";
56 static public void setUp() {
57 document = new Document();
58 document.setFileURI(testUriMusicCollection);
60 final boolean retval = document.load(error);
62 assertEquals(error, 0);
66 static public void tearDown() {
70 public void testDocumentInfo() {
71 assertThat(document.getDatabaseTitleOriginal(), is("Music Collection"));
72 assertThat(document.getDefaultTable(), is("artists"));
76 public void testReadTableNames() {
77 final List<String> tableNames = document.getTableNames();
78 assertEquals(4, tableNames.size());
80 String tables = tableNames.get(0);
81 for (int i = 1; i < tableNames.size(); i++) {
82 tables += ", " + tableNames.get(i);
84 assertThat(tables, is("artists, albums, songs, publishers"));
88 public void testReadTableFieldSizes() {
90 List<Field> fields = document.getTableFields("albums");
91 assertEquals(6, fields.size());
93 Field field = fields.get(0);
94 String titles = field.getTitleOrName(locale);
95 for (int i = 1; i < fields.size(); i++) {
96 field = fields.get(i);
97 titles += ", " + field.getTitleOrName(locale);
100 // TODO: The sequence is not important. It's only important that they are all there.
101 assertThat(titles, is("Publisher ID, Artist ID, Album ID, Name, Year, Comments"));
103 fields = document.getTableFields("artists");
104 assertEquals(4, fields.size());
106 field = fields.get(0);
107 titles = field.getTitleOrName(locale);
108 for (int i = 1; i < fields.size(); i++) {
109 field = fields.get(i);
110 titles += ", " + field.getTitleOrName(locale);
113 // TODO: The sequence is not important. It's only important that they are all there.
114 assertThat(titles, is("Artist ID, Name, Description, Comments"));
116 fields = document.getTableFields("publishers");
117 assertEquals(3, fields.size());
119 field = fields.get(0);
120 titles = field.getTitleOrName(locale);
121 for (int i = 1; i < fields.size(); i++) {
122 field = fields.get(i);
123 titles += ", " + field.getTitleOrName(locale);
126 // TODO: The sequence is not important. It's only important that they are all there.
127 assertThat(titles, is("Name, Publisher ID, Comments"));
129 fields = document.getTableFields("songs");
130 assertEquals(4, fields.size());
132 field = fields.get(0);
133 titles = field.getTitleOrName(locale);
134 for (int i = 1; i < fields.size(); i++) {
135 field = fields.get(i);
136 titles += ", " + field.getTitleOrName(locale);
139 // TODO: The sequence is not important. It's only important that they are all there.
140 assertThat(titles, is("Song ID, Album ID, Name, Comments"));
144 public void testReadLayoutListInfo() {
145 final String[] tables = { "albums", "artists", "publishers", "songs" };
146 final int[] sortClauseSizes = { 0, 1, 1, 1 };
147 final int[] layoutFieldSizes = { 7, 4, 3, 4 };
149 for (int i = 0; i < tables.length; i++) {
150 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", tables[i]);
151 assertTrue(!layoutList.isEmpty());
152 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
153 final List<LayoutItemField> layoutFields = new ArrayList<LayoutItemField>();
154 final SortClause sortClause = new SortClause(); // TODO: Why use a SortClause instead of a List?
155 final int numItems = safeLongToInt(layoutItems.size());
156 for (int j = 0; j < numItems; j++) {
157 final LayoutItem item = layoutItems.get(j);
159 if (item instanceof LayoutItemField) {
160 final LayoutItemField field = (LayoutItemField) item;
161 layoutFields.add(field);
162 final Field details = field.getFullFieldDetails();
163 if (details != null && details.getPrimaryKey()) {
164 sortClause.add(new SortClause.SortField(field, true)); // ascending
168 assertEquals(sortClauseSizes[i], sortClause.size());
169 assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
174 * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when
175 * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting.
178 public void testGetNumericFormat() {
179 final List<String> tableNames = document.getTableNames();
181 for (int i = 0; i < tableNames.size(); i++) {
182 final String table = tableNames.get(i);
183 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
184 assertTrue(!layoutList.isEmpty());
185 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
186 final int numItems = safeLongToInt(layoutItems.size());
187 for (int j = 0; j < numItems; j++) {
188 final LayoutItem item = layoutItems.get(j);
189 assertTrue(item != null);
191 if (item instanceof LayoutItemField) {
192 final LayoutItemField itemField = (LayoutItemField) item;
193 // don't keep a reference to the FeildFormatting object
194 final NumericFormat numFormat = itemField.getFormattingUsed().getNumericFormat();
195 assertTrue(numFormat != null);
198 final boolean altForegroundColorForNegatives = numFormat.getUseAltForegroundColorForNegatives();
199 final String currencySymbol = numFormat.getCurrencySymbol();
200 final long decimalPlaces = numFormat.getDecimalPlaces();
201 final boolean decimalPlacesRestricted = numFormat.getDecimalPlacesRestricted();
202 final boolean useThousandsSepator = numFormat.getUseThousandsSeparator();
203 final String alternativeColorForNegatives = NumericFormat.getAlternativeColorForNegatives();
204 final long defaultPrecision = NumericFormat.getDefaultPrecision();
206 // Simulate a garbage collection
208 System.runFinalization();
210 // re-get the values and test
211 assertEquals(altForegroundColorForNegatives, numFormat.getUseAltForegroundColorForNegatives());
212 assertEquals(currencySymbol, numFormat.getCurrencySymbol());
213 assertEquals(decimalPlaces, numFormat.getDecimalPlaces());
214 assertEquals(decimalPlacesRestricted, numFormat.getDecimalPlacesRestricted());
215 assertEquals(useThousandsSepator, numFormat.getUseThousandsSeparator());
216 assertEquals(alternativeColorForNegatives, NumericFormat.getAlternativeColorForNegatives());
217 assertEquals(defaultPrecision, NumericFormat.getDefaultPrecision());
225 * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship.
228 public void testUsesRelationshipMethods() {
229 final String table = "albums";
230 final List<LayoutGroup> layoutList = document.getDataLayoutGroups("list", table);
231 final List<LayoutItem> layoutItems = layoutList.get(0).getItems();
233 String names = null, hasRelationshipNames = null, tablesUsed = null;
234 final LayoutItem firstItem = layoutItems.get(0);
236 if (firstItem instanceof LayoutItemField) {
237 final LayoutItemField firstItemField = (LayoutItemField) firstItem;
238 names = firstItemField.getName();
239 hasRelationshipNames = "" + firstItemField.getHasRelationshipName();
240 tablesUsed = firstItemField.getTableUsed(table);
242 final int numItems = safeLongToInt(layoutItems.size());
243 for (int j = 1; j < numItems; j++) {
244 final LayoutItem item = layoutItems.get(j);
246 if (item instanceof LayoutItemField) {
247 final LayoutItemField itemField = (LayoutItemField) item;
248 names += ", " + itemField.getName();
249 hasRelationshipNames += ", " + itemField.getHasRelationshipName();
250 tablesUsed += ", " + itemField.getTableUsed(table);
253 assertEquals("name, year, artist_id, name, publisher_id, name, comments", names);
254 assertEquals("false, false, false, true, false, true, false", hasRelationshipNames);
255 assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed);
259 public void testGetSuitableTableToViewDetails() {
261 // Create a new document for the film manager
262 final Document filmManagerDocument = new Document();
263 filmManagerDocument.setFileURI(testUriFilmManager);
265 final boolean retval = filmManagerDocument.load(error);
267 assertEquals(error, 0);
269 // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details
270 // view layout. I've included safety checks that will fail if the layout changes.
271 final List<LayoutGroup> detailsLayout = filmManagerDocument.getDataLayoutGroups("details", "scenes");
272 assertEquals(3, detailsLayout.size());
274 LayoutGroup layoutGroup = detailsLayout.get(1);
275 assertEquals("details", layoutGroup.getName());
277 layoutGroup = detailsLayout.get(2);
278 assertEquals("details_lower", layoutGroup.getName());
280 List<LayoutItem> items = layoutGroup.getItems();
281 assertEquals(2, items.size());
283 final LayoutItem notebookItem = items.get(0);
284 assertEquals("notebook", notebookItem.getName());
285 assertTrue(notebookItem instanceof LayoutItemNotebook);
286 final LayoutItemNotebook notebook = (LayoutItemNotebook) notebookItem;
287 items = notebook.getItems();
288 assertEquals(7, items.size());
289 final LayoutItem portalItem = items.get(0);
290 assertTrue(portalItem instanceof LayoutItemPortal);
291 final LayoutItemPortal portal = (LayoutItemPortal) portalItem;
292 assertTrue(portal != null);
294 assertEquals(portal.getRelationshipNameUsed(), "scene_cast");
296 // call getSuitableTableToCiewDetails
297 final LayoutItemPortal.TableToViewDetails viewDetails = portal
298 .getSuitableTableToViewDetails(filmManagerDocument);
299 assertTrue(viewDetails != null);
301 // Simulate a garbage collection
303 System.runFinalization();
305 // Check if things are working like we expect
306 assertEquals("characters", viewDetails.tableName);
307 assertTrue(viewDetails.usesRelationship != null);
308 final Relationship relationship = viewDetails.usesRelationship.getRelationship();
309 assertTrue(relationship != null);
310 assertEquals("cast", relationship.getName());
311 assertTrue(viewDetails.usesRelationship.getRelatedRelationship() == null);
316 public void testReadReportNames() {
317 final List<String> reportNames = document.getReportNames("albums");
318 assertEquals(1, reportNames.size()); // TODO: Test something with more reports.
320 String reports = reportNames.get(0);
321 for (int i = 1; i < reportNames.size(); i++) {
322 reports += ", " + reportNames.get(i);
324 assertThat(reports, is("albums_by_artist"));
328 public void testReadReportStructure() {
329 final Report report = document.getReport("albums", "albums_by_artist");
330 assertTrue(report != null);
331 final LayoutGroup layoutGroup = report.getLayoutGroup();
332 assertTrue(layoutGroup != null);
333 final List<LayoutItem> layoutItems = layoutGroup.getItems();
334 final int numItems = safeLongToInt(layoutItems.size());
335 assertEquals(1, numItems);
337 LayoutItem layoutItem = layoutItems.get(0);
338 assertTrue(layoutItem != null);
339 final LayoutGroup asGroup = (LayoutGroup) layoutItem;
340 assertTrue(asGroup != null);
341 final LayoutItemGroupBy groupby = (LayoutItemGroupBy) layoutItem;
342 assertTrue(groupby != null);
344 assertTrue(groupby.getHasFieldGroupBy());
345 final LayoutItemField fieldGroupBy = groupby.getFieldGroupBy();
346 assertTrue(fieldGroupBy != null);
347 assertThat(fieldGroupBy.getName(), is("artist_id"));
349 final LayoutGroup groupSecondaries = groupby.getSecondaryFields();
350 assertTrue(groupSecondaries != null);
352 final List<LayoutItem> innerItems = groupby.getItems();
353 assertTrue(innerItems != null);
354 final int numInnerItems = safeLongToInt(innerItems.size());
355 assertEquals(2, numInnerItems);
357 layoutItem = innerItems.get(0);
358 assertTrue(layoutItem != null);
359 assertTrue(layoutItem instanceof LayoutItemField);
360 LayoutItemField field = (LayoutItemField) layoutItem;
361 assertTrue(field != null);
362 assertThat(field.getName(), is("name"));
363 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_TEXT));
365 layoutItem = innerItems.get(1);
366 assertTrue(layoutItem != null);
367 assertTrue(layoutItem instanceof LayoutItemField);
368 field = (LayoutItemField) layoutItem;
369 assertTrue(field != null);
370 assertThat(field.getName(), is("year"));
371 assertThat(field.getGlomType(), is(Field.GlomFieldType.TYPE_NUMERIC));
374 // Test thread class that runs all the tests.
375 private class TestThread implements Runnable {
379 for (int i = 0; i < 20; i++) {
381 testGetNumericFormat();
382 testGetSuitableTableToViewDetails();
383 testReadLayoutListInfo();
384 testReadTableFieldSizes();
385 testReadTableNames();
386 testUsesRelationshipMethods();
392 * Tests threaded access to java-libglom.
395 public void testThreadedAccess() throws InterruptedException {
396 // create the threads
397 final Thread thread1 = new Thread(new TestThread());
398 final Thread thread2 = new Thread(new TestThread());
399 final Thread thread3 = new Thread(new TestThread());
400 final Thread thread4 = new Thread(new TestThread());
408 // wait for the treads to finish
411 } catch (final InterruptedException e) {
412 System.out.println("Thread 1 had a problem finishing. " + e);
418 } catch (final InterruptedException e) {
419 System.out.println("Thread 2 had a problem finishing. " + e);
425 } catch (final InterruptedException e) {
426 System.out.println("Thread 3 had a problem finishing. " + e);
432 } catch (final InterruptedException e) {
433 System.out.println("Thread 4 had a problem finishing. " + e);
439 * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
441 * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
443 private static int safeLongToInt(final long l) {
444 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
445 throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");