1 /* 2 * Copyright (c) 2020, 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 24 import java.io.IOException; 25 import java.nio.file.Path; 26 import jdk.jpackage.test.TKit; 27 import jdk.jpackage.test.PackageTest; 28 import jdk.jpackage.test.PackageType; 29 import jdk.jpackage.test.Annotations.Test; 30 import jdk.jpackage.test.Annotations.Parameters; 31 import java.util.List; 32 import java.util.function.Predicate; 33 import java.util.stream.Stream; 34 import java.util.stream.Collectors; 35 import jdk.jpackage.test.Executor; 36 37 /* 38 * @test 39 * @summary Custom l10n of msi installers in jpackage 40 * @library ../helpers 41 * @key jpackagePlatformPackage 42 * @requires (jpackage.test.SQETest == null) 43 * @build jdk.jpackage.test.* 44 * @requires (os.family == "windows") 45 * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal 46 * @compile WinL10nTest.java 47 * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main 48 * --jpt-run=WinL10nTest 49 */ 50 51 public class WinL10nTest { 52 53 public WinL10nTest(WixFileInitializer wxlFileInitializers[], 54 String expectedCulture, String expectedErrorMessage) { 55 this.wxlFileInitializers = wxlFileInitializers; 56 this.expectedCulture = expectedCulture; 57 this.expectedErrorMessage = expectedErrorMessage; 58 } 59 60 @Parameters 61 public static List<Object[]> data() { 62 return List.of(new Object[][]{ 63 {null, "en-us", null}, 64 {new WixFileInitializer[] { 65 WixFileInitializer.create("a.wxl", "en-us") 66 }, "en-us", null}, 67 {new WixFileInitializer[] { 68 WixFileInitializer.create("a.wxl", "fr") 69 }, "fr;en-us", null}, 70 {new WixFileInitializer[] { 71 WixFileInitializer.create("a.wxl", "fr"), 72 WixFileInitializer.create("b.wxl", "fr") 73 }, "fr;en-us", null}, 74 {new WixFileInitializer[] { 75 WixFileInitializer.create("a.wxl", "it"), 76 WixFileInitializer.create("b.wxl", "fr") 77 }, "it;fr;en-us", null}, 78 {new WixFileInitializer[] { 79 WixFileInitializer.create("c.wxl", "it"), 80 WixFileInitializer.create("b.wxl", "fr") 81 }, "fr;it;en-us", null}, 82 {new WixFileInitializer[] { 83 WixFileInitializer.create("a.wxl", "fr"), 84 WixFileInitializer.create("b.wxl", "it"), 85 WixFileInitializer.create("c.wxl", "fr"), 86 WixFileInitializer.create("d.wxl", "it") 87 }, "fr;it;en-us", null}, 88 {new WixFileInitializer[] { 89 WixFileInitializer.create("c.wxl", "it"), 90 WixFileInitializer.createMalformed("b.wxl") 91 }, null, null} 92 }); 93 } 94 95 private final static Stream<String> getLightCommandLine( 96 Executor.Result result) { 97 return result.getOutput().stream() 98 .filter(s -> s.contains("Running")) 99 .filter(s -> s.contains("light.exe")) 100 .filter(s -> !s.contains("/?")); 101 } 102 103 @Test 104 public void test() throws IOException { 105 106 final boolean allWxlFilesValid; 107 if (wxlFileInitializers != null) { 108 allWxlFilesValid = Stream.of(wxlFileInitializers).allMatch( 109 WixFileInitializer::isValid); 110 } else { 111 allWxlFilesValid = true; 112 } 113 114 PackageTest test = new PackageTest() 115 .forTypes(PackageType.WINDOWS) 116 .configureHelloApp() 117 .addInitializer(cmd -> { 118 // 1. Set fake run time to save time by skipping jlink step of jpackage. 119 // 2. Instruct test to save jpackage output. 120 cmd.setFakeRuntime().saveConsoleOutput(true); 121 }) 122 .addBundleVerifier((cmd, result) -> { 123 if (expectedCulture != null) { 124 TKit.assertTextStream("-cultures:" + expectedCulture).apply( 125 getLightCommandLine(result)); 126 } 127 128 if (expectedErrorMessage != null) { 129 TKit.assertTextStream(expectedErrorMessage) 130 .apply(result.getOutput().stream()); 131 } 132 133 if (wxlFileInitializers != null) { 134 if (allWxlFilesValid) { 135 for (var v : wxlFileInitializers) { 136 v.createCmdOutputVerifier(resourceDir).apply( 137 getLightCommandLine(result)); 138 } 139 } else { 140 Stream.of(wxlFileInitializers) 141 .filter(Predicate.not(WixFileInitializer::isValid)) 142 .forEach(v -> v.createCmdOutputVerifier( 143 resourceDir).apply(result.getOutput().stream())); 144 TKit.assertFalse( 145 getLightCommandLine(result).findAny().isPresent(), 146 "Check light.exe was not invoked"); 147 } 148 } 149 }); 150 151 if (wxlFileInitializers != null) { 152 test.addInitializer(cmd -> { 153 resourceDir = TKit.createTempDirectory("resources"); 154 155 cmd.addArguments("--resource-dir", resourceDir); 156 157 for (var v : wxlFileInitializers) { 158 v.apply(resourceDir); 159 } 160 }); 161 } 162 163 if (expectedErrorMessage != null || !allWxlFilesValid) { 164 test.setExpectedExitCode(1); 165 } 166 167 test.run(); 168 } 169 170 final private WixFileInitializer wxlFileInitializers[]; 171 final private String expectedCulture; 172 final private String expectedErrorMessage; 173 private Path resourceDir; 174 175 private static class WixFileInitializer { 176 static WixFileInitializer create(String name, String culture) { 177 return new WixFileInitializer(name, culture); 178 } 179 180 static WixFileInitializer createMalformed(String name) { 181 return new WixFileInitializer(name, null) { 182 @Override 183 public void apply(Path root) throws IOException { 184 TKit.createTextFile(root.resolve(name), List.of( 185 "<?xml version=\"1.0\" encoding=\"utf-8\"?>", 186 "<WixLocalization>")); 187 } 188 189 @Override 190 public String toString() { 191 return String.format("name=%s; malformed xml", name); 192 } 193 194 @Override 195 boolean isValid() { 196 return false; 197 } 198 199 @Override 200 TKit.TextStreamVerifier createCmdOutputVerifier(Path root) { 201 return TKit.assertTextStream(String.format( 202 "Failed to parse %s file", 203 root.resolve("b.wxl").toAbsolutePath())); 204 } 205 }; 206 } 207 208 private WixFileInitializer(String name, String culture) { 209 this.name = name; 210 this.culture = culture; 211 } 212 213 void apply(Path root) throws IOException { 214 TKit.createTextFile(root.resolve(name), List.of( 215 "<?xml version=\"1.0\" encoding=\"utf-8\"?>", 216 culture == null ? "<WixLocalization/>" : "<WixLocalization Culture=\"" 217 + culture 218 + "\" xmlns=\"http://schemas.microsoft.com/wix/2006/localization\" Codepage=\"1252\"/>")); 219 } 220 221 TKit.TextStreamVerifier createCmdOutputVerifier(Path root) { 222 return TKit.assertTextStream( 223 root.resolve(name).toAbsolutePath().toString()); 224 } 225 226 boolean isValid() { 227 return true; 228 } 229 230 @Override 231 public String toString() { 232 return String.format("name=%s; culture=%s", name, culture); 233 } 234 235 private final String name; 236 private final String culture; 237 } 238 }