Repository: incubator-stratos
Updated Branches:
  refs/heads/stratos-651-cli-test-suite [created] cb3a22e8c


added integration test suite


Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/cb3a22e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/cb3a22e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/cb3a22e8

Branch: refs/heads/stratos-651-cli-test-suite
Commit: cb3a22e8c0a07027e6a90dd6923cce08122a7c15
Parents: 6892d21
Author: Chris Snow <[email protected]>
Authored: Sun May 11 05:48:50 2014 +0000
Committer: Chris Snow <[email protected]>
Committed: Sun May 11 05:48:50 2014 +0000

----------------------------------------------------------------------
 components/org.apache.stratos.cli/README.md     |   7 +
 components/org.apache.stratos.cli/pom.xml       | 118 ++++++++++-
 .../src/test/python/.gitignore                  |  20 ++
 .../src/test/python/__files/body_cookie.json    |   1 +
 .../test/python/__files/body_tenant_create.json |   1 +
 .../python/__files/body_tenant_deactivate.json  |   1 +
 .../test/python/__files/body_tenant_list.json   |   1 +
 .../src/test/python/__init__.py                 |  19 ++
 .../src/test/python/mappings/cookie.json        |  18 ++
 .../src/test/python/mappings/tenant-create.json |  19 ++
 .../test/python/mappings/tenant-deactivate.json |  16 ++
 .../src/test/python/mappings/tenant-list.json   |  16 ++
 .../src/test/python/test_common.py              |  99 ++++++++++
 .../src/test/python/test_interactive.py         | 195 +++++++++++++++++++
 .../src/test/python/test_noninteractive.py      |  87 +++++++++
 .../src/test/python/wiremock.py                 | 106 ++++++++++
 16 files changed, 723 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/README.md
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/README.md 
b/components/org.apache.stratos.cli/README.md
new file mode 100644
index 0000000..f03d1b3
--- /dev/null
+++ b/components/org.apache.stratos.cli/README.md
@@ -0,0 +1,7 @@
+### CLI Integration Tests
+
+Run CLI integration tests with:
+
+```mvn -P cli-test integration-test```
+
+You will need python ane pexpect installed.

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/pom.xml 
b/components/org.apache.stratos.cli/pom.xml
index 18d01d2..62b9e97 100644
--- a/components/org.apache.stratos.cli/pom.xml
+++ b/components/org.apache.stratos.cli/pom.xml
@@ -34,6 +34,7 @@
        
        <properties>
                <slf4j.version>1.7.6</slf4j.version>
+               <wiremock.version>1.46</wiremock.version>
        </properties>
 
        <dependencies>
@@ -119,7 +120,7 @@
                                        <descriptors>
                                                
<descriptor>src/main/assembly/src.xml</descriptor>
                                        </descriptors>
-                    <appendAssemblyId>false</appendAssemblyId>
+                                       
<appendAssemblyId>false</appendAssemblyId>
                                </configuration>
                                <executions>
                                        <execution>
@@ -131,7 +132,122 @@
                                        </execution>
                                </executions>
                        </plugin>
+                       <plugin>  
+                               <groupId>org.apache.maven.plugins</groupId> 
+                               
<artifactId>maven-dependency-plugin</artifactId> 
+                               <version>2.7</version> 
+                               <executions>
+                                       <execution> 
+                                               <id>copy</id> 
+                                               
<phase>pre-integration-test</phase>
+                                               <goals> 
+                                                       <goal>copy</goal>
+                                               </goals> 
+                                               <configuration> 
+                                                       <artifactItems>
+                                                               <!-- Copy the 
CLI --> 
+                                                               <artifactItem> 
+                                                                       
<groupId>${project.groupId}</groupId> 
+                                                                       
<artifactId>${project.artifactId}</artifactId> 
+                                                                       
<version>${project.version}</version> 
+                                                                       
<type>jar</type> 
+                                                                       
<overWrite>true</overWrite> 
+                                                                       
<outputDirectory>${maven.output.build.path}</outputDirectory> 
+                                                               </artifactItem> 
+                                                       </artifactItems> 
+                                                       <artifactItems> 
+                                                               <artifactItem> 
+                                                                       
<groupId>com.github.tomakehurst</groupId> 
+                                                                       
<artifactId>wiremock</artifactId> 
+                                                                       
<version>${wiremock.version}</version> 
+                                                                       
<classifier>standalone</classifier> 
+                                                                       
<type>jar</type> 
+                                                                       
<overWrite>true</overWrite> 
+                                                                       
<outputDirectory>${maven.output.build.path}</outputDirectory> 
+                                                               </artifactItem> 
+                                                       </artifactItems> 
+                                               </configuration> 
+                                       </execution> 
+                               </executions> 
+                       </plugin> 
                </plugins>
        </build>
 
