Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
C
corepost
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
nexlab
corepost
Commits
a08b5e25
Commit
a08b5e25
authored
Aug 30, 2011
by
Jacek Furmankiewicz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BDDs + fix for bizarre Twisted bug that was not parsing form params on PUT
parent
1b68675b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
164 additions
and
28 deletions
+164
-28
url_routing.feature
corepost/test/feature/url_routing.feature
+54
-0
home_resource.py
corepost/test/home_resource.py
+44
-0
steps.py
corepost/test/steps.py
+57
-23
web.py
corepost/web.py
+9
-5
No files found.
corepost/test/feature/url_routing.feature
0 → 100644
View file @
a08b5e25
Using step definitions from
:
'../steps'
Feature
:
URL routing
CorePost should be able to
correctly route requests
depending on how the Resource instances
were registered
@single @single_get
Scenario
:
Single resource - GET
Given 'home_resource' is running
When as user 'None
:
None' I GET 'http
:
//127.0.0.1
:
8080'
Then
I expect HTTP code 200
And
I expect content contains '{}'
When as user 'None
:
None' I GET 'http
:
//127.0.0.1
:
8080/?test=value'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value'}'
When as user 'None
:
None' I GET 'http
:
//127.0.0.1
:
8080/test?query=test'
Then
I expect HTTP code 200
And I expect content contains '{'query'
:
'test'}'
When as user 'None
:
None' I GET 'http
:
//127.0.0.1
:
8080/test/23/resource/someid'
Then
I expect HTTP code 200
And
I expect content contains '23 - someid'
@single
@single_post
Scenario
:
Single resource - POST
Given 'home_resource' is running
When as user 'None
:
None' I POST 'http
:
//127.0.0.1
:
8080/post'
with
'test=value&test2=value2'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value', 'test2'
:
'value2'}'
@single
@single_put
Scenario
:
Single resource - PUT
Given 'home_resource' is running
When as user 'None
:
None' I PUT 'http
:
//127.0.0.1
:
8080/put'
with
'test=value&test2=value2'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value', 'test2'
:
'value2'}'
@single
@single_delete
Scenario
:
Single resource - DELETE
Given 'home_resource' is running
When as user 'None
:
None' I DELETE 'http
:
//127.0.0.1
:
8080/delete'
Then
I expect HTTP code 200
@single
@single_post
@single_put
Scenario
:
Single resource - multiple methods at same URL
Given 'home_resource' is running
When as user 'None
:
None' I POST 'http
:
//127.0.0.1
:
8080/postput'
with
'test=value&test2=value2'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value', 'test2'
:
'value2'}'
When as user 'None
:
None' I PUT 'http
:
//127.0.0.1
:
8080/postput'
with
'test=value&test2=value2'
Then
I expect HTTP code 200
And I expect content contains '{'test'
:
'value', 'test2'
:
'value2'}'
\ No newline at end of file
corepost/test/
web_test
.py
→
corepost/test/
home_resource
.py
View file @
a08b5e25
...
@@ -8,7 +8,6 @@ from corepost.enums import Http
...
@@ -8,7 +8,6 @@ from corepost.enums import Http
from
twisted.internet
import
defer
from
twisted.internet
import
defer
app
=
CorePost
()
app
=
CorePost
()
app
.
isLeaf
=
True
@
app
.
route
(
"/"
,
Http
.
GET
)
@
app
.
route
(
"/"
,
Http
.
GET
)
@
defer
.
inlineCallbacks
@
defer
.
inlineCallbacks
...
@@ -21,16 +20,25 @@ def root(request,**kwargs):
...
@@ -21,16 +20,25 @@ def root(request,**kwargs):
def
test
(
request
,
**
kwargs
):
def
test
(
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
@
app
.
route
(
"/test/<int:
jacek>/yo/<some
id>"
,
Http
.
GET
)
@
app
.
route
(
"/test/<int:
numericid>/resource/<string
id>"
,
Http
.
GET
)
def
test_get_resources
(
request
,
jacek
,
some
id
,
**
kwargs
):
def
test_get_resources
(
request
,
numericid
,
string
id
,
**
kwargs
):
return
"
%
s -
%
s"
%
(
jacek
,
some
id
)
return
"
%
s -
%
s"
%
(
numericid
,
string
id
)
@
app
.
route
(
"/
test"
,
Http
.
POST
)
@
app
.
route
(
"/
post"
,(
Http
.
POST
,
Http
.
PUT
)
)
def
test_post
(
request
,
**
kwargs
):
def
test_post
(
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
return
"
%
s"
%
kwargs
if
__name__
==
'__main__'
:
@
app
.
route
(
"/put"
,(
Http
.
POST
,
Http
.
PUT
))
# hookup submodule
def
test_put
(
request
,
**
kwargs
):
#from submodule_test import submodule
return
"
%
s"
%
kwargs
app
.
putChild
(
"submodule"
,
submodule
)
@
app
.
route
(
"/postput"
,(
Http
.
POST
,
Http
.
PUT
))
def
test_postput
(
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
@
app
.
route
(
"/delete"
,
Http
.
DELETE
)
def
test_delete
(
request
,
**
kwargs
):
return
"
%
s"
%
kwargs
def
run_app_home
():
app
.
run
()
app
.
run
()
\ No newline at end of file
corepost/test/steps.py
View file @
a08b5e25
...
@@ -3,19 +3,33 @@ Common Freshen BDD steps
...
@@ -3,19 +3,33 @@ Common Freshen BDD steps
@author: jacekf
@author: jacekf
'''
'''
import
httplib2
from
multiprocessing
import
Process
from
freshen
import
*
#@UnusedWildImport
import
httplib2
,
json
,
re
,
time
from
freshen
import
Before
,
After
,
Given
,
When
,
Then
,
scc
,
assert_equals
,
assert_true
#@UnresolvedImport
from
urllib
import
urlencode
from
corepost.test.home_resource
import
run_app_home
apps
=
{
'home_resource'
:
run_app_home
}
def
as_dict
(
parameters
):
dict_val
=
{}
for
pair
in
parameters
.
split
(
'&'
)
:
params
=
pair
.
split
(
'='
,
1
)
if
(
params
[
0
]
!=
None
)
and
(
len
(
params
)
==
2
):
dict_val
[
params
[
0
]]
=
params
[
1
]
return
dict_val
##################################
##################################
# BEFORE / AFTER
# BEFORE / AFTER
##################################
##################################
@
Before
@
Before
def
setup
():
def
setup
(
slc
):
scc
.
processes
=
[]
scc
.
processes
=
[]
scc
.
http_headers
=
{}
@
After
@
After
def
cleanup
():
def
cleanup
(
slc
):
# shut down processes
# shut down processes
for
process
in
scc
.
processes
:
for
process
in
scc
.
processes
:
process
.
terminate
()
process
.
terminate
()
...
@@ -24,40 +38,60 @@ def cleanup():
...
@@ -24,40 +38,60 @@ def cleanup():
# GIVEN
# GIVEN
##################################
##################################
@
Given
(
"'(.+)' is running
"
)
@
Given
(
r"^'(.+)' is running\s*$
"
)
def
given_process_is_running
(
processname
):
def
given_process_is_running
(
processname
):
pass
process
=
Process
(
target
=
apps
[
processname
])
process
.
daemon
=
True
process
.
start
()
scc
.
processes
.
append
(
process
)
time
.
sleep
(
0.25
)
# let it start up
##################################
##################################
# WHEN
# WHEN
##################################
##################################
@
When
(
"^as user '(.+):(.+)' I (GET|DELETE) '(.+)'
\
s*$"
)
@
When
(
r"^as user '(.+):(.+)' I (GET|DELETE) '(.+)'\s*$"
)
def
when_as_user_i_send_get_delete_to_url
(
user
,
passord
,
method
,
url
):
def
when_as_user_i_send_get_delete_to_url
(
user
,
password
,
method
,
url
):
pass
h
=
httplib2
.
Http
()
h
.
follow_redirects
=
False
h
.
add_credentials
(
user
,
password
)
scc
.
response
,
scc
.
content
=
h
.
request
(
url
,
method
)
@
When
(
"^as user '(.+):(.+)' I (POST|PUT) '(.+)' with '(.+)'
\
s*$"
)
@
When
(
r
"^as user '(.+):(.+)' I (POST|PUT) '(.+)' with '(.+)'\s*$"
)
def
when_as_user_i_send_post_put_to_url
(
user
,
password
,
method
,
url
,
params
):
def
when_as_user_i_send_post_put_to_url
(
user
,
password
,
method
,
url
,
params
):
pass
h
=
httplib2
.
Http
()
h
.
follow_redirects
=
False
@
When
(
"^as user '(.+):(.+)' I (POST|PUT) '(.+)' (XML|JSON)
\
s*$"
)
h
.
add_credentials
(
user
,
password
)
def
when_as_user_i_send_post_put_xml_json_to_url
(
payload
,
user
,
passord
,
method
,
url
):
scc
.
http_headers
[
'Content-type'
]
=
'application/x-www-form-urlencoded'
pass
scc
.
response
,
scc
.
content
=
h
.
request
(
url
,
method
,
urlencode
(
as_dict
(
params
)),
headers
=
scc
.
http_headers
)
@
When
(
r"^as user '(.+):(.+)' I (POST|PUT) '(.+)' with (XML|JSON)\s*$"
)
def
when_as_user_i_send_post_put_xml_json_to_url
(
payload
,
user
,
password
,
method
,
url
,
request_type
):
h
=
httplib2
.
Http
()
h
.
follow_redirects
=
False
h
.
add_credentials
(
user
,
password
)
scc
.
http_headers
[
'Content-type'
]
=
'application/json'
if
request_type
==
"JSON"
else
'text/xml'
scc
.
response
,
scc
.
content
=
h
.
request
(
url
,
method
,
payload
,
headers
=
scc
.
http_headers
)
##################################
##################################
# THEN
# THEN
##################################
##################################
@
Then
(
"^I expect HTTP code
\
d+
\
s*$"
)
@
Then
(
r"^I expect HTTP code (\d+)
\s*$"
)
def
expect_http_code
(
code
):
def
expect_http_code
(
code
):
pass
assert_equals
(
int
(
code
),
int
(
scc
.
response
.
status
),
msg
=
"
%
s !=
%
s
\n
%
s
\n
%
s"
%
(
code
,
scc
.
response
.
status
,
scc
.
response
,
scc
.
content
))
@
Then
(
r"^I expect content contains '(.+)'\s*$"
)
def
expect_content
(
content
):
assert_true
(
scc
.
content
.
find
(
content
)
>=
0
,
"Did not find:
\n
%
s
\n
in content:
\n
%
s"
%
(
content
,
scc
.
content
))
@
Then
(
"^I expect content contains
\
s*$"
)
@
Then
(
r
"^I expect content contains\s*$"
)
def
expect_content
(
con
ntent
):
def
expect_content
_multiline
(
co
ntent
):
pass
assert_true
(
scc
.
content
.
find
(
content
)
>=
0
,
"Did not find:
\n
%
s
\n
in content:
\n
%
s"
%
(
content
,
scc
.
content
))
@
Then
(
"^I expect header '(.+)' contains '(.+)'
\
s*$"
)
@
Then
(
r"^I expect '([^']*)' header matches '([^']*)'\s*$"
)
def
expect_header_contains
(
conntent
):
def
then_check_http_header_matches
(
header
,
regex
):
pass
assert_true
(
re
.
search
(
regex
,
scc
.
response
[
header
.
lower
()],
re
.
X
|
re
.
I
)
!=
None
,
"the regex
%
s does not match the response
\n
%
s"
%
(
regex
,
scc
.
response
[
header
.
lower
()]))
corepost/web.py
View file @
a08b5e25
...
@@ -7,6 +7,7 @@ import re, copy
...
@@ -7,6 +7,7 @@ import re, copy
from
twisted.internet
import
reactor
,
defer
from
twisted.internet
import
reactor
,
defer
from
twisted.web.resource
import
Resource
from
twisted.web.resource
import
Resource
from
twisted.web.server
import
Site
,
NOT_DONE_YET
from
twisted.web.server
import
Site
,
NOT_DONE_YET
from
twisted.web.http
import
parse_qs
from
collections
import
defaultdict
from
collections
import
defaultdict
from
enums
import
MediaType
from
enums
import
MediaType
from
corepost.enums
import
Http
from
corepost.enums
import
Http
...
@@ -159,11 +160,17 @@ class CorePost(Resource):
...
@@ -159,11 +160,17 @@ class CorePost(Resource):
#actual call
#actual call
if
urlrouter
!=
None
and
pathargs
!=
None
:
if
urlrouter
!=
None
and
pathargs
!=
None
:
allargs
=
copy
.
deepcopy
(
pathargs
)
allargs
=
copy
.
deepcopy
(
pathargs
)
# handler for weird Twisted logic where PUT does not get form params
# see: http://twistedmatrix.com/pipermail/twisted-web/2007-March/003338.html
requestargs
=
request
.
args
if
request
.
method
==
Http
.
PUT
:
requestargs
=
parse_qs
(
request
.
content
.
read
(),
1
)
#merge form args
#merge form args
for
arg
in
request
.
args
.
keys
():
for
arg
in
requestargs
.
keys
():
# maintain first instance of an argument always
# maintain first instance of an argument always
if
arg
not
in
allargs
:
if
arg
not
in
allargs
:
allargs
[
arg
]
=
request
.
args
[
arg
][
0
]
allargs
[
arg
]
=
requestargs
[
arg
][
0
]
# if POST/PUT, check if we need to automatically parse JSON
# if POST/PUT, check if we need to automatically parse JSON
# TODO
# TODO
...
@@ -178,9 +185,6 @@ class CorePost(Resource):
...
@@ -178,9 +185,6 @@ class CorePost(Resource):
return
val
return
val
else
:
else
:
# could be part of a submodule
return
self
.
__renderError
(
request
,
404
,
"URL '
%
s' not found
\n
"
%
request
.
path
)
return
self
.
__renderError
(
request
,
404
,
"URL '
%
s' not found
\n
"
%
request
.
path
)
def
__renderError
(
self
,
request
,
code
,
message
):
def
__renderError
(
self
,
request
,
code
,
message
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment