class Test_export_html(object): def setUp(self): self.database = Database( Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False) ), cache=Stub_cache(), ) self.database.execute_script(file("model/schema.sqlite").read(), commit=True) self.username = u"mulder" self.password = u"trustno1" self.email_address = u"*****@*****.**" self.user = User.create(self.database.next_id(User), self.username, self.password, self.email_address) self.database.save(self.user, commit=False) self.trash = Notebook.create(self.database.next_id(Notebook), u"trash") self.database.save(self.trash, commit=False) self.notebook = Notebook.create( self.database.next_id(Notebook), u"notebook", self.trash.object_id, user_id=self.user.object_id ) self.database.save(self.notebook, commit=False) note_id = self.database.next_id(Note) self.note1 = Note.create( note_id, u"<h3>my title</h3>blah", notebook_id=self.notebook.object_id, startup=True, user_id=self.user.object_id, ) self.database.save(self.note1, commit=False) note_id = self.database.next_id(Note) self.note2 = Note.create( note_id, u"<h3>other title</h3>whee", notebook_id=self.notebook.object_id, user_id=self.user.object_id ) self.database.save(self.note2, commit=False) def test_export_html(self): note3 = Note.create("55", u"<h3>blah</h3>foo", notebook_id=self.notebook.object_id) self.database.save(note3) response_headers = {} expected_notes = (self.note1, self.note2, note3) result = invoke("export", "html", self.database, self.notebook, expected_notes, response_headers) # response headers should be unchanged assert response_headers == {} notes = result.get("notes") assert len(notes) == len(expected_notes) # assert that the notes are in the expected order for (note, expected_note) in zip(notes, expected_notes): assert note.object_id == expected_note.object_id assert note.revision == expected_note.revision assert note.title == expected_note.title assert note.contents == expected_note.contents assert note.notebook_id == expected_note.notebook_id assert note.startup == expected_note.startup assert note.deleted_from_id == expected_note.deleted_from_id assert note.rank == expected_note.rank assert note.user_id == expected_note.user_id assert note.creation == expected_note.creation
class Test_controller( object ): def __init__( self ): from model.User import User from model.Group import Group from model.Notebook import Notebook from model.Note import Note from model.Invite import Invite from model.User_revision import User_revision from model.File import File def setUp( self ): # trick tested methods into using a fake SMTP server Stub_smtp.reset() smtplib.SMTP = Stub_smtp from controller.Root import Root cherrypy.lowercase_api = True self.database = Database( Connection_wrapper( sqlite.connect( ":memory:", detect_types = sqlite.PARSE_DECLTYPES, check_same_thread = False ) ), cache = Stub_cache(), ) self.database.execute_script( file( "model/schema.sqlite" ).read(), commit = True ) self.settings = { u"global": { u"server.environment": "production", u"session_filter.on": True, u"session_filter.storage_type": u"ram", u"encoding_filter.on": True, u"encoding_filter.encoding": "utf-8", u"decoding_filter.on": True, u"decoding_filter.encoding": "utf-8", u"server.log_to_screen": False, u"luminotes.http_url" : u"http://luminotes.com", u"luminotes.https_url" : u"https://luminotes.com", u"luminotes.http_proxy_ip" : u"127.0.0.1", u"luminotes.https_proxy_ip" : u"127.0.0.2", u"luminotes.support_email": "*****@*****.**", u"luminotes.payment_email": "*****@*****.**", u"luminotes.rate_plans": [ { u"name": u"super", u"storage_quota_bytes": 1337 * 10, u"notebook_collaboration": False, u"user_admin": False, u"included_users": 1, u"fee": 1.99, u"yearly_fee": 19.90, u"button": u"[subscribe here user %s!] button (modify=%s)", u"yearly_button": u"[yearly subscribe here user %s!] button (modify=%s)", }, { u"name": "extra super", u"storage_quota_bytes": 31337 * 1000, u"notebook_collaboration": True, u"user_admin": True, u"included_users": 3, u"fee": 9.00, u"yearly_fee": 90.00, u"button": u"[or here user %s!] button (modify=%s)", u"yearly_button": u"[yearly or here user %s!] button (modify=%s)", }, ], "luminotes.download_products": [ { "name": "local desktop extravaganza", "designed_for": "individuals", "storage_quota_bytes": None, "included_users": 1, "notebook_sharing": False, "notebook_collaboration": False, "user_admin": False, "fee": "30.00", "item_number": "5000", "filename": "test.exe", "button": u"", }, ], }, u"/files/download": { u"stream_response": True, u"encoding_filter.on": False, }, u"/files/download_product": { u"stream_response": True, u"encoding_filter.on": False, }, u"/notebooks/export_csv": { u"stream_response": True, u"encoding_filter.on": False, }, u"/files/progress": { u"stream_response": True, }, } cherrypy.root = Root( self.database, self.settings, suppress_exceptions = True ) cherrypy.config.update( self.settings ) cherrypy.server.start( init_only = True, server_class = None ) # since we only want to test the controller, use the stub view for all exposed methods import controller.Expose Stub_view.result = None controller.Expose.view_override = Stub_view def tearDown( self ): self.database.close() cherrypy.server.stop() def http_get( self, http_path, headers = None, session_id = None, pretend_https = False ): """ Perform an HTTP GET with the given path on the test server. Return the result dict as returned by the invoked method. """ if headers is None: headers = [] if session_id: headers.append( ( u"Cookie", "session_id=%s" % session_id ) ) # will break if unicode is used for the value if pretend_https: proxy_ip = self.settings[ "global" ].get( u"luminotes.https_proxy_ip" ) else: proxy_ip = self.settings[ "global" ].get( u"luminotes.http_proxy_ip" ) request = cherrypy.server.request( ( proxy_ip, 1234 ), u"127.0.0.5" ) response = request.run( "GET %s HTTP/1.0" % str( http_path ), headers = headers, rfile = StringIO() ) session_id = response.simple_cookie.get( u"session_id" ) if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status = response.status, headers = response.headers, body = response.body, ) result[ u"session_id" ] = session_id return result finally: request.close() def http_post( self, http_path, form_args, headers = None, session_id = None ): """ Perform an HTTP POST with the given path on the test server, sending the provided form_args dict. Return the result dict as returned by the invoked method. """ from urllib import urlencode if isinstance( form_args, dict ): form_args = form_args.items() post_data = urlencode( [ ( k, isinstance( v, unicode ) and v.encode( "utf-8" ) or v ) for ( k, v ) in form_args ] ) if headers is None: headers = [] headers.extend( [ ( u"Content-Type", u"application/x-www-form-urlencoded" ), ( u"Content-Length", unicode( len( post_data ) ) ), ] ) if session_id: headers.append( ( u"Cookie", "session_id=%s" % session_id ) ) # will break if unicode is used for the value request = cherrypy.server.request( ( u"127.0.0.1", 1234 ), u"127.0.0.5" ) response = request.run( "POST %s HTTP/1.0" % str( http_path ), headers = headers, rfile = StringIO( post_data ) ) session_id = response.simple_cookie.get( u"session_id" ) if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status = response.status, headers = response.headers, body = response.body, ) result[ u"session_id" ] = session_id return result finally: request.close() def http_upload( self, http_path, form_args, filename, file_data, content_type, simulate_cancel = False, headers = None, session_id = None ): """ Perform an HTTP POST with the given path on the test server, sending the provided form_args and file_data as a multipart form file upload. Return the result dict as returned by the invoked method. """ boundary = "boundarygoeshere" post_data = [ "--%s\n" % boundary ] for ( name, value ) in form_args.items(): post_data.append( 'Content-Disposition: form-data; name="%s"\n\n%s\n--%s\n' % ( str( name ), str( value ), boundary ) ) post_data.append( 'Content-Disposition: form-data; name="upload"; filename="%s"\n' % ( filename.encode( "utf8" ) ) ) post_data.append( "Content-Type: %s\nContent-Transfer-Encoding: binary\n\n%s\n--%s--\n" % ( content_type, file_data, boundary ) ) if headers is None: headers = [] post_data = "".join( post_data ) headers.append( ( "Content-Type", "multipart/form-data; boundary=%s" % boundary ) ) if "Content-Length" not in [ name for ( name, value ) in headers ]: headers.append( ( "Content-Length", str( len( post_data ) ) ) ) if session_id: headers.append( ( u"Cookie", "session_id=%s" % session_id ) ) # will break if unicode is used for the value if simulate_cancel: file_wrapper = Truncated_StringIO( post_data ) else: file_wrapper = Wrapped_StringIO( post_data ) request = cherrypy.server.request( ( u"127.0.0.1", 1234 ), u"127.0.0.5" ) response = request.run( "POST %s HTTP/1.0" % str( http_path ), headers = headers, rfile = file_wrapper ) session_id = response.simple_cookie.get( u"session_id" ) if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status = response.status, headers = response.headers, body = response.body, ) result[ u"session_id" ] = session_id return result finally: request.close()
class Test_export_html(object): def setUp(self): self.database = Database( Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)), cache=Stub_cache(), ) self.database.execute_script(file("model/schema.sqlite").read(), commit=True) self.username = u"mulder" self.password = u"trustno1" self.email_address = u"*****@*****.**" self.user = User.create(self.database.next_id(User), self.username, self.password, self.email_address) self.database.save(self.user, commit=False) self.trash = Notebook.create(self.database.next_id(Notebook), u"trash") self.database.save(self.trash, commit=False) self.notebook = Notebook.create(self.database.next_id(Notebook), u"notebook", self.trash.object_id, user_id=self.user.object_id) self.database.save(self.notebook, commit=False) note_id = self.database.next_id(Note) self.note1 = Note.create(note_id, u"<h3>my title</h3>blah", notebook_id=self.notebook.object_id, startup=True, user_id=self.user.object_id) self.database.save(self.note1, commit=False) note_id = self.database.next_id(Note) self.note2 = Note.create(note_id, u"<h3>other title</h3>whee", notebook_id=self.notebook.object_id, user_id=self.user.object_id) self.database.save(self.note2, commit=False) def test_export_html(self): note3 = Note.create("55", u"<h3>blah</h3>foo", notebook_id=self.notebook.object_id) self.database.save(note3) response_headers = {} expected_notes = (self.note1, self.note2, note3) result = invoke( "export", "html", self.database, self.notebook, expected_notes, response_headers, ) # response headers should be unchanged assert response_headers == {} notes = result.get("notes") assert len(notes) == len(expected_notes) # assert that the notes are in the expected order for (note, expected_note) in zip(notes, expected_notes): assert note.object_id == expected_note.object_id assert note.revision == expected_note.revision assert note.title == expected_note.title assert note.contents == expected_note.contents assert note.notebook_id == expected_note.notebook_id assert note.startup == expected_note.startup assert note.deleted_from_id == expected_note.deleted_from_id assert note.rank == expected_note.rank assert note.user_id == expected_note.user_id assert note.creation == expected_note.creation
class Test_export_csv( object ): def setUp( self ): self.database = Database( Connection_wrapper( sqlite.connect( ":memory:", detect_types = sqlite.PARSE_DECLTYPES, check_same_thread = False ) ), cache = Stub_cache(), ) self.database.execute_script( file( "model/schema.sqlite" ).read(), commit = True ) self.username = u"mulder" self.password = u"trustno1" self.email_address = u"*****@*****.**" self.user = User.create( self.database.next_id( User ), self.username, self.password, self.email_address ) self.database.save( self.user, commit = False ) self.trash = Notebook.create( self.database.next_id( Notebook ), u"trash" ) self.database.save( self.trash, commit = False ) self.notebook = Notebook.create( self.database.next_id( Notebook ), u"notebook", self.trash.object_id, user_id = self.user.object_id ) self.database.save( self.notebook, commit = False ) note_id = self.database.next_id( Note ) self.note1 = Note.create( note_id, u"<h3>my title</h3>blah", notebook_id = self.notebook.object_id, startup = True, user_id = self.user.object_id ) self.database.save( self.note1, commit = False ) note_id = self.database.next_id( Note ) self.note2 = Note.create( note_id, u"<h3>other title</h3>whee", notebook_id = self.notebook.object_id, user_id = self.user.object_id ) self.database.save( self.note2, commit = False ) def test_export_csv( self, note_contents = None, expected_contents = None ): if not note_contents: note_contents = u"<h3>blah</h3>foo" note3 = Note.create( self.database.next_id( Note ), note_contents, notebook_id = self.notebook.object_id, user_id = self.user.object_id ) self.database.save( note3 ) response_headers = {} expected_notes = ( self.note1, self.note2, note3 ) result = invoke( "export", "csv", self.database, self.notebook, expected_notes, response_headers, ) assert response_headers assert response_headers[ u"Content-Type" ] == u"text/csv;charset=utf-8" assert response_headers[ u"Content-Disposition" ] == 'attachment; filename=%s.csv' % self.notebook.friendly_id assert isinstance( result, types.GeneratorType ) pieces = [] for piece in result: pieces.append( piece ) csv_data = "".join( pieces ) reader = csv.reader( StringIO( csv_data ) ) row = reader.next() expected_header = [ u"contents", u"title", u"note_id", u"startup", u"username", u"revision_date" ] assert row == expected_header note_count = 0 # assert that startup notes come first, then normal notes in descending revision order for row in reader: assert len( row ) == len( expected_header ) ( contents, title, note_id, startup, username, revision_date ) = row assert note_count < len( expected_notes ) expected_note = expected_notes[ note_count ] assert expected_note if expected_contents and note_id == note3.object_id: assert contents.decode( "utf8" ) == expected_contents.replace( "\n", " " ).strip() else: assert contents.decode( "utf8" ) == expected_note.contents.replace( "\n", " " ).strip() if expected_note.title: assert title.decode( "utf8" ) == expected_note.title.strip() else: assert not title assert note_id.decode( "utf8" ) == expected_note.object_id assert startup.decode( "utf8" ) == expected_note.startup and u"1" or "0" assert username.decode( "utf8" ) == ( expected_note.user_id and self.user.username or u"" ) assert revision_date.decode( "utf8" ) == unicode( expected_note.revision ) note_count += 1 assert note_count == len( expected_notes ) def test_export_csv_with_unicode( self ): self.test_export_csv( note_contents = u"<h3>blah</h3>ümlaut.png" ) def test_export_csv_without_note_title( self ): self.test_export_csv( note_contents = u"there's no title" ) def test_export_csv_with_trailing_newline_in_title( self ): self.test_export_csv( note_contents = u"<h3>blah\n</h3>foo" ) def test_export_csv_with_trailing_newline_in_contents( self ): self.test_export_csv( note_contents = u"<h3>blah</h3>foo\n" ) def test_export_csv_with_file_attachment_in_contents( self ): self.test_export_csv( note_contents = u"<h3>blah</h3>foo<a href=\"/files/download?file_id=blah"e_filename=False\">file</a>", expected_contents = "<h3>blah</h3>foo<a>file</a>", ) def test_export_csv_with_image_in_contents( self ): self.test_export_csv( note_contents = u"<h3>blah</h3>foo<a href=\"/files/download?file_id=blah"e_filename=False\"><img src=\"whee.png\" /></a>", expected_contents = "<h3>blah</h3>foo<a></a>", ) def test_export_csv_with_blank_username( self ): self.user._User__username = None self.database.save( self.user ) self.test_export_csv( note_contents = u"<h3>blah</h3>foo" )
class Test_export_csv(object): def setUp(self): self.database = Database( Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)), cache=Stub_cache(), ) self.database.execute_script(file("model/schema.sqlite").read(), commit=True) self.username = u"mulder" self.password = u"trustno1" self.email_address = u"*****@*****.**" self.user = User.create(self.database.next_id(User), self.username, self.password, self.email_address) self.database.save(self.user, commit=False) self.trash = Notebook.create(self.database.next_id(Notebook), u"trash") self.database.save(self.trash, commit=False) self.notebook = Notebook.create(self.database.next_id(Notebook), u"notebook", self.trash.object_id, user_id=self.user.object_id) self.database.save(self.notebook, commit=False) note_id = self.database.next_id(Note) self.note1 = Note.create(note_id, u"<h3>my title</h3>blah", notebook_id=self.notebook.object_id, startup=True, user_id=self.user.object_id) self.database.save(self.note1, commit=False) note_id = self.database.next_id(Note) self.note2 = Note.create(note_id, u"<h3>other title</h3>whee", notebook_id=self.notebook.object_id, user_id=self.user.object_id) self.database.save(self.note2, commit=False) def test_export_csv(self, note_contents=None, expected_contents=None): if not note_contents: note_contents = u"<h3>blah</h3>foo" note3 = Note.create(self.database.next_id(Note), note_contents, notebook_id=self.notebook.object_id, user_id=self.user.object_id) self.database.save(note3) response_headers = {} expected_notes = (self.note1, self.note2, note3) result = invoke( "export", "csv", self.database, self.notebook, expected_notes, response_headers, ) assert response_headers assert response_headers[u"Content-Type"] == u"text/csv;charset=utf-8" assert response_headers[ u"Content-Disposition"] == 'attachment; filename=%s.csv' % self.notebook.friendly_id assert isinstance(result, types.GeneratorType) pieces = [] for piece in result: pieces.append(piece) csv_data = "".join(pieces) reader = csv.reader(StringIO(csv_data)) row = reader.next() expected_header = [ u"contents", u"title", u"note_id", u"startup", u"username", u"revision_date" ] assert row == expected_header note_count = 0 # assert that startup notes come first, then normal notes in descending revision order for row in reader: assert len(row) == len(expected_header) (contents, title, note_id, startup, username, revision_date) = row assert note_count < len(expected_notes) expected_note = expected_notes[note_count] assert expected_note if expected_contents and note_id == note3.object_id: assert contents.decode("utf8") == expected_contents.replace( "\n", " ").strip() else: assert contents.decode( "utf8") == expected_note.contents.replace("\n", " ").strip() if expected_note.title: assert title.decode("utf8") == expected_note.title.strip() else: assert not title assert note_id.decode("utf8") == expected_note.object_id assert startup.decode( "utf8") == expected_note.startup and u"1" or "0" assert username.decode("utf8") == (expected_note.user_id and self.user.username or u"") assert revision_date.decode("utf8") == unicode( expected_note.revision) note_count += 1 assert note_count == len(expected_notes) def test_export_csv_with_unicode(self): self.test_export_csv(note_contents=u"<h3>blah</h3>ümlaut.png") def test_export_csv_without_note_title(self): self.test_export_csv(note_contents=u"there's no title") def test_export_csv_with_trailing_newline_in_title(self): self.test_export_csv(note_contents=u"<h3>blah\n</h3>foo") def test_export_csv_with_trailing_newline_in_contents(self): self.test_export_csv(note_contents=u"<h3>blah</h3>foo\n") def test_export_csv_with_file_attachment_in_contents(self): self.test_export_csv( note_contents= u"<h3>blah</h3>foo<a href=\"/files/download?file_id=blah"e_filename=False\">file</a>", expected_contents="<h3>blah</h3>foo<a>file</a>", ) def test_export_csv_with_image_in_contents(self): self.test_export_csv( note_contents= u"<h3>blah</h3>foo<a href=\"/files/download?file_id=blah"e_filename=False\"><img src=\"whee.png\" /></a>", expected_contents="<h3>blah</h3>foo<a></a>", ) def test_export_csv_with_blank_username(self): self.user._User__username = None self.database.save(self.user) self.test_export_csv(note_contents=u"<h3>blah</h3>foo")
class Test_controller(object): def __init__(self): from model.User import User from model.Group import Group from model.Notebook import Notebook from model.Note import Note from model.Invite import Invite from model.User_revision import User_revision from model.File import File def setUp(self): # trick tested methods into using a fake SMTP server Stub_smtp.reset() smtplib.SMTP = Stub_smtp from controller.Root import Root cherrypy.lowercase_api = True self.database = Database( Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)), cache=Stub_cache(), ) self.database.execute_script(file("model/schema.sqlite").read(), commit=True) self.settings = { u"global": { u"server.environment": "production", u"session_filter.on": True, u"session_filter.storage_type": u"ram", u"encoding_filter.on": True, u"encoding_filter.encoding": "utf-8", u"decoding_filter.on": True, u"decoding_filter.encoding": "utf-8", u"server.log_to_screen": False, u"luminotes.http_url": u"http://luminotes.com", u"luminotes.https_url": u"https://luminotes.com", u"luminotes.http_proxy_ip": u"127.0.0.1", u"luminotes.https_proxy_ip": u"127.0.0.2", u"luminotes.support_email": "*****@*****.**", u"luminotes.payment_email": "*****@*****.**", u"luminotes.rate_plans": [ { u"name": u"super", u"storage_quota_bytes": 1337 * 10, u"notebook_collaboration": False, u"user_admin": False, u"included_users": 1, u"fee": 1.99, u"yearly_fee": 19.90, u"button": u"[subscribe here user %s!] button (modify=%s)", u"yearly_button": u"[yearly subscribe here user %s!] button (modify=%s)", }, { u"name": "extra super", u"storage_quota_bytes": 31337 * 1000, u"notebook_collaboration": True, u"user_admin": True, u"included_users": 3, u"fee": 9.00, u"yearly_fee": 90.00, u"button": u"[or here user %s!] button (modify=%s)", u"yearly_button": u"[yearly or here user %s!] button (modify=%s)", }, ], "luminotes.download_products": [ { "name": "local desktop extravaganza", "designed_for": "individuals", "storage_quota_bytes": None, "included_users": 1, "notebook_sharing": False, "notebook_collaboration": False, "user_admin": False, "fee": "30.00", "item_number": "5000", "filename": "test.exe", "button": u"", }, ], }, u"/files/download": { u"stream_response": True, u"encoding_filter.on": False, }, u"/files/download_product": { u"stream_response": True, u"encoding_filter.on": False, }, u"/notebooks/export_csv": { u"stream_response": True, u"encoding_filter.on": False, }, u"/files/progress": { u"stream_response": True, }, } cherrypy.root = Root(self.database, self.settings, suppress_exceptions=True) cherrypy.config.update(self.settings) cherrypy.server.start(init_only=True, server_class=None) # since we only want to test the controller, use the stub view for all exposed methods import controller.Expose Stub_view.result = None controller.Expose.view_override = Stub_view def tearDown(self): self.database.close() cherrypy.server.stop() def http_get(self, http_path, headers=None, session_id=None, pretend_https=False): """ Perform an HTTP GET with the given path on the test server. Return the result dict as returned by the invoked method. """ if headers is None: headers = [] if session_id: headers.append( (u"Cookie", "session_id=%s" % session_id)) # will break if unicode is used for the value if pretend_https: proxy_ip = self.settings["global"].get(u"luminotes.https_proxy_ip") else: proxy_ip = self.settings["global"].get(u"luminotes.http_proxy_ip") request = cherrypy.server.request((proxy_ip, 1234), u"127.0.0.5") response = request.run("GET %s HTTP/1.0" % str(http_path), headers=headers, rfile=StringIO()) session_id = response.simple_cookie.get(u"session_id") if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status=response.status, headers=response.headers, body=response.body, ) result[u"session_id"] = session_id return result finally: request.close() def http_post(self, http_path, form_args, headers=None, session_id=None): """ Perform an HTTP POST with the given path on the test server, sending the provided form_args dict. Return the result dict as returned by the invoked method. """ from urllib import urlencode if isinstance(form_args, dict): form_args = form_args.items() post_data = urlencode([(k, isinstance(v, unicode) and v.encode("utf-8") or v) for (k, v) in form_args]) if headers is None: headers = [] headers.extend([ (u"Content-Type", u"application/x-www-form-urlencoded"), (u"Content-Length", unicode(len(post_data))), ]) if session_id: headers.append( (u"Cookie", "session_id=%s" % session_id)) # will break if unicode is used for the value request = cherrypy.server.request((u"127.0.0.1", 1234), u"127.0.0.5") response = request.run("POST %s HTTP/1.0" % str(http_path), headers=headers, rfile=StringIO(post_data)) session_id = response.simple_cookie.get(u"session_id") if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status=response.status, headers=response.headers, body=response.body, ) result[u"session_id"] = session_id return result finally: request.close() def http_upload(self, http_path, form_args, filename, file_data, content_type, simulate_cancel=False, headers=None, session_id=None): """ Perform an HTTP POST with the given path on the test server, sending the provided form_args and file_data as a multipart form file upload. Return the result dict as returned by the invoked method. """ boundary = "boundarygoeshere" post_data = ["--%s\n" % boundary] for (name, value) in form_args.items(): post_data.append( 'Content-Disposition: form-data; name="%s"\n\n%s\n--%s\n' % (str(name), str(value), boundary)) post_data.append( 'Content-Disposition: form-data; name="upload"; filename="%s"\n' % (filename.encode("utf8"))) post_data.append( "Content-Type: %s\nContent-Transfer-Encoding: binary\n\n%s\n--%s--\n" % (content_type, file_data, boundary)) if headers is None: headers = [] post_data = "".join(post_data) headers.append( ("Content-Type", "multipart/form-data; boundary=%s" % boundary)) if "Content-Length" not in [name for (name, value) in headers]: headers.append(("Content-Length", str(len(post_data)))) if session_id: headers.append( (u"Cookie", "session_id=%s" % session_id)) # will break if unicode is used for the value if simulate_cancel: file_wrapper = Truncated_StringIO(post_data) else: file_wrapper = Wrapped_StringIO(post_data) request = cherrypy.server.request((u"127.0.0.1", 1234), u"127.0.0.5") response = request.run("POST %s HTTP/1.0" % str(http_path), headers=headers, rfile=file_wrapper) session_id = response.simple_cookie.get(u"session_id") if session_id: session_id = session_id.value try: if Stub_view.result is not None: result = Stub_view.result Stub_view.result = None else: result = dict( status=response.status, headers=response.headers, body=response.body, ) result[u"session_id"] = session_id return result finally: request.close()