diff options
author | Valerij Fredriksen <valerij92@gmail.com> | 2020-04-04 17:19:33 +0200 |
---|---|---|
committer | Valerij Fredriksen <valerijf@verizonmedia.com> | 2020-04-04 23:25:52 +0200 |
commit | 84b1401cb1a92885205a39a13b76f98df7762f08 (patch) | |
tree | ac1ead1c2ef89e6962d24c168af26e404b97c714 /node-admin | |
parent | b75b9ceb0ea1ac9a2689a7c4c7b57c3829d264d3 (diff) |
Implement YumTester
Diffstat (limited to 'node-admin')
2 files changed, 181 insertions, 0 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java new file mode 100644 index 00000000000..4d04e1199c5 --- /dev/null +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTester.java @@ -0,0 +1,120 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.node.admin.task.util.yum; + +import com.yahoo.vespa.hosted.node.admin.task.util.process.TestChildProcess2; +import com.yahoo.vespa.hosted.node.admin.task.util.process.TestTerminal; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * A {@link Yum} tester that simplifies testing interaction with yum. + * + * @author freva + */ +public class YumTester extends Yum { + + private final TestTerminal terminal; + + public YumTester(TestTerminal terminal) { + super(terminal); + this.terminal = terminal; + } + + public GenericYumCommandExpectation expectInstall(String... packages) { + return new GenericYumCommandExpectation("install", packages); + } + + public GenericYumCommandExpectation expectUpdate(String... packages) { + return new GenericYumCommandExpectation("upgrade", packages); + } + + public GenericYumCommandExpectation expectRemove(String... packages) { + return new GenericYumCommandExpectation("remove", packages); + } + + public InstallFixedCommandExpectation expectInstallFixedVersion(String yumPackage) { + return new InstallFixedCommandExpectation(yumPackage); + } + + public QueryInstalledExpectation expectQueryInstalled(String packageName) { + return new QueryInstalledExpectation(packageName); + } + + + public class GenericYumCommandExpectation { + private final String command; + protected final List<YumPackageName> packages; + private List<String> enableRepos = List.of(); + + private GenericYumCommandExpectation(String command, String... packages) { + this.command = command; + this.packages = Stream.of(packages).map(YumPackageName::fromString).collect(Collectors.toList()); + } + + public GenericYumCommandExpectation withEnableRepo(String... repo) { + this.enableRepos = List.of(repo); + return this; + } + + /** Mock the return value of the converge(TaskContext) method for this operation (true iff system was modified) */ + public YumTester andReturn(boolean value) { + if (value) return execute("Success"); + switch (command) { + case "install": return execute("Nothing to do"); + case "upgrade": return execute("No packages marked for update"); + case "remove": return execute("No Packages marked for removal"); + default: throw new IllegalArgumentException("Unknown command: " + command); + } + } + + private YumTester execute(String output) { + StringBuilder cmd = new StringBuilder(); + cmd.append("yum ").append(command).append(" --assumeyes"); + enableRepos.forEach(repo -> cmd.append(" --enablerepo=").append(repo)); + packages.forEach(pkg -> cmd.append(" ").append(pkg.toName())); + cmd.append(" 2>&1"); + + terminal.expectCommand(cmd.toString(), 0, output); + return YumTester.this; + } + } + + public class InstallFixedCommandExpectation extends GenericYumCommandExpectation { + private InstallFixedCommandExpectation(String yumPackage) { + super("install", yumPackage); + } + + @Override + public YumTester andReturn(boolean value) { + // Pretend package is already correctly version locked to simplify expectations + terminal.expectCommand("yum --quiet versionlock list 2>&1", 0, packages.get(0).toVersionLockName()); + return super.andReturn(value); + } + } + + public class QueryInstalledExpectation { + private final String packageName; + + public QueryInstalledExpectation(String packageName) { + this.packageName = packageName; + } + + /** Package name to return or null if package is not installed */ + public YumTester andReturn(YumPackageName yumPackage) { + TestChildProcess2 process = new TestChildProcess2( + yumPackage == null ? 1 : 0, + yumPackage == null ? "not installed" : String.join("\n", + yumPackage.getName(), + yumPackage.getEpoch().orElse("(none)"), + yumPackage.getVersion().orElseThrow(() -> new IllegalArgumentException("Version must be set")), + yumPackage.getRelease().orElseThrow(() -> new IllegalArgumentException("Release must be set")), + yumPackage.getArchitecture().orElse("(none)"))); + + terminal.expectCommand("rpm -q " + packageName + " --queryformat \"%{NAME}\\\\n%{EPOCH}\\\\n%{VERSION}\\\\n%{RELEASE}\\\\n%{ARCH}\" 2>&1", process); + return YumTester.this; + } + } + +} diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java new file mode 100644 index 00000000000..ef380046b75 --- /dev/null +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumTesterTest.java @@ -0,0 +1,61 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.node.admin.task.util.yum; + +import com.yahoo.vespa.hosted.node.admin.component.TestTaskContext; +import com.yahoo.vespa.hosted.node.admin.task.util.process.TestTerminal; +import org.junit.Test; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +/** + * @author freva + */ +public class YumTesterTest { + + private static final String[] packages = {"pkg1", "pkg2"}; + private static final String[] repos = {"repo1", "repo2"}; + private static final YumPackageName minimalPackage = YumPackageName.fromString("my-pkg-1.13.1-0.el7"); + private static final YumPackageName fullPackage = YumPackageName.fromString("2:my-pkg-1.13.1-0.el7.x86_64"); + + private final TestTerminal terminal = new TestTerminal(); + private final YumTester yum = new YumTester(terminal); + private final TestTaskContext context = new TestTaskContext(); + + @Test + public void generic_yum_methods() { + assertYumMethod(yum -> yum.expectInstall(packages).withEnableRepo(repos), + yum -> yum.install(List.of(packages)).enableRepo(repos).converge(context)); + + assertYumMethod(yum -> yum.expectUpdate(packages).withEnableRepo(repos), + yum -> yum.upgrade(List.of(packages)).enableRepo(repos).converge(context)); + + assertYumMethod(yum -> yum.expectRemove(packages).withEnableRepo(repos), + yum -> yum.remove(List.of(packages)).enableRepo(repos).converge(context)); + + assertYumMethod(yum -> yum.expectInstallFixedVersion(minimalPackage.toName()).withEnableRepo(repos), + yum -> yum.installFixedVersion(minimalPackage).enableRepo(repos).converge(context)); + } + + @Test + public void expect_query_installed() { + Stream.of(minimalPackage, fullPackage, null).forEach(pkg -> { + yum.expectQueryInstalled(packages[0]).andReturn(pkg); + assertEquals(Optional.ofNullable(pkg), yum.queryInstalled(context, packages[0])); + terminal.verifyAllCommandsExecuted(); + }); + } + + private void assertYumMethod(Function<YumTester, YumTester.GenericYumCommandExpectation> yumTesterExpectationFunction, + Function<Yum, Boolean> yumFunction) { + List.of(true, false).forEach(wantedReturnValue -> { + yumTesterExpectationFunction.apply(yum).andReturn(wantedReturnValue); + assertEquals(wantedReturnValue, yumFunction.apply(yum)); + terminal.verifyAllCommandsExecuted(); + }); + } +}
\ No newline at end of file |