~benji/charms/precise/juju-gui/fix-cache-headers

« back to all changes in this revision

Viewing changes to server/guiserver/tests/helpers.py

  • Committer: Benji York
  • Date: 2013-07-31 22:08:34 UTC
  • mfrom: (60.13.9 noncharmers)
  • Revision ID: benji.york@canonical.com-20130731220834-hr78mvsri3ou0x59
mergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This file is part of the Juju GUI, which lets users view and manage Juju
 
2
# environments within a graphical interface (https://launchpad.net/juju-gui).
 
3
# Copyright (C) 2013 Canonical Ltd.
 
4
#
 
5
# This program is free software: you can redistribute it and/or modify it under
 
6
# the terms of the GNU Affero General Public License version 3, as published by
 
7
# the Free Software Foundation.
 
8
#
 
9
# This program is distributed in the hope that it will be useful, but WITHOUT
 
10
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
 
11
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
# Affero General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU Affero General Public License
 
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 
 
17
"""Juju GUI server test utilities."""
 
18
 
 
19
import json
 
20
 
 
21
from tornado import websocket
 
22
 
 
23
from guiserver import auth
 
24
 
 
25
 
 
26
class EchoWebSocketHandler(websocket.WebSocketHandler):
 
27
    """A WebSocket server echoing back messages."""
 
28
 
 
29
    def initialize(self, close_future, io_loop):
 
30
        """Echo WebSocket server initializer.
 
31
 
 
32
        The handler receives a close Future and the current Tornado IO loop.
 
33
        The close Future is fired when the connection is closed.
 
34
        The close Future can also be used to force a connection termination by
 
35
        manually firing it.
 
36
        """
 
37
        self._closed_future = close_future
 
38
        self._connected = True
 
39
        io_loop.add_future(close_future, self.force_close)
 
40
 
 
41
    def force_close(self, future):
 
42
        """Close the connection to the client."""
 
43
        if self._connected:
 
44
            self.close()
 
45
 
 
46
    def on_message(self, message):
 
47
        """Echo back the received message."""
 
48
        self.write_message(message, isinstance(message, bytes))
 
49
 
 
50
    def on_close(self):
 
51
        """Fire the _closed_future if not already done."""
 
52
        self._connected = False
 
53
        if not self._closed_future.done():
 
54
            self._closed_future.set_result(None)
 
55
 
 
56
 
 
57
class GoAPITestMixin(object):
 
58
    """Add helper methods for testing the Go API implementation."""
 
59
 
 
60
    def get_auth_backend(self):
 
61
        """Return an authentication backend suitable for the Go API."""
 
62
        return auth.get_backend('go')
 
63
 
 
64
    def make_login_request(
 
65
            self, request_id=42, username='user', password='passwd',
 
66
            encoded=False):
 
67
        """Create and return a login request message.
 
68
 
 
69
        If encoded is set to True, the returned message will be JSON encoded.
 
70
        """
 
71
        data = {
 
72
            'RequestId': request_id,
 
73
            'Type': 'Admin',
 
74
            'Request': 'Login',
 
75
            'Params': {'AuthTag': username, 'Password': password},
 
76
        }
 
77
        return json.dumps(data) if encoded else data
 
78
 
 
79
    def make_login_response(
 
80
            self, request_id=42, successful=True, encoded=False):
 
81
        """Create and return a login response message.
 
82
 
 
83
        If encoded is set to True, the returned message will be JSON encoded.
 
84
        By default, a successful response is returned. Set successful to False
 
85
        to return an authentication failure.
 
86
        """
 
87
        data = {'RequestId': request_id, 'Response': {}}
 
88
        if not successful:
 
89
            data['Error'] = 'invalid entity name or password'
 
90
        return json.dumps(data) if encoded else data
 
91
 
 
92
 
 
93
class PythonAPITestMixin(object):
 
94
    """Add helper methods for testing the Python API implementation."""
 
95
 
 
96
    def get_auth_backend(self):
 
97
        """Return an authentication backend suitable for the Python API."""
 
98
        return auth.get_backend('python')
 
99
 
 
100
    def make_login_request(
 
101
            self, request_id=42, username='user', password='passwd',
 
102
            encoded=False):
 
103
        """Create and return a login request message.
 
104
 
 
105
        If encoded is set to True, the returned message will be JSON encoded.
 
106
        """
 
107
        data = {
 
108
            'request_id': request_id,
 
109
            'op': 'login',
 
110
            'user': username,
 
111
            'password': password,
 
112
        }
 
113
        return json.dumps(data) if encoded else data
 
114
 
 
115
    def make_login_response(
 
116
            self, request_id=42, successful=True, encoded=False):
 
117
        """Create and return a login response message.
 
118
 
 
119
        If encoded is set to True, the returned message will be JSON encoded.
 
120
        By default, a successful response is returned. Set successful to False
 
121
        to return an authentication failure.
 
122
        """
 
123
        data = {'request_id': request_id, 'op': 'login'}
 
124
        if successful:
 
125
            data['result'] = True
 
126
        else:
 
127
            data['err'] = True
 
128
        return json.dumps(data) if encoded else data
 
129
 
 
130
 
 
131
class WSSTestMixin(object):
 
132
    """Add some helper methods for testing secure WebSocket handlers."""
 
133
 
 
134
    def get_wss_url(self, path):
 
135
        """Return an absolute secure WebSocket url for the given path."""
 
136
        return 'wss://localhost:{}{}'.format(self.get_http_port(), path)