You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CellFormatTestBase.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.format;
  16. import junit.framework.TestCase;
  17. import org.apache.poi.ss.usermodel.*;
  18. import org.apache.poi.ss.ITestDataProvider;
  19. import javax.swing.*;
  20. import java.awt.*;
  21. import java.util.*;
  22. import static java.awt.Color.*;
  23. import java.io.IOException;
  24. /**
  25. * This class is a base class for spreadsheet-based tests, such as are used for
  26. * cell formatting. This reads tests from the spreadsheet, as well as reading
  27. * flags that can be used to paramterize these tests.
  28. * <p/>
  29. * Each test has four parts: The expected result (column A), the format string
  30. * (column B), the value to format (column C), and a comma-separated list of
  31. * categores that this test falls in. Normally all tests are run, but if the
  32. * flag "Categories" is not empty, only tests that have at least one category
  33. * listed in "Categories" are run.
  34. */
  35. @SuppressWarnings(
  36. {"JUnitTestCaseWithNoTests", "JUnitTestClassNamingConvention"})
  37. public class CellFormatTestBase extends TestCase {
  38. private final ITestDataProvider _testDataProvider;
  39. protected Workbook workbook;
  40. private String testFile;
  41. private Map<String, String> testFlags;
  42. private boolean tryAllColors;
  43. private JLabel label;
  44. private static final String[] COLOR_NAMES =
  45. {"Black", "Red", "Green", "Blue", "Yellow", "Cyan", "Magenta",
  46. "White"};
  47. private static final Color[] COLORS =
  48. {BLACK, RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA, WHITE};
  49. public static final Color TEST_COLOR = ORANGE.darker();
  50. protected CellFormatTestBase(ITestDataProvider testDataProvider) {
  51. _testDataProvider = testDataProvider;
  52. }
  53. abstract static class CellValue {
  54. abstract Object getValue(Cell cell);
  55. @SuppressWarnings({"UnusedDeclaration"})
  56. Color getColor(Cell cell) {
  57. return TEST_COLOR;
  58. }
  59. void equivalent(String expected, String actual, CellFormatPart format) {
  60. assertEquals("format \"" + format + "\"", '"' + expected + '"',
  61. '"' + actual + '"');
  62. }
  63. }
  64. protected void runFormatTests(String workbookName, CellValue valueGetter)
  65. throws IOException {
  66. openWorkbook(workbookName);
  67. readFlags(workbook);
  68. Set<String> runCategories = new TreeSet<String>(
  69. String.CASE_INSENSITIVE_ORDER);
  70. String runCategoryList = flagString("Categories", "");
  71. if (runCategoryList != null) {
  72. runCategories.addAll(Arrays.asList(runCategoryList.split(
  73. "\\s*,\\s*")));
  74. runCategories.remove(""); // this can be found and means nothing
  75. }
  76. Sheet sheet = workbook.getSheet("Tests");
  77. int end = sheet.getLastRowNum();
  78. // Skip the header row, therefore "+ 1"
  79. for (int r = sheet.getFirstRowNum() + 1; r <= end; r++) {
  80. Row row = sheet.getRow(r);
  81. if (row == null)
  82. continue;
  83. int cellnum = 0;
  84. String expectedText = row.getCell(cellnum).getStringCellValue();
  85. String format = row.getCell(1).getStringCellValue();
  86. String testCategoryList = row.getCell(3).getStringCellValue();
  87. boolean byCategory = runByCategory(runCategories, testCategoryList);
  88. if ((!expectedText.isEmpty() || !format.isEmpty()) && byCategory) {
  89. Cell cell = row.getCell(2);
  90. tryFormat(r, expectedText, format, valueGetter, cell);
  91. }
  92. }
  93. }
  94. /**
  95. * Open a given workbook.
  96. *
  97. * @param workbookName The workbook name. This is presumed to live in the
  98. * "spreadsheets" directory under the directory named in
  99. * the Java property "POI.testdata.path".
  100. *
  101. * @throws IOException
  102. */
  103. protected void openWorkbook(String workbookName)
  104. throws IOException {
  105. workbook = _testDataProvider.openSampleWorkbook(workbookName);
  106. workbook.setMissingCellPolicy(Row.CREATE_NULL_AS_BLANK);
  107. testFile = workbookName;
  108. }
  109. /**
  110. * Read the flags from the workbook. Flags are on the sheet named "Flags",
  111. * and consist of names in column A and values in column B. These are put
  112. * into a map that can be queried later.
  113. *
  114. * @param wb The workbook to look in.
  115. */
  116. private void readFlags(Workbook wb) {
  117. Sheet flagSheet = wb.getSheet("Flags");
  118. testFlags = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
  119. if (flagSheet != null) {
  120. int end = flagSheet.getLastRowNum();
  121. // Skip the header row, therefore "+ 1"
  122. for (int r = flagSheet.getFirstRowNum() + 1; r <= end; r++) {
  123. Row row = flagSheet.getRow(r);
  124. if (row == null)
  125. continue;
  126. String flagName = row.getCell(0).getStringCellValue();
  127. String flagValue = row.getCell(1).getStringCellValue();
  128. if (flagName.length() > 0) {
  129. testFlags.put(flagName, flagValue);
  130. }
  131. }
  132. }
  133. tryAllColors = flagBoolean("AllColors", true);
  134. }
  135. /**
  136. * Returns <tt>true</tt> if any of the categories for this run are contained
  137. * in the test's listed categories.
  138. *
  139. * @param categories The categories of tests to be run. If this is
  140. * empty, then all tests will be run.
  141. * @param testCategories The categories that this test is in. This is a
  142. * comma-separated list. If <em>any</em> tests in
  143. * this list are in <tt>categories</tt>, the test will
  144. * be run.
  145. *
  146. * @return <tt>true</tt> if the test should be run.
  147. */
  148. private boolean runByCategory(Set<String> categories,
  149. String testCategories) {
  150. if (categories.isEmpty())
  151. return true;
  152. // If there are specified categories, find out if this has one of them
  153. for (String category : testCategories.split("\\s*,\\s*")) {
  154. if (categories.contains(category)) {
  155. return true;
  156. }
  157. }
  158. return false;
  159. }
  160. private void tryFormat(int row, String expectedText, String desc,
  161. CellValue getter, Cell cell) {
  162. Object value = getter.getValue(cell);
  163. Color testColor = getter.getColor(cell);
  164. if (testColor == null)
  165. testColor = TEST_COLOR;
  166. if (label == null)
  167. label = new JLabel();
  168. label.setForeground(testColor);
  169. label.setText("xyzzy");
  170. System.out.printf("Row %d: \"%s\" -> \"%s\": expected \"%s\"", row + 1,
  171. String.valueOf(value), desc, expectedText);
  172. System.out.flush();
  173. String actualText = tryColor(desc, null, getter, value, expectedText,
  174. testColor);
  175. System.out.printf(", actual \"%s\")%n", actualText);
  176. System.out.flush();
  177. if (tryAllColors && testColor != TEST_COLOR) {
  178. for (int i = 0; i < COLOR_NAMES.length; i++) {
  179. String cname = COLOR_NAMES[i];
  180. tryColor(desc, cname, getter, value, expectedText, COLORS[i]);
  181. }
  182. }
  183. }
  184. private String tryColor(String desc, String cname, CellValue getter,
  185. Object value, String expectedText, Color expectedColor) {
  186. if (cname != null)
  187. desc = "[" + cname + "]" + desc;
  188. Color origColor = label.getForeground();
  189. CellFormatPart format = new CellFormatPart(desc);
  190. if (!format.apply(label, value).applies) {
  191. // If this doesn't apply, no color change is expected
  192. expectedColor = origColor;
  193. }
  194. String actualText = label.getText();
  195. Color actualColor = label.getForeground();
  196. getter.equivalent(expectedText, actualText, format);
  197. assertEquals(cname == null ? "no color" : "color " + cname,
  198. expectedColor, actualColor);
  199. return actualText;
  200. }
  201. /**
  202. * Returns the value for the given flag. The flag has the value of
  203. * <tt>true</tt> if the text value is <tt>"true"</tt>, <tt>"yes"</tt>, or
  204. * <tt>"on"</tt> (ignoring case).
  205. *
  206. * @param flagName The name of the flag to fetch.
  207. * @param expected The value for the flag that is expected when the tests
  208. * are run for a full test. If the current value is not the
  209. * expected one, you will get a warning in the test output.
  210. * This is so that you do not accidentally leave a flag set
  211. * to a value that prevents running some tests, thereby
  212. * letting you accidentally release code that is not fully
  213. * tested.
  214. *
  215. * @return The value for the flag.
  216. */
  217. protected boolean flagBoolean(String flagName, boolean expected) {
  218. String value = testFlags.get(flagName);
  219. boolean isSet;
  220. if (value == null)
  221. isSet = false;
  222. else {
  223. isSet = value.equalsIgnoreCase("true") || value.equalsIgnoreCase(
  224. "yes") || value.equalsIgnoreCase("on");
  225. }
  226. warnIfUnexpected(flagName, expected, isSet);
  227. return isSet;
  228. }
  229. /**
  230. * Returns the value for the given flag.
  231. *
  232. * @param flagName The name of the flag to fetch.
  233. * @param expected The value for the flag that is expected when the tests
  234. * are run for a full test. If the current value is not the
  235. * expected one, you will get a warning in the test output.
  236. * This is so that you do not accidentally leave a flag set
  237. * to a value that prevents running some tests, thereby
  238. * letting you accidentally release code that is not fully
  239. * tested.
  240. *
  241. * @return The value for the flag.
  242. */
  243. protected String flagString(String flagName, String expected) {
  244. String value = testFlags.get(flagName);
  245. if (value == null)
  246. value = "";
  247. warnIfUnexpected(flagName, expected, value);
  248. return value;
  249. }
  250. private void warnIfUnexpected(String flagName, Object expected,
  251. Object actual) {
  252. if (!actual.equals(expected)) {
  253. System.err.println(
  254. "WARNING: " + testFile + ": " + "Flag " + flagName +
  255. " = \"" + actual + "\" [not \"" + expected + "\"]");
  256. }
  257. }
  258. }