Update hacky paths in test
[online-glom:gwt-glom.git] / src / test / java / org / glom / web / server / libglom / DocumentTest.java
1 /*
2  * Copyright (C) 2009, 2010, 2011 Openismus GmbH
3  *
4  * This file is part of Java-libglom.
5  *
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.
10  *
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
14  * for more details.
15  *
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/>.
18  */
19
20 package org.glom.web.server.libglom;
21
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;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
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;
44
45 /**
46  * Simple test to ensure that the generated bindings are working.
47  */
48 public class DocumentTest {
49
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/server/libglom/example_music_collection.glom";
53         final static String testUriFilmManager = "src/test/java/org/glom/web/server/libglom/example_film_manager.glom";
54
55         @BeforeClass
56         static public void setUp() {
57                 document = new Document();
58                 document.setFileURI(testUriMusicCollection);
59                 final int error = 0;
60                 final boolean retval = document.load(error);
61                 assertTrue(retval);
62                 assertEquals(error, 0);
63         }
64
65         @AfterClass
66         static public void tearDown() {
67         }
68
69         @Test
70         public void testDocumentInfo() {
71                 assertThat(document.getDatabaseTitleOriginal(), is("Music Collection"));
72                 assertThat(document.getDefaultTable(), is("artists"));
73         }
74
75         @Test
76         public void testReadTableNames() {
77                 final List<String> tableNames = document.getTableNames();
78                 assertEquals(4, tableNames.size());
79
80                 String tables = tableNames.get(0);
81                 for (int i = 1; i < tableNames.size(); i++) {
82                         tables += ", " + tableNames.get(i);
83                 }
84                 assertThat(tables, is("artists, albums, songs, publishers"));
85         }
86
87         @Test
88         public void testReadTableFieldSizes() {
89
90                 List<Field> fields = document.getTableFields("albums");
91                 assertEquals(6, fields.size());
92
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);
98                 }
99
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"));
102
103                 fields = document.getTableFields("artists");
104                 assertEquals(4, fields.size());
105
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);
111                 }
112
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"));
115
116                 fields = document.getTableFields("publishers");
117                 assertEquals(3, fields.size());
118
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);
124                 }
125
126                 // TODO: The sequence is not important. It's only important that they are all there.
127                 assertThat(titles, is("Name, Publisher ID, Comments"));
128
129                 fields = document.getTableFields("songs");
130                 assertEquals(4, fields.size());
131
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);
137                 }
138
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"));
141         }
142
143         @Test
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 };
148
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);
158
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
165                                         }
166                                 }
167                         }
168                         assertEquals(sortClauseSizes[i], sortClause.size());
169                         assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
170                 }
171         }
172
173         /*
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.
176          */
177         @Test
178         public void testGetNumericFormat() {
179                 final List<String> tableNames = document.getTableNames();
180
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);
190
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);
196
197                                         // get the values
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();
205
206                                         // Simulate a garbage collection
207                                         System.gc();
208                                         System.runFinalization();
209
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());
218
219                                 }
220                         }
221                 }
222         }
223
224         /*
225          * A smoke test for the methods added to LayoutItemField for accessing methods in Glom::UsesRelationship.
226          */
227         @Test
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();
232
233                 String names = null, hasRelationshipNames = null, tablesUsed = null;
234                 final LayoutItem firstItem = layoutItems.get(0);
235
236                 if (firstItem instanceof LayoutItemField) {
237                         final LayoutItemField firstItemField = (LayoutItemField) firstItem;
238                         names = firstItemField.getName();
239                         hasRelationshipNames = "" + firstItemField.getHasRelationshipName();
240                         tablesUsed = firstItemField.getTableUsed(table);
241                 }
242                 final int numItems = safeLongToInt(layoutItems.size());
243                 for (int j = 1; j < numItems; j++) {
244                         final LayoutItem item = layoutItems.get(j);
245
246                         if (item instanceof LayoutItemField) {
247                                 final LayoutItemField itemField = (LayoutItemField) item;
248                                 names += ", " + itemField.getName();
249                                 hasRelationshipNames += ", " + itemField.getHasRelationshipName();
250                                 tablesUsed += ", " + itemField.getTableUsed(table);
251                         }
252                 }
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);
256         }
257
258         @Test
259         public void testGetSuitableTableToViewDetails() {
260
261                 // Create a new document for the film manager
262                 final Document filmManagerDocument = new Document();
263                 filmManagerDocument.setFileURI(testUriFilmManager);
264                 final int error = 0;
265                 final boolean retval = filmManagerDocument.load(error);
266                 assertTrue(retval);
267                 assertEquals(error, 0);
268
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());
273
274                 LayoutGroup layoutGroup = detailsLayout.get(1);
275                 assertEquals("details", layoutGroup.getName());
276
277                 layoutGroup = detailsLayout.get(2);
278                 assertEquals("details_lower", layoutGroup.getName());
279
280                 List<LayoutItem> items = layoutGroup.getItems();
281                 assertEquals(2, items.size());
282
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);
293
294                 assertEquals(portal.getRelationshipNameUsed(), "scene_cast");
295
296                 // call getSuitableTableToCiewDetails
297                 final LayoutItemPortal.TableToViewDetails viewDetails = portal
298                                 .getSuitableTableToViewDetails(filmManagerDocument);
299                 assertTrue(viewDetails != null);
300
301                 // Simulate a garbage collection
302                 System.gc();
303                 System.runFinalization();
304
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);
312
313         }
314
315         @Test
316         public void testReadReportNames() {
317                 final List<String> reportNames = document.getReportNames("albums");
318                 assertEquals(1, reportNames.size()); // TODO: Test something with more reports.
319
320                 String reports = reportNames.get(0);
321                 for (int i = 1; i < reportNames.size(); i++) {
322                         reports += ", " + reportNames.get(i);
323                 }
324                 assertThat(reports, is("albums_by_artist"));
325         }
326
327         @Test
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);
336
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);
343
344                 assertTrue(groupby.getHasFieldGroupBy());
345                 final LayoutItemField fieldGroupBy = groupby.getFieldGroupBy();
346                 assertTrue(fieldGroupBy != null);
347                 assertThat(fieldGroupBy.getName(), is("artist_id"));
348
349                 final LayoutGroup groupSecondaries = groupby.getSecondaryFields();
350                 assertTrue(groupSecondaries != null);
351
352                 final List<LayoutItem> innerItems = groupby.getItems();
353                 assertTrue(innerItems != null);
354                 final int numInnerItems = safeLongToInt(innerItems.size());
355                 assertEquals(2, numInnerItems);
356
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));
364
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));
372         }
373
374         // Test thread class that runs all the tests.
375         private class TestThread implements Runnable {
376
377                 @Override
378                 public void run() {
379                         for (int i = 0; i < 20; i++) {
380                                 testDocumentInfo();
381                                 testGetNumericFormat();
382                                 testGetSuitableTableToViewDetails();
383                                 testReadLayoutListInfo();
384                                 testReadTableFieldSizes();
385                                 testReadTableNames();
386                                 testUsesRelationshipMethods();
387                         }
388                 }
389         }
390
391         /*
392          * Tests threaded access to java-libglom.
393          */
394         @Test
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());
401
402                 // start the threads
403                 thread1.start();
404                 thread2.start();
405                 thread3.start();
406                 thread4.start();
407
408                 // wait for the treads to finish
409                 try {
410                         thread1.join();
411                 } catch (final InterruptedException e) {
412                         System.out.println("Thread 1 had a problem finishing. " + e);
413                         throw e;
414                 }
415
416                 try {
417                         thread2.join();
418                 } catch (final InterruptedException e) {
419                         System.out.println("Thread 2 had a problem finishing. " + e);
420                         throw e;
421                 }
422
423                 try {
424                         thread3.join();
425                 } catch (final InterruptedException e) {
426                         System.out.println("Thread 3 had a problem finishing. " + e);
427                         throw e;
428                 }
429
430                 try {
431                         thread4.join();
432                 } catch (final InterruptedException e) {
433                         System.out.println("Thread 4 had a problem finishing. " + e);
434                         throw e;
435                 }
436         }
437
438         /*
439          * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
440          * 
441          * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
442          */
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.");
446                 }
447                 return (int) l;
448         }
449
450 }