def setUp(self): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute(Stub_object.sql_create_table()) self.database = Database(self.connection, self.cache)
def main(args): import cherrypy from config import Common cherrypy.config.update(Common.settings) desktop = False if args and "-d" in args: from config import Development settings = Development.settings args.remove("-d") elif args and "-l" in args: from config import Desktop settings = Desktop.settings desktop = True args.remove("-l") else: from config import Production settings = Production.settings cherrypy.config.update(settings) database = Database( host=cherrypy.config.configMap[u"global"].get(u"luminotes.db_host"), ssl_mode=cherrypy.config.configMap[u"global"].get( u"luminotes.db_ssl_mode"), data_dir=".", ) ranker = Thread_maker(database, *args)
def setUp(self): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute(Stub_object.sql_create_table()) self.fake_files = { } # map of fake filename (full path) to fake file contents self.database = Database(self.connection, self.cache) self.upgrader = Schema_upgrader(self.database, glob=self.glob, read_file=self.read_file)
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 main(args): import cherrypy from config import Common cherrypy.config.update(Common.settings) if args and "-d" in args: from config import Development settings = Development.settings elif args and "-l" in args: from config import Desktop settings = Desktop.settings else: from config import Production settings = Production.settings cherrypy.config.update(settings) database = Database( host=cherrypy.config.configMap[u"global"].get(u"luminotes.db_host"), ssl_mode=cherrypy.config.configMap[u"global"].get( u"luminotes.db_ssl_mode"), data_dir=".", ) initializer = Updater(database, cherrypy.config.configMap)
def setUp( self ): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect( ":memory:", detect_types = sqlite.PARSE_DECLTYPES, check_same_thread = False ) ) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute( Stub_object.sql_create_table() ) self.database = Database( self.connection, self.cache )
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 main(args=None): nuke = False import cherrypy from config import Common cherrypy.config.update(Common.settings) desktop = False if args and "-d" in args: from config import Development settings = Development.settings elif args and "-l" in args: from config import Desktop settings = Desktop.settings desktop = True else: from config import Production settings = Production.settings cherrypy.config.update(settings) if args and ("-n" in args or "--nuke" in args): nuke = True print "This will nuke the contents of the database before initializing it with default data. Continue (y/n)? ", confirmation = sys.stdin.readline().strip() print if confirmation.lower()[0] != 'y': print "Exiting without touching the database." return print "Initializing the database with default data." host = cherrypy.config[u"luminotes.db_host"] # TODO : this fails database = Database( host=host, ssl_mode=cherrypy.config[u"luminotes.db_ssl_mode"], data_dir=".", ) #initializer = Initializer( database, host, cherrypy.config.configMap, desktop, nuke ) initializer = Initializer(database, host, cherrypy.config, desktop, nuke)
def main(args): import cherrypy from config import Common cherrypy.config.update(Common.settings) if args and "-d" in args: from config import Development settings = Development.settings else: from config import Production settings = Production.settings cherrypy.config.update(settings) database = Database( host=cherrypy.config.configMap[u"global"].get(u"luminotes.db_host"), ssl_mode=cherrypy.config.configMap[u"global"].get( u"luminotes.db_ssl_mode"), data_dir=".", ) class Stub_root(object): def __init__(self, database): self.database = database cherrypy.root = Stub_root(database) sessions = Session_storage() session_count = 0 for session_filename in os.listdir(u"session/"): pickled_data = file(u"session/%s" % session_filename).read() (data, expiration_time) = pickle.loads(pickled_data) session_id = data[u"_id"] sessions.save(session_id, data, expiration_time) session_count += 1 print "converted %d sessions" % session_count
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
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
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()
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
class Test_database( object ): def setUp( self ): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect( ":memory:", detect_types = sqlite.PARSE_DECLTYPES, check_same_thread = False ) ) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute( Stub_object.sql_create_table() ) self.database = Database( self.connection, self.cache ) def tearDown( self ): self.database.close() def test_save_and_load( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.save( basic_obj ) obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == original_revision assert obj.value == basic_obj.value def test_save_and_load_without_commit( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.save( basic_obj, commit = False ) self.connection.rollback() # if commit wasn't called, this should back out the save obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj == None def test_save_and_load_with_explicit_commit( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.save( basic_obj, commit = False ) self.database.commit() self.connection.rollback() # should have no effect because of the call to commit obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == original_revision assert obj.value == basic_obj.value def test_select_one( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.save( basic_obj ) obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == original_revision assert obj.value == basic_obj.value def test_select_datetime( self ): # this revision (with .504099) happens to test for a bug caused by floating point rounding errors original_revision = "2008-01-01 01:00:42.504099+00:00" basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 ) self.database.save( basic_obj ) obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) ) assert obj.object_id == basic_obj.object_id assert str( obj.revision.replace( tzinfo = utc ) ) == original_revision assert obj.value == basic_obj.value def test_select_datetime_with_many_fractional_digits( self ): original_revision = "2008-01-01 01:00:42.5032429489284+00:00" basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 ) self.database.save( basic_obj ) obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) ) assert obj.object_id == basic_obj.object_id assert str( obj.revision.replace( tzinfo = utc ) ) == "2008-01-01 01:00:42.503242+00:00" assert obj.value == basic_obj.value def test_select_datetime_with_zero_fractional_seconds( self ): original_revision = "2008-01-01 01:00:42.0+00:00" basic_obj = Stub_object( object_id = "5", revision = original_revision, value = 1 ) self.database.save( basic_obj ) obj = self.database.select_one( Stub_object, Stub_object.sql_load( basic_obj.object_id ) ) assert obj.object_id == basic_obj.object_id assert str( obj.revision.replace( tzinfo = utc ) ) == "2008-01-01 01:00:42+00:00" assert obj.value == basic_obj.value def test_select_one_tuple( self ): obj = self.database.select_one( tuple, Stub_object.sql_tuple() ) assert len( obj ) == 2 assert obj[ 0 ] == 1 assert obj[ 1 ] == 2 def test_select_many( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision basic_obj2 = Stub_object( object_id = "6", value = 2 ) original_revision2 = basic_obj2.revision self.database.save( basic_obj ) self.database.save( basic_obj2 ) objs = self.database.select_many( Stub_object, Stub_object.sql_load_em_all() ) assert len( objs ) == 2 assert objs[ 0 ].object_id == basic_obj.object_id assert objs[ 0 ].revision.replace( tzinfo = utc ) == original_revision assert objs[ 0 ].value == basic_obj.value assert objs[ 1 ].object_id == basic_obj2.object_id assert objs[ 1 ].revision.replace( tzinfo = utc ) == original_revision2 assert objs[ 1 ].value == basic_obj2.value def test_select_many_tuples( self ): objs = self.database.select_many( tuple, Stub_object.sql_tuple() ) assert len( objs ) == 1 assert len( objs[ 0 ] ) == 2 assert objs[ 0 ][ 0 ] == 1 assert objs[ 0 ][ 1 ] == 2 def test_select_many_with_no_matches( self ): objs = self.database.select_many( Stub_object, Stub_object.sql_load_em_all() ) assert len( objs ) == 0 def test_save_and_load_revision( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.save( basic_obj ) basic_obj.value = 2 self.database.save( basic_obj ) obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == basic_obj.revision assert obj.value == basic_obj.value revised = self.database.load( Stub_object, basic_obj.object_id, revision = original_revision ) assert revised.object_id == basic_obj.object_id assert revised.value == 1 assert revised.revision.replace( tzinfo = utc ) == original_revision def test_execute( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.execute( basic_obj.sql_create() ) obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == original_revision assert obj.value == basic_obj.value def test_execute_without_commit( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.execute( basic_obj.sql_create(), commit = False ) self.connection.rollback() obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj == None def test_execute_with_explicit_commit( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) original_revision = basic_obj.revision self.database.execute( basic_obj.sql_create(), commit = False ) self.database.commit() obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id assert obj.revision.replace( tzinfo = utc ) == original_revision assert obj.value == basic_obj.value def test_load_unknown( self ): basic_obj = Stub_object( object_id = "5", value = 1 ) obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj == None def test_next_id( self ): next_id = self.database.next_id( Stub_object ) assert next_id assert self.database.load( Stub_object, next_id ) prev_ids = [ next_id ] next_id = self.database.next_id( Stub_object ) assert next_id assert next_id not in prev_ids assert self.database.load( Stub_object, next_id ) prev_ids.append( next_id ) next_id = self.database.next_id( Stub_object ) assert next_id assert next_id not in prev_ids assert self.database.load( Stub_object, next_id ) def test_next_id_without_commit( self ): next_id = self.database.next_id( Stub_object, commit = False ) self.connection.rollback() assert self.database.load( Stub_object, next_id ) == None def test_next_id_with_explicit_commit( self ): next_id = self.database.next_id( Stub_object, commit = False ) self.database.commit() assert next_id assert self.database.load( Stub_object, next_id ) def test_synchronize( self ): def make_objects(): for i in range( 50 ): object_id = self.database.next_id( Stub_object ) basic_obj = Stub_object( object_id, value = 1 ) original_revision = basic_obj.revision self.database.execute( basic_obj.sql_create() ) obj = self.database.load( Stub_object, basic_obj.object_id ) assert obj.object_id == basic_obj.object_id delta = abs( obj.revision.replace( tzinfo = utc ) - original_revision ) assert delta <= timedelta( seconds = 0.000001 ) assert obj.value == basic_obj.value object_id = self.database.next_id( Stub_object ) # if synchronization (locking) is working properly, then these two threads should be able to run # simultaneously without error. without locking, SQLite will raise thread1 = Thread( target = make_objects ) thread2 = Thread( target = make_objects ) thread1.start() thread2.start() thread1.join() thread2.join() def test_backend( self ): assert self.database.backend == Persistent.SQLITE_BACKEND
def main(args): database = Database(cache={}) ranker = Dumper(database)
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_schema_upgrader(object): def setUp(self): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute(Stub_object.sql_create_table()) self.fake_files = { } # map of fake filename (full path) to fake file contents self.database = Database(self.connection, self.cache) self.upgrader = Schema_upgrader(self.database, glob=self.glob, read_file=self.read_file) def tearDown(self): self.database.close() def glob(self, glob_pattern): """ A fake glob function that doesn't use the filesystem. """ re_pattern = re.compile(glob_pattern.replace("*", "[^/]*")) return [ filename for filename in self.fake_files.keys() if re_pattern.search(filename) ] def read_file(self, filename): """ A fake read file function that doesn't use the filesystem. """ contents = self.fake_files.get(filename) if not contents: raise IOError() return contents def test_upgrade_schema(self, to_version=None): if not to_version: to_version = u"5.7.11" self.fake_files = { u"model/delta/5.6.7.sqlite": u"create table new_table ( foo text ); insert into new_table values ( 'hi' );", u"model/delta/5.6.8.sqlite": u"insert into new_table values ( 'bye' );", u"model/delta/5.6.10.sqlite": u"alter table new_table add column bar text;", u"model/delta/5.7.11.sqlite": u"insert into new_table values ( 'whee', 'stuff' );", u"model/delta/5.7.18.sqlite": u"insert into new_table values ( 'more', 'things' );", } self.upgrader.upgrade_schema(to_version) result = self.database.select_many(tuple, u"select * from new_table;") if to_version == u"5.7.11": assert result == [(u"hi", None), (u"bye", None), ("whee", "stuff")] else: assert result == [(u"hi", None), (u"bye", None), ("whee", "stuff"), ("more", "things")] result = self.database.select_many(tuple, u"select * from schema_version;") if to_version == u"5.7.11": assert result == [(5, 7, 11)] else: assert result == [(5, 7, 18)] def test_upgrade_schema_with_schema_version_table(self): self.database.execute( u"create table schema_version ( major numeric, minor numeric, \"release\" numeric );" ) self.database.execute( u"insert into schema_version values ( 0, 0, 0 );") self.test_upgrade_schema() def test_upgrade_schema_with_schema_version_table_and_starting_version( self): self.database.execute( u"create table schema_version ( major numeric, minor numeric, \"release\" numeric );" ) self.database.execute( u"insert into schema_version values ( 5, 6, 6 );") self.fake_files[ u"model/delta/5.6.1.sqlite"] = u"this is not valid sql and should not be executed anyway;" self.fake_files[u"model/delta/5.6.6.sqlite"] = u"also invalid;" self.test_upgrade_schema() def test_upgrade_schema_with_schema_version_table_and_target_version_without_schema( self): self.database.execute( u"create table schema_version ( major numeric, minor numeric, \"release\" numeric );" ) self.database.execute( u"insert into schema_version values ( 0, 0, 0 );") self.test_upgrade_schema(to_version=u"5.7.20") def test_upgrade_schema_with_schema_version_table_and_starting_version_and_target_version_without_schema( self): self.database.execute( u"create table schema_version ( major numeric, minor numeric, \"release\" numeric );" ) self.database.execute( u"insert into schema_version values ( 5, 6, 6 );") self.test_upgrade_schema(to_version=u"5.7.20") def test_upgrade_schema_with_future_ending_version(self): self.fake_files = { u"model/delta/5.6.7.sqlite": u"create table new_table ( foo text ); insert into new_table values ( 'hi' );", u"model/delta/5.6.8.sqlite": u"insert into new_table values ( 'bye' );", u"model/delta/5.6.10.sqlite": u"alter table new_table add column bar text;", u"model/delta/5.7.11.sqlite": u"insert into new_table values ( 'whee', 'stuff' );", u"model/delta/5.7.18.sqlite": u"insert into new_table values ( 'more', 'and more' );", } self.upgrader.upgrade_schema(u"5.8.55") result = self.database.select_many(tuple, u"select * from new_table;") assert result == [(u"hi", None), (u"bye", None), ("whee", "stuff"), ("more", "and more")] result = self.database.select_many(tuple, u"select * from schema_version;") assert result == [(5, 7, 18)] def test_upgrade_schema_twice(self): self.test_upgrade_schema() # the second upgrade should have no effect, because at this point it's already upgraded self.test_upgrade_schema() def test_upgrade_schema_with_filename_with_invalid_version(self): # the filename, not composed of all-integer parts, should be skipped self.fake_files[ u"model/delta/5.6.9b.sqlite"] = u"this is not valid sql and should not be executed anyway;" self.test_upgrade_schema() def test_upgrade_schema_default_to_start_version_of_1_5_4(self): # test that if no schema_version table exists, then the starting version is assumed to be 1.5.4 self.fake_files = { u"model/delta/1.5.3.sqlite": u"invalid sql;", u"model/delta/1.5.4.sqlite": u"should not be invoked;", u"model/delta/1.5.5.sqlite": u"create table new_table ( foo text ); insert into new_table values ( 'hi' );", u"model/delta/1.5.6.sqlite": u"insert into new_table values ( 'bye' );", } self.upgrader.upgrade_schema(u"1.5.6") result = self.database.select_many(tuple, u"select * from new_table;") assert result == [ (u"hi", ), (u"bye", ), ] result = self.database.select_many(tuple, u"select * from schema_version;") assert result == [(1, 5, 6)] def test_apply_schema_delta(self): self.database.execute( u"create table schema_version ( major numeric, minor numeric, \"release\" numeric );" ) self.database.execute( u"insert into schema_version values ( 0, 0, 0 );") self.fake_files = { u"model/delta/5.6.5.sqlite": u"insert into new_table values ( 'should not show up' );", u"model/delta/5.6.7.sqlite": u"create table new_table ( foo text ); insert into new_table values ( 'hi' );", u"model/delta/5.7.18.sqlite": u"insert into new_table values ( 'should not be present' );", } self.upgrader.apply_schema_delta((5, 6, 7), u"model/delta/5.6.7.sqlite") result = self.database.select_many(unicode, u"select * from new_table;") assert result == [u"hi"] result = self.database.select_many(tuple, u"select * from schema_version;") assert result == [(5, 6, 7)] @raises(IOError) def test_apply_schema_delta_with_unknown_file(self): self.upgrader.apply_schema_delta((5, 6, 7), u"model/delta/5.6.7.sqlite") def test_version_string_to_tuple(self): version = self.upgrader.version_string_to_tuple("2.5.13") assert len(version) == 3 assert version[0] == 2 assert version[1] == 5 assert version[2] == 13 def test_version_string_to_tuple_with_extension(self): version = self.upgrader.version_string_to_tuple("2.5.13.sqlite") assert len(version) == 3 assert version[0] == 2 assert version[1] == 5 assert version[2] == 13 @raises(ValueError) def test_version_string_to_tuple_with_too_many_parts(self): version = self.upgrader.version_string_to_tuple("3.14.159.26.5") @raises(ValueError) def test_version_string_to_tuple_with_too_few_parts(self): version = self.upgrader.version_string_to_tuple("3.14") @raises(ValueError) def test_version_string_to_tuple_with_non_integer_part(self): version = self.upgrader.version_string_to_tuple("2.5b.13") @raises(ValueError) def test_version_string_to_tuple_with_empty_part(self): version = self.upgrader.version_string_to_tuple("2..13")
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_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_database(object): def setUp(self): # make an in-memory sqlite database to use during testing self.connection = Connection_wrapper( sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES, check_same_thread=False)) self.cache = Stub_cache() cursor = self.connection.cursor() cursor.execute(Stub_object.sql_create_table()) self.database = Database(self.connection, self.cache) def tearDown(self): self.database.close() def test_save_and_load(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.save(basic_obj) obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == original_revision assert obj.value == basic_obj.value def test_save_and_load_without_commit(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.save(basic_obj, commit=False) self.connection.rollback( ) # if commit wasn't called, this should back out the save obj = self.database.load(Stub_object, basic_obj.object_id) assert obj == None def test_save_and_load_with_explicit_commit(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.save(basic_obj, commit=False) self.database.commit() self.connection.rollback( ) # should have no effect because of the call to commit obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == original_revision assert obj.value == basic_obj.value def test_select_one(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.save(basic_obj) obj = self.database.select_one( Stub_object, Stub_object.sql_load(basic_obj.object_id)) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == original_revision assert obj.value == basic_obj.value def test_select_datetime(self): # this revision (with .504099) happens to test for a bug caused by floating point rounding errors original_revision = "2008-01-01 01:00:42.504099+00:00" basic_obj = Stub_object(object_id="5", revision=original_revision, value=1) self.database.save(basic_obj) obj = self.database.select_one( Stub_object, Stub_object.sql_load(basic_obj.object_id)) assert obj.object_id == basic_obj.object_id assert str(obj.revision.replace(tzinfo=utc)) == original_revision assert obj.value == basic_obj.value def test_select_datetime_with_many_fractional_digits(self): original_revision = "2008-01-01 01:00:42.5032429489284+00:00" basic_obj = Stub_object(object_id="5", revision=original_revision, value=1) self.database.save(basic_obj) obj = self.database.select_one( Stub_object, Stub_object.sql_load(basic_obj.object_id)) assert obj.object_id == basic_obj.object_id assert str(obj.revision.replace( tzinfo=utc)) == "2008-01-01 01:00:42.503242+00:00" assert obj.value == basic_obj.value def test_select_datetime_with_zero_fractional_seconds(self): original_revision = "2008-01-01 01:00:42.0+00:00" basic_obj = Stub_object(object_id="5", revision=original_revision, value=1) self.database.save(basic_obj) obj = self.database.select_one( Stub_object, Stub_object.sql_load(basic_obj.object_id)) assert obj.object_id == basic_obj.object_id assert str( obj.revision.replace(tzinfo=utc)) == "2008-01-01 01:00:42+00:00" assert obj.value == basic_obj.value def test_select_one_tuple(self): obj = self.database.select_one(tuple, Stub_object.sql_tuple()) assert len(obj) == 2 assert obj[0] == 1 assert obj[1] == 2 def test_select_many(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision basic_obj2 = Stub_object(object_id="6", value=2) original_revision2 = basic_obj2.revision self.database.save(basic_obj) self.database.save(basic_obj2) objs = self.database.select_many(Stub_object, Stub_object.sql_load_em_all()) assert len(objs) == 2 assert objs[0].object_id == basic_obj.object_id assert objs[0].revision.replace(tzinfo=utc) == original_revision assert objs[0].value == basic_obj.value assert objs[1].object_id == basic_obj2.object_id assert objs[1].revision.replace(tzinfo=utc) == original_revision2 assert objs[1].value == basic_obj2.value def test_select_many_tuples(self): objs = self.database.select_many(tuple, Stub_object.sql_tuple()) assert len(objs) == 1 assert len(objs[0]) == 2 assert objs[0][0] == 1 assert objs[0][1] == 2 def test_select_many_with_no_matches(self): objs = self.database.select_many(Stub_object, Stub_object.sql_load_em_all()) assert len(objs) == 0 def test_save_and_load_revision(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.save(basic_obj) basic_obj.value = 2 self.database.save(basic_obj) obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == basic_obj.revision assert obj.value == basic_obj.value revised = self.database.load(Stub_object, basic_obj.object_id, revision=original_revision) assert revised.object_id == basic_obj.object_id assert revised.value == 1 assert revised.revision.replace(tzinfo=utc) == original_revision def test_execute(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.execute(basic_obj.sql_create()) obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == original_revision assert obj.value == basic_obj.value def test_execute_without_commit(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.execute(basic_obj.sql_create(), commit=False) self.connection.rollback() obj = self.database.load(Stub_object, basic_obj.object_id) assert obj == None def test_execute_with_explicit_commit(self): basic_obj = Stub_object(object_id="5", value=1) original_revision = basic_obj.revision self.database.execute(basic_obj.sql_create(), commit=False) self.database.commit() obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id assert obj.revision.replace(tzinfo=utc) == original_revision assert obj.value == basic_obj.value def test_load_unknown(self): basic_obj = Stub_object(object_id="5", value=1) obj = self.database.load(Stub_object, basic_obj.object_id) assert obj == None def test_next_id(self): next_id = self.database.next_id(Stub_object) assert next_id assert self.database.load(Stub_object, next_id) prev_ids = [next_id] next_id = self.database.next_id(Stub_object) assert next_id assert next_id not in prev_ids assert self.database.load(Stub_object, next_id) prev_ids.append(next_id) next_id = self.database.next_id(Stub_object) assert next_id assert next_id not in prev_ids assert self.database.load(Stub_object, next_id) def test_next_id_without_commit(self): next_id = self.database.next_id(Stub_object, commit=False) self.connection.rollback() assert self.database.load(Stub_object, next_id) == None def test_next_id_with_explicit_commit(self): next_id = self.database.next_id(Stub_object, commit=False) self.database.commit() assert next_id assert self.database.load(Stub_object, next_id) def test_synchronize(self): def make_objects(): for i in range(50): object_id = self.database.next_id(Stub_object) basic_obj = Stub_object(object_id, value=1) original_revision = basic_obj.revision self.database.execute(basic_obj.sql_create()) obj = self.database.load(Stub_object, basic_obj.object_id) assert obj.object_id == basic_obj.object_id delta = abs( obj.revision.replace(tzinfo=utc) - original_revision) assert delta <= timedelta(seconds=0.000001) assert obj.value == basic_obj.value object_id = self.database.next_id(Stub_object) # if synchronization (locking) is working properly, then these two threads should be able to run # simultaneously without error. without locking, SQLite will raise thread1 = Thread(target=make_objects) thread2 = Thread(target=make_objects) thread1.start() thread2.start() thread1.join() thread2.join() def test_backend(self): assert self.database.backend == Persistent.SQLITE_BACKEND
def main(options): change_to_main_dir() cherrypy.config.update(Common.settings) if options.development: from config import Development settings = Development.settings elif options.desktop: from config import Desktop settings = Desktop.settings else: from config import Production settings = Production.settings cherrypy.config.update(settings) # Don't launch web browser if -w flag is set if options.no_webbrowser: launch_browser = False else: launch_browser = cherrypy.config[u"luminotes.launch_browser"] socket.setdefaulttimeout(INITIAL_SOCKET_TIMEOUT_SECONDS) port_filename = cherrypy.config[u"luminotes.port_file"] socket_port = cherrypy.config[u"server.socket_port"] existing_socket_port = port_filename and os.path.exists( port_filename) and file(port_filename).read() or socket_port server_url = u"http://localhost:%s/" % existing_socket_port server_present = True # if requested, attempt to shutdown an existing server and exit if options.kill: try: urllib.urlopen("%sshutdown" % server_url) except urllib.URLError: pass sys.exit(0) # check to see if the server is already running try: urllib.urlopen("%sping" % server_url) except urllib.URLError: server_present = False if server_present is True: print "Luminotes server is already running. aborting" if launch_browser is True: webbrowser.open_new(server_url) sys.exit(0) server_url = u"http://127.0.0.1:%s/" % socket_port # remove the existing log files, if any try: log_access_file = cherrypy.config[u"server.log_access_file"] if log_access_file: os.remove(log_access_file) except OSError: pass try: log_file = cherrypy.config[u"server.log_file"] if log_file: os.remove(log_file) except OSError: pass socket.setdefaulttimeout(SOCKET_TIMEOUT_SECONDS) database = Database( host=cherrypy.config[u"luminotes.db_host"], ssl_mode=cherrypy.config[u"luminotes.db_ssl_mode"], ) # if necessary, upgrade the database schema to match this current version of the code schema_upgrader = Schema_upgrader(database) schema_upgrader.upgrade_schema(to_version=VERSION) cherrypy.lowercase_api = True root = Root(database, cherrypy.config) cherrypy.tree.mount(root, '/', config=settings) cherrypy.engine.start_with_callback( callback, (log_access_file, log_file, server_url, port_filename, socket_port, launch_browser)) cherrypy.engine.block()
def main( args ): database = Database() ranker = Ranker( database )