aboutsummaryrefslogtreecommitdiff
path: root/test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy
diff options
context:
space:
mode:
Diffstat (limited to 'test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy')
-rw-r--r--test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy259
1 files changed, 259 insertions, 0 deletions
diff --git a/test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy b/test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy
new file mode 100644
index 00000000..8c8a852a
--- /dev/null
+++ b/test/src/smokes/package/src/test/groovy/org/apache/bigtop/itest/packagesmoke/TestPackagesSingleNode.groovy
@@ -0,0 +1,259 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.bigtop.itest.packagesmoke
+
+import org.junit.BeforeClass
+import org.junit.Test
+import org.junit.rules.ErrorCollector
+import org.junit.Rule
+import static org.junit.Assert.assertTrue
+import static org.hamcrest.CoreMatchers.equalTo
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized.Parameters
+import org.junit.AfterClass
+
+import org.apache.bigtop.itest.pmanager.PackageInstance
+import org.apache.bigtop.itest.junit.OrderedParameterized
+import org.apache.bigtop.itest.junit.OrderedParameterized.RunStage
+
+import static org.apache.bigtop.itest.shell.OS.linux_flavor
+import org.apache.bigtop.itest.shell.Shell
+
+@RunWith(OrderedParameterized.class)
+class TestPackagesSingleNode extends PackageTestCommon {
+ private static PackageTestRepoMgr repo;
+ // Ideally, we would want to have PackageInstance implementation be efficient in how it manages different
+ // objects representing the same package. That would allow us to have PackageInstance per testcase and
+ // not worry about managing it ourselves via the following static Map. For now, however, we rely on
+ // constructors being synchronized and thus inserting just one copy of PackageInstance for each package we test
+ private static Map<String, PackageInstance> pkgs = [:];
+ private static String selectedTests = System.getProperty("cdh.packages.test", ".");
+ private static String skippedTests = System.getProperty("cdh.packages.skip", "\$^");
+
+ private Node golden;
+
+ static {
+ // repo = new PackageTestRepoMgr("3", "", "http://nightly.cloudera.com/debian/",
+ // "http://nightly.cloudera.com/debian/archive.key");
+ repo = new PackageTestRepoMgr();
+ TestPackagesSingleNode.pm = repo.getPm();
+ }
+
+ @Rule
+ public ErrorCollector errors = new ErrorCollector();
+
+ @BeforeClass
+ public static void setUp() {
+ tryOrFail({repo.addRepo()}, 2, "adding repository failed");
+ tryOrFail({(repo.getPm().refresh() == 0)}, 1, "refreshing repository failed");
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ repo.removeRepo();
+ }
+
+ @Parameters
+ public static Map<String, Object[]> generateTests() {
+ String type = TestPackagesSingleNode.pm.getType();
+ String arch = (new Shell()).exec("uname -m").getOut().get(0).replaceAll(/i.86/,"i386").replaceAll(/x86_64/,"amd64");
+ String archTranslated = (type == "apt") ? "" : ((arch == "amd64") ? ".x86_64" : ".${arch}");
+ def config = new XmlParser().parse(TestPackagesSingleNode.class.getClassLoader().
+ getResourceAsStream("package_data_${type}.xml"));
+
+ Map<String, Object[]> res = [:];
+
+ config.children().each {
+ String name = it.name();
+
+ if ((name =~ /\.(amd64|i386)$/).find()) {
+ name = (name =~ "${arch}\$").find() ? name.replaceAll("\\.${arch}\$", archTranslated) : null;
+
+ // TODO: this is a total hack
+ if ((name =~ /\.i386$/).find() && linux_flavor == "RedHatEnterpriseServer") {
+ name = null;
+ }
+ }
+
+ if (name != null && (name =~ selectedTests).find() && !(name =~ skippedTests).find()) {
+ res[name] = ([name, it] as Object[]);
+ }
+ };
+
+ return res;
+ }
+
+ public TestPackagesSingleNode(String pkgName, Node pkgGolden) {
+ result = errors;
+ name = pkgName;
+ golden = pkgGolden;
+ // hopefully the following line will go away soon, once PackageInstance becomes more sophisticated
+ synchronized (pkgs) { pkgs[name] = pkgs[name] ?: PackageInstance.getPackageInstance(pm, name); }
+ pkg = pkgs[name];
+ }
+
+ @RunStage(level=-3)
+ @Test
+ synchronized void testRemoteMetadata() {
+ if (!isUpgrade()) {
+ if (pkg.isInstalled()) {
+ checkThat("package $name is alredy installed and could not be removed",
+ pkg.remove(), equalTo(0));
+ }
+
+ checkRemoteMetadata(getMap(golden.metadata), false);
+ }
+ }
+
+ @RunStage(level=-2)
+ @Test
+ synchronized void testPackageInstall() {
+ // WARNING: sometimes packages do not install because the server is busy
+ int i;
+ for (i=3; pkg.install() && i>0; i--);
+ checkThat("could only install package $name on the ${3-i} try",
+ i, equalTo(3));
+
+ // TODO: we need to come up with a way to abort any further execution to avoid spurious failures
+
+ checkThat("package $name is expected to be installed",
+ pm.isInstalled(pkg), equalTo(true));
+
+ pkg.refresh();
+ }
+
+ @RunStage(level=-1)
+ @Test
+ void testPackageUpgrade() {
+ if (isUpgrade()) {
+ checkThat("upgrade sequence on a package $name failed to be executed",
+ CDHUpgradeSequence.execute(name, System.getProperty("cdh.prev.repo.version"), "3"), equalTo(0));
+ }
+ }
+
+ @Test
+ void testRepoFile() {
+ // TODO: not sure what level of textual comparison of repo files do we actually need to implement
+ }
+
+ @Test
+ void testPulledDeps() {
+ checkPulledDeps(getMap(golden.deps));
+ }
+
+ @Test
+ void testPackageMetadata() {
+ checkMetadata(getMap(golden.metadata));
+ }
+
+ @Test
+ void testPackageContent() {
+ Map files = getMap(golden.content);
+ checkFiles(files.config, files.doc, files.file);
+ }
+
+ @Test
+ void testPackageServices() {
+ checkServices(getMap(golden.services));
+ }
+
+ @Test
+ void testUsers() {
+ checkUsers(getMap(golden.users));
+ }
+
+ @Test
+ void testGroups() {
+ checkGroups(getMap(golden.groups));
+ }
+
+ @Test
+ void testAlternatives() {
+ checkAlternatives(getMap(golden.alternatives));
+ }
+
+ @RunStage(level=1)
+ @Test
+ void testPackageRemove() {
+ checkRemoval();
+ }
+
+ static void tryOrFail(Closure cl, int retries, String fail) {
+ while (!cl.call()) {
+ retries--;
+ assertTrue(fail, retries > 0);
+ sleep(3001);
+ }
+ }
+
+ Map getMap(NodeList nodeList) {
+ switch (nodeList.size()) {
+ case 0: return [:];
+ case 1: return getMapN(nodeList.get(0));
+ default: return null; // poor man's XML validation
+ }
+ }
+
+ Map getMapN(Node node) {
+ String packagerType = pm.getType();
+ Map res = [:];
+ node.attributes()
+ node.children().each {
+ String key = it.name().toString();
+ if (key == "tag" && it.attributes()["name"] != null) { // <tag name="foo"/> -> <foo/>
+ key = it.attributes()["name"];
+ }
+ def value = null;
+ if (it.children().size() == 0) { // empty tags <foo/>
+ Map attr = it.attributes();
+ value = (attr.size() > 0) ? attr : key;
+ } else if (it.children().size() == 1 && it.children().get(0) instanceof java.lang.String) { // text tags <foo>bar</foo>
+ value = it.text();
+ } else if (["apt", "yum", "zypper"].contains(key)) { // poor man's XML filtering
+ res.putAll((packagerType == key) ? getMapN(it) : [:]);
+ } else {
+ value = getMapN(it);
+ }
+
+ // this is a little bit more tricky than it has to be :-(
+ if (value != null) {
+ // turn tags with a property name into a tag of its own <tag name="foo"> -> <tag><foo name="foo"</foo></tag>
+ if (value instanceof Map && value.name != null) {
+ Map tmpMap = [:];
+ tmpMap.put(value.name, value);
+ value = tmpMap;
+ }
+ if (res[key] == null) {
+ res[key] = value;
+ } else {
+ if (res[key] instanceof Map && value instanceof Map) {
+ res[key].putAll(value);
+ } else {
+ if (!(res[key] instanceof List)) {
+ res[key] = [res[key]];
+ }
+ res[key].add(value);
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+}