def tearDownClass(cls):
        """
		Stop all mocking.
		Tear down database after testcase finish.
		"""
        #stop mocking
        cls.mock_flask_db_patcher.stop()

        db_config = cls.global_db_config.copy()
        #connect to postgres DB to drop DB TestDB.
        db_config['database'] = 'postgres'
        engine = db_connect(db_config=db_config)
        conn = engine.connect()
        #prevent fulture connection to TestDB
        conn.execute("""REVOKE CONNECT ON DATABASE "%s" FROM public;""" %
                     (cls.db_test_name, ))
        #terminal all connections to TestDB
        conn.execute(
            """SELECT pid, pg_terminate_backend(pid) FROM pg_stat_activity \
			WHERE datname = '%s' AND pid <> pg_backend_pid();""" % (cls.db_test_name, ))
        conn.execute("commit")
        conn.execute("""DROP DATABASE IF EXISTS "%s";""" %
                     (cls.db_test_name, ))  #run outside of transaction block
        conn.close()
        engine.dispose()
        logger.info('End of %s , database: %s has been torn down.' %
                    (cls.__name__, cls.db_test_name))
Exemplo n.º 2
0
	def __init__(self, order_id, request):
		self.order_id = order_id
		self.request = request
		self.inputs = StatusSchema(self.request)
		self.new_status = None
		self.engine = db_connect()
		self.Session = sessionmaker(bind=self.engine)
Exemplo n.º 3
0
    def insert_new_order(self, distance):
        """
		Insert new order into Order table. Return dict of the newly inserted order.
		Roll back if exception caught.
		"""
        engine = db_connect()
        Session = sessionmaker(bind=engine)
        item = {'distance': distance}
        session = Session()  # invokes sessionmaker.__call__()
        logger.info("Created database session.")
        new_order = Order(**item)
        new_order_item = {}
        err_msg = None
        try:
            session.add(new_order)
            session.commit()
            new_order_item['id'] = new_order.id
            new_order_item['distance'] = new_order.distance
            new_order_item['status'] = new_order.status
            logger.info(
                "Inserted new order with id %s, distance %s and status %s." %
                (new_order.id, new_order.distance, new_order.status))
        except Exception as e:
            session.rollback()
            logger.error("Roll back insert new order.")
            logger.error(e)
            err_msg = "New order cannot be created."
        finally:
            session.close()
            logger.info("Closed database session.")
        engine.dispose(
        )  # Prevent OperationalError: (psycopg2.OperationalError) FATAL:  sorry, too many clients already
        return new_order_item, err_msg
    def setUpClass(cls):
        """
		Define integration test DB connection string, and the databaes for test,
		followed by creating the TestDB and the related tables.
		Initialize args for PlaceOrder, with predefinitions in json file.
		Start all mocking necessary for testing.
		"""
        cls.db_test_name = 'TestDB'
        cls.global_db_config = {
            'drivername': 'postgresql',
            'host': os.getenv('DB_HOST'),
            'port': os.getenv('DB_PORT'),
            'username': os.getenv('DB_USERNAME'),
            'password': os.getenv('DB_PASSWORD'),
            'database': cls.db_test_name
        }

        create_db_if_not_exists(db_config=cls.global_db_config)
        cls.engine = db_connect(db_config=cls.global_db_config)
        create_tables(cls.engine)

        #start mocking db_connect bahavior to connect to TestDB in order_app.take_order
        cls.mock_db_connect_patcher = patch('order_app.take_order.db_connect')
        cls.mock_db_connect = cls.mock_db_connect_patcher.start()
        cls.mock_db_connect.return_value = cls.engine

        #start mocking the request object of PlceOrder
        cls.mock_request_patcher = patch('order_app.take_order.request')
        cls.mock_request = cls.mock_request_patcher.start()
Exemplo n.º 5
0
	def update_order_status(self):
		"""
		1. query order
		2. check if order exists (.scalar() is not None), but if order locked --> OperationalError. 
			else obtain a lock on the row.
		3. take one, and does the update operation.
		4. if update or commit has errors occur, rollback and fail.
		"""
		success = False
		err_msg = None
		engine = db_connect()
		Session = sessionmaker(bind=engine)
		session = Session()
		logger.info("Created database session.")
		try:
			#Row level lock (FOR UPDATE clause: 
			#other transactions that attempt UPDATE, DELETE, or SELECT FOR UPDATE of these rows will be blocked until the current transaction ends.
			#With nowait=True, the statement reports an error, rather than waiting, if a selected row cannot be locked immediately.
			order_query = session.query(Order).filter(Order.id==self.order_id).with_for_update(nowait=True, of=Order)
			#row lock is only obatain when query executes.
			if order_query.scalar(): #check if exists and obtain lock 
				order = order_query.one()
				if not order.status == 'TAKEN':
					order.status = self.request.json['status']
					session.commit() #commit update, release row lock
					logger.info("Order (id: %s) status is sucessfully updated to %s." % (order.id, order.status))
					success = True
				else:
					err_msg = "Order is already taken."
					logger.info("Order is already taken.")
			else:
				err_msg = "Order does not exist."
				logger.info("Order with id %s does not exist." % (self.order_id,))
		except OperationalError as e: #catch exception of psycopg2.errors.LockNotAvailable
			session.rollback()
			err_msg = "Order is currently occupied. Update status to TAKEN fail."
			logger.info("Roll back update order with id %s." % (self.order_id,))
			logger.info("OperationalError caught: %s." % (e,))
		except Exception as e:
			session.rollback()
			err_msg = "Cannot update order status with id %s. " % (self.order_id,)
			logger.info("Roll back update order with id %s." % (self.order_id,))
			logger.error(e)
		finally:
			session.close() #release row lock
			logger.info("Closed database session.")
		engine.dispose() # Prevent OperationalError: (psycopg2.OperationalError) FATAL:  sorry, too many clients already
		return success, err_msg
