Merge lp:~mbruzek/charms/precise/memcached/trunk into lp:charms/memcached

Proposed by Matt Bruzek
Status: Merged
Merged at revision: 60
Proposed branch: lp:~mbruzek/charms/precise/memcached/trunk
Merge into: lp:charms/memcached
Diff against target: 175 lines (+165/-0)
2 files modified
tests/00_setup.sh (+19/-0)
tests/10_deploy_test.py (+146/-0)
To merge this branch: bzr merge lp:~mbruzek/charms/precise/memcached/trunk
Reviewer Review Type Date Requested Status
Marco Ceppi (community) Approve
Review via email: mp+203565@code.launchpad.net

Description of the change

Added Juju Amulet tests for memcached charm.

Added a deploy test, testing memcached with telnet, and configuration test.

https://codereview.appspot.com/55950045/

To post a comment you must log in.
Revision history for this message
Matt Bruzek (mbruzek) wrote :

Please take a look.

Revision history for this message
Matt Bruzek (mbruzek) wrote :

Reviewers: mp+203565_code.launchpad.net,

Message:
Please take a look.

Description:
Added Juju Amulet tests for memcached charm.

Added a deploy test, testing memcached with telnet, and configuration
test.

https://code.launchpad.net/~mbruzek/charms/precise/memcached/trunk/+merge/203565

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/55950045/

Affected files (+154, -0 lines):
   A [revision details]
   A tests/00_setup.sh
   A tests/10_deploy_test.py

Revision history for this message
Charles Butler (lazypower) wrote :

Matt, Thank you for your work on this charm test suite, it looks
comprehensive enough to be comfortable, the only issue I found was in
the setup script there were missing dependencies.

Correct those issues and you get a +1 from me

https://codereview.appspot.com/55950045/diff/1/tests/00_setup.sh
File tests/00_setup.sh (right):

https://codereview.appspot.com/55950045/diff/1/tests/00_setup.sh#newcode13
tests/00_setup.sh:13: sudo apt-get install -y amulet
This is missing python3, and any associated python3 libraries to
complete the test run. The assumption is we are running this test on a
machine with nothing more than juju-core on it.

https://codereview.appspot.com/55950045/diff/1/tests/10_deploy_test.py
File tests/10_deploy_test.py (right):

https://codereview.appspot.com/55950045/diff/1/tests/10_deploy_test.py#newcode65
tests/10_deploy_test.py:65: try:
I like how you did this test. +1

https://codereview.appspot.com/55950045/diff/1/tests/10_deploy_test.py#newcode137
tests/10_deploy_test.py:137: message = 'The memcached charm passed the
deply tests!'
Typo on Deploy

https://codereview.appspot.com/55950045/

61. By Matt Bruzek <email address hidden>

Making changes based on lazyPower's code review comments.

Revision history for this message
Matt Bruzek (mbruzek) wrote :
Revision history for this message
Matt Bruzek (mbruzek) wrote :

I updated the code to respond to lazypower's code review comments.

https://codereview.appspot.com/55950045/

Revision history for this message
Marco Ceppi (marcoceppi) wrote :

This looks good as a test, needs some additional robustness, see inline
comments

https://codereview.appspot.com/55950045/diff/20001/tests/10_deploy_test.py
File tests/10_deploy_test.py (right):

https://codereview.appspot.com/55950045/diff/20001/tests/10_deploy_test.py#newcode96
tests/10_deploy_test.py:96: except:
It would be nice if you used

except Exception as e:

which would allow you to use the e to detail which of the areas failed
in the test. So for your message you could add a third option, str(e) to
get the message of the error which caused the exception. This should
help show authors why the charm is failing if it fails

https://codereview.appspot.com/55950045/diff/20001/tests/10_deploy_test.py#newcode133
tests/10_deploy_test.py:133: relation = mediawiki_unit.relation('cache',
'memcached:cache')
The cache relation for memcache sends host, port, and udp-port with the
last two being configurable. You should set these to non-standard ports
in the initial configuration and test that the values are sent on the
wire properly.

