<s> import mock <EOL> from threading import current_thread <EOL> from threading import Event <EOL> from threading import Thread <EOL> from sqlalchemy . orm import exc <EOL> from nailgun import consts <EOL> from nailgun . db import db <EOL> from nailgun . db import deadlock_detector as dd <EOL> from nailgun . db . sqlalchemy import models <EOL> from nailgun . test . base import BaseTestCase <EOL> class TestDeadlockDetector ( BaseTestCase ) : <EOL> patchers = [ <EOL> mock . patch ( '<STR_LIT>' , <EOL> return_value = False ) <EOL> ] <EOL> @ classmethod <EOL> def setUpClass ( cls ) : <EOL> super ( TestDeadlockDetector , cls ) . setUpClass ( ) <EOL> for patcher in cls . patchers : <EOL> patcher . start ( ) <EOL> @ classmethod <EOL> def tearDownClass ( cls ) : <EOL> super ( TestDeadlockDetector , cls ) . tearDownClass ( ) <EOL> for patcher in cls . patchers : <EOL> patcher . stop ( ) <EOL> def tearDown ( self ) : <EOL> super ( TestDeadlockDetector , self ) . tearDown ( ) <EOL> db ( ) . rollback ( ) <EOL> def test_no_locks ( self ) : <EOL> len_exp = len ( dd . context . locks ) <EOL> db ( ) . query ( models . Node ) . all ( ) <EOL> self . assertEquals ( len_exp , len ( dd . context . locks ) ) <EOL> db ( ) . query ( models . Node ) . all ( ) <EOL> db ( ) . query ( models . Cluster ) . all ( ) <EOL> self . assertEquals ( len_exp , len ( dd . context . locks ) ) <EOL> def test_lock_same_table ( self ) : <EOL> db ( ) . commit ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertEquals ( <NUM_LIT:1> , len ( dd . context . locks ) ) <EOL> db ( ) . commit ( ) <EOL> def test_lock_cleaned_on_commit ( self ) : <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertGreater ( len ( dd . context . locks ) , <NUM_LIT:0> ) <EOL> db ( ) . commit ( ) <EOL> self . assertEquals ( <NUM_LIT:0> , len ( dd . context . locks ) ) <EOL> def test_lock_not_cleaned_on_flush ( self ) : <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> self . assertGreater ( len ( dd . context . locks ) , <NUM_LIT:0> ) <EOL> db ( ) . flush ( ) <EOL> self . assertGreater ( len ( dd . context . locks ) , <NUM_LIT:0> ) <EOL> def test_lock_cleaned_on_rollback ( self ) : <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertGreater ( len ( dd . context . locks ) , <NUM_LIT:0> ) <EOL> db ( ) . rollback ( ) <EOL> self . assertEquals ( <NUM_LIT:0> , len ( dd . context . locks ) ) <EOL> def test_unknown_locks_chain_failed ( self ) : <EOL> db ( ) . query ( models . Release ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertRaises ( <EOL> dd . LockTransitionNotAllowedError , <EOL> db ( ) . query ( models . Node ) . with_lockmode , '<STR_LIT>' <EOL> ) <EOL> db ( ) . rollback ( ) <EOL> db ( ) . query ( models . Task ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertRaises ( <EOL> dd . LockTransitionNotAllowedError , <EOL> db ( ) . query ( models . Task ) . with_lockmode , '<STR_LIT>' <EOL> ) <EOL> db ( ) . rollback ( ) <EOL> def test_locks_chain ( self ) : <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . commit ( ) <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . commit ( ) <EOL> def lock_tables ( self , objects , results , event , threads_num ) : <EOL> try : <EOL> for obj in objects : <EOL> db ( ) . query ( obj ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> except Exception : <EOL> pass <EOL> finally : <EOL> results . append ( current_thread ( ) ) <EOL> if len ( results ) == threads_num : <EOL> event . set ( ) <EOL> event . wait ( ) <EOL> try : <EOL> self . assertEquals ( <EOL> len ( objects ) , <EOL> len ( dd . context . locks ) <EOL> ) <EOL> results . append ( True ) <EOL> except Exception as e : <EOL> results . append ( False ) <EOL> raise e <EOL> finally : <EOL> db ( ) . commit ( ) <EOL> def test_lock_context_isolation_in_threads ( self ) : <EOL> results = [ ] <EOL> objects_for_locks = ( <EOL> ( models . Cluster , models . Node ) , <EOL> ( models . Node , models . Cluster ) , <EOL> ( models . Release , ) <EOL> ) <EOL> threads = [ ] <EOL> event = Event ( ) <EOL> for objects in objects_for_locks : <EOL> t = Thread ( <EOL> target = self . lock_tables , <EOL> args = ( objects , results , event , len ( objects_for_locks ) ) <EOL> ) <EOL> t . start ( ) <EOL> threads . append ( t ) <EOL> for thread in threads : <EOL> thread . join ( ) <EOL> self . assertTrue ( all ( results ) ) <EOL> def test_find_lock ( self ) : <EOL> self . assertIsNone ( dd . find_lock ( '<STR_LIT>' , strict = False ) ) <EOL> db ( ) . query ( models . Release ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> lock = dd . find_lock ( models . Release . __tablename__ , strict = True ) <EOL> self . assertIsNotNone ( lock ) <EOL> self . assertEqual ( models . Release . __tablename__ , lock . table ) <EOL> def test_find_lock_failed ( self ) : <EOL> db ( ) . query ( models . Release ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> self . assertRaisesWithMessage ( <EOL> dd . LockNotFound , <EOL> "<STR_LIT>" , <EOL> dd . find_lock , models . Node . __tablename__ , strict = True ) <EOL> def test_ids_traced_select_from_single_table ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> self . assertEqual ( lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> def test_select_failed_with_wrong_order ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> db ( ) . query ( models . Node ) . order_by ( models . Node . id . desc ( ) ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> def test_locking_already_locked_objects ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> self . assertEqual ( lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . get ( nodes [ <NUM_LIT:0> ] . id ) <EOL> self . assertEqual ( lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> def test_ids_traced_select_from_different_tables ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:3> ) <EOL> clusters = db ( ) . query ( models . Cluster ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> nodes_lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> clusters_lock = dd . find_lock ( models . Cluster . __tablename__ ) <EOL> self . assertEqual ( nodes_lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> self . assertEqual ( clusters_lock . locked_ids , set ( o . id for o in clusters ) ) <EOL> def test_id_traced_in_get ( self ) : <EOL> node = db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . get ( <NUM_LIT:0> ) <EOL> self . assertIsNone ( node ) <EOL> nodes_lock = dd . find_lock ( models . Node . __tablename__ , strict = False ) <EOL> self . assertIsNotNone ( nodes_lock ) <EOL> self . assertEqual ( set ( ) , nodes_lock . locked_ids ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> for node in nodes : <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . get ( node . id ) <EOL> nodes_lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> self . assertEqual ( nodes_lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> def test_wrong_order_in_get_failed ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . get ( nodes [ <NUM_LIT:0> ] . id ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . get ( nodes [ <NUM_LIT:1> ] . id ) <EOL> def test_updating_already_locked_object ( self ) : <EOL> cluster = self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> self . env . create_cluster ( ) <EOL> self . assertGreater ( len ( self . env . clusters ) , <NUM_LIT:1> ) <EOL> db ( ) . query ( models . Cluster ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . with_lockmode ( '<STR_LIT>' ) . all ( ) <EOL> cluster . status = consts . CLUSTER_STATUSES . error <EOL> def test_id_traced_on_updating_object ( self ) : <EOL> cluster = self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> self . env . create_cluster ( ) <EOL> self . assertGreater ( len ( self . env . clusters ) , <NUM_LIT:1> ) <EOL> cluster . status = consts . CLUSTER_STATUSES . error <EOL> cluster_lock = dd . find_lock ( models . Cluster . __tablename__ ) <EOL> self . assertEqual ( cluster_lock . locked_ids , set ( [ cluster . id ] ) ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> for node in nodes : <EOL> node . status = consts . NODE_STATUSES . error <EOL> node_lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> self . assertEqual ( node_lock . locked_ids , set ( o . id for o in nodes ) ) <EOL> def test_updating_ids_in_wrong_order_failed ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT>' ) . all ( ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> for node in nodes : <EOL> node . status = consts . NODE_STATUSES . error <EOL> def test_lock_ids_in_non_last_lock_failed ( self ) : <EOL> cluster = self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> another_cluster = self . env . create_cluster ( ) <EOL> self . assertGreater ( len ( self . env . clusters ) , <NUM_LIT:1> ) <EOL> cluster . status = consts . CLUSTER_STATUSES . error <EOL> cluster_lock = dd . find_lock ( models . Cluster . __tablename__ ) <EOL> self . assertEqual ( cluster_lock . locked_ids , set ( [ cluster . id ] ) ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> last_lock = dd . context . locks [ - <NUM_LIT:1> ] <EOL> self . assertNotEqual ( cluster_lock , last_lock ) <EOL> with self . assertRaises ( dd . TablesLockingOrderViolation ) : <EOL> another_cluster . status = consts . CLUSTER_STATUSES . error <EOL> def test_bulk_update_query_ids_traced ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> self . assertIsNone ( dd . find_lock ( <EOL> models . Node . __tablename__ , strict = False ) ) <EOL> node = self . env . nodes [ <NUM_LIT:0> ] <EOL> db ( ) . query ( models . Node ) . filter ( models . Node . id == node . id ) . update ( { '<STR_LIT:status>' : consts . NODE_STATUSES . error } ) <EOL> nodes_lock = dd . find_lock ( models . Node . __tablename__ , strict = False ) <EOL> self . assertIsNotNone ( nodes_lock ) <EOL> self . assertEqual ( nodes_lock . locked_ids , set ( [ node . id ] ) ) <EOL> def test_bulk_delete_query_ids_traced ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> node = self . env . nodes [ <NUM_LIT:0> ] <EOL> db ( ) . query ( models . Node ) . filter ( models . Node . id == node . id ) . delete ( ) <EOL> node_lock = dd . find_lock ( models . Node . __tablename__ , strict = False ) <EOL> self . assertIsNotNone ( node_lock ) <EOL> self . assertEqual ( node_lock . locked_ids , set ( [ node . id ] ) ) <EOL> def test_id_traced_for_fetching_first ( self ) : <EOL> node = db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . first ( ) <EOL> self . assertIsNone ( node ) <EOL> node_lock = dd . find_lock ( models . Node . __tablename__ , strict = False ) <EOL> self . assertIsNotNone ( node_lock ) <EOL> self . assertEqual ( set ( ) , node_lock . locked_ids ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> node = db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . first ( ) <EOL> self . assertIsNotNone ( node ) <EOL> self . assertIn ( node . id , node_lock . locked_ids ) <EOL> def test_lock_failed_on_wrong_order_for_fetching_first ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == nodes [ <NUM_LIT:0> ] . id ) . first ( ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == nodes [ <NUM_LIT:1> ] . id ) . first ( ) <EOL> def test_id_traced_for_fetching_one ( self ) : <EOL> with self . assertRaises ( exc . NoResultFound ) : <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == <NUM_LIT:0> ) . one ( ) <EOL> node_lock = dd . find_lock ( models . Node . __tablename__ , strict = False ) <EOL> self . assertIsNotNone ( node_lock ) <EOL> self . assertEqual ( set ( ) , node_lock . locked_ids ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> node = self . env . nodes [ <NUM_LIT:0> ] <EOL> node = db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == node . id ) . one ( ) <EOL> self . assertIsNotNone ( node ) <EOL> self . assertIn ( node . id , node_lock . locked_ids ) <EOL> def test_lock_failed_on_wrong_order_for_fetching_one ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == nodes [ <NUM_LIT:0> ] . id ) . one ( ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . filter ( models . Node . id == nodes [ <NUM_LIT:1> ] . id ) . one ( ) <EOL> def test_id_traced_on_object_deletion ( self ) : <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> node = self . env . nodes [ <NUM_LIT:0> ] <EOL> node_id = node . id <EOL> db ( ) . delete ( node ) <EOL> node_lock = dd . find_lock ( models . Node . __tablename__ ) <EOL> self . assertEqual ( node_lock . locked_ids , set ( [ node_id ] ) ) <EOL> def test_deletion_already_locked_object ( self ) : <EOL> self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> cluster = db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . first ( ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> db ( ) . delete ( cluster ) <EOL> def test_deletion_in_wrong_order_failed ( self ) : <EOL> self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> nodes = db ( ) . query ( models . Node ) . order_by ( '<STR_LIT>' ) . all ( ) <EOL> db ( ) . delete ( nodes [ <NUM_LIT:0> ] ) <EOL> with self . assertRaises ( dd . ObjectsLockingOrderViolation ) : <EOL> db ( ) . delete ( nodes [ <NUM_LIT:1> ] ) <EOL> def test_deletion_with_non_last_lock_failed ( self ) : <EOL> old_cluster = self . env . create_cluster ( ) <EOL> self . env . create_nodes ( <NUM_LIT:2> ) <EOL> new_cluster = self . env . create_cluster ( ) <EOL> db ( ) . query ( models . Cluster ) . with_lockmode ( '<STR_LIT>' ) . get ( old_cluster . id ) <EOL> db ( ) . query ( models . Node ) . with_lockmode ( '<STR_LIT>' ) . order_by ( '<STR_LIT:id>' ) . all ( ) <EOL> last_lock = dd . context . locks [ - <NUM_LIT:1> ] <EOL> cluster_lock = dd . find_lock ( models . Cluster . __tablename__ ) <EOL> self . assertNotEqual ( cluster_lock , last_lock ) <EOL> with self . assertRaises ( dd . TablesLockingOrderViolation ) : <EOL> db ( ) . delete ( new_cluster ) </s>