+       <profiles>
+               <!-- Integration testing the CLI -->
+               <profile>
+                       <id>cli-test</id>
+                       <build>
+                               <plugins>
+                                       <plugin>
+                                               
<groupId>org.codehaus.mojo</groupId>
+                                               
<artifactId>exec-maven-plugin</artifactId>
+                                               <version>1.3</version>
+                                               <executions>
+                                                       <execution>
+                                                               <configuration>
+                                                                       
<executable>python</executable>
+                                                                       
<workingDirectory>src/test/python</workingDirectory>
+                                                                       <!-- 
tests common to both interactive and non-interactive use cases -->
+                                                                       
<arguments>
+                                                                               
<argument>test_common.py</argument>
+                                                                       
</arguments>
+                                                                       
<environmentVariables>
+                                                                               
<PYTHONPATH>../../main/python:$PYTHONPATH</PYTHONPATH>
+                                                                               
<CLI_JAR>${project.build.directory}/${project.build.finalName}.jar</CLI_JAR>
+                                                                               
<WIREMOCK_JAR>${project.build.directory}/dependency/wiremock-${wiremock.version}-standalone.jar</WIREMOCK_JAR>
+                                                                       
</environmentVariables>
+                                                               </configuration>
+                                                               
<id>python-test-common</id>
+                                                               
<phase>integration-test</phase>
+                                                               <goals>
+                                                                       
<goal>exec</goal>
+                                                               </goals>
+                                                       </execution>
+                                                       <execution>
+                                                               <configuration>
+                                                                       
<executable>python</executable>
+                                                                       
<workingDirectory>src/test/python</workingDirectory>
+                                                                       <!-- 
interactive use cases -->
+                                                                       
<arguments>
+                                                                               
<argument>test_interactive.py</argument>
+                                                                       
</arguments>
+                                                                       
<environmentVariables>
+                                                                               
<PYTHONPATH>../../main/python:$PYTHONPATH</PYTHONPATH>
+                                                                               
<CLI_JAR>${project.build.directory}/${project.build.finalName}.jar</CLI_JAR>
+                                                                               
<WIREMOCK_JAR>${project.build.directory}/dependency/wiremock-${wiremock.version}-standalone.jar</WIREMOCK_JAR>
+                                                                       
</environmentVariables>
+                                                               </configuration>
+                                                               
<id>python-test-interactive</id>
+                                                               
<phase>integration-test</phase>
+                                                               <goals>
+                                                                       
<goal>exec</goal>
+                                                               </goals>
+                                                       </execution>
+                                                       <execution>
+                                                               <configuration>
+                                                                       
<executable>python</executable>
+                                                                       
<workingDirectory>src/test/python</workingDirectory>
+                                                                       <!-- 
non-interactive use cases -->
+                                                                       
<arguments>
+                                                                               
<argument>test_noninteractive.py</argument>
+                                                                       
</arguments>
+                                                                       
<environmentVariables>
+                                                                               
<PYTHONPATH>../../main/python:$PYTHONPATH</PYTHONPATH>
+                                                                               
<CLI_JAR>${project.build.directory}/${project.build.finalName}.jar</CLI_JAR>
+                                                                               
<WIREMOCK_JAR>${project.build.directory}/dependency/wiremock-${wiremock.version}-standalone.jar</WIREMOCK_JAR>
+                                                                       
</environmentVariables>
+                                                               </configuration>
+                                                               
<id>python-test-noninteractive</id>
+                                                               
<phase>integration-test</phase>
+                                                               <goals>
+                                                                       
<goal>exec</goal>
+                                                               </goals>
+                                                       </execution>
+                                               </executions>
+                                       </plugin>
+                               </plugins>
+                       </build>
+               </profile>
+       </profiles>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/.gitignore
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/test/python/.gitignore 
b/components/org.apache.stratos.cli/src/test/python/.gitignore
new file mode 100644
index 0000000..9ef57cb
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/.gitignore
@@ -0,0 +1,20 @@
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+
+*.pyc

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/__files/body_cookie.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/__files/body_cookie.json 
b/components/org.apache.stratos.cli/src/test/python/__files/body_cookie.json
new file mode 100644
index 0000000..33924ae
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/__files/body_cookie.json
@@ -0,0 +1 @@
+{"Success":{ "sessionId": "BD425955D0F64102B3C67B39D0C946F0"}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_create.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_create.json
 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_create.json
new file mode 100644
index 0000000..8ab5eb1
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_create.json
@@ -0,0 +1 @@
+{"stratosAdminResponse":{"message":"Successfully added new tenant with domain 
tenant.com"}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_deactivate.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_deactivate.json
 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_deactivate.json
new file mode 100644
index 0000000..d323d70
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_deactivate.json
@@ -0,0 +1 @@
+{"stratosAdminResponse":{"message":"Successfully deactivated tenant 
tenant.com"}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_list.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_list.json
 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_list.json
new file mode 100644
index 0000000..5952ccb
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/__files/body_tenant_list.json
@@ -0,0 +1 @@
+{"tenantInfoBean":[{"active":true,"createdDate":"2014-05-09T05:40:11Z","email":"[email protected]","tenantDomain":"tenant.com","tenantId":1}]}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/__init__.py
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/test/python/__init__.py 
b/components/org.apache.stratos.cli/src/test/python/__init__.py
new file mode 100644
index 0000000..314303d
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/__init__.py
@@ -0,0 +1,19 @@
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/mappings/cookie.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/mappings/cookie.json 
b/components/org.apache.stratos.cli/src/test/python/mappings/cookie.json
new file mode 100644
index 0000000..31336ba
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/mappings/cookie.json
@@ -0,0 +1,18 @@
+{
+  "request" : {
+    "url" : "/stratos/admin/cookie",
+    "method" : "GET"
+  },
+  "response" : {
+    "status" : 200,
+    "bodyFileName" : "body_cookie.json",
+    "headers" : {
+      "Set-Cookie" : "JSESSIONID=BD425955D0F64102B3C67B39D0C946F0; 
Path=/stratos/; Secure; HttpOnly",
+      "Date" : "Fri, 09 May 2014 05:40:05 GMT",
+      "WWW-Authenticate" : "Basic",
+      "Content-Type" : "application/json",
+      "Content-Length" : "62",
+      "Server" : "WSO2 Carbon Server"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/mappings/tenant-create.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/mappings/tenant-create.json 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-create.json
new file mode 100644
index 0000000..3f3ce05
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-create.json
@@ -0,0 +1,19 @@
+{
+  "request" : {
+    "url" : "/stratos/admin/tenant",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalTo" : 
"{\"admin\":\"tenant1\",\"firstname\":\"John\",\"lastname\":\"Doe\",\"adminPassword\":\"secret\",\"tenantDomain\":\"tenant.com\",\"email\":\"[email protected]\",\"active\":false,\"tenantId\":0}"
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "bodyFileName" : "body_tenant_create.json",
+    "headers" : {
+      "Date" : "Fri, 09 May 2014 05:40:12 GMT",
+      "Content-Type" : "application/json",
+      "Transfer-Encoding" : "chunked",
+      "Server" : "WSO2 Carbon Server"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/mappings/tenant-deactivate.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/mappings/tenant-deactivate.json
 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-deactivate.json
new file mode 100644
index 0000000..4691f6b
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-deactivate.json
@@ -0,0 +1,16 @@
+{
+  "request" : {
+    "url" : "/stratos/admin/tenant/deactivate/tenant.com",
+    "method" : "POST"
+  },
+  "response" : {
+    "status" : 200,
+    "bodyFileName" : "body_tenant_deactivate.json",
+    "headers" : {
+      "Date" : "Sat, 10 May 2014 10:07:14 GMT",
+      "Content-Type" : "application/json",
+      "Transfer-Encoding" : "chunked",
+      "Server" : "WSO2 Carbon Server"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/mappings/tenant-list.json
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/mappings/tenant-list.json 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-list.json
new file mode 100644
index 0000000..36588cd
--- /dev/null
+++ 
b/components/org.apache.stratos.cli/src/test/python/mappings/tenant-list.json
@@ -0,0 +1,16 @@
+{
+  "request" : {
+    "url" : "/stratos/admin/tenant/list",
+    "method" : "GET"
+  },
+  "response" : {
+    "status" : 200,
+    "bodyFileName" : "body_tenant_list.json",
+    "headers" : {
+      "Date" : "Fri, 09 May 2014 05:45:15 GMT",
+      "Content-Type" : "application/json",
+      "Transfer-Encoding" : "chunked",
+      "Server" : "WSO2 Carbon Server"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/test_common.py
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/test/python/test_common.py 
b/components/org.apache.stratos.cli/src/test/python/test_common.py
new file mode 100755
index 0000000..407a178
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/test_common.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python 
+# ----------------------------------------------------------------------------
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+
+import unittest
+import pexpect
+import os
+import signal
+import subprocess
+import urllib
+import urllib2
+import json
+from wiremock import WiremockClient
+
+class TestCommon(unittest.TestCase):
+
+    cli_cmd = "java -jar " + os.environ["CLI_JAR"]
+
+    @classmethod
+    def setUpClass(cls):
+        TestCommon.wiremock = WiremockClient()
+        TestCommon.wiremock.start()
+
+    @classmethod
+    def tearDownClass(cls):
+        TestCommon.wiremock.stop()
+
+    def setUp(self):
+        # unset these environment variables
+        if 'STRATOS_USERNAME' in os.environ: del 
os.environ["STRATOS_USERNAME"] # unset env var
+        if 'STRATOS_PASSWORD' in os.environ: del 
os.environ["STRATOS_PASSWORD"] # unset env var
+
+    def tearDown(self):
+        TestCommon.wiremock.reset()
+
+    def test_error_if_stratos_url_not_set(self):
+        if 'STRATOS_URL' in os.environ: del os.environ["STRATOS_URL"]      # 
unset env var
+        child = pexpect.spawn(TestCommon.cli_cmd)
+        child.expect ('Could not find required "STRATOS_URL" variable in your 
environment.')
+        child.expect (pexpect.EOF)
+
+    def test_error_if_port_not_provided_in_stratos_url(self):
+        os.environ["STRATOS_URL"] = "https://localhost";  # no port
+        child = pexpect.spawn(TestCommon.cli_cmd)
+        child.expect ('The "STRATOS_URL" variable in your environment is not a 
valid URL. You have provided "https://localhost";')
+        child.expect ('Please provide the Stratos Controller URL as follows')
+        child.expect ('https://<host>:<port>')
+        child.expect (pexpect.EOF)
+
+    def test_error_if_context_path_is_provided_in_stratos_url(self):
+        os.environ["STRATOS_URL"] = "https://localhost:9443/somecontext/"; # 
context path
+        child = pexpect.spawn(TestCommon.cli_cmd)
+        child.expect ('The "STRATOS_URL" variable in your environment is not a 
valid URL. You have provided "https://localhost:9443/somecontext/";')
+        child.expect ('Please provide the Stratos Controller URL as follows')
+        child.expect ('https://<host>:<port>')
+        child.expect (pexpect.EOF)
+
+    def test_error_if_non_https_scheme_is_provided_in_stratos_url(self):
+        os.environ["STRATOS_URL"] = "http://localhost:9443"; # http scheme
+        child = pexpect.spawn(TestCommon.cli_cmd)
+        child.expect ('The "STRATOS_URL" variable in your environment is not a 
valid URL. You have provided "http://localhost:9443";')
+        child.expect ('Please provide the Stratos Controller URL as follows')
+        child.expect ('https://<host>:<port>')
+        child.expect (pexpect.EOF)
+
+    def test_error_if_invalid_format_is_given_for_stratos_url(self):
+        # we need to ensure the url is valid and not that it just has 2 colons 
and 3 or less slashes!
+        os.environ["STRATOS_URL"] = ":://"
+        child = pexpect.spawn(TestCommon.cli_cmd)
+        child.expect ('The "STRATOS_URL" variable in your environment is not a 
valid URL. You have provided ":://"')
+        child.expect ('Please provide the Stratos Controller URL as follows')
+        child.expect ('https://<host>:<port>')
+        child.expect (pexpect.EOF)
+
+if __name__ == '__main__':
+    try: 
+        unittest.main()
+    # handle CTRL-C
+    except KeyboardInterrupt:
+        # shut down wiremock 
+        TestCommon.wiremock.stop()
+        exit(1) 

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/test_interactive.py
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/test_interactive.py 
b/components/org.apache.stratos.cli/src/test/python/test_interactive.py
new file mode 100755
index 0000000..cf1bb3e
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/test_interactive.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python 
+# ----------------------------------------------------------------------------
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+
+import unittest
+import pexpect
+import os
+import signal
+import subprocess
+import urllib
+import urllib2
+import json
+from wiremock import WiremockClient
+
+class TestInteractive(unittest.TestCase):
+
+    cli_cmd = "java -jar " + os.environ["CLI_JAR"]
+
+    @classmethod
+    def setUpClass(cls):
+        TestInteractive.wiremock = WiremockClient()
+        TestInteractive.wiremock.start()
+
+    @classmethod
+    def tearDownClass(cls):
+        TestInteractive.wiremock.stop()
+
+    def setUp(self):
+        # set default STRATOS_URL
+        os.environ["STRATOS_URL"] = "https://localhost:9443"; 
+        # ensure other env vars not set
+        if 'STRATOS_USERNAME' in os.environ: del 
os.environ["STRATOS_USERNAME"] # unset env var
+        if 'STRATOS_PASSWORD' in os.environ: del 
os.environ["STRATOS_PASSWORD"] # unset env var
+
+    def tearDown(self):
+        TestInteractive.wiremock.reset()
+
+    def test_interactive_mode_username_and_password_sent_to_server(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd)
+        child.expect   ('Username: ')
+        child.sendline ('1234')
+        child.expect   ('Password: ')
+        child.sendline ('abcd')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "1234:abcd")
+
+    def test_interactive_mode_standard_username_parameter_provided(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd + " -username xxx", 
timeout=10)
+        child.expect   ('Username: xxx')
+        child.expect   ('Password: ')
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "xxx:zzz")
+
+    def test_interactive_mode_short_username_parameter_provided(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd + " -u xxx", timeout=10)
+        child.expect   ('Username: xxx')
+        child.expect   ('Password: ')
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "xxx:zzz")
+
+    def test_interactive_mode_long_username_parameter_provided(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd + " --username xxx", 
timeout=10)
+        child.expect   ('Username: xxx')
+        child.expect   ('Password: ')
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "xxx:zzz")
+
+    def test_interactive_mode_username_env_var_provided(self):
+        os.environ["STRATOS_USERNAME"] = "yyy" 
+        # ensure other env vars not set
+        child = pexpect.spawn(TestInteractive.cli_cmd, timeout=10)
+        child.expect   ('Username: yyy')
+        child.expect   ('Password: ')
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "yyy:zzz")
+
+    def test_interactive_mode_standard_password_parameter_provided(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd + " -password xxx", 
timeout=10)
+        child.expect   ('Username: ')
+        child.sendline ('1234') 
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "1234:xxx")
+
+    def test_interactive_mode_list_tenants(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd, timeout=10)
+        child.expect   ('Username: ')
+        child.sendline ('1234') 
+        child.expect   ('\r\nPassword: ') # TODO - why do we need \r\n?
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('list-tenants')
+        child.expect   ('Available Tenants')
+        # in the table below, + characters have been replaced with .
+        # because the + is a special regex character
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.expect   ('| Domain     | Tenant ID | Email           | State  | 
Created Date         |')
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.expect   ('| tenant.com | 1         | [email protected] | Active | 
2014-05-09T05:40:11Z |')
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "1234:zzz")
+        self.assertEqual(self.wiremock.get_cookie_req_count(), 1)
+        self.assertEqual(self.wiremock.get_tenant_list_req_count(), 1)
+
+    def test_interactive_mode_create_tenant(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd, timeout=10)
+        child.expect   ('Username: ')
+        child.sendline ('1234') 
+        child.expect   ('\r\nPassword: ') # TODO - why do we need \r\n?
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('create-tenant --username tenant1 --password secret 
--first-name John --last-name Doe --domain-name tenant.com --email 
[email protected]')
+        child.expect   ('Tenant added successfully')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "1234:zzz")
+        self.assertEqual(self.wiremock.get_cookie_req_count(), 1)
+        self.assertEqual(self.wiremock.tenant_create_req_count(), 1)
+
+    def test_interactive_mode_deactivate_tenant(self):
+        child = pexpect.spawn(TestInteractive.cli_cmd, timeout=10)
+        child.expect   ('Username: ')
+        child.sendline ('1234') 
+        child.expect   ('\r\nPassword: ') # TODO - why do we need \r\n?
+        child.sendline ('zzz')
+        child.expect   ('Successfully Authenticated.')
+        child.expect   ('stratos> ')
+        child.sendline ('deactivate-tenant tenant.com')
+        child.expect   ('You have succesfully deactivate tenant.com tenant')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # CLI sends GET request to mock server url /stratos/admin/coookie
+        self.assertEqual(self.wiremock.get_cookie_auth_header(), "1234:zzz")
+        self.assertEqual(self.wiremock.get_cookie_req_count(), 1)
+        self.assertEqual(self.wiremock.tenant_deactivate_req_count(), 1)
+
+
+if __name__ == '__main__':
+    try: 
+        unittest.main()
+    # handle CTRL-C
+    except KeyboardInterrupt:
+        # shut down wiremock 
+        TestInteractive.wiremock.stop()
+        exit(1) 

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/test_noninteractive.py
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cli/src/test/python/test_noninteractive.py 
b/components/org.apache.stratos.cli/src/test/python/test_noninteractive.py
new file mode 100755
index 0000000..8379165
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/test_noninteractive.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python 
+# ----------------------------------------------------------------------------
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+
+import unittest
+import pexpect
+import os
+import signal
+import subprocess
+import urllib
+import urllib2
+import json
+from wiremock import WiremockClient
+
+class TestNonInteractive(unittest.TestCase):
+
+    cli_cmd = "java -jar " + os.environ["CLI_JAR"]
+
+    @classmethod
+    def setUpClass(cls):
+        TestNonInteractive.wiremock = WiremockClient()
+        TestNonInteractive.wiremock.start()
+
+    @classmethod
+    def tearDownClass(cls):
+        TestNonInteractive.wiremock.stop()
+
+    def setUp(self):
+        # set default STRATOS_URL
+        os.environ["STRATOS_URL"] = "https://localhost:9443"; 
+        # ensure other env vars not set
+        if 'STRATOS_USERNAME' in os.environ: del 
os.environ["STRATOS_USERNAME"] # unset env var
+        if 'STRATOS_PASSWORD' in os.environ: del 
os.environ["STRATOS_PASSWORD"] # unset env var
+
+    def tearDown(self):
+        TestNonInteractive.wiremock.reset()
+
+    def test_noninteractive_mode_list_tenants(self):
+        child = pexpect.spawn(TestNonInteractive.cli_cmd + " -username admin 
-password admin list-tenants", timeout=10)
+        child.expect   ('Available Tenants')
+        # in the table below, + characters have been replaced with .
+        # because the + is a special regex character
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.expect   ('| Domain     | Tenant ID | Email           | State  | 
Created Date         |')
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.expect   ('| tenant.com | 1         | [email protected] | Active | 
2014-05-09T05:40:11Z |')
+        child.expect   
('.------------.-----------.-----------------.--------.----------------------.')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # verify /stratos/admin/tenant/list was called
+        self.assertEqual(self.wiremock.get_tenant_list_req_count(), 1)
+
+    def test_noninteractive_mode_create_tenant(self):
+        command = "create-tenant -u tenant1 -p secret -f John -l Doe -d 
tenant.com -e [email protected]"
+        child = pexpect.spawn(TestNonInteractive.cli_cmd + " -u adminuser -p 
adminpass " + command, timeout=10)
+        child.expect   ('Username: adminuser')
+        child.expect   ('Tenant added successfully')
+        child.sendline ('exit')
+        child.expect   (pexpect.EOF)
+        # verify POST /stratos/admin/tenant/list was called
+        self.assertEqual(self.wiremock.tenant_create_req_count(), 1)
+
+if __name__ == '__main__':
+    try: 
+        unittest.main()
+    # handle CTRL-C
+    except KeyboardInterrupt:
+        # shut down wiremock 
+        TestNonInteractive.wiremock.stop()
+        exit(1) 

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cb3a22e8/components/org.apache.stratos.cli/src/test/python/wiremock.py
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/test/python/wiremock.py 
b/components/org.apache.stratos.cli/src/test/python/wiremock.py
new file mode 100755
index 0000000..aa81e7f
--- /dev/null
+++ b/components/org.apache.stratos.cli/src/test/python/wiremock.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python 
+# ----------------------------------------------------------------------------
+#
+#  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
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  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.
+#
+
+import os
+import signal
+import subprocess
+import urllib
+import urllib2
+import json
+import base64
+
+class WiremockClient():
+
+    reset_url = 'http://localhost:8080/__admin/mappings/reset'
+
+    find_url = 'http://localhost:8080/__admin/requests/find'
+
+    count_url = 'http://localhost:8080/__admin/requests/count'
+
+    cookies_req_json = '{ "method": "GET", "url": "/stratos/admin/cookie" }'
+
+    tenant_list_req_json = '{ "method": "GET", "url": 
"/stratos/admin/tenant/list" }'
+
+    tenant_create_req_json = '{ "method": "POST", "url": 
"/stratos/admin/tenant" }'
+
+    tenant_deactivate_req_json = '{ "method": "POST", "url": 
"/stratos/admin/tenant/deactivate/tenant.com" }'
+
+    wiremock = "java -jar " + os.environ["WIREMOCK_JAR"] + " --https-port 9443"
+
+    def start(self):
+        # execute wiremock and return handle so it can be torn down
+        # Note: the requests that wiremock handles and the response it will 
return 
+        # for a request can be found in the 'mapping' directory
+        self.wiremock_process = subprocess.Popen(self.wiremock.split(), 
+                               stdout=subprocess.PIPE, 
+                               preexec_fn=os.setsid) 
+
+    def __del__(self):
+        self.stop()
+
+    def stop(self):
+        # kill wiremock process
+        os.killpg(self.wiremock_process.pid, signal.SIGTERM)
+
+    def reset(self):
+        # ignore errors when resetting
+        try:
+            req = urllib2.Request(WiremockClient.reset_url, data="")
+            urllib2.urlopen(req)
+        except:
+            pass
+
+    def get_cookie_requests_and_responses(self):
+        # send GET request to mock server url /stratos/admin/coookie
+        req = urllib2.Request(WiremockClient.find_url)
+        req.add_header('Content-Type', 'application/json')
+        response = urllib2.urlopen(req, WiremockClient.cookies_req_json)
+        return json.load(response)
+
+    def get_cookie_auth_header(self):
+        data = self.get_cookie_requests_and_responses()
+        encoded_username_password = 
data["requests"][0]["headers"]["Authorization"]
+        return base64.b64decode(encoded_username_password.split(" ")[1])
+   
+    # lots of repeated code below - TODO refactor to method
+    def get_cookie_req_count(self):
+        req = urllib2.Request(WiremockClient.count_url)
+        req.add_header('Content-Type', 'application/json')
+        response = urllib2.urlopen(req, WiremockClient.cookies_req_json)
+        return json.load(response)["count"]
+
+    def get_tenant_list_req_count(self):
+        req = urllib2.Request(WiremockClient.count_url)
+        req.add_header('Content-Type', 'application/json')
+        response = urllib2.urlopen(req, WiremockClient.tenant_list_req_json)
+        return json.load(response)["count"]
+             
+    def tenant_create_req_count(self):
+        req = urllib2.Request(WiremockClient.count_url)
+        req.add_header('Content-Type', 'application/json')
+        response = urllib2.urlopen(req, WiremockClient.tenant_create_req_json)
+        return json.load(response)["count"]
+
+    def tenant_deactivate_req_count(self):
+        req = urllib2.Request(WiremockClient.count_url)
+        req.add_header('Content-Type', 'application/json')
+        response = urllib2.urlopen(req, 
WiremockClient.tenant_deactivate_req_json)
+        return json.load(response)["count"]

Reply via email to