https://codereview.appspot.com/55950045/

62. By Matt Bruzek <email address hidden>

Addressed code review comments.

Revision history for this message
Matt Bruzek (mbruzek) wrote :
Revision history for this message
Marco Ceppi (marcoceppi) wrote :

LGTM, with one minor fix below

https://codereview.appspot.com/55950045/diff/40001/tests/10_deploy_test.py
File tests/10_deploy_test.py (right):

https://codereview.appspot.com/55950045/diff/40001/tests/10_deploy_test.py#newcode62
tests/10_deploy_test.py:62: port_string =
memcached_unit.info['open-ports'][0]
It'd be better to use configuration['tcp-port'] for this, instead of
querying the unit.info data.

https://codereview.appspot.com/55950045/

63. By Matt Bruzek <email address hidden>

Addressing the tcp-port review comment.

Revision history for this message
Matt Bruzek (mbruzek) wrote :
Revision history for this message
Marco Ceppi (marcoceppi) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'tests'
2=== added file 'tests/00_setup.sh'
3--- tests/00_setup.sh 1970-01-01 00:00:00 +0000
4+++ tests/00_setup.sh 2014-02-06 18:10:42 +0000
5@@ -0,0 +1,19 @@
6+#!/bin/sh
7+
8+# The script installs amulet and other tools needed for the amulet tests.
9+
10+set -x
11+
12+# Get the status of the amulet package, this returns 0 of package is installed.
13+dpkg -s amulet
14+if [ $? -ne 0 ]; then
15+ # Install the Amulet testing harness.
16+ sudo add-apt-repository -y ppa:juju/stable
17+ sudo apt-get update
18+ sudo apt-get install -y amulet juju-core charm-tools
19+fi
20+dpkg -s python3
21+if [ $? -ne 0 ]; then
22+ # Install the Python3 libraries.
23+ sudo apt-get install -y python3
24+fi
25
26=== added file 'tests/10_deploy_test.py'
27--- tests/10_deploy_test.py 1970-01-01 00:00:00 +0000
28+++ tests/10_deploy_test.py 2014-02-06 18:10:42 +0000
29@@ -0,0 +1,146 @@
30+#!/usr/bin/python3
31+
32+## This Amulet test deploys memcached.
33+
34+import amulet
35+import telnetlib
36+import time
37+
38+# The number of seconds to wait for the environment to setup.
39+seconds = 1200
40+
41+d = amulet.Deployment()
42+# Add the memcached charm to the deployment.
43+d.add('memcached')
44+# Add the mediawiki charm to the deployment.
45+d.add('mediawiki')
46+# Create a relation from memcached to mediawiki
47+d.relate('memcached:cache', 'mediawiki:cache')
48+
49+# Create a configuration dictionary for custom memcached values.
50+configuration = {'size': 512, 'connection-limit': 128, 'factor': 1.10,
51+ 'tcp-port': 11212, 'udp-port': 11213}
52+d.configure('memcached', configuration)
53+# Expose memcached so it is visible to the tests.
54+d.expose('memcached')
55+
56+try:
57+ # Execute the deployer with the current mapping.
58+ d.setup(timeout=seconds)
59+ # Wait for the relation to finish the translations.
60+ d.sentry.wait(seconds)
61+except amulet.helpers.TimeoutError:
62+ message = 'The environment did not setup in %d seconds.' % seconds
63+ # The SKIP status enables skip or fail the test based on configuration.
64+ amulet.raise_status(amulet.SKIP, msg=message)
65+except:
66+ raise
67+
68+# Get the sentry for memcached.
69+memcached_unit = d.sentry.unit['memcached/0']
70+
71+## Test if the memcached service is running.
72+
73+# Run the command that checks if the memcached server instance is running.
74+command = 'service memcached status'
75+# Execute the command on the deployed service.
76+output, code = memcached_unit.run(command)
77+
78+if code != 0:
79+ message = 'The ' + command + ' returned %d.' % code
80+ print(output)
81+ amulet.raise_status(amulet.FAIL, msg=message)
82+else:
83+ message = 'The memcached service is running.'
84+ print(output)
85+ print(message)
86+
87+## Test memcached using telnet commands.
88+
89+# Get the public address for memcached instance.
90+memcached_address = memcached_unit.info['public-address']
91+# Get the port for memcached instance.
92+memcached_port = configuration['tcp-port']
93+
94+try:
95+ # Connect to memcached via telnet.
96+ tn = telnetlib.Telnet(memcached_address, memcached_port)
97+ date_time = time.strftime("%F %r")
98+ # Write the command that gets the current greeting.
99+ tn.write(b'get greeting\r\n')
100+ # Read the current greeting.
101+ response = tn.read_until(b'END', 2)
102+ # Create a string with date and time for this test.
103+ string = 'memcached test %s' % date_time
104+ command = 'set greeting 1 0 %d' % len(string)
105+ # Write the command that sets the new greeting.
106+ tn.write(command.encode() + b'\r\n')
107+ tn.write(string.encode() + b'\r\n')
108+ # Read the response
109+ response = tn.read_until(b'STORED', 2)
110+ # Write the command that gets the greeting.
111+ tn.write(b'get greeting\r\n')
112+ # Get the new greeting in memcached.
113+ response = tn.read_until(b'END', 2)
114+ response = response.decode()
115+ print('get greeting response:')
116+ print(response)
117+ # Look for the string in the response.
118+ index = response.find(string)
119+ if index != -1:
120+ print('Found %s in the greeting response.' % string)
121+ else:
122+ print(response)
123+ message = 'Did not find %s in the greeting from memcached.' % string
124+ amulet.raise_status(amulet.FAIL, msg=message)
125+ tn.write(b'quit\n')
126+except Exception as e:
127+ message = 'An error occurred communicating with memcached over telnet ' \
128+ '{0}:{1} {3}'.format(memcached_address, memcached_port, str(e))
129+ amulet.raise_status(amulet.FAIL, msg=message)
130+finally:
131+ tn.close()
132+
133+## Test if the memcached service is configured properly.
134+
135+# Get the contents of the memcached configuration file.
136+config_string = memcached_unit.file_contents('/etc/memcached.conf')
137+# Parse the configuration file for the values sent in the deployment.
138+for line in config_string.splitlines():
139+ if line.startswith('-m '):
140+ size = line.split()[1]
141+ elif line.startswith('-c '):
142+ limit = line.split()[1]
143+ elif line.startswith('-f '):
144+ factor = line.split()[1]
145+
146+# Check for the configured values.
147+if (configuration['size'] != int(size) or
148+ configuration['connection-limit'] != int(limit) or
149+ configuration['factor'] != float(factor)):
150+ message = 'The memcached deployment was not configured correctly, size: ' \
151+ '{0} limit: {1} factor: {2}'.format(size, limit, factor)
152+ amulet.raise_status(amulet.FAIL, msg=message)
153+else:
154+ message = 'The memcached deployment was configured correctly.'
155+ print(message)
156+
157+## Test if the relation is complete and data was exchanged properly.
158+
159+memcached_unit = d.sentry.unit['memcached/0']
160+# Get the relation from memcached to mediawiki.
161+relation = memcached_unit.relation('cache', 'mediawiki:cache')
162+
163+# Make sure the relation got the port information set by the configuration.
164+if (configuration['tcp-port'] != int(relation['port']) or
165+ configuration['udp-port'] != int(relation['udp-port'])):
166+ message = 'The memcached relation was not configured correctly, port: ' \
167+ '{0} udp-port: {1}'.format(relation['port'], relation['udp-port'])
168+ amulet.raise_status(amulet.FAIL, msg=message)
169+else:
170+ message = 'The memcached relation was configured correctly.'
171+ print(message)
172+
173+# Print a message indicating the charm passed all the tests.
174+message = 'The memcached charm passed the deploy tests!'
175+print(message)

Subscribers

People subscribed via source and target branches

to all changes: