changeset 185:3ec1dcfecb16

Adds new test class ShellCommandsTest, which tests commands in thermostat shell.
author Zdenek Zambersky <zzambers@redhat.com>
date Fri, 15 May 2015 19:12:02 +0200
parents 40990362e151
children 7bc828291ea4
files src/org/thermostat/qa2/framework/Assert.java src/org/thermostat/qa2/framework/utils/FileUtilities.java src/org/thermostat/qa2/framework/utils/ThermostatUtilities.java src/org/thermostat/qa2/tests/AgentSaveOnExitTest.java src/org/thermostat/qa2/tests/ShellCommandsTest.java
diffstat 5 files changed, 366 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/thermostat/qa2/framework/Assert.java	Fri May 15 19:09:02 2015 +0200
+++ b/src/org/thermostat/qa2/framework/Assert.java	Fri May 15 19:12:02 2015 +0200
@@ -89,6 +89,10 @@
         }
     }
 
+    public static void assertNotContainsPattern(List<String> lines, String patterns) {
+        assertNotContainsPatterns(lines, new String[]{patterns});
+    }
+
     public static void assertNotContainsPatterns(List<String> lines, String[] patterns) {
         for (String pattern : patterns) {
             boolean b = CommonUtilities.findInLineList(lines, pattern, false);
--- a/src/org/thermostat/qa2/framework/utils/FileUtilities.java	Fri May 15 19:09:02 2015 +0200
+++ b/src/org/thermostat/qa2/framework/utils/FileUtilities.java	Fri May 15 19:12:02 2015 +0200
@@ -41,6 +41,7 @@
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import org.thermostat.qa2.framework.ThermostatQAConfig;
 
 /**
  *
@@ -62,10 +63,18 @@
         return name;
     }
 
+    public static String getUniqueTempFile(String name) {
+        return getUniqueFile(ThermostatQAConfig.backupDir + File.separator + name);
+    }
+
     public static void copyFile(String src, String dest) throws Exception {
         ProcessUtilities.run("cp", "--", src, dest);
     }
 
+    public static void removeFile(String file) throws Exception {
+        ProcessUtilities.run("rm", "-rf", "--", file);
+    }
+
     public static List<String> getLineListFromFile(String file) throws FileNotFoundException, IOException {
         ArrayList<String> list = new ArrayList();
         return addLinesFromFileToList(list, file);
@@ -96,7 +105,7 @@
         }
     }
 
-    public static void printLineListToFile(String file, List<String> list) throws FileNotFoundException  {
+    public static void printLineListToFile(String file, List<String> list) throws FileNotFoundException {
         FileOutputStream fos = null;
         PrintStream ps = null;
 
--- a/src/org/thermostat/qa2/framework/utils/ThermostatUtilities.java	Fri May 15 19:09:02 2015 +0200
+++ b/src/org/thermostat/qa2/framework/utils/ThermostatUtilities.java	Fri May 15 19:12:02 2015 +0200
@@ -279,17 +279,28 @@
     }
 
     public static String getRunningVmLine() throws Exception {
-        return ThermostatUtilities.getRunningVmLine("tested");
+        return ThermostatUtilities.getRunningVmLine("tested", null);
     }
 
-    public static String getRunningVmLine(String target) throws Exception {
+    public static String getRunningVmLine(String name) throws Exception {
+        return ThermostatUtilities.getRunningVmLine("tested", name);
+    }
+
+    public static String getRunningVmLine(String target, String name) throws Exception {
         List<String> vmsLines = ThermostatUtilities.getListVmsOutput(target);
         String vmLine = null;
 
         for (String line : vmsLines) {
-            if (line.contains("RUNNING") && !line.contains("com.redhat.thermostat.main.Thermostat")) {
-                vmLine = line;
-                break;
+            if (name == null) {
+                if (line.contains("RUNNING") && !line.contains("com.redhat.thermostat.main.Thermostat") && !line.contains("org.netbeans.main")) {
+                    vmLine = line;
+                    break;
+                }
+            } else {
+                if (line.contains("RUNNING") && line.contains(name)) {
+                    vmLine = line;
+                    break;
+                }
             }
         }
         return vmLine;
@@ -299,6 +310,37 @@
         return getShellCommandOutput(target, "list-heap-dumps");
     }
 
+    public static String findLastHeapDump(String hostId, String vmId) throws Exception {
+        return findLastHeapDump("tested", hostId, vmId);
+    }
+
+    public static String findLastHeapDump(String target, String hostId, String vmId) throws Exception {
+        List<String> lines = getListHeapDumpsOutput(target);
+        int start = 0;
+        for (String currentLine : lines) {
+            if (currentLine.contains("HOST ID") && currentLine.contains("VM ID") && currentLine.contains("HEAP ID")) {
+                break;
+            }
+            ++start;
+        }
+        int size = lines.size();
+        for (int i = size - 1; i > start; --i) {
+            String line = lines.get(i);
+            if (line.contains(hostId) && line.contains(vmId)) {
+                return line;
+            }
+        }
+        return null;
+    }
+
+    public static List<String> gc(String vmId) throws Exception {
+        return getShellCommandOutput("tested", "gc --vmId " + vmId);
+    }
+
+    public static List<String> killVm(String hostId, String vmId) throws Exception {
+        return getShellCommandOutput("tested", "kill-vm --vmId " + vmId + " --hostId " + hostId);
+    }
+
     public static String getHeapDumpLine(String hostId, String vmId) throws Exception {
         return getHeapDumpLine("tested", hostId, vmId);
     }
@@ -316,6 +358,18 @@
         return heapLine;
     }
 
+    public static List<String> showHistogram(String heapId) throws Exception {
+        return getShellCommandOutput("tested", "show-heap-histogram --heapId " + heapId);
+    }
+
+    public static List<String> findObjects(String heapId, String pattern) throws Exception {
+        return getShellCommandOutput("tested", "find-objects --heapId " + heapId + " " + pattern);
+    }
+
+    public static List<String> findRoot(String heapId, String objectId) throws Exception {
+        return getShellCommandOutput("tested", "find-root --objectId " + objectId + " --heapId " + heapId);
+    }
+
     public static void dumpHeap(String hostId, String vmId) throws Exception {
         dumpHeap("tested", hostId, vmId);
     }
@@ -324,6 +378,10 @@
         getShellCommandOutput(target, "dump-heap --hostId " + hostId + " --vmId " + vmId);
     }
 
+    public static List<String> saveHeapDumpToFile(String heapId, String file) throws Exception {
+        return getShellCommandOutput("tested", "save-heap-dump-to-file --file " + file + " --heapId " + heapId);
+    }
+
     public static List<String> profileVm(String target, String hostId, String vmId, String action) throws Exception {
         return getShellCommandOutput(target, "profile-vm --hostId " + hostId + " --vmId " + vmId + " " + action);
     }
--- a/src/org/thermostat/qa2/tests/AgentSaveOnExitTest.java	Fri May 15 19:09:02 2015 +0200
+++ b/src/org/thermostat/qa2/tests/AgentSaveOnExitTest.java	Fri May 15 19:12:02 2015 +0200
@@ -61,7 +61,7 @@
         thermostatOtherAgent.start();
         assertRuns(thermostatOtherAgent, "Agent should be running");
 
-        String[] vmLineSegments = ThermostatUtilities.getRunningVmLine(target1).split(" ");
+        String[] vmLineSegments = ThermostatUtilities.getRunningVmLine(target1, null).split(" ");
         String hostId = vmLineSegments[0];
         String vmId = vmLineSegments[2];
 
@@ -110,7 +110,7 @@
         thermostatOtherAgent.start();
         assertRuns(thermostatOtherAgent, "Agent should be running");
 
-        String[] vmLineSegments = ThermostatUtilities.getRunningVmLine(target1).split(" ");
+        String[] vmLineSegments = ThermostatUtilities.getRunningVmLine(target1, null).split(" ");
         String hostId = vmLineSegments[0];
         String vmId = vmLineSegments[2];
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/thermostat/qa2/tests/ShellCommandsTest.java	Fri May 15 19:12:02 2015 +0200
@@ -0,0 +1,287 @@
+/*
+ ThermostatQA - test framework for Thermostat Monitoring Tool
+
+ Copyright 2015 Red Hat, Inc.
+
+ This file is part of ThermostatQA
+
+ ThermostatQA is distributed under the GNU General Public License,
+ version 2 or any later version (with a special exception described
+ below, commonly known as the "Classpath Exception").
+
+ A copy of GNU General Public License (GPL) is included in this
+ distribution, in the file COPYING.
+
+ Linking ThermostatQA code with other modules is making a combined work
+ based on ThermostatQA.  Thus, the terms and conditions of the GPL
+ cover the whole combination.
+
+ As a special exception, the copyright holders of ThermostatQA give you
+ permission to link this code with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on ThermostatQA code.  If you modify ThermostatQA, you may
+ extend this exception to your version of the software, but you are
+ not obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+package org.thermostat.qa2.tests;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import static org.thermostat.qa2.framework.Assert.*;
+import org.thermostat.qa2.framework.NativeProcess;
+import org.thermostat.qa2.framework.Shell;
+import org.thermostat.qa2.framework.ThermostatQAConfig;
+import org.thermostat.qa2.framework.ThermostatQAConfig.Login;
+import org.thermostat.qa2.framework.annotations.RunAgent;
+import org.thermostat.qa2.framework.annotations.RunGnomeKeyring;
+import org.thermostat.qa2.framework.annotations.RunStorage;
+import org.thermostat.qa2.framework.annotations.SetupStorage;
+import org.thermostat.qa2.framework.annotations.Test;
+import org.thermostat.qa2.framework.utils.CommonUtilities;
+import org.thermostat.qa2.framework.utils.FileUtilities;
+import org.thermostat.qa2.framework.utils.ProcessUtilities;
+import org.thermostat.qa2.framework.utils.ThermostatUtilities;
+
+/**
+ *
+ * @author Zdeněk Žamberský
+ */
+@SetupStorage(type = "mongo")
+@RunStorage
+@RunAgent
+@RunGnomeKeyring
+public class ShellCommandsTest {
+
+    public static String[] findTestSuiteVm() throws Exception {
+        String line = ThermostatUtilities.getRunningVmLine(testRunnerClassName);
+        assertNotNull(line, "there should be testsuite (" + testRunnerClassName + ") vm in list");
+        String[] lineParts = line.split(" ");
+        return lineParts;
+    }
+
+    public static String dumpTestSuiteHeap() throws Exception {
+        String[] lineParts = findTestSuiteVm();
+        String hostId = lineParts[0];
+        String vmId = lineParts[2];
+        ThermostatUtilities.dumpHeap(hostId, vmId);
+
+        String line = ThermostatUtilities.findLastHeapDump(hostId, vmId);
+        assertNotNull(line, "there should be heap dump in db");
+        lineParts = line.split(" ");
+        String heapId = lineParts[2];
+        return heapId;
+    }
+
+    public static String getObjectId(String heapId, String pattern) throws Exception {
+        List<String> lines = ThermostatUtilities.findObjects(heapId, pattern);
+        String line = null;
+        int start = 0;
+        for (String currentLine : lines) {
+            if (currentLine.contains("ID") && currentLine.contains("TYPE")) {
+                break;
+            }
+            ++start;
+        }
+        for (; start < lines.size(); ++start) {
+            String currentLine = lines.get(start);
+            if (currentLine.contains(pattern)) {
+                line = currentLine;
+                break;
+            }
+        }
+        if (line == null) {
+            return null;
+        }
+        String[] lineParts = line.split(" ");
+        String objectId = lineParts[0];
+        return objectId;
+    }
+
+    public static void connect(Shell shell) throws IOException {
+        shell.writeln("connect -d " + ThermostatQAConfig.getStroageUrl(false));
+        Login login = ThermostatQAConfig.clientLogin;
+        shell.writeln(login.getUsername());
+        shell.writeln(login.getPassword());
+    }
+
+    public static final String testRunnerClassName = "org.thermostat.qa2.framework.TestRunner";
+    public static final String thisClass = "org.thermostat.qa2.tests.ShellCommandsTest";
+    public static final String infiniteLoopClass = thisClass + "$InfiniteLoop";
+    public static final String searchedClass1Name = thisClass + "$SearchedClass1";
+    public static final String searchedClass2Name = thisClass + "$SearchedClass2";
+
+    @Test
+    public void connect() throws Exception {
+        Shell shell = ProcessUtilities.createThermostatShell();
+        shell.setStdOutMode(NativeProcess.MODE_LOG_AND_BUFFER);
+
+        shell.start();
+        connect(shell);
+        shell.writeln("exit");
+        shell.waitFor();
+
+        List<String> lines = shell.getStdoutLines();
+        assertContainsPattern(lines, "Thermostat + > exit");
+    }
+
+    @Test
+    public void disconnect() throws Exception {
+        Shell shell = ProcessUtilities.createThermostatShell();
+        shell.setStdOutMode(NativeProcess.MODE_LOG_AND_BUFFER);
+
+        shell.start();
+        connect(shell);
+        shell.writeln("disconnect");
+        shell.writeln("exit");
+        shell.waitFor();
+
+        List<String> lines = shell.getStdoutLines();
+        assertContainsPattern(lines, "Thermostat - > exit");
+    }
+
+    @Test
+    public void killVm() throws Exception {
+        String line = ThermostatUtilities.getRunningVmLine(thisClass);
+        assertNull(line, infiniteLoopClass + " should not be in vm list");
+
+        NativeProcess process = new NativeProcess("java", "-cp", "bin/classes", infiniteLoopClass);
+        try {
+            process.start();
+
+            CommonUtilities.sleep(2000);
+
+            line = ThermostatUtilities.getRunningVmLine(infiniteLoopClass);
+            assertNotNull(line, infiniteLoopClass + " should be in vm list");
+
+            String[] lineParts = line.split(" ");
+            String hostId = lineParts[0];
+            String vmId = lineParts[2];
+            ThermostatUtilities.killVm(hostId, vmId);
+
+            CommonUtilities.sleep(2000);
+
+            line = ThermostatUtilities.getRunningVmLine(infiniteLoopClass);
+            assertNull(line, infiniteLoopClass + " should not be in vm list");
+
+        } finally {
+            process.destroy();
+            process.waitForRaw();
+        }
+    }
+
+    @Test
+    public void saveHeapDumpToFile() throws Exception {
+        String file = FileUtilities.getUniqueTempFile("heapDump");
+        String heapId = dumpTestSuiteHeap();
+
+        ThermostatUtilities.saveHeapDumpToFile(heapId, file);
+        assertTrue(new File(file).exists(), "heap dump file (" + file + ") should exist");
+        FileUtilities.removeFile(file);
+    }
+
+    @Test
+    public void listVms() throws Exception {
+        findTestSuiteVm();
+    }
+
+    @Test
+    public void dumpHeap() throws Exception {
+        dumpTestSuiteHeap();
+    }
+
+    @Test
+    public void findObjects() throws Exception {
+        String heapId = dumpTestSuiteHeap();
+        String line = getObjectId(heapId, searchedClass1Name);
+        assertNull(line, "Instance of class " + searchedClass1Name + " should not be in heap");
+
+        SearchedClass1 toSearch = new SearchedClass1();
+
+        heapId = dumpTestSuiteHeap();
+        line = getObjectId(heapId, searchedClass1Name);
+        assertNotNull(line, "Instance of class " + searchedClass1Name + " should be in heap");
+    }
+
+    @Test
+    public void showHistogram() throws Exception {
+        String heapId = dumpTestSuiteHeap();
+        List<String> lines = ThermostatUtilities.showHistogram(heapId);
+        assertNotContainsPattern(lines, searchedClass1Name);
+
+        SearchedClass1 toSearch = new SearchedClass1();
+
+        heapId = dumpTestSuiteHeap();
+        lines = ThermostatUtilities.showHistogram(heapId);
+        assertContainsPattern(lines, searchedClass1Name);
+    }
+
+    @Test
+    public void findRoot() throws Exception {
+        SearchedClass1 toSearch = new SearchedClass1();
+        toSearch.ref = new SearchedClass2();
+
+        String heapId = dumpTestSuiteHeap();
+
+        List<String> lines = ThermostatUtilities.showHistogram(heapId);
+        assertContainsPattern(lines, searchedClass1Name);
+        assertContainsPattern(lines, searchedClass2Name);
+
+        String line = getObjectId(heapId, searchedClass1Name);
+        assertNotNull(line, "Instance of class " + searchedClass1Name + " should be in heap");
+        String[] lineParts = line.split(" ");
+        String objectId1 = lineParts[0];
+
+        line = getObjectId(heapId, searchedClass2Name);
+        assertNotNull(line, "Instance of class " + searchedClass2Name + " should be in heap");
+        lineParts = line.split(" ");
+        String objectId2 = lineParts[0];
+
+        lines = ThermostatUtilities.findRoot(heapId, objectId2);
+        assertContainsPattern(lines, "field ref in " + searchedClass1Name + "@" + objectId1 + " -> " + searchedClass2Name + "@" + objectId2);
+    }
+
+    @Test
+    public void gc() throws Exception {
+        SearchedClass1 toSearch = new SearchedClass1();
+        String heapId = dumpTestSuiteHeap();
+
+        // find object instead?
+        List<String> lines = ThermostatUtilities.showHistogram(heapId);
+        assertContainsPattern(lines, searchedClass1Name);
+
+        toSearch = null;
+
+        String[] lineParts = findTestSuiteVm();
+        String vmId = lineParts[2];
+
+        lines = ThermostatUtilities.gc(vmId);
+        assertContainsPattern(lines, "GC Successful");
+
+        heapId = dumpTestSuiteHeap();
+        lines = ThermostatUtilities.showHistogram(heapId);
+        assertNotContainsPattern(lines, searchedClass1Name);
+    }
+
+    public static class SearchedClass1 {
+
+        SearchedClass2 ref;
+    }
+
+    public static class SearchedClass2 {
+    }
+
+    public static class InfiniteLoop {
+
+        public static void main(String[] args) {
+            for (;;) {
+            }
+        }
+    }
+
+}