/******************************************************************************* * Copyright 2017 Ivan Shubin http://galenframework.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.galenframework.suite.reader; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.List; import java.util.Properties; import com.galenframework.parser.SyntaxException; import com.galenframework.specs.Place; import com.galenframework.utils.GalenUtils; import com.galenframework.parser.VarsContext; import com.galenframework.tests.GalenBasicTest; public class GalenSuiteLineProcessor { private RootNode rootNode = new RootNode(); private Node<?> currentNode = rootNode; private boolean disableNextSuite = false; private String contextPath; private Properties properties; private List<String> groupsForNextTest; public GalenSuiteLineProcessor(Properties properties, String contextPath) { this.contextPath = contextPath; this.properties = properties; } public void processLine(String text, Place place) throws IOException { if (!isBlank(text) && !isCommented(text) && !isSeparator(text)) { if (text.startsWith("@@")) { Node<?> node = processSpecialInstruction(text.substring(2).trim(), place); if (node != null) { currentNode = node; } } else { int spaces = calculateIndentationSpaces(text); Node<?> processingNode = currentNode.findProcessingNodeByIndentation(spaces); Node<?> newNode = processingNode.processNewNode(text, place); if (newNode instanceof TestNode) { if (disableNextSuite) { disableNextSuite = false; ((TestNode)newNode).setDisabled(true); } if (groupsForNextTest != null) { ((TestNode)newNode).setGroups(groupsForNextTest); groupsForNextTest = null; } } currentNode = newNode; } } } private Node<?> processSpecialInstruction(String text, Place place) throws IOException { currentNode = rootNode; int indexOfFirstSpace = text.indexOf(' '); String firstWord; String leftover; if (indexOfFirstSpace > 0) { firstWord = text.substring(0, indexOfFirstSpace).toLowerCase(); leftover = text.substring(indexOfFirstSpace).trim(); } else { firstWord = text.toLowerCase(); leftover = ""; } if (firstWord.equals("set")) { return processInstructionSet(leftover, place); } else if (firstWord.equals("table")){ return processTable(leftover, place); } else if (firstWord.equals("parameterized")){ return processParameterized(leftover, place); } else if (firstWord.equals("disabled")) { markNextSuiteAsDisabled(); return null; } else if (firstWord.equals("groups")) { markNextSuiteGroupedWith(leftover); return null; } else if (firstWord.equals("import")) { List<Node<?>> nodes = importSuite(leftover, place); rootNode.getChildNodes().addAll(nodes); return null; } else throw new SuiteReaderException("Unknown instruction: " + firstWord); } private List<Node<?>> importSuite(String path, Place place) throws IOException { if (path.isEmpty()) { throw new SyntaxException(place, "No path specified for importing"); } String fullChildPath = contextPath + File.separator + path; String childContextPath = new File(fullChildPath).getParent(); GalenSuiteLineProcessor childProcessor = new GalenSuiteLineProcessor(properties, childContextPath); File file = new File(fullChildPath); if (!file.exists()) { throw new SyntaxException(place, "File doesn't exist: " + file.getAbsolutePath()); } childProcessor.readLines(new FileInputStream(file), fullChildPath); return childProcessor.rootNode.getChildNodes(); } private void markNextSuiteGroupedWith(String commaSeparatedGroups) { String[] groupsArray = commaSeparatedGroups.split(","); List<String> groups = new LinkedList<>(); for (String group : groupsArray) { String trimmedGroup = group.trim(); if (!trimmedGroup.isEmpty()) { groups.add(trimmedGroup); } } this.groupsForNextTest = groups; } private void markNextSuiteAsDisabled() { this.disableNextSuite = true; } private Node<?> processParameterized(String text, Place place) { ParameterizedNode parameterizedNode = new ParameterizedNode(text, place); if (disableNextSuite) { parameterizedNode.setDisabled(true); disableNextSuite = false; } if (groupsForNextTest != null) { parameterizedNode.setGroups(groupsForNextTest); groupsForNextTest = null; } currentNode.add(parameterizedNode); return parameterizedNode; } private Node<?> processTable(String text, Place place) { TableNode tableNode = new TableNode(text, place); currentNode.add(tableNode); return tableNode; } private Node<?> processInstructionSet(String text, Place place) { SetNode newNode = new SetNode(text, place); currentNode.add(newNode); return newNode; } public List<GalenBasicTest> buildSuites() { return rootNode.build(new VarsContext(properties)); } public static int calculateIndentationSpaces(String text) { int spacesCount = 0; for (int i=0; i< text.length(); i++) { if (text.charAt(i) == ' ') { spacesCount++; } else if (text.charAt(i) == '\t') { spacesCount += 4; } else { return spacesCount; } } return 0; } private boolean isSeparator(String text) { text = text.trim(); if (text.length() > 3) { char ch = text.charAt(0); for (int i = 1; i < text.length(); i++) { if (ch != text.charAt(i)) { return false; } } return true; } else return false; } private boolean isBlank(String text) { return text.trim().isEmpty(); } private boolean isCommented(String text) { return text.trim().startsWith("#"); } public void readLines(InputStream inputStream, String sourceName) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String lineText = bufferedReader.readLine(); int lineNumber = 0; while(lineText != null){ lineNumber++; lineText = GalenUtils.removeNonPrintableControlSymbols(lineText); processLine(lineText, new Place(sourceName, lineNumber)); lineText = bufferedReader.readLine(); } } }