class MilestoneFactoryTestCase(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self.assertNumOfMilestonesInDbEquals( 0 )

    def tearDown( self ):
        self._db.close()
        MilestoneFactory._cache = {}

    def assertNumOfMilestonesInDbEquals( self, num ):
        query = 'SELECT COUNT(*) FROM milestone'
        cursor = self._db.cursor()
        cursor.execute( query )
        result = cursor.fetchone()
        self.assertEquals( num, int( result[ 0 ]))

    def insertMilestones( self, names ):
        query = 'INSERT INTO milestone ( name ) VALUES ( %s )'
        cursor = self._db.cursor()
        arguments = [ ( name, ) for name in names ]
        cursor.executemany( query, arguments )
        cursor.close()
        self.assertNumOfMilestonesInDbEquals( len( names ))

    def testGetAll( self ):
        self.insertMilestones([ 'random-1', 'random-2' ])
        m = MilestoneFactory( self._db, None, None )
        milestones = m.getAllIDs()
        self.assertEquals( 2, len ( milestones ))
        self.assertEquals( 'random-1', milestones[ 0 ] )
        self.assertEquals( 'random-2', milestones[ 1 ] )
class UserFactoryTestCase(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self.assertNumOfUsersInDbEquals( 0 )

    def tearDown( self ):
        self._db.close()

    def assertNumOfUsersInDbEquals( self, num ):
        query = 'SELECT COUNT( DISTINCT username ) FROM permission'
        cursor = self._db.cursor()
        cursor.execute( query )
        result = cursor.fetchone()
        self.assertEquals( num, int( result[ 0 ]))

    def insertUsers( self, usernames ):
        query = 'INSERT INTO permission ( username ) VALUES ( %s )'
        cursor = self._db.cursor()
        arguments = [ ( name, ) for name in usernames ]
        cursor.executemany( query, arguments )
        cursor.close()
        self.assertNumOfUsersInDbEquals( len( usernames ))

    def testGetAll( self ):
        usernames = [ 'user-1', 'user-2' ]
        self.insertUsers( usernames )
        userFactory  = UserFactory( self._db )
        self.assertEquals( usernames, userFactory.getAllIDs() )
class ComponentFactoryTest(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self.assertNumOfComponentsInDbEquals( 0 )

    def tearDown( self ):
        self._db.close()
        ComponentFactory._cache = {}

    def assertNumOfComponentsInDbEquals( self, num ):
        query = 'SELECT COUNT(*) FROM component'
        cursor = self._db.cursor()
        cursor.execute( query )
        result = cursor.fetchone()
        self.assertEquals( num, int( result[ 0 ]))

    def testGetAll( self ):
        componentIDs = [ 'component-a', 'component-b' ]
        self.insertComponentsIntoDb( componentIDs )
        componentFactory = ComponentFactory( self._db )
        all = componentFactory.getAllIDs()
        self.assertEquals( componentIDs, all )

    def insertComponentsIntoDb( self, ids ):
        query = 'INSERT INTO component ( name ) VALUES ( %s )'
        cursor = self._db.cursor()
        arguments = [ ( id, ) for id in ids ]
        cursor.executemany( query, arguments )
        cursor.close()
        self.assertNumOfComponentsInDbEquals( len( ids ))


    def testSameObjectOnSameName( self ):
        componentFactory = ComponentFactory( None )
        o1 = componentFactory.getByName( 'test' )
        o2 = componentFactory.getByName( 'test' )
        o3 = componentFactory.getByName( 'test2' )
        self.assertTrue( o1 is o2 )
        self.assertFalse( o1 is o3 )
class MilestoneRelationshipResolverTestCase(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self._cursor = self._db.cursor()
        self.assertFalse( self.milestoneRelationshipTableExists() )

    def tearDown( self ):
        self._cursor.close()
        self._db.close()

    def milestoneRelationshipTableExists( self ):
        query = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=%s"
        try:
            cursor = self._db.cursor()
            cursor.execute( query, [ 'milestoneRelationship' ])
            result = cursor.fetchone()
            return int( result[ 0 ]) == 1
        finally:
            try: cursor.close()
            except Exception,e: pass

    def testTableAutomaticallyCreated( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        self.assertTrue( self.milestoneRelationshipTableExists() )

    def testGetAllAssignedComponentes( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        self.assertEquals( [], resolver.getAllAssignedComponentIDs() )

    def testGetAllAssignedProjects( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        self.assertEquals( [], resolver.getAllAssignedProjectIDs() )

    def testAssignComponent( self ):
        resolver1 = MilestoneRelationshipResolver( 'test-milestone', self._db ) 
        resolver2 = MilestoneRelationshipResolver( 'test-milestone-2', self._db ) 
        resolver1.assignToComponentID( 'test-component-name' )
        resolver2.assignToComponentID( 'another-component-name' )

        components1 = resolver1.getAllAssignedComponentIDs()
        components2 = resolver2.getAllAssignedComponentIDs()
        self.assertEquals([ 'test-component-name' ], components1 )
        self.assertEquals([ 'another-component-name' ], components2 )

    def testAssignProject( self ):
        resolver1 = MilestoneRelationshipResolver( 'test-milestone', self._db )
        resolver2 = MilestoneRelationshipResolver( 'test-milestone-2', self._db )
        resolver1.assignToProjectID( 'test-project-name' )
        resolver2.assignToProjectID( 'another-project-name' )

        projects1 = resolver1.getAllAssignedProjectIDs()
        projects2 = resolver2.getAllAssignedProjectIDs()
        self.assertEquals([ 'test-project-name' ], projects1 )
        self.assertEquals([ 'another-project-name' ], projects2 )

    def testAssignComponentsChangedDatabase( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        resolver.assignToComponentID( 'component-a' )
        self.assertDatabaseContainsSingleRow( 
                ( 'test-milestone', 'component', 'component-a' ))

    def testAssignProjectChangesDatabase( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        resolver.assignToProjectID( 'project-a' )
        self.assertDatabaseContainsSingleRow( 
                ( 'test-milestone', 'project', 'project-a' ))

    def testUnassignCompoent( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        resolver.assignToComponentID( 'test-component' )
        components = resolver.getAllAssignedComponentIDs()
        self.assertEquals([ 'test-component' ], components )
        
        resolver.unassignFromComponentID( 'test-component' )
        components = resolver.getAllAssignedComponentIDs()
        self.assertEquals( [], components )
        self.assertDatabaseContainsNoRow()

    def testUnassignProject( self ):
        resolver = MilestoneRelationshipResolver( 'test-milestone', self._db )
        resolver.assignToProjectID( 'test-project' )
        projects = resolver.getAllAssignedProjectIDs()
        self.assertEquals([ 'test-project' ], projects )
        
        resolver.unassignFromProjectID( 'test-project' )
        projects = resolver.getAllAssignedProjectIDs()
        self.assertEquals( [], projects )
        self.assertDatabaseContainsNoRow()

    def assertDatabaseContainsSingleRow( self, row ):
        query = 'SELECT milestoneId, relationshipType, id FROM milestoneRelationship';
        self._cursor.execute( query )
        result = self._cursor.fetchall()
        self.assertEquals( 1, len( result ))
        self.assertEquals( row, result[ 0 ])

    def assertDatabaseContainsNoRow( self ):
        query = 'SELECT * FROM milestoneRelationship'
        self._cursor.execute( query )
        result = self._cursor.fetchall()
        self.assertEquals( 0, len( result ), result )
class TicketFactoryTest(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self.assertNumOfTicketsInDb( 0 )

    def tearDown( self ):
        self._db.close()
        TicketFactory._cache = {}

    def assertNumOfTicketsInDb( self, num ):
        query = 'SELECT COUNT(*) FROM ticket'
        cursor = self._db.cursor()
        cursor.execute( query )
        result = cursor.fetchone()
        self.assertEquals( int( result[ 0 ]), num )

    def testGetByNameDoesntRaiseException( self ):
        factory = TicketFactory( self._db, None, None )
        factory.getById( 123 )
    
    def testTicketAndProjectCorrectly( self ):
        componentFactory = MockFactory()
        projectFactory = MockFactory()
        self._insertTicketInDb( 1, 'test-1', 'random-component-1', 
                'random-project-1' )
        self._insertTicketInDb( 2, 'test-2', 'random-component-2', 
                'random-project-2' )
        factory = TicketFactory( self._db, componentFactory, projectFactory )


        def assertTicketProperties( ticket, index ):
            self.assertEqual( index, ticket.id() )
            self.assertEqual( 'test-%s' % index, ticket.title() )
            self.assertEqual([ 'random-component-%s' % index ], 
                    componentFactory.requestedNames )
            self.assertEqual([ 'random-project-%s' % index ], 
                    projectFactory.requestedNames )

            componentFactory.requestedNames = []
            projectFactory.requestedNames = []


        ticket = factory.getById( 1 )
        assertTicketProperties( ticket, 1 )

        ticket = factory.getById( 2 )
        assertTicketProperties( ticket, 2 )


    def testCanBeAccessed( self ):
        self._insertTicketInDb( 1, 'test', 'random-component', 'random-project' )

        accessibleFactory = MockFactory( True )
        unaccessibleFactory = MockFactory( False )

        factory = TicketFactory( self._db, unaccessibleFactory, unaccessibleFactory )
        self.assertFalse( factory.getById( 1 ).canBeAccessedBy( None ))
        
        TicketFactory._cache = {}
        factory = TicketFactory( self._db, accessibleFactory, unaccessibleFactory )
        self.assertTrue( factory.getById( 1 ).canBeAccessedBy( None ))

        TicketFactory._cache = {}
        factory = TicketFactory( self._db, unaccessibleFactory, accessibleFactory )
        self.assertTrue( factory.getById( 1 ).canBeAccessedBy( None ))

        TicketFactory._cache = {}
        factory = TicketFactory( self._db, accessibleFactory, accessibleFactory )
        self.assertTrue( factory.getById( 1 ).canBeAccessedBy( None ))

    def _insertTicketInDb( self, id, title, componentName, projectName ):
        query= 'INSERT INTO ticket ( id, summary, component ) VALUES ( %s, %s, %s )'
        cursor = self._db.cursor()
        cursor.execute( query, [ id, title, componentName ])

        query = "INSERT INTO ticket_custom ( ticket, name, value ) VALUES ( %s, " + \
                "'project', %s )"
        cursor.execute( query, [ id, projectName ])
        cursor.close()
class PermissionManagerTestCase(unittest.TestCase):
    def setUp( self ):
        self._db = InMemoryDatabase()
        self.assertEmptyPermissionsTable()

    def tearDown( self ):
        self._db.close()

    def assertEmptyPermissionsTable( self ):
        try:
            cursor = self._db.cursor()
            cursor.execute( 'SELECT COUNT(*) FROM permission' )
            result = cursor.fetchone()
            self.assertEquals( 0, int( result[ 0 ]))
        finally:
            try: cursor.close()
            except Exception,e: pass

    def testEmptyHasPermission( self ):
        permManager = PermissionManager( 'test', self._db )
        self.assertFalse( permManager.hasPermission( 'random' ))

    def testHasPermissionByGrantedPermission( self ):
        permManager = PermissionManager( 'test', self._db )
        permManager.grantPermission( 'random' )
        permManager.hasPermission( 'random' )
        self.assertTrue( permManager.hasPermission( 'random' ))

    def testHasDeepPermission( self ):
        permManager = PermissionManager( 'group1', self._db )
        permManager.grantPermission( 'group2' )

        permManager = PermissionManager( 'group2', self._db )
        permManager.grantPermission( 'deepPerm' )

        permManager = PermissionManager( 'user', self._db )
        self.assertFalse( permManager.hasPermission( 'group1' ))
        self.assertFalse( permManager.hasPermission( 'deepPerm' ))
        permManager.grantPermission( 'group1' )
        self.assertTrue( permManager.hasPermission( 'group1' ))
        self.assertTrue( permManager.hasPermission( 'deepPerm' ))
        
    def testWrittenToDabatabse( self ):
        permManager = PermissionManager( 'test', self._db )
        permManager.grantPermission( 'perm' )
        try:
            cursor = self._db.cursor()
            cursor.execute( 'SELECT username, action FROM permission' );
            result = cursor.fetchall()
            self.assertEquals( 1, len( result ))
            self.assertEquals( ( 'test', 'perm' ), result[ 0 ])
        finally:
            try: cursor.close()
            except Exception,e: pass


    def testRemovePermission( self ):
        permManager = PermissionManager( 'test', self._db )
        permManager.grantPermission( 'perm1' )
        permManager.grantPermission( 'perm2' )
        permManager.removePermission( 'perm1' )
        self.assertFalse( permManager.hasPermission( 'perm1' ))
        self.assertTrue( permManager.hasPermission( 'perm2' ))
        permManager.removePermission( 'perm2' )
        self.assertFalse( permManager.hasPermission( 'perm2' ))
        self.assertEmptyPermissionsTable()