aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/junitparams/naming/MacroSubstitutionNamingStrategy.java
blob: ce5684717b0c707214c0398bbd68f54e5488f7db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package junitparams.naming;

import junitparams.internal.TestMethod;
import junitparams.internal.Utils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.regex.Pattern;

public class MacroSubstitutionNamingStrategy implements TestCaseNamingStrategy {
    private static final String MACRO_PATTERN = "\\{[^\\}]{0,50}\\}";
    // Pattern that keeps delimiters in split result
    private static final Pattern MACRO_SPLIT_PATTERN = Pattern.compile(String.format("(?=%s)|(?<=%s)", MACRO_PATTERN, MACRO_PATTERN));
    private static final String MACRO_START = "{";
    private static final String MACRO_END = "}";
    static final String DEFAULT_TEMPLATE = "[{index}] {params} ({method})";
    private TestMethod method;

    public MacroSubstitutionNamingStrategy(TestMethod testMethod) {
        this.method = testMethod;
    }

    @Override
    public String getTestCaseName(int parametersIndex, Object parameters) {
        TestCaseName testCaseName = method.getAnnotation(TestCaseName.class);

        String template = getTemplate(testCaseName);
        String builtName = buildNameByTemplate(template, parametersIndex, parameters);

        if (builtName.trim().isEmpty()) {
            return buildNameByTemplate(DEFAULT_TEMPLATE, parametersIndex, parameters);
        } else {
            return builtName;
        }
    }

    private String getTemplate(TestCaseName testCaseName) {
        if (testCaseName != null) {
            return testCaseName.value();
        }

        return DEFAULT_TEMPLATE;
    }

    private String buildNameByTemplate(String template, int parametersIndex, Object parameters) {
        StringBuilder nameBuilder = new StringBuilder();

        String[] parts = MACRO_SPLIT_PATTERN.split(template);

        for (String part : parts) {
            String transformedPart = transformPart(part, parametersIndex, parameters);
            nameBuilder.append(transformedPart);
        }

        return nameBuilder.toString();
    }

    private String transformPart(String part, int parametersIndex, Object parameters) {
        if (isMacro(part)) {
            return lookupMacroValue(part, parametersIndex, parameters);
        }

        return part;
    }

    private String lookupMacroValue(String macro, int parametersIndex, Object parameters) {
        String macroKey = getMacroKey(macro);

        switch (Macro.parse(macroKey)) {
            case INDEX: return String.valueOf(parametersIndex);
            case PARAMS: return Utils.stringify(parameters);
            case METHOD: return method.name();
            default: return substituteDynamicMacro(macro, macroKey, parameters);
        }
    }

    private String substituteDynamicMacro(String macro, String macroKey, Object parameters) {
        if (isMethodParameterIndex(macroKey)) {
            int index = parseIndex(macroKey);
            return Utils.getParameterStringByIndexOrEmpty(parameters, index);
        }

        return macro;
    }

    private boolean isMethodParameterIndex(String macroKey) {
        return macroKey.matches("\\d+");
    }

    private int parseIndex(String macroKey) {
        return Integer.parseInt(macroKey);
    }

    private String getMacroKey(String macro) {
        return macro
                .substring(MACRO_START.length(), macro.length() - MACRO_END.length())
                .toUpperCase(Locale.ENGLISH);
    }

    private boolean isMacro(String part) {
        return part.startsWith(MACRO_START) && part.endsWith(MACRO_END);
    }

    private enum Macro {
        INDEX,
        PARAMS,
        METHOD,
        NONE;

        public static Macro parse(String value) {
            if (macros.contains(value)) {
                return Macro.valueOf(value);
            } else {
                return Macro.NONE;
            }
        }

        private static final HashSet<String> macros = new HashSet<String>(Arrays.asList(
                Macro.INDEX.toString(), Macro.PARAMS.toString(), Macro.METHOD.toString())
        );
    }
}