Skip to content

Commit 01270d3

Browse files
Update tests and implementation to comply with the CSR (env var names are case-insesitive on Windows)
1 parent 642ad20 commit 01270d3

3 files changed

Lines changed: 96 additions & 5 deletions

File tree

src/jdk.jpackage/share/native/applauncher/CfgFile.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
#ifndef CfgFile_h
2828
#define CfgFile_h
2929

30-
#include <map>
31-
#include "tstrings.h"
30+
#include "StringProcessing.h"
3231

3332

3433
class CfgFile {
@@ -90,7 +89,7 @@ class CfgFile {
9089
std::swap(empty, other.empty);
9190
}
9291

93-
typedef std::map<tstring, tstring> Macros;
92+
typedef StringProcessing::VariableValues Macros;
9493

9594
/**
9695
* Returns copy of this instance with the given macros and environment variables expanded.

src/jdk.jpackage/share/native/applauncher/StringProcessing.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,16 @@ class Token {
5959

6060
typedef std::vector<Token> TokenizedString;
6161
typedef std::vector<tstring> VariableNameList;
62+
#ifdef _WIN32
63+
struct less_ignore_case {
64+
bool operator() (const tstring& x, const tstring& y) const {
65+
return std::less<tstring>()(tstrings::toLower(x), tstrings::toLower(y));
66+
}
67+
};
68+
typedef std::map<tstring, tstring, less_ignore_case> VariableValues;
69+
#else
6270
typedef std::map<tstring, tstring> VariableValues;
71+
#endif
6372

6473
TokenizedString tokenize(const tstring& str);
6574

test/jdk/tools/jpackage/share/AppLauncherSubstTest.java

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121
* questions.
2222
*/
2323

24+
import static jdk.internal.util.OperatingSystem.WINDOWS;
2425
import static jdk.jpackage.test.HelloApp.configureAndExecute;
2526

2627
import java.io.IOException;
2728
import java.nio.file.Files;
2829
import java.nio.file.Path;
30+
import java.util.ArrayList;
2931
import java.util.Collection;
30-
import java.util.HashMap;
32+
import java.util.LinkedHashMap;
33+
import java.util.List;
3134
import java.util.Map;
3235
import java.util.Objects;
3336
import java.util.Optional;
@@ -79,7 +82,7 @@ TestSpec create() {
7982

8083
private String str;
8184
private String expectedStr;
82-
private Map<String, String> env = new HashMap<>();
85+
private Map<String, String> env = new LinkedHashMap<>();
8386
}
8487

8588
public TestSpec {
@@ -115,6 +118,8 @@ public String toString() {
115118

116119
@Test
117120
@ParameterSupplier
121+
@ParameterSupplier(value = "testCaseSensitive", ifNotOS = WINDOWS)
122+
@ParameterSupplier(value = "testCaseInsensitive", ifOS = WINDOWS)
118123
public static void test(TestSpec spec) throws IOException {
119124
final var cmd = JPackageCommand.helloAppImage(TEST_APP_JAVA + "*Hello")
120125
.ignoreFakeRuntime()
@@ -161,6 +166,84 @@ public static Collection<Object[]> test() {
161166
}).toList();
162167
}
163168

169+
public static Collection<Object[]> testCaseSensitive() {
170+
final List<TestSpec> testCases = new ArrayList<>();
171+
for (final var token : PredefinedToken.values()) {
172+
testCases.addAll(token.createTestCases(true));
173+
}
174+
175+
testCases.addAll(Stream.of(
176+
testSpec("$ALPHA $alpha").expect("A a").var("ALPHA", "A").var("alpha", "a"),
177+
testSpec("$ALPHA $alpha").expect("$ALPHA a").var("alpha", "a"),
178+
testSpec("$ALPHA $alpha").expect("A $alpha").var("ALPHA", "A")
179+
).map(TestSpec.Builder::create).toList());
180+
181+
return testCases.stream().map(v -> {
182+
return new Object[] {v};
183+
}).toList();
184+
}
185+
186+
public static Collection<Object[]> testCaseInsensitive() {
187+
final List<TestSpec> testCases = new ArrayList<>();
188+
for (final var token : PredefinedToken.values()) {
189+
testCases.addAll(token.createTestCases(false));
190+
}
191+
192+
testCases.addAll(Stream.of(
193+
testSpec("$ALPHA $alpha").expect("A A").var("AlphA", "A"),
194+
testSpec("$ALPHA $alpha").expect("a a").var("alpha", "a"),
195+
testSpec("$ALPHA $alpha").expect("A A").var("ALPHA", "A")
196+
).map(TestSpec.Builder::create).toList());
197+
198+
return testCases.stream().map(v -> {
199+
return new Object[] {v};
200+
}).toList();
201+
}
202+
203+
private enum PredefinedToken {
204+
APPDIR,
205+
BINDIR,
206+
ROOTDIR;
207+
208+
List<TestSpec> createTestCases(boolean caseSensitive) {
209+
final var name = name();
210+
final var name2 = name.transform(str -> {
211+
final var chars = name.toCharArray();
212+
for (int i = 0; i < chars.length; i += 2) {
213+
chars[i] = Character.toLowerCase(chars[i]);
214+
}
215+
return new String(chars);
216+
});
217+
218+
if (name.equals(name2)) {
219+
throw new UnsupportedOperationException();
220+
}
221+
222+
final var testSpec = testSpec(String.format("${%s}${%s}", name, name2)).var(name, "A").var(name2, "[foo]");
223+
if (caseSensitive) {
224+
testSpec.expect(String.format("@@%s@@[foo]", name, name2));
225+
} else {
226+
testSpec.expect(String.format("@@%s@@@@%s@@", name, name));
227+
}
228+
229+
final var testSpec2 = testSpec(String.format("${%s}${%s}", name, name2)).var(name, "A");
230+
if (caseSensitive) {
231+
testSpec2.expect(String.format("@@%s@@${%s}", name, name2));
232+
} else {
233+
testSpec2.expect(String.format("@@%s@@@@%s@@", name, name));
234+
}
235+
236+
final var testSpec3 = testSpec(String.format("${%s}${%s}", name, name2));
237+
if (caseSensitive) {
238+
testSpec3.expect(String.format("@@%s@@${%s}", name, name2));
239+
} else {
240+
testSpec3.expect(String.format("@@%s@@@@%s@@", name, name));
241+
}
242+
243+
return Stream.of(testSpec, testSpec2).map(TestSpec.Builder::create).toList();
244+
}
245+
}
246+
164247
private static TestSpec.Builder testSpec(String str) {
165248
return new TestSpec.Builder().str(str);
166249
}

0 commit comments

Comments
 (0)