• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package junitparams.naming;
2 
3 import junitparams.internal.TestMethod;
4 import junitparams.internal.Utils;
5 
6 import java.util.Arrays;
7 import java.util.HashSet;
8 import java.util.Locale;
9 import java.util.regex.Pattern;
10 
11 public class MacroSubstitutionNamingStrategy implements TestCaseNamingStrategy {
12     private static final String MACRO_PATTERN = "\\{[^\\}]{0,50}\\}";
13     // Pattern that keeps delimiters in split result
14     private static final Pattern MACRO_SPLIT_PATTERN = Pattern.compile(String.format("(?=%s)|(?<=%s)", MACRO_PATTERN, MACRO_PATTERN));
15     private static final String MACRO_START = "{";
16     private static final String MACRO_END = "}";
17     // Android-changed: CTS and AndroidJUnitRunner rely on specific format to test names, changing
18     // them will prevent CTS and AndroidJUnitRunner from working properly; see b/36541809
19     static final String DEFAULT_TEMPLATE = "{method}[{index}]";
20     private TestMethod method;
21 
MacroSubstitutionNamingStrategy(TestMethod testMethod)22     public MacroSubstitutionNamingStrategy(TestMethod testMethod) {
23         this.method = testMethod;
24     }
25 
26     @Override
getTestCaseName(int parametersIndex, Object parameters)27     public String getTestCaseName(int parametersIndex, Object parameters) {
28         TestCaseName testCaseName = method.getAnnotation(TestCaseName.class);
29 
30         String template = getTemplate(testCaseName);
31         String builtName = buildNameByTemplate(template, parametersIndex, parameters);
32 
33         if (builtName.trim().isEmpty()) {
34             return buildNameByTemplate(DEFAULT_TEMPLATE, parametersIndex, parameters);
35         } else {
36             return builtName;
37         }
38     }
39 
getTemplate(TestCaseName testCaseName)40     private String getTemplate(TestCaseName testCaseName) {
41         if (testCaseName != null) {
42             // Android-changed: CTS and AndroidJUnitRunner rely on specific format to test names,
43             // changing them will prevent CTS and AndroidJUnitRunner from working properly;
44             // see b/36541809
45             throw new IllegalStateException(
46                     "@TestCaseName not currently supported as it breaks running tests in CTS");
47             // return testCaseName.value();
48         }
49 
50         return DEFAULT_TEMPLATE;
51     }
52 
buildNameByTemplate(String template, int parametersIndex, Object parameters)53     private String buildNameByTemplate(String template, int parametersIndex, Object parameters) {
54         StringBuilder nameBuilder = new StringBuilder();
55 
56         String[] parts = MACRO_SPLIT_PATTERN.split(template);
57 
58         for (String part : parts) {
59             String transformedPart = transformPart(part, parametersIndex, parameters);
60             nameBuilder.append(transformedPart);
61         }
62 
63         return nameBuilder.toString();
64     }
65 
transformPart(String part, int parametersIndex, Object parameters)66     private String transformPart(String part, int parametersIndex, Object parameters) {
67         if (isMacro(part)) {
68             return lookupMacroValue(part, parametersIndex, parameters);
69         }
70 
71         return part;
72     }
73 
lookupMacroValue(String macro, int parametersIndex, Object parameters)74     private String lookupMacroValue(String macro, int parametersIndex, Object parameters) {
75         String macroKey = getMacroKey(macro);
76 
77         switch (Macro.parse(macroKey)) {
78             case INDEX: return String.valueOf(parametersIndex);
79             case PARAMS: return Utils.stringify(parameters);
80             case METHOD: return method.name();
81             default: return substituteDynamicMacro(macro, macroKey, parameters);
82         }
83     }
84 
substituteDynamicMacro(String macro, String macroKey, Object parameters)85     private String substituteDynamicMacro(String macro, String macroKey, Object parameters) {
86         if (isMethodParameterIndex(macroKey)) {
87             int index = parseIndex(macroKey);
88             return Utils.getParameterStringByIndexOrEmpty(parameters, index);
89         }
90 
91         return macro;
92     }
93 
isMethodParameterIndex(String macroKey)94     private boolean isMethodParameterIndex(String macroKey) {
95         return macroKey.matches("\\d+");
96     }
97 
parseIndex(String macroKey)98     private int parseIndex(String macroKey) {
99         return Integer.parseInt(macroKey);
100     }
101 
getMacroKey(String macro)102     private String getMacroKey(String macro) {
103         return macro
104                 .substring(MACRO_START.length(), macro.length() - MACRO_END.length())
105                 .toUpperCase(Locale.ENGLISH);
106     }
107 
isMacro(String part)108     private boolean isMacro(String part) {
109         return part.startsWith(MACRO_START) && part.endsWith(MACRO_END);
110     }
111 
112     private enum Macro {
113         INDEX,
114         PARAMS,
115         METHOD,
116         NONE;
117 
parse(String value)118         public static Macro parse(String value) {
119             if (macros.contains(value)) {
120                 return Macro.valueOf(value);
121             } else {
122                 return Macro.NONE;
123             }
124         }
125 
126         private static final HashSet<String> macros = new HashSet<String>(Arrays.asList(
127                 Macro.INDEX.toString(), Macro.PARAMS.toString(), Macro.METHOD.toString())
128         );
129     }
130 }
131