1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package selectionresolution;
25
26import java.util.function.Consumer;
27import java.util.Collection;
28import java.util.LinkedList;
29import java.util.List;
30
31/**
32 * A master superclass for all selection/resolution tests.  Contains a
33 * couple of standard definitions that make writing these tests
34 * easier.
35 */
36public abstract class SelectionResolutionTest {
37
38    /**
39     * A unified output function, to ensure that all output goes to
40     * the right string (System.err).
41     *
42     * @param str The line to print.
43     */
44    protected void println(final String str) {
45        System.err.println(str);
46    }
47
48    /**
49     * A test group is a generator for a set of tests that should
50     * share common characteristics.  The Simple class provides a
51     * default implementation that should work for most purposes.
52     */
53    public static interface TestGroup {
54        /**
55         * Given an action that runs a given test case, generate and
56         * run all cases in this test group.
57         */
58        public void runCases(Consumer<SelectionResolutionTestCase> runner);
59
60        /**
61         * The basic implementation of TestGroup.  Produces one case
62         * for every possible combination of cases from each of its
63         * templates, by running them in order on an empty
64         * SelectionResolutionTestCase.Builder.  This should be good
65         * enough for writing most tests.
66         */
67        public static class Simple implements TestGroup {
68            private final Template[] templates;
69            private final SelectionResolutionTestCase.Builder initBuilder;
70
71            public Simple(final SelectionResolutionTestCase.Builder initBuilder,
72                          final Template... templates) {
73                this.templates = templates;
74                this.initBuilder = initBuilder;
75            }
76
77            @Override
78            public void runCases(final Consumer<SelectionResolutionTestCase> runner) {
79                Consumer<SelectionResolutionTestCase.Builder> curr = (builder) -> {
80                    runner.accept(builder.build());
81                };
82
83                for(int i = templates.length - 1; i >= 0; i--) {
84                    final Consumer<SelectionResolutionTestCase.Builder> next = curr;
85                    final Template template = templates[i];
86                    curr = (builder) -> {
87                        template.runCases(next, builder);
88                    };
89                }
90
91                curr.accept(initBuilder);
92            }
93        }
94    }
95
96    private final List<String> errs = new LinkedList<String>();
97
98    private final Collection<TestGroup> testGroups;
99
100    private int testcount = 0;
101
102    /**
103     * Create a test from a set of test groups.  Most actual tests can
104     * just define the test groups and pass them into this
105     * constructor, then call run.
106     */
107    protected SelectionResolutionTest(final Collection<TestGroup> testGroups) {
108        this.testGroups = testGroups;
109    }
110
111    /**
112     * Run all the tests, report errors if they happen.
113     */
114    protected void run() {
115        testGroups.stream().forEach(
116                (group) -> {
117                    group.runCases((final SelectionResolutionTestCase testcase) -> {
118                            testcount++;
119                            final String err = testcase.run();
120
121                            if (err != null) {
122                                errs.add(err);
123                            }
124                        });
125                });
126
127        println("Ran " + testcount + " cases");
128
129        if(!errs.isEmpty()) {
130            println("Errors occurred in test:");
131            for(final String err : errs) {
132                println(err);
133            }
134            throw new RuntimeException("Errors occurred in test");
135        } else {
136            println("All test cases succeeded");
137        }
138    }
139}
140