Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TestFileParser.java
Go to the documentation of this file.
1 // Copyright (c) 2012 Cloudera, Inc. All rights reserved.
2 
3 package com.cloudera.impala.testutil;
4 
5 import static org.junit.Assert.fail;
6 
7 import java.io.BufferedReader;
8 import java.io.File;
9 import java.io.FileReader;
10 import java.io.IOException;
11 import java.util.ArrayList;
12 import java.util.EnumMap;
13 import java.util.List;
14 import java.util.Scanner;
15 
16 import org.apache.log4j.Logger;
17 
18 import com.google.common.base.Joiner;
19 import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps;
21 
51 public class TestFileParser {
52  private static final Logger LOG = Logger.getLogger(TestCase.class);
53 
57  public enum Section {
70 
71  // Return header line for this section
72  public String getHeader() {
73  return "---- " + this.toString();
74  }
75  }
76 
81  public static class TestCase {
82 
83  private final EnumMap<Section, ArrayList<String>> expectedResultSections =
84  Maps.newEnumMap(Section.class);
85 
86  // Line number in the test case file where this case started
87  private final int startLineNum;
88 
89  public TestCase(int lineNum) {
91  }
92 
93  public int getStartingLineNum() {
94  return startLineNum;
95  }
96 
97  protected void addSection(Section section, ArrayList<String> contents) {
98  expectedResultSections.put(section, contents);
99  }
100 
105  public ArrayList<String> getSectionContents(Section section) {
106  return getSectionContents(section, false);
107  }
108 
109  public ArrayList<String> getSectionContents(Section section, boolean withComments) {
110  return getSectionContents(section, withComments, null);
111  }
112 
125  public ArrayList<String> getSectionContents(Section section, boolean withComments,
126  String dbSuffix) {
127  ArrayList<String> ret = expectedResultSections.get(section);
128  if (ret == null) {
129  return Lists.newArrayList();
130  } else if (withComments && dbSuffix == null) {
131  return ret;
132  }
133 
134  ArrayList<String> retList = Lists.newArrayList();
135  for (String s : ret) {
136  if (!(s.startsWith("#") || s.startsWith("//"))) {
137  if (dbSuffix != null) {
138  retList.add(s.replaceAll("\\$DATABASE", dbSuffix));
139  } else {
140  retList.add(s);
141  }
142  } else if (withComments) {
143  retList.add(s);
144  }
145  }
146 
147  return retList;
148  }
149 
150  public String getSectionAsString(Section section, boolean withComments,
151  String delimiter) {
152  return getSectionAsString(section, withComments, delimiter, null);
153  }
154 
159  public String getSectionAsString(Section section, boolean withComments,
160  String delimiter, String dbSuffix) {
161  List<String> sectionList = getSectionContents(section, withComments, dbSuffix);
162  if (sectionList == null) {
163  return null;
164  }
165 
166  return Joiner.on(delimiter).join(sectionList);
167  }
168 
172  public String getQuery() {
173  return getSectionAsString(Section.QUERY, false, "\n");
174  }
175 
179  public boolean isValid() {
180  return !getQuery().isEmpty() && (!getSectionContents(Section.PLAN).isEmpty() ||
182  !getSectionContents(Section.LINEAGE).isEmpty());
183  }
184  }
185 
186  private final List<TestCase> testCases = Lists.newArrayList();
187 
188  private int lineNum = 0;
189  private final String fileName;
190  private BufferedReader reader;
191  private Scanner scanner;
192  private boolean hasSetupSection = false;
193 
198  static private final ArrayList<Section> defaultSectionOrder =
199  Lists.newArrayList(Section.QUERY, Section.TYPES, Section.RESULTS);
200 
201  public TestFileParser(String fileName) {
202  this.fileName = fileName;
203  }
204 
205  public List<TestCase> getTestCases() {
206  return testCases;
207  }
208 
209  public String getTestFileName() {
210  return fileName;
211  }
212 
213  public boolean hasSetupSection() {
214  return hasSetupSection;
215  }
216 
220  private void open(String table) {
221  try {
222  String testFileBaseDir =
223  new File(System.getenv("IMPALA_HOME"), "testdata/workloads").getPath();
224  String fullPath = new File(testFileBaseDir, fileName).getPath();
225  reader = new BufferedReader(new FileReader(fullPath));
226  scanner = new Scanner(reader);
227  } catch (Exception e) {
228  fail(e.getMessage());
229  }
230  }
231 
236  Section currentSection = Section.QUERY;
237  ArrayList<String> sectionContents = Lists.newArrayList();
238  TestCase currentTestCase = new TestCase(lineNum);
239  int sectionCount = 0;
240 
241  while (scanner.hasNextLine()) {
242  String line = scanner.nextLine();
243  ++lineNum;
244  if (line.startsWith("====") && sectionCount > 0) {
245  currentTestCase.addSection(currentSection, sectionContents);
246  if(!currentTestCase.isValid()) {
247  throw new IllegalStateException("Invalid test case" +
248  " at line " + currentTestCase.startLineNum + " detected.");
249  }
250  return currentTestCase; // done with this test case
251  }
252  if (line.startsWith("----")) {
253  sectionCount++;
254  // New section
255  currentTestCase.addSection(currentSection, sectionContents);
256  boolean found = false;
257  line = line.trim().toLowerCase();
258 
259  // Check for section header - a missing header probably means an old test file.
260  if (!line.endsWith("----")) {
261  for (Section s : Section.values()) {
262  if (line.matches("----\\s+" + s.toString().toLowerCase() + "\\b.*")) {
263  currentSection = s;
264  if (s == Section.SETUP) {
265  hasSetupSection = true;
266  }
267  found = true;
268  break;
269  }
270  }
271  if (!found) {
272  throw new IllegalStateException("Unknown section name: " + line);
273  }
274  } else {
275  // Backwards compatibility only - TODO remove once all test files have section
276  // headers.
277  if (sectionCount >= defaultSectionOrder.size()) {
278  throw new IllegalStateException("Unexpected number of untitled sections: "
279  + sectionCount);
280  }
281  currentSection = defaultSectionOrder.get(sectionCount);
282  LOG.warn("No section header found. Guessing: " + currentSection);
283  }
284 
285  sectionContents = Lists.newArrayList();
286  } else {
287  sectionContents.add(line);
288  }
289  }
290 
291  if(!currentTestCase.isValid()) {
292  throw new IllegalStateException("Invalid test case" +
293  " at line " + currentTestCase.startLineNum + " detected.");
294  }
295 
296  return currentTestCase;
297  }
298 
302  public void parseFile() {
303  parseFile(null);
304  }
305 
306  public void parseFile(String table) {
307  try {
308  open(table);
309  testCases.clear();
310  while (scanner.hasNextLine()) {
311  testCases.add(parseOneTestCase());
312  }
313  } finally {
314  close();
315  }
316  }
317 
318  private void close() {
319  if (reader != null) {
320  try {
321  reader.close();
322  } catch (IOException e) {
323  fail(e.getMessage());
324  }
325  }
326 
327  if (scanner != null) {
328  scanner.close();
329  }
330  }
331 }
ArrayList< String > getSectionContents(Section section)
String getSectionAsString(Section section, boolean withComments, String delimiter, String dbSuffix)
ArrayList< String > getSectionContents(Section section, boolean withComments)
static final ArrayList< Section > defaultSectionOrder
String getSectionAsString(Section section, boolean withComments, String delimiter)
final EnumMap< Section, ArrayList< String > > expectedResultSections
void addSection(Section section, ArrayList< String > contents)
ArrayList< String > getSectionContents(Section section, boolean withComments, String dbSuffix)