Skip to content

Commit

Permalink
Added tests for HTTPS transports
Browse files Browse the repository at this point in the history
- In fact, simply check if we get an SSL error: if so, we're trying to
  connect a Remote Service using HTTPS (which is OK)
- Refactored HTTP tests to inherit tests
  • Loading branch information
tcalmant committed Aug 27, 2016
1 parent d3203c6 commit d519cbf
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 14 deletions.
33 changes: 19 additions & 14 deletions tests/remote/test_transports_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,13 @@ class HttpTransportsTest(unittest.TestCase):
"""
Tests Pelix built-in Remote Services transports
"""
def __run_test(self, transport_bundle, exporter_factory, importer_factory,
test_kwargs=True):
def __init__(self, *args, **kwargs):
super(HttpTransportsTest, self).__init__(*args, **kwargs)
self._load_framework = load_framework
self._export_framework = export_framework

def _run_test(self, transport_bundle, exporter_factory, importer_factory,
test_kwargs=True):
"""
Runs a remote service call test
Expand All @@ -215,7 +220,7 @@ def __run_test(self, transport_bundle, exporter_factory, importer_factory,

# Start the remote framework
status_queue = Queue()
peer = WrappedProcess(target=export_framework,
peer = WrappedProcess(target=self._export_framework,
args=(status_queue, transport_bundle,
components))
peer.start()
Expand All @@ -226,7 +231,7 @@ def __run_test(self, transport_bundle, exporter_factory, importer_factory,
self.assertEqual(state, "ready")

# Load the local framework (after the fork)
framework = load_framework(transport_bundle, components)
framework = self._load_framework(transport_bundle, components)
context = framework.get_bundle_context()

# Look for the remote service
Expand Down Expand Up @@ -326,10 +331,10 @@ def test_xmlrpc(self):
Tests the XML-RPC transport
"""
try:
self.__run_test("pelix.remote.xml_rpc",
pelix.remote.FACTORY_TRANSPORT_XMLRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_XMLRPC_IMPORTER,
False)
self._run_test("pelix.remote.xml_rpc",
pelix.remote.FACTORY_TRANSPORT_XMLRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_XMLRPC_IMPORTER,
False)
except queue.Empty:
# Process error
self.fail("Remote framework took to long to reply")
Expand All @@ -339,9 +344,9 @@ def test_jsonrpc(self):
Tests the JSON-RPC transport
"""
try:
self.__run_test("pelix.remote.json_rpc",
pelix.remote.FACTORY_TRANSPORT_JSONRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_JSONRPC_IMPORTER)
self._run_test("pelix.remote.json_rpc",
pelix.remote.FACTORY_TRANSPORT_JSONRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_JSONRPC_IMPORTER)
except queue.Empty:
# Process error
self.fail("Remote framework took to long to reply")
Expand All @@ -351,9 +356,9 @@ def test_jabsorbrpc(self):
Tests the JABSORB-RPC transport
"""
try:
self.__run_test("pelix.remote.transport.jabsorb_rpc",
pelix.remote.FACTORY_TRANSPORT_JABSORBRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_JABSORBRPC_IMPORTER)
self._run_test("pelix.remote.transport.jabsorb_rpc",
pelix.remote.FACTORY_TRANSPORT_JABSORBRPC_EXPORTER,
pelix.remote.FACTORY_TRANSPORT_JABSORBRPC_IMPORTER)
except queue.Empty:
# Process error
self.fail("Remote framework took to long to reply")
Expand Down
190 changes: 190 additions & 0 deletions tests/remote/test_transports_https.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#!/usr/bin/python
# -- Content-Encoding: UTF-8 --
"""
Tests remote services transports based on HTTPS
:author: Thomas Calmant
:copyright: Copyright 2016, Thomas Calmant
:license: Apache License 2.0
..
Copyright 2016 Thomas Calmant
Licensed 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.
"""

# Standard library
import os
import shutil
import ssl
import threading
import tempfile

try:
import unittest2 as unittest
except ImportError:
import unittest

