-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.py
More file actions
228 lines (177 loc) · 8.89 KB
/
test.py
File metadata and controls
228 lines (177 loc) · 8.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/usr/bin/env python
###### COPYRIGHT NOTICE ########################################################
#
# Copyright (C) 2007-2011, Cycle Computing, LLC.
#
# 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.txt
#
# 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.
#
################################################################################
################################################################################
# USAGE
################################################################################
# test.py <URL Prefix>
#
# Where <URL Prefix> would be the base URL for the CycleServer hosting the test
# plugins. Something like: http://localhost:8080/cycle/cache_config
#
# The test platform assumes that the plugins in the tests/plugins directory have
# been installed in a CycleServer instance.
#
# This can be done by symlinking the tests/plugins/cycle directory to "cycle"
# inside of CycleServer's plugins directory. Or by copying the files to the
# plugins directory for the CycleServer instance.
################################################################################
# IMPORTS
################################################################################
import os
import sys
import time
import subprocess
import re
################################################################################
# GLOBALS
################################################################################
# Keep track of files opened by tests
opened_files = {}
################################################################################
# CLASSES
################################################################################
class TestError(Exception):
'''Error class for test runs.'''
pass
################################################################################
# METHODS
################################################################################
def run(cmdLine):
'''Run a command line executable and report it\'s output back.'''
args = cmdLine.strip().split()
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate()
if p.returncode != 0:
raise Exception("Error running " + cmdLine)
return stdout.strip()
def runTest(site, test, defaultCache, **kwArgs):
'''Run a test against a particular CycleServer instance using
a particular cache file.'''
print "Running test %s" % test
opened_files["cache_file"] = True
if os.path.exists("cache_file"):
os.remove("cache_file")
if defaultCache != None:
fp = open("cache_file", "w")
fp.write(defaultCache)
fp.close()
# set this to be a minute old so we always hit the site
modtime = time.time() - 60
os.utime("cache_file", (modtime, modtime))
args = kwArgs.copy()
if not args.has_key("fallback"):
args["fallback"] = ""
args["site"] = site
args["test"] = test
result = run("python cache_config.py cache_file 30 30 %(site)s/%(test)s %(fallback)s" % args)
return result
def assertEquals(expected, actual, test):
# normalize for Windows
actual = re.sub(r'(\r\n|\r|\n)', '\n', actual)
if expected != actual:
raise TestError(test + ": Expected\n" + expected + "\nbut got\n" + actual)
def runTests(site):
# success case (no initial cache)
result = runTest(site, "success", None)
assertEquals("Success\nLine2", result, "200 case")
# server error case (no initial cache)
result = runTest(site, "error_nocache", None)
assertEquals('CONFIG_FILE_ERROR="Exception updating config: HTTP Error 500: Internal Server Error"',
result, "500 case")
# server error case (no initial cache, fallback URL that works)
result = runTest(site, "error_fallback", None, fallback=site + "/success")
assertEquals('CONFIG_FILE_ERROR = "Exception updating config: HTTP Error 500: Internal Server Error"\n\nSuccess\nLine2',
result, "500 case")
# server error case (no initial cache, fallback URL that fails, second that works)
result = runTest(site, "error_two_failures", None, fallback=site + "/error " + site + "/success")
assertEquals('CONFIG_FILE_ERROR = "Exception updating config: HTTP Error 500: Internal Server Error; HTTP Error 500: Internal Server Error"\n\nSuccess\nLine2',
result, "500 case")
opened_files["alt_file"] = True
fp = open("alt_file", "w")
fp.write("Got from file")
fp.close()
# server error case (no initial cache, fallback URL that fails, then to file)
result = runTest(site, "error_fallback_to_file", None, fallback=site + "/error file://" + os.path.abspath("alt_file"))
assertEquals('CONFIG_FILE_ERROR = "Exception updating config: HTTP Error 500: Internal Server Error; HTTP Error 500: Internal Server Error"\n\nCONFIG_FILE_ERROR="Exception updating config: <urlopen error [Error 3] The system cannot find the path specified: \'\'>"',
result, "500 case")
# server error case (initial cache to use)
result = runTest(site, "error_cache", 'Error Cached copy')
assertEquals('CONFIG_FILE_ERROR="Exception updating config: HTTP Error 500: Internal Server Error"\n\nError Cached copy',
result, "500 case")
# auth requested case
result = runTest(site, "auth", 'Auth Cached copy')
assertEquals('CONFIG_FILE_ERROR="Exception updating config: HTTP Error 401: Unauthorized"\n\nAuth Cached copy',
result, "auth case")
# cached case, successfully in cache (but after requesting from the server, not in lieu of it)
result = runTest(site, "not_modified/fresh", '304 Cached copy')
assertEquals('304 Cached copy', result, "not-modified case (use cache)")
# cached case, needs update
result = runTest(site, "not_modified/stale", '304 Cached copy')
assertEquals('Downloaded copy', result, "not-modified case (download)")
# timeout requested case
startTime = time.time()
result = runTest(site, "timeout", 'Timeout Cached copy')
runTime = time.time() - startTime
expected = 2
if runTime > expected + 1:
raise TestError("Waited %f seconds for response; expected %s" % (runTime, expected))
# should still have a good config
assertEquals('CONFIG_FILE_ERROR="Exception updating config: <urlopen error timed out>"\n\nTimeout Cached copy',
result, "timeout case")
# re-run to make sure it works the second time without requesting
startTime = time.time()
result = run("python cache_config.py cache_file 30 30 %(site)s/%(test)s"
% { "site" : site, "test" : "timeout" })
runTime = time.time() - startTime
if runTime > 1:
raise TestError("Second response should have been in the cache; took %s sec" % (runTime))
# same result as before (error message is preserved)
assertEquals('CONFIG_FILE_ERROR="Exception updating config: <urlopen error timed out>"\n\nTimeout Cached copy',
result, "timeout case")
# age the file so we hit the site again
modtime = time.time() - 60
os.utime("cache_file", (modtime, modtime))
# re-run to make sure error messages aren't accumulated
startTime = time.time()
result = run("python cache_config.py cache_file 30 30 %(site)s/%(test)s"
% { "site" : site, "test" : "timeout" })
runTime = time.time() - startTime
if runTime < expected - 1:
# here we WANT the timeout to make sure the code is trying again
raise TestError("Only waited %s sec for site; expected timeout" % (runTime))
# same result as before (error message is preserved but not duplicated)
assertEquals('CONFIG_FILE_ERROR="Exception updating config: <urlopen error timed out>"\n\nTimeout Cached copy',
result, "timeout case")
if __name__ == "__main__":
if len(sys.argv) < 2:
print "Usage: %s SITE_PREFIX" % sys.argv[0]
print "Install the plugins in the tests directory in a CycleServer instance."
print "SITE_PREFIX is the path to the plugins (eg, http://localhost:8080/cycle/cache_config)"
sys.exit(1)
status = 0
try:
runTests(sys.argv[1])
print "All tests ran successfully"
except TestError, e:
print "*** Test Failure:\n" + str(e)
status = 1
for k in opened_files.keys():
if os.path.exists(k):
os.remove(k)
sys.exit(status)