jdk-24/test/jdk/tools/jpackage/windows/WinLongVersionTest.java
Alexey Semenyuk fea5f2b145 8344415: Restruct jpackage utility classes
Reviewed-by: almatvee
2024-11-19 13:54:57 +00:00

213 lines
9.4 KiB
Java

/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.function.Supplier;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import jdk.jpackage.internal.util.XmlUtils;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Executor;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.PackageType;
import jdk.jpackage.test.RunnablePackageTest.Action;
import jdk.jpackage.test.TKit;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
/**
* Test --app-version parameter properly supports long version numbers, i.e.
* version numbers with more than three components.
* Output of the test should be WinLongVersionTest-1.0.exe,
* WinLongVersionTest-2.0.0.1.exe, and WinLongVersionTest-2.0.0.2.exe installers.
* The output installers should provide the same functionality as
* the default installer (see description of the default installer in
* SimplePackageTest.java) but have the same product code and different
* versions.
* Test scenario:
* - Run WinLongVersionTest-2.0.0.2.exe;
* - Run WinLongVersionTest-1.0.exe; package installed with
* WinLongVersionTest-2.0.0.2.exe command must remain installed
* - Run WinLongVersionTest-2.0.0.1.exe; packages installed with
* WinLongVersionTest-2.0.0.2.exe and WinLongVersionTest-1.0.exe installers
* must be automatically uninstalled, only WinLongVersionTest-2.0.0.1 package
* must remain installed
* - Uninstall WinLongVersionTest-2.0.0.2; all packages installed in the test
* scenario must be uninstalled
*/
/*
* @test
* @summary jpackage with long version number
* @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest != null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
* @compile WinLongVersionTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinLongVersionTest.test
*/
/*
* @test
* @summary jpackage with long version number
* @library /test/jdk/tools/jpackage/helpers
* @key jpackagePlatformPackage
* @requires (jpackage.test.SQETest == null)
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
* @compile WinLongVersionTest.java
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinLongVersionTest
*/
public class WinLongVersionTest {
@Test
public static void test() throws IOException {
Supplier<PackageTest> init = () -> {
final UUID upgradeCode = UUID.fromString(
"65099D7A-D5B1-4E5B-85B1-717F0DE4D5D5");
return new PackageTest()
.forTypes(PackageType.WINDOWS)
.configureHelloApp()
.addInitializer(cmd -> cmd.addArguments("--win-upgrade-uuid",
upgradeCode.toString())) ;
};
PackageTest test1 = init.get().addInitializer(cmd -> {
cmd.setArgumentValue("--app-version", "2.0.0.2");
cmd.setArgumentValue("--arguments", "bar");
cmd.setArgumentValue("--install-dir", cmd.name() + "-1");
});
// Tweak Upgrade table of the second package in a way the default
// FindRelatedProducts MSI action will find 1st package, but custom
// jpackage's FindRelatedProductsEx action will not as it gracefuly
// handles more than 3 components of version strings.
// In MSI log of the 2nd package installartion session it will be something like:
/*
Action start 12:08:38: FindRelatedProducts.
FindRelatedProducts: Found application: {D88EEA02-56CC-34AD-8216-C2CC244FA898}
MSI (c) (0C:14) [12:08:38:040]: PROPERTY CHANGE: Adding JP_DOWNGRADABLE_FOUND property. Its value is '{D88EEA02-56CC-34AD-8216-C2CC244FA898}'.
MSI (c) (0C:14) [12:08:38:040]: PROPERTY CHANGE: Adding MIGRATE property. Its value is '{D88EEA02-56CC-34AD-8216-C2CC244FA898}'.
Action ended 12:08:38: FindRelatedProducts. Return value 1.
...
Action start 12:08:38: JpFindRelatedProducts.
Java [12:08:38.180 libwixhelper.cpp:120 (FindRelatedProductsEx)] TRACE: Entering FindRelatedProductsEx
Java [12:08:38.185 libwixhelper.cpp:85 (`anonymous-namespace'::findInstalledPackages)] TRACE: Found {D88EEA02-56CC-34AD-8216-C2CC244FA898} product
Java [12:08:38.187 MsiCA.cpp:61 (msi::CAImpl::removeProperty)] TRACE: Removing MSI property 'JP_UPGRADABLE_FOUND'
Java [12:08:38.187 MsiCA.cpp:61 (msi::CAImpl::removeProperty)] TRACE: Removing MSI property 'MIGRATE'
Java [12:08:38.189 MsiCA.cpp:61 (msi::CAImpl::removeProperty)] TRACE: Removing MSI property 'JP_DOWNGRADABLE_FOUND'
Java [12:08:38.190 libwixhelper.cpp:0 (FindRelatedProductsEx)] TRACE: Exiting FindRelatedProductsEx (entered at libwixhelper.cpp:120)
Action ended 12:08:38: JpFindRelatedProducts. Return value 1.
*/
PackageTest test2 = init.get().addInstallVerifier(cmd -> {
if (!cmd.isPackageUnpacked()) {
// Installation of this package must NOT uninstall
// previously installed package. Verify that.
test1.run(Action.VERIFY_INSTALL);
}
}).forTypes(PackageType.WIN_EXE)
.addInitializer(cmd -> {
final Path resourceDir = TKit.createTempDirectory("resources");
cmd.addArguments("--resource-dir", resourceDir);
Path scriptPath = resourceDir.resolve(String.format(
"%s-post-msi.wsf", cmd.name()));
XmlUtils.createXml(scriptPath, xml -> {
xml.writeStartElement("job");
xml.writeAttribute("id", "main");
xml.writeStartElement("script");
xml.writeAttribute("language", "JScript");
xml.writeCData(String.join("\n", Files.readAllLines(
TKit.TEST_SRC_ROOT.resolve(String.format(
"resources/%s-edit-msi.js", cmd.name())))));
xml.writeEndElement();
xml.writeEndElement();
});
}).forTypes(PackageType.WIN_MSI)
.addBundleVerifier(cmd -> {
Executor.of("cscript.exe", "//Nologo")
.addArgument(TKit.TEST_SRC_ROOT.resolve(String.format(
"resources/%s-edit-msi.js", cmd.name())))
.addArgument(cmd.outputBundle())
.execute();
});
// Replace real uninstall commands for the first packages with nop action.
// They will be uninstalled automatically when the last package will
// be installed.
test1.disablePackageUninstaller();
test2.disablePackageUninstaller();
PackageTest test3 = init.get().addInitializer(cmd -> {
cmd.setArgumentValue("--app-version", "2.0.0.1");
cmd.setArgumentValue("--arguments", "buzz");
});
new PackageTest.Group(test1, test2, test3).run();
}
@Test
public static void testNoUpgradeTable() throws IOException {
new PackageTest()
.forTypes(PackageType.WINDOWS)
.configureHelloApp()
.addInitializer(cmd -> {
final Path resourceDir = TKit.createTempDirectory("resources");
cmd.addArguments("--resource-dir", resourceDir);
cmd.setFakeRuntime();
// Create package without Upgrade table
Document doc = XmlUtils.initDocumentBuilder().parse(
Files.newInputStream(TKit.SRC_ROOT.resolve(
"windows/classes/jdk/jpackage/internal/resources/main.wxs")));
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xPath.evaluate("/Wix/Product/Upgrade",
doc, XPathConstants.NODESET);
nodes.item(0).getParentNode().removeChild(nodes.item(0));
Source source = new DOMSource(doc);
Result result = new StreamResult(Files.newOutputStream(
resourceDir.resolve("main.wxs")));
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(source, result);
}).run();
}
}