try:
# Try to import modules
from multiprocessing import Process, Queue
# IronPython fails when creating a queue
Queue()
except ImportError:
# Some interpreters don't have support for multiprocessing
raise unittest.SkipTest("Interpreter doesn't support multiprocessing")

try:
import queue
except ImportError:
import Queue as queue

# Pelix
from pelix.framework import create_framework
from pelix.ipopo.constants import use_ipopo
import pelix.http
import pelix.remote


# Local utilities
from tests.http.test_basic_ssl import install_ipopo, make_certs, \
instantiate_server
from tests.remote.test_transports_http import RemoteService, SVC_SPEC, \
HttpTransportsTest

# ------------------------------------------------------------------------------

# Documentation strings format
__docformat__ = "restructuredtext en"

# ------------------------------------------------------------------------------


def load_framework(transport, components, start_server=True):
"""
Starts a Pelix framework in the local process
:param transport: Name of the transport bundle to install
:param components: Tuples (factory, name) of instances to start
"""
all_bundles = ['pelix.ipopo.core',
'pelix.http.basic',
'pelix.remote.dispatcher',
'pelix.remote.registry',
'pelix.remote.discovery.multicast',
transport]

# Start the framework
framework = create_framework(all_bundles)
framework.start()

with use_ipopo(framework.get_bundle_context()) as ipopo:
if start_server:
# Start a HTTP service on a random port
ipopo.instantiate(pelix.http.FACTORY_HTTP_BASIC,
"http-server",
{pelix.http.HTTP_SERVICE_ADDRESS: "0.0.0.0",
pelix.http.HTTP_SERVICE_PORT: 0})

ipopo.instantiate(pelix.remote.FACTORY_REGISTRY_SERVLET,
"dispatcher-servlet")

# Start the multicast discovery
ipopo.instantiate(pelix.remote.FACTORY_DISCOVERY_MULTICAST,
"multicast-discovery")

# Start other components
for factory, name in components:
ipopo.instantiate(factory, name)

return framework


def export_framework(state_queue, transport, components):
"""
Starts a Pelix framework, on the export side
:param state_queue: Queue to store status
:param transport: Name of the transport bundle to install
:param components: Tuples (factory, name) of instances to start
"""
tmp_dir = tempfile.mkdtemp(prefix="ipopo-tests-https")

try:
# Load the framework
framework = load_framework(transport, components, False)
context = framework.get_bundle_context()
ipopo = install_ipopo(framework)

# Prepare certificates
make_certs(tmp_dir, None)

# Setup the HTTPS server
instantiate_server(
ipopo, cert_file=os.path.join(tmp_dir, "server.crt"),
key_file=os.path.join(tmp_dir, "server.key"),
address="0.0.0.0", port=0)

# Register the exported service
event = threading.Event()
context.register_service(
SVC_SPEC, RemoteService(state_queue, event),
{pelix.remote.PROP_EXPORTED_INTERFACES: '*'})

# Send the ready state
state_queue.put("ready")

# Loop until the end message
event.wait()

# Stopping
state_queue.put("stopping")
framework.stop()

except Exception as ex:
state_queue.put("Error: {0}".format(ex))
finally:
shutil.rmtree(tmp_dir)

# ------------------------------------------------------------------------------


class HttpsTransportsTest(HttpTransportsTest):
"""
Tests Pelix built-in Remote Services transports
"""
def __init__(self, *args, **kwargs):
super(HttpsTransportsTest, self).__init__(*args, **kwargs)
self._load_framework = load_framework
self._export_framework = export_framework

def _run_test(self, transport_bundle, exporter_factory, importer_factory,
test_kwargs=True):
try:
super(HttpsTransportsTest, self)._run_test(
transport_bundle, exporter_factory, importer_factory,
test_kwargs)
except ssl.SSLError:
# This should happen as the communication happens on a self-signed
# certificate
return True

# ------------------------------------------------------------------------------

if __name__ == "__main__":
# Set logging level
import logging
logging.basicConfig(level=logging.DEBUG)

unittest.main()

0 comments on commit d519cbf

Please sign in to comment.