001/*
002 * Copyright (C) 2009-2011 Mathias Doenitz
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.parboiled.testing;
018
019import org.parboiled.Node;
020import org.parboiled.Rule;
021import org.parboiled.buffers.InputBuffer;
022import org.parboiled.common.Predicate;
023import org.parboiled.parserunners.RecoveringParseRunner;
024import org.parboiled.parserunners.ReportingParseRunner;
025import org.parboiled.support.ParsingResult;
026import org.parboiled.parserunners.RecoveringParseRunner;
027import org.parboiled.parserunners.ReportingParseRunner;
028import org.parboiled.support.ParseTreeUtils;
029import org.parboiled.support.ParsingResult;
030
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.Collections;
034import java.util.List;
035
036import static org.parboiled.errors.ErrorUtils.printParseErrors;
037import static org.parboiled.support.ParseTreeUtils.printNodeTree;
038
039public abstract class ParboiledTest<V> {
040
041    public class TestResult<V> {
042        public final ParsingResult<V> result;
043
044        public TestResult(ParsingResult<V> result) {
045            this.result = result;
046        }
047
048        public TestResult<V> hasNoErrors() {
049            if (result.hasErrors()) {
050                fail("\n--- ParseErrors ---\n" +
051                        printParseErrors(result) +
052                        "\n--- ParseTree ---\n" +
053                        ParseTreeUtils.printNodeTree(result)
054                );
055            }
056            return this;
057        }
058
059        public TestResult<V> hasErrors(String expectedErrors) {
060            assertEquals(printParseErrors(result), expectedErrors);
061            return this;
062        }
063
064        public TestResult<V> hasParseTree(String expectedTree) {
065            assertEquals(ParseTreeUtils.printNodeTree(result), expectedTree);
066            return this;
067        }
068
069        public TestResult<V> hasParseTree(Predicate<Node<V>> nodeFilter, Predicate<Node<V>> subTreeFilter,
070                                          String expectedTree) {
071            assertEquals(ParseTreeUtils.printNodeTree(result, nodeFilter, subTreeFilter), expectedTree);
072            return this;
073        }
074
075        public TestResult<V> hasResult(V... expectedResults) {
076            assertEquals(toListReversed(result.valueStack), Arrays.asList(expectedResults));
077            return this;
078        }
079        
080        private <T> List<T> toListReversed(Iterable<T> iterable) {
081            List<T> list = new ArrayList<T>();
082            for (T t : iterable) list.add(t);
083            Collections.reverse(list);
084            return list;
085        }
086    }
087
088    public TestResult<V> test(Rule rule, String input) {
089        return new TestResult<V>(new ReportingParseRunner<V>(rule).run(input));
090    }
091    
092    public TestResult<V> test(Rule rule, InputBuffer inputBuffer) {
093        return new TestResult<V>(new ReportingParseRunner<V>(rule).run(inputBuffer));
094    }
095
096    public TestResult<V> testWithRecovery(Rule rule, String input) {
097        return new TestResult<V>(new RecoveringParseRunner<V>(rule).run(input));
098    }
099    
100    public TestResult<V> testWithRecovery(Rule rule, InputBuffer inputBuffer) {
101        return new TestResult<V>(new RecoveringParseRunner<V>(rule).run(inputBuffer));
102    }
103
104    protected abstract void fail(String message);
105
106    protected abstract void assertEquals(Object actual, Object expected);
107}