001: package jimm.datavision.test;
002:
003: import jimm.datavision.*;
004: import jimm.datavision.field.*;
005: import jimm.datavision.test.mock.source.MockDataSource;
006: import java.util.List;
007: import java.io.File;
008: import java.text.DecimalFormat;
009: import junit.framework.TestCase;
010: import junit.framework.TestSuite;
011: import junit.framework.Test;
012:
013: /**
014: * Reads a report from an XML file, tests its structure, and tests various
015: * pieces like parameter and formula substitution.
016: *
017: * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
018: */
019: public class ReportTest extends TestCase {
020:
021: protected static final File EXAMPLE_REPORT = new File(AllTests
022: .testDataFile("test.xml"));
023: protected static final File PARAM_INPUT_FILE = new File(AllTests
024: .testDataFile("test_parameters.xml"));
025:
026: protected Report report;
027: protected DecimalFormat dollarFormatter;
028: protected DecimalFormat lastColFormatter;
029:
030: public static Test suite() {
031: return new TestSuite(ReportTest.class);
032: }
033:
034: public ReportTest(String name) {
035: super (name);
036: }
037:
038: public void setUp() throws Exception {
039: report = new Report();
040: report.setDataSource(new MockDataSource(report));
041: report.read(EXAMPLE_REPORT);
042: report.setParameterXMLInput(PARAM_INPUT_FILE);
043: }
044:
045: public void tearDown() {
046: report = null;
047: }
048:
049: public void testAttributes() {
050: assertEquals("example1", report.getName());
051: assertEquals("Example Report", report.getTitle());
052: assertEquals("Jim Menard", report.getAuthor());
053: assertEquals(new Long(7), report.generateNewParameterId());
054: }
055:
056: public void testPaperFormat() {
057: PaperFormat pf = report.getPaperFormat();
058: assertNotNull(pf);
059: assertEquals(PaperFormat.PORTRAIT, pf.getOrientation());
060: assertEquals("US-Letter", pf.getName());
061: }
062:
063: public void testImages() {
064: Section detail = report
065: .getFirstSectionByArea(SectionArea.DETAIL);
066:
067: // Add an image, passing in a file path, and make sure the URL is
068: // correct.
069: ImageField image = new ImageField(new Long(99), report, detail,
070: "/tmp/foo.gif", true);
071: // I expected to see "file:///tmp/foo.gif", but apparently the URL
072: // class modifies that to be "file:/tmp/foo.gif".
073: assertEquals("file:/tmp/foo.gif", image.getImageURL()
074: .toString());
075:
076: // Now set value to a URL string.
077: String url = "http://localhost/foo.gif";
078: image.setValue(url);
079: assertEquals(url, image.getImageURL().toString());
080: }
081:
082: public void testSections() {
083: // Sections
084: assertEquals(1, report.headers().size());
085: assertEquals(1, report.footers().size());
086: assertEquals(1, report.pageHeaders().size());
087: assertEquals(1, report.pageFooters().size());
088: assertEquals(1, report.details().size());
089: assertEquals(2, report.countGroups());
090:
091: // Add a new detail section
092: Section detail = report
093: .getFirstSectionByArea(SectionArea.DETAIL);
094: assertNotNull(detail);
095: report.insertSectionBelow(detail);
096: assertEquals(2, report.details().size());
097: }
098:
099: public void testFormulas() {
100: Formula formula = report.findFormula("1");
101: Long id = new Long(1);
102: assertNotNull(formula);
103: assertEquals("hourly rate / 100", formula.getName());
104: assertEquals(
105: "{jobs.hourly rate}.nil? ? nil : {jobs.hourly rate} / 100.0",
106: formula.getExpression());
107: assertEquals("formula:1", formula.dragString());
108: assertEquals("{@hourly rate / 100}", formula.designLabel());
109: assertEquals("{@1}", formula.formulaString());
110: // We test StringUtils.formulaToDisplay() and
111: // StringUtils.displayToFormula() in FormulaTest.java.
112:
113: formula = report.findFormula(id);
114: assertNotNull(formula);
115: assertEquals(id, formula.getId());
116: }
117:
118: public void testFormulaReferences() {
119: refTest("1", true);
120: refTest("2", true);
121: refTest("3", false); // Formula exists, but not in any report field
122:
123: // Now put formula 3 in the report's startup script and look for it.
124: // (We already know that report.findFormula won't return null.)
125: Formula f = new Formula(null, report, "startup script", report
126: .findFormula("3").formulaString());
127: report.setStartFormula(f);
128: refTest("3", true);
129: }
130:
131: protected void refTest(String formulaId, boolean shouldFindReference) {
132: Formula f = report.findFormula(formulaId);
133: assertNotNull(f);
134: assertTrue("reference to formula " + formulaId
135: + ": wanted to find = " + shouldFindReference
136: + " but opposite happened", report
137: .containsReferenceTo(f) == shouldFindReference);
138: }
139:
140: public void testUserColumnReferences() {
141: UserColumn uc = report.findUserColumn("1");
142: assertNotNull(uc);
143:
144: // We should not find the user column inside any report field
145: assertTrue("shouldn't find reference to user column 1", !report
146: .containsReferenceTo(uc));
147:
148: // Add the user column to a formula that has a report field, so that
149: // containsRefereceTo should return true.
150: Formula f = report.findFormula("1");
151: f.setExpression(uc.formulaString());
152: assertTrue("can't find reference to user column 1", report
153: .containsReferenceTo(uc));
154:
155: // Now remove the user column from that formula and instead place it
156: // inside a suppression proc.
157: f.setExpression("");
158: Section detail = report.findField("10").getSection();
159: f = detail.getSuppressionProc().getFormula();
160: f.setExpression(uc.formulaString());
161: assertTrue(
162: "can't find reference to user column 1 in suppression proc",
163: report.containsReferenceTo(uc));
164:
165: // Now remove the user column from the suppression proc and put it in
166: // the report's startup script instead.
167: f.setExpression("");
168: f = new Formula(null, report, "startup script", uc
169: .formulaString());
170: report.setStartFormula(f);
171: assertTrue(
172: "can't find reference to user column 1 in startup script",
173: report.containsReferenceTo(uc));
174: }
175:
176: public void testParameterReferences() {
177: Parameter p = report.findParameter("1");
178: assertNotNull(p);
179:
180: // Unlike the other testXXXReferences methods, we *should* find the
181: // parameter inside a report field because it's there in the group
182: // header.
183: assertTrue("should find reference to parameter 1", report
184: .containsReferenceTo(p));
185:
186: // Now remove the parameter from the header and instead place it
187: // inside a suppression proc.
188: report.removeField(report.findField("15"));
189: Section detail = report.findField("10").getSection();
190: Formula f = detail.getSuppressionProc().getFormula();
191: f.setExpression(p.formulaString());
192: assertTrue(
193: "can't find reference to parameter 1 in suppression proc",
194: report.containsReferenceTo(p));
195:
196: // Now remove the parameter from the suppression proc and put it in the
197: // report's startup script instead.
198: f.setExpression("");
199: f = new Formula(null, report, "startup script", p
200: .formulaString());
201: report.setStartFormula(f);
202: assertTrue(
203: "can't find reference to parameter 1 in startup script",
204: report.containsReferenceTo(p));
205: }
206:
207: public void testFieldReferences() {
208: Field f;
209: for (int i = 0; (f = report.findField("" + i)) != null; ++i)
210: assertTrue("reference to field " + i + " not found", report
211: .containsReferenceTo(f));
212: }
213:
214: public void testParameters() {
215: Parameter param = report.findParameter("5");
216: Long id = new Long(5);
217: assertNotNull(param);
218: assertEquals("parameter:5", param.dragString());
219: assertEquals("{?5}", param.formulaString());
220: assertEquals("{?Yes/No}", param.designLabel());
221: assertEquals(Parameter.TYPE_BOOLEAN, param.getType());
222: assertEquals(Parameter.ARITY_ONE, param.getArity());
223: assertEquals(id, param.getId());
224: assertEquals("Yes/No", param.getName());
225: assertEquals("Do you breathe regularly?", param.getQuestion());
226:
227: param = report.findParameter(id);
228: assertNotNull(param);
229: assertEquals(id, param.getId());
230:
231: // Get ready to read values from parameter values file when asked.
232: // We have to add a parameter to the report somewhere. If we don't,
233: // the report won't read the XML file.
234: report.getDataSource().getQuery().setEditableWhereClause(
235: "office.name = {?String Param}");
236:
237: id = new Long(2);
238: param = report.findParameter(id);
239: assertNotNull(param);
240:
241: Object obj = report.getParameterValue(id); // Reads values from XML
242: assertNotNull("range param value should not be null", obj);
243:
244: assertTrue("range param value is not a list; class = "
245: + obj.getClass().getName(), obj instanceof List);
246: List list = (List) obj;
247:
248: assertTrue(
249: "range param value list does not have length 2; it has length "
250: + list.size(), list.size() == 2);
251:
252: assertEquals(new Integer(50), list.get(0));
253: assertEquals(new Integer(75), list.get(1));
254: }
255:
256: public void testNullFieldIds() {
257: // Empty reports start with one detail section
258: Section detail = report
259: .getFirstSectionByArea(SectionArea.DETAIL);
260: assertNotNull(detail);
261:
262: // Add fields.
263: TextField f = new TextField(null, report, detail, "field 1",
264: true);
265: assertNotNull(f.getId());
266: Object id = f.getId();
267: assertTrue("field id is not a Long", id instanceof Long);
268: long longVal = ((Long) id).longValue();
269: assertTrue("field id is not > 1", longVal >= 1);
270: detail.addField(f);
271:
272: f = new TextField(null, report, detail, "field 2", true);
273: Object newId = f.getId();
274: assertNotNull(newId);
275: long newLongVal = ((Long) newId).longValue();
276: assertEquals(longVal + 1, newLongVal);
277: detail.addField(f);
278:
279: id = newId;
280: longVal = newLongVal;
281:
282: f = new TextField(null, report, detail, "field 3", true);
283: newId = f.getId();
284: assertNotNull(newId);
285: newLongVal = ((Long) newId).longValue();
286: assertEquals(longVal + 1, newLongVal);
287: detail.addField(f);
288: }
289:
290: public void testCaseSensitivity() {
291: assertNotNull(report.findColumn("jobs.ID"));
292:
293: // These should fail since by default we search case-sensitively
294: assertNull(report.findColumn("jobs.id"));
295: assertNull(report.findColumn("JOBS.ID"));
296: assertNull(report.findColumn("jOBs.id"));
297:
298: // These should succeed, because the table and column names are
299: // all upper-case in the database. We go straight to the data
300: // source because the report does not contain this column but
301: // the database does.
302: assertNotNull(report.getDataSource()
303: .findColumn("ALL_CAPS.COL1"));
304:
305: // Now tell the report to ignore case with table and column names
306: report.setCaseSensitiveDatabaseNames(false);
307: assertNotNull(report.findColumn("jobs.id"));
308: assertNotNull(report.findColumn("JOBS.ID"));
309: assertNotNull(report.findColumn("jOBs.id"));
310:
311: // Formula name search is always case-insensitive
312: assertNotNull(report.findFormulaByName("refs f1"));
313: assertNotNull(report.findFormulaByName("REFS F1"));
314: assertNotNull(report.findFormulaByName("rEFs f1"));
315:
316: // Parameter name search is always case-insensitive
317: assertNotNull(report.findParameterByName("Yes/No"));
318: assertNotNull(report.findParameterByName("yes/no"));
319: assertNotNull(report.findParameterByName("yES/No"));
320: }
321:
322: public void testFormat() {
323: Format f = report.getDefaultField().getFormat();
324: Format f2 = (Format) f.clone();
325: assertEquals("Default and cloned formats should be equal", f,
326: f2);
327:
328: assertNotNull(f.getColor());
329:
330: Field field = Field.createFromDragString(report,
331: "column:jobs.ID");
332: assertNotNull(field);
333:
334: Format fmt = field.getFormat();
335: assertNotNull(fmt);
336:
337: Format defaultFormat = report.getDefaultField().getFormat();
338:
339: assertEquals(defaultFormat, field.getFormat());
340:
341: // Test "transparency"; the format's format string is really null, but
342: // it will return the default format's format string;
343: assertEquals(defaultFormat.getFormat(), fmt.getFormat());
344: }
345:
346: public void testCloning() {
347: // Make sure whatever we create here does not have a value that
348: // depends upon running the report and having data.
349: Section s = report
350: .getFirstSectionByArea(SectionArea.REPORT_HEADER);
351: SpecialField f = (SpecialField) Field.create(null, report, s,
352: "special", "report.date", true);
353:
354: f.setFormat((Format) report.getDefaultField().getFormat()
355: .clone());
356: f.setBounds(new Rectangle(1.0, 2.0, 3.0, 4.0));
357: f.setBorder(new Border(f));
358:
359: SpecialField f2 = (SpecialField) f.clone();
360: assertNotNull(f2);
361:
362: // assertEquals does too much, and we don't need Field.equals
363: // anywhere else, so let's do it piece by piece
364:
365: assertEquals(f.getBounds().x, f2.getBounds().x, 0.00001);
366: assertEquals(f.getBounds().y, f2.getBounds().y, 0.00001);
367: assertEquals(f.getBounds().width, f2.getBounds().width, 0.00001);
368: assertEquals(f.getBounds().height, f2.getBounds().height,
369: 0.00001);
370: assertEquals(f.getFormat(), f2.getFormat());
371: assertEquals(f.getBorder(), f2.getBorder());
372:
373: // The value is a date. Ignore the seconds in both values
374: // just in case they are different.
375: String fVal = f.getValue().toString();
376: String f2Val = f2.getValue().toString();
377: assertEquals(fVal.substring(0, 16), f2Val.substring(0, 16));
378: assertEquals(fVal.substring(19), f2Val.substring(19));
379: }
380:
381: public void testHasParameterFields() {
382: assertEquals(true, report.hasParameterFields());
383: }
384:
385: public void testIdGeneration() {
386: long nextFormulaId = report.generateNewFormulaId().longValue();
387: long nextParameterId = report.generateNewParameterId()
388: .longValue();
389: long nextUserColumnId = report.generateNewUserColumnId()
390: .longValue();
391:
392: // The new objects' id numbers will be the same as nextXXXId (instead
393: // of nextXXXid + 1) because the new id numbers only get bumped up when
394: // a new object is added to the report, not wehn generateNewXXXId gets
395: // called or the object gets created.
396:
397: for (int i = 0; i < 3; ++i) {
398: Formula f = new Formula(null, report, "");
399: Object id = f.getId();
400: assertTrue("formula id is not a Long", id instanceof Long);
401: long longVal = ((Long) id).longValue();
402: assertEquals(nextFormulaId, longVal);
403: report.addFormula(f);
404: ++nextFormulaId;
405:
406: Parameter p = new Parameter(null, report);
407: id = p.getId();
408: assertTrue("parameter id is not a Long", id instanceof Long);
409: longVal = ((Long) id).longValue();
410: assertEquals(nextParameterId, longVal);
411: report.addParameter(p);
412: ++nextParameterId;
413:
414: UserColumn uc = new UserColumn(null, report, "", "");
415: id = uc.getId();
416: assertTrue("user column id is not a Long",
417: id instanceof Long);
418: longVal = ((Long) id).longValue();
419: assertEquals(nextUserColumnId, longVal);
420: report.addUserColumn(uc);
421: ++nextUserColumnId;
422: }
423: }
424:
425: public static void main(String[] args) {
426: junit.textui.TestRunner.run(suite());
427: System.exit(0);
428: }
429:
430: }
|