Package jimm.datavision.test

Source Code of jimm.datavision.test.CharSepTest

package jimm.datavision.test;
import jimm.datavision.*;
import jimm.datavision.field.*;
import jimm.datavision.layout.CharSepLE;
import jimm.datavision.source.Column;
import jimm.datavision.source.charsep.CharSepSource;
import java.io.*;
import java.util.Date;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.Test;

/**
* Reads a report from an XML file, runs it, and verifies the output. Uses
* a {@link CharSepSource} data source and the {@link CharSepLE} layout engine
* to produce a tab-delimited output file.
* <p>
* These tests are tightly coupled with the contents of the files
* <code>charsep.xml</code> and <code>charsep_data.csv</code>.
*
* @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
*/
public class CharSepTest extends TestCase {

protected static final File EXAMPLE_REPORT =
    new File(AllTests.testDataFile("charsep.xml"));
protected static final String DATA_FILE =
    AllTests.testDataFile("charsep_data.csv");
protected static final String EMPTY_DATA_FILE =
    AllTests.testDataFile("empty.csv");
protected static final String DATA_FILE_WITH_SHORT_LINES =
    AllTests.testDataFile("short_lines.csv");
protected static final File OUT_FILE =
    new File(System.getProperty("java.io.tmpdir"),
       "datavision_charsep_test_out.txt");
// This must match the format string for the report.date field in
// EXAMPLE_REPORT.
protected static final String REPORT_DATE_FORMAT = "yyyy-MM-dd";
// This must be an alphabetically sorted list of office names from the
// offices table, EXCEPT for Chicago, which is excluded by the where
// clause.
protected static final String OFFICES[] = {
    "New Jersey", "New York"
};
// The value of the report.title special field, which appears
// in the report header.
protected static final String REPORT_TITLE = "Example Report";

protected Report report;
protected CharSepSource dataSource;
protected DecimalFormat dollarFormatter;
protected DecimalFormat lastColFormatter;
protected SimpleDateFormat titleDateFormatter;
protected int reportRowNumber;
protected int officeRowNumber;
protected int postDateRowNumber;

public static Test suite() {
    return new TestSuite(CharSepTest.class);
}

public CharSepTest(String name) {
    super(name);
}

public void setUp() throws Exception {
    dollarFormatter = new DecimalFormat("$#,###.00");
    lastColFormatter = new DecimalFormat("#,###.##");
    titleDateFormatter = new SimpleDateFormat(REPORT_DATE_FORMAT);

    report = new Report();
    reportRowNumber = officeRowNumber = postDateRowNumber = 1;

    OUT_FILE.deleteOnExit();
    PrintWriter out = new PrintWriter(new FileWriter(OUT_FILE));
    report.setLayoutEngine(new CharSepLE(out, '\t'));

    report.read(EXAMPLE_REPORT); // Must come after setting password

    dataSource = (CharSepSource)report.getDataSource();
    dataSource.setSepChar(',');
    dataSource.setInput(DATA_FILE);
}

public void tearDown() {
    if (OUT_FILE.exists())
  OUT_FILE.delete();
}

public void testColumnInfo() {
    String[] colNames = { "office.name", "jobs.ID", "jobs.title",
        "jobs.hourly rate", "jobs.post_date" };
    for (int i = 0; i < colNames.length; ++i) {
  Column col;
  assertNotNull(col = dataSource.findColumn(colNames[i]));
  assertEquals(i, dataSource.indexOfSelectable(col));
    }
}

public void testReportRun() throws IOException, FileNotFoundException {
    assertEquals("{office.name} != 'Chicago'",
     report.getDataSource().getQuery().getWhereClause());

    // Run report in this thread, not a separate one. Running the
    // report closes the output stream.
    report.runReport();

    // Open the output and look for various things.
    BufferedReader in = new BufferedReader(new FileReader(OUT_FILE));

    expectHeaders(in);

    // Each of the office groups. checkOfficeGroup() returns the total
    // dollar amount (really the total id number amount, but that is proved
    // to be the same thing within checkDetailLine()).
    int total = 0;
    for (int i = 0; i < OFFICES.length; ++i)
  total += checkOfficeGroup(in, OFFICES[i]);

    // The grand total.
    String line = in.readLine();
    assertNotNull(line);
    if (line.startsWith("Page "))
  assertNotNull(line = in.readLine());

    assertEquals("Grand Total:\t" + dollarFormatter.format(total)
     + "\t" + (reportRowNumber - 1)
     + "\t" + (reportRowNumber - 1),
     line);

    // The final page number.
    assertNotNull(line = in.readLine());
    assertEquals("Page ", line.substring(0, 5));

    // Make sure we are at the end of the file.
    assertNull(in.readLine());

    in.close();
}

protected void expectHeaders(BufferedReader in) throws IOException {
    String line;

    // Line 1: report title and formatted date.
    // since that will most definitely be different.
    assertNotNull(line = in.readLine());
    assertEquals(REPORT_TITLE + '\t'
     + "file:examples/Home16.gif"
     + '\t' + titleDateFormatter.format(new Date()),
     line);

    // Line 2: the page header.
    assertNotNull(line = in.readLine());
    assertEquals(0, line.indexOf("Job #\tTitle\tHourly Rate"));
}

/**
* Checks a group (header plus detail lines) and returns the total
* of the dollar amounts in the group.
*
* @param in the input reader
* @param officeName the group name
* @return the total dollar amount in the group
*/
protected int checkOfficeGroup(BufferedReader in, String officeName)
    throws IOException
{
    String line;
    int aggregate = 0;

    officeRowNumber = 1;

    // The office name. Skip page delimiters ("Page" at foot and
    // page headers at top).
    assertNotNull(line = in.readLine());
    while (line.startsWith("Page ") || line.startsWith("Job #\t"))
  assertNotNull(line = in.readLine());
    assertEquals(officeName, line);

    Object postDateGroupEnd;
    while ((postDateGroupEnd = checkPostDateGroup(in)) instanceof Integer)
  aggregate += ((Integer)postDateGroupEnd).intValue();
    line = (String)postDateGroupEnd;

    assertEquals("Total:\t" + dollarFormatter.format(aggregate)
     + "\t" + (reportRowNumber - 1)
     + "\t" + (officeRowNumber - 1),
     line);

    return aggregate;
}

/**
* Checks a subgroup (header plus detail lines) and returns the total
* of the dollar amounts in the group. If the next report section is
* not a subgroup, it will be a group total line; we return the line
*
* @param in the input reader
* @return either an Integer containing the total or the next line read
* from the report
*/
protected Object checkPostDateGroup(BufferedReader in) throws IOException {
    int aggregate = 0;
    String line;

    postDateRowNumber = 1;

    // Read either post date or next (super)group name. Return false if we
    // see a non-date group name; that means we're done. Skip page
    // delimiters ("Page" at foot and page headers at top).
    while (true) {
  assertNotNull(line = in.readLine());
  if (line.startsWith("Page ") || line.startsWith("Job #\t"))
      continue;
  if (line.startsWith("Total:"))
      return line;

  // Primitive date check
  assertTrue(Character.isDigit(line.charAt(0)) && line.length() == 10
       && line.charAt(4) == '-' && line.charAt(7) == '-');
  break;
    }

    // The detail lines. Collect the id number from the beginning of each
    // detail line. It is the same as the dollar amount value. Add that
    // amount to the aggregate.
    while (true) {
  assertNotNull(line = in.readLine());
  if (line.startsWith("Post Date Total:"))
      break;
  if (line.startsWith("Page ") || line.startsWith("Job #\t"))
      continue;

  aggregate += checkDetailLine(line);
    }

    assertEquals("Post Date Total:\t" + dollarFormatter.format(aggregate)
     + "\t" + (reportRowNumber - 1)
     + "\t" + (postDateRowNumber - 1),
     line);

    return new Integer(aggregate);
}

/**
* Checks the format of a detail line and returns the integer id found
* at the beginning of line. This is the same as the dollar amount.
*
* @param line a detail line
* @return the id number
*/
protected int checkDetailLine(String line) {
    // Read job id from the beginning of the line.
    int id = Integer.parseInt(line.substring(0, line.indexOf("\t")));

    // The description, at random, may be repeated ("job 3 job 3"). We
    // check for the first full description.
    String str = "" + id + "\tThis is the short description of job " + id;
    assertTrue("line does not start with \"" + str + "\"",
         line.startsWith(str));

    // Check for the remaining columns at the end of the line. We are also
    // assuring that the dollar amount is the same as the id number.
    if (id == 0) {
  assertEquals("0\tThis is the short description of job 0\t\t\t\t"
         + reportRowNumber + "\t" + postDateRowNumber,
         line);
    }
    else {
  str = "\t" + (id * 100)
      + "\t" + dollarFormatter.format(id)
      + "\t" + lastColFormatter.format(id)
      + "\t" + reportRowNumber
      + "\t" + postDateRowNumber;
  assertTrue("line \"" + line + "\" does not end with \"" + str,
       line.endsWith(str));
    }

    ++reportRowNumber;
    ++officeRowNumber;
    ++postDateRowNumber;

    return id;
}

// We used to throw an exception if there were no records returned
// by the query but there was a column field in the page header or
// report header.
public void testNoRecords() {
    try {
  // Add a column field to the report header
  Section pageHeader =
      report.getFirstSectionByArea(SectionArea.PAGE_HEADER);
  assertNotNull(pageHeader);
  ColumnField f = new ColumnField(null, report, pageHeader,
          "office.name", true);
  pageHeader.addField(f);

  // Create a query that returns 0 records
  report.getDataSource().getQuery().setWhereClause("1 == 2");

  // Run the report. We shouldn't throw an exception.
  report.runReport();
    }
    catch (Exception e) {
  fail("should not throw an exception just 'cause there are no records");
    }
}

// public void testWhereClause() {
// }

public void testEmptyFile() {
    try {
  dataSource.setInput(EMPTY_DATA_FILE);
  report.runReport();
    }
    catch (Exception e) {
  fail("should not throw an exception just 'cause the file is empty");
    }
}

public void testShortInputLines() {
    try {
  dataSource.setInput(DATA_FILE_WITH_SHORT_LINES);
  report.runReport();
    }
    catch (Exception e) {
  fail("should not throw an exception just 'cause some lines are short");
    }
}

public static void main(String[] args) {
    junit.textui.TestRunner.run(suite());
    System.exit(0);
}

}
TOP

Related Classes of jimm.datavision.test.CharSepTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.