Exemplo n.º 6
0
    def setUpClass(cls):
        """
		Define integration test DB connection string, and the databaes for test,
		followed by creating the TestDB and the related tables.
		Initialize args for PlaceOrder, with predefinitions in json file.
		Start all mocking necessary for testing.
		"""
        cls.db_test_name = 'TestDB'
        cls.global_db_config = {
            'drivername': 'postgresql',
            'host': os.getenv('DB_HOST'),
            'port': os.getenv('DB_PORT'),
            'username': os.getenv('DB_USERNAME'),
            'password': os.getenv('DB_PASSWORD'),
            'database': cls.db_test_name
        }

        create_db_if_not_exists(db_config=cls.global_db_config)
        cls.engine = db_connect(db_config=cls.global_db_config)
        create_tables(cls.engine)

        with open(
                os.path.join(TEST_DIR, 'support',
                             'gmap_distance_matrix_api_resp.json')) as f:
            cls.predefined_gmap_resp = json.loads(f.read())
        cls.origins = cls.predefined_gmap_resp['success']['request_body'][
            'origins']
        cls.destinations = cls.predefined_gmap_resp['success']['request_body'][
            'destinations']
        cls.distance = cls.predefined_gmap_resp['success']['response_body'][
            'rows'][0]['elements'][0]['distance']['value']

        #start mocking db_connect bahavior to connect to TestDB in order_app.place_order
        cls.mock_db_connect_patcher = patch('order_app.place_order.db_connect')
        cls.mock_db_connect = cls.mock_db_connect_patcher.start()
        cls.mock_db_connect.return_value = cls.engine

        #start mocking the request object of PlceOrder
        cls.mock_request_patcher = patch('order_app.place_order.request')
        cls.mock_request = cls.mock_request_patcher.start()

        #start mocking requests.get behavior in app.place_order
        cls.mock_get_patcher = patch('order_app.place_order.requests.get')
        cls.mock_get = cls.mock_get_patcher.start()
    def setUpClass(cls):
        """
		Define integration test DB connection string, and the databaes for test,
		followed by creating the TestDB and the related tables.
		Initialize args for PlaceOrder, with predefinitions in json file.
		Start all mocking necessary for testing.
		"""
        cls.db_test_name = 'TestDB'
        cls.global_db_config = {
            'drivername': 'postgresql',
            'host': os.getenv('DB_HOST'),
            'port': os.getenv('DB_PORT'),
            'username': os.getenv('DB_USERNAME'),
            'password': os.getenv('DB_PASSWORD'),
            'database': cls.db_test_name
        }

        create_db_if_not_exists(db_config=cls.global_db_config)
        cls.engine = db_connect(db_config=cls.global_db_config)
        create_tables(cls.engine)

        #Create test data
        cls.engine.execute(
            """INSERT INTO "Order" (id, distance, status) VALUES (100, 111, 'UNASSIGNED');"""
        )

        #Mock flask-sqlalchemy db connection
        cls.mock_flask_db_patcher = patch("order_app.models.db")
        cls.mock_flask_db = cls.mock_flask_db_patcher.start()
        cls.test_app = Flask("test_order_list")
        cls.test_app.config[
            'SQLALCHEMY_DATABASE_URI'] = "%s://%s:%s@%s:%s/%s" % (
                cls.global_db_config['drivername'],
                cls.global_db_config['username'],
                cls.global_db_config['password'], cls.global_db_config['host'],
                cls.global_db_config['port'], cls.global_db_config['database'])
        cls.test_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
        cls.test_db = SQLAlchemy(cls.test_app)
        cls.mock_flask_db.return_value = cls.test_db
Exemplo n.º 8
0
from order_app.models import db_connect, create_tables, create_db_if_not_exists

if __name__ == '__main__':
    create_db_if_not_exists()
    create_tables(db_connect())