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.shared.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.List;
29 import org.glom.web.shared.libglom.Document;
30 import org.glom.libglom.Glom;
31 import org.glom.libglom.LayoutFieldVector;
32 import org.glom.libglom.LayoutGroup;
33 import org.glom.libglom.LayoutGroupVector;
34 import org.glom.libglom.LayoutItem;
35 import org.glom.libglom.LayoutItem_GroupBy;
36 import org.glom.libglom.LayoutItemVector;
37 import org.glom.libglom.LayoutItem_Field;
38 import org.glom.libglom.LayoutItem_Notebook;
39 import org.glom.libglom.LayoutItem_Portal;
40 import org.glom.libglom.NumericFormat;
41 import org.glom.libglom.Relationship;
42 import org.glom.libglom.SortClause;
43 import org.glom.libglom.SortFieldPair;
44 import org.glom.libglom.StringVector;
45 import org.junit.AfterClass;
46 import org.junit.BeforeClass;
47 import org.junit.Test;
50 * Simple test to ensure that the generated bindings are working.
52 public class DocumentTest {
54 private static Document document;
55 private static String locale = ""; //This means the original locale.
56 final static String testUriMusicCollection = "src/test/java/org/glom/web/shared/libglom/example_music_collection.glom";
57 final static String testUriFilmManager = "src/test/java/org/glom/web/shared/libglom/example_film_manager.glom";
60 static public void setUp() {
61 document = new Document();
62 document.set_file_uri(testUriMusicCollection);
64 boolean retval = document.load(error);
66 assertEquals(error, 0);
70 static public void tearDown() {
71 Glom.libglom_deinit();
75 public void testDocumentInfo() {
76 assertThat(document.get_database_title_original(), is("Music Collection"));
77 assertThat(document.get_default_table(), is("artists"));
81 public void testReadTableNames() {
82 StringVector tableNames = document.get_table_names();
83 assertEquals(4, tableNames.size());
85 String tables = tableNames.get(0);
86 for (int i = 1; i < tableNames.size(); i++) {
87 tables += ", " + tableNames.get(i);
89 assertThat(tables, is("artists, albums, songs, publishers"));
93 public void testReadTableFieldSizes() {
95 List<Field> fields = document.get_table_fields("albums");
96 assertEquals(6, fields.size());
98 Field field = fields.get(0);
99 String titles = field.get_title_or_name(locale);
100 for (int i = 1; i < fields.size(); i++) {
101 field = fields.get(i);
102 titles += ", " + field.get_title_or_name(locale);
104 assertThat(titles, is("Album ID, Comments, Name, Artist ID, Publisher ID, Year"));
106 fields = document.get_table_fields("artists");
107 assertEquals(4, fields.size());
109 field = fields.get(0);
110 titles = field.get_title_or_name(locale);
111 for (int i = 1; i < fields.size(); i++) {
112 field = fields.get(i);
113 titles += ", " + field.get_title_or_name(locale);
115 assertThat(titles, is("Artist ID, Description, Comments, Name"));
117 fields = document.get_table_fields("publishers");
118 assertEquals(3, fields.size());
120 field = fields.get(0);
121 titles = field.get_title_or_name(locale);
122 for (int i = 1; i < fields.size(); i++) {
123 field = fields.get(i);
124 titles += ", " + field.get_title_or_name(locale);
126 assertThat(titles, is("Publisher ID, Comments, Name"));
128 fields = document.get_table_fields("songs");
129 assertEquals(4, fields.size());
131 field = fields.get(0);
132 titles = field.get_title_or_name(locale);
133 for (int i = 1; i < fields.size(); i++) {
134 field = fields.get(i);
135 titles += ", " + field.get_title_or_name(locale);
137 assertThat(titles, is("Song ID, Comments, Album ID, Name"));
141 public void testReadLayoutListInfo() {
142 String[] tables = { "albums", "artists", "publishers", "songs" };
143 int[] sortClauseSizes = { 0, 1, 1, 1 };
144 int[] layoutFieldSizes = { 7, 4, 3, 4 };
146 for (int i = 0; i < tables.length; i++) {
147 LayoutGroupVector layoutList = document.get_data_layout_groups("list", tables[i]);
148 LayoutItemVector layoutItems = layoutList.get(0).get_items();
149 LayoutFieldVector layoutFields = new LayoutFieldVector();
150 SortClause sortClause = new SortClause();
151 int numItems = safeLongToInt(layoutItems.size());
152 for (int j = 0; j < numItems; j++) {
153 LayoutItem item = layoutItems.get(j);
154 LayoutItem_Field field = LayoutItem_Field.cast_dynamic(item);
156 layoutFields.add(field);
157 Field details = field.get_full_field_details();
158 if (details != null && details.get_primary_key()) {
159 sortClause.add(new SortFieldPair(field, true)); // ascending
163 assertEquals(sortClauseSizes[i], sortClause.size());
164 assertEquals(layoutFieldSizes[i], safeLongToInt(layoutFields.size()));
169 * This tests if getting values from a NumericFormat object is working. This test was failing with a JVM crash when
170 * using the glom_sharedptr macro with Glom::UsesRelationship and Glom::Formatting.
173 public void testGetNumericFormat() {
174 StringVector tableNames = document.get_table_names();
176 for (int i = 0; i < tableNames.size(); i++) {
177 String table = tableNames.get(i);
178 LayoutGroupVector layoutList = document.get_data_layout_groups("list", table);
179 LayoutItemVector layoutItems = layoutList.get(0).get_items();
180 int numItems = safeLongToInt(layoutItems.size());
181 for (int j = 0; j < numItems; j++) {
182 LayoutItem item = layoutItems.get(j);
183 LayoutItem_Field item_field = LayoutItem_Field.cast_dynamic(item);
184 if (item_field != null) {
185 // don't keep a reference to the FeildFormatting object
186 NumericFormat numFormat = item_field.get_formatting_used().get_numeric_format();
189 boolean altForegroundColorForNegatives = numFormat.get_alt_foreground_color_for_negatives();
190 String currencySymbol = numFormat.get_currency_symbol();
191 long decimalPlaces = numFormat.get_decimal_places();
192 boolean decimalPlacesRestricted = numFormat.get_decimal_places_restricted();
193 boolean useThousandsSepator = numFormat.get_use_thousands_separator();
194 String alternativeColorForNegatives = NumericFormat.get_alternative_color_for_negatives();
195 long defaultPrecision = NumericFormat.get_default_precision();
197 // Simulate a garbage collection
199 System.runFinalization();
201 // re-get the values and test
202 assertEquals(altForegroundColorForNegatives, numFormat.get_alt_foreground_color_for_negatives());
203 assertEquals(currencySymbol, numFormat.get_currency_symbol());
204 assertEquals(decimalPlaces, numFormat.get_decimal_places());
205 assertEquals(decimalPlacesRestricted, numFormat.get_decimal_places_restricted());
206 assertEquals(useThousandsSepator, numFormat.get_use_thousands_separator());
207 assertEquals(alternativeColorForNegatives, NumericFormat.get_alternative_color_for_negatives());
208 assertEquals(defaultPrecision, NumericFormat.get_default_precision());
216 * A smoke test for the methods added to LayoutItem_Field for accessing methods in Glom::UsesRelationship.
219 public void testUsesRelationshipMethods() {
220 String table = "albums";
221 LayoutGroupVector layoutList = document.get_data_layout_groups("list", table);
222 LayoutItemVector layoutItems = layoutList.get(0).get_items();
224 String names = null, hasRelationshipNames = null, tablesUsed = null;
225 LayoutItem firstItem = layoutItems.get(0);
226 LayoutItem_Field firstItemField = LayoutItem_Field.cast_dynamic(firstItem);
227 if (firstItemField != null) {
228 names = firstItemField.get_name();
229 hasRelationshipNames = "" + firstItemField.get_has_relationship_name();
230 tablesUsed = firstItemField.get_table_used(table);
232 int numItems = safeLongToInt(layoutItems.size());
233 for (int j = 1; j < numItems; j++) {
234 LayoutItem item = layoutItems.get(j);
235 LayoutItem_Field itemField = LayoutItem_Field.cast_dynamic(item);
236 if (itemField != null) {
237 names += ", " + itemField.get_name();
238 hasRelationshipNames += ", " + itemField.get_has_relationship_name();
239 tablesUsed += ", " + itemField.get_table_used(table);
242 assertEquals("name, year, artist_id, name, publisher_id, name, comments", names);
243 assertEquals("false, false, false, true, false, true, false", hasRelationshipNames);
244 assertEquals("albums, albums, albums, artists, albums, publishers, albums", tablesUsed);
248 public void testGetSuitableTableToViewDetails() {
250 // Create a new document for the film manager
251 Document filmManagerDocument = new Document();
252 filmManagerDocument.set_file_uri(testUriFilmManager);
254 boolean retval = filmManagerDocument.load(error);
256 assertEquals(error, 0);
258 // Get the "Scene Cast" related list portal. This relies on specific details of the film manager details
259 // view layout. I've included safety checks that will fail if the layout changes.
260 LayoutGroupVector detailsLayout = filmManagerDocument.get_data_layout_groups("details", "scenes");
261 assertEquals(3, detailsLayout.size());
263 LayoutGroup layoutGroup = detailsLayout.get(1);
264 assertEquals("details", layoutGroup.get_name());
266 layoutGroup = detailsLayout.get(2);
267 assertEquals("details_lower", layoutGroup.get_name());
269 LayoutItemVector items = layoutGroup.get_items();
270 assertEquals(2, items.size());
272 LayoutItem notebookItem = items.get(0);
273 assertEquals("notebook", notebookItem.get_name());
274 LayoutItem_Notebook notebook = LayoutItem_Notebook.cast_dynamic(notebookItem);
275 items = notebook.get_items();
276 assertEquals(7, items.size());
277 LayoutItem portalItem = items.get(0);
278 LayoutItem_Portal portal = LayoutItem_Portal.cast_dynamic(portalItem);
279 assertTrue(portal != null);
281 // call get_suitable_table_to_view_details
282 StringBuffer navigation_table_name = new StringBuffer();
283 LayoutItem_Field navigation_relationship = new LayoutItem_Field(); // LayoutItem_Field is being used in place of
285 //TODO: portal.get_suitable_table_to_view_details(navigation_table_name, navigation_relationship, filmManagerDocument);
287 // Simulate a garbage collection
289 System.runFinalization();
291 // Check if things are working like we expect
292 assertEquals("characters", navigation_table_name.toString());
293 assertTrue(navigation_relationship != null);
294 Relationship relationship = navigation_relationship.get_relationship();
295 assertTrue(relationship != null);
296 assertEquals("cast", relationship.get_name());
297 assertTrue(navigation_relationship.get_related_relationship() == null);
302 public void testReadReportNames() {
303 StringVector reportNames = document.get_report_names("albums");
304 assertEquals(1, reportNames.size()); //TODO: Test something with more reports.
306 String reports = reportNames.get(0);
307 for (int i = 1; i < reportNames.size(); i++) {
308 reports += ", " + reportNames.get(i);
310 assertThat(reports, is("albums_by_artist"));
314 public void testReadReportStructure() {
315 Report report = document.get_report("albums", "albums_by_artist");
316 assertTrue(report != null);
317 LayoutGroup layoutGroup = report.get_layout_group();
318 assertTrue(layoutGroup != null);
319 LayoutItemVector layoutItems = layoutGroup.get_items();
320 final int numItems = safeLongToInt(layoutItems.size());
321 assertEquals(1, numItems);
323 LayoutItem layoutItem = layoutItems.get(0);
324 assertTrue(layoutItem != null);
325 LayoutGroup asGroup = LayoutGroup.cast_dynamic(layoutItem);
326 assertTrue(asGroup != null);
327 LayoutItem_GroupBy groupby = LayoutItem_GroupBy.cast_dynamic(layoutItem);
328 assertTrue(groupby != null);
330 assertTrue(groupby.get_has_field_group_by());
331 LayoutItem_Field fieldGroupBy = groupby.get_field_group_by();
332 assertTrue(fieldGroupBy != null);
333 assertThat(fieldGroupBy.get_name(), is("artist_id"));
335 LayoutGroup groupSecondaries = groupby.get_secondary_fields();
336 assertTrue(groupSecondaries != null);
338 LayoutItemVector innerItems = groupby.get_items();
339 assertTrue(innerItems != null);
340 final int numInnerItems = safeLongToInt(innerItems.size());
341 assertEquals(2, numInnerItems);
343 layoutItem = layoutItems.get(0);
344 assertTrue(layoutItem != null);
345 LayoutItem_Field field = LayoutItem_Field.cast_dynamic(layoutItem);
346 assertTrue(field != null);
347 assertThat(field.get_name(), is("name"));
348 assertThat(field.get_glom_type(), is(Field.glom_field_type.TYPE_TEXT));
350 layoutItem = layoutItems.get(1);
351 assertTrue(layoutItem != null);
352 field = LayoutItem_Field.cast_dynamic(layoutItem);
353 assertTrue(field != null);
354 assertThat(field.get_name(), is("year"));
355 assertThat(field.get_glom_type(), is(Field.glom_field_type.TYPE_NUMERIC));
358 // Test thread class that runs all the tests.
359 private class TestThread implements Runnable {
362 for (int i = 0; i < 20; i++) {
364 testGetNumericFormat();
365 testGetSuitableTableToViewDetails();
366 testReadLayoutListInfo();
367 testReadTableFieldSizes();
368 testReadTableNames();
369 testUsesRelationshipMethods();
375 * Tests threaded access to java-libglom.
378 public void testThreadedAccess() throws InterruptedException {
379 // create the threads
380 Thread thread1 = new Thread(new TestThread());
381 Thread thread2 = new Thread(new TestThread());
382 Thread thread3 = new Thread(new TestThread());
383 Thread thread4 = new Thread(new TestThread());
391 // wait for the treads to finish
394 } catch (InterruptedException e) {
395 System.out.println("Thread 1 had a problem finishing. " + e);
401 } catch (InterruptedException e) {
402 System.out.println("Thread 2 had a problem finishing. " + e);
408 } catch (InterruptedException e) {
409 System.out.println("Thread 3 had a problem finishing. " + e);
415 } catch (InterruptedException e) {
416 System.out.println("Thread 4 had a problem finishing. " + e);
422 * This method safely converts longs from libglom into ints. This method was taken from stackoverflow:
424 * http://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java
426 private static int safeLongToInt(long l) {
427 if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
428 throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");