You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			267 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			267 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Python
		
	
#!/usr/bin/env vpython3
 | 
						|
# Copyright (c) 2020 The Chromium Authors. All rights reserved.
 | 
						|
# Use of this source code is governed by a BSD-style license that can be
 | 
						|
# found in the LICENSE file.
 | 
						|
 | 
						|
import os
 | 
						|
import sys
 | 
						|
import unittest
 | 
						|
from unittest import mock
 | 
						|
 | 
						|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 | 
						|
 | 
						|
import gerrit_util
 | 
						|
import owners_client
 | 
						|
 | 
						|
alice = 'alice@example.com'
 | 
						|
bob = 'bob@example.com'
 | 
						|
chris = 'chris@example.com'
 | 
						|
dave = 'dave@example.com'
 | 
						|
emily = 'emily@example.com'
 | 
						|
 | 
						|
 | 
						|
class GerritClientTest(unittest.TestCase):
 | 
						|
    def setUp(self):
 | 
						|
        self.client = owners_client.GerritClient('host', 'project', 'branch')
 | 
						|
        self.addCleanup(mock.patch.stopall)
 | 
						|
 | 
						|
    def testListOwners(self):
 | 
						|
        mock.patch('gerrit_util.GetOwnersForFile',
 | 
						|
                   return_value={
 | 
						|
                       "code_owners": [{
 | 
						|
                           "account": {
 | 
						|
                               "email": 'approver@example.com'
 | 
						|
                           }
 | 
						|
                       }, {
 | 
						|
                           "account": {
 | 
						|
                               "email": 'reviewer@example.com'
 | 
						|
                           },
 | 
						|
                       }, {
 | 
						|
                           "account": {
 | 
						|
                               "email": 'missing@example.com'
 | 
						|
                           },
 | 
						|
                       }, {
 | 
						|
                           "account": {},
 | 
						|
                       }]
 | 
						|
                   }).start()
 | 
						|
        self.assertEqual([
 | 
						|
            'approver@example.com', 'reviewer@example.com',
 | 
						|
            'missing@example.com'
 | 
						|
        ], self.client.ListOwners(os.path.join('bar', 'everyone', 'foo.txt')))
 | 
						|
 | 
						|
        # Result should be cached.
 | 
						|
        self.assertEqual([
 | 
						|
            'approver@example.com', 'reviewer@example.com',
 | 
						|
            'missing@example.com'
 | 
						|
        ], self.client.ListOwners(os.path.join('bar', 'everyone', 'foo.txt')))
 | 
						|
        # Always use slashes as separators.
 | 
						|
        gerrit_util.GetOwnersForFile.assert_called_once_with(
 | 
						|
            'host',
 | 
						|
            'project',
 | 
						|
            'branch',
 | 
						|
            'bar/everyone/foo.txt',
 | 
						|
            resolve_all_users=False,
 | 
						|
            highest_score_only=False,
 | 
						|
            seed=mock.ANY)
 | 
						|
 | 
						|
    def testListOwnersOwnedByAll(self):
 | 
						|
        mock.patch('gerrit_util.GetOwnersForFile',
 | 
						|
                   side_effect=[
 | 
						|
                       {
 | 
						|
                           "code_owners": [
 | 
						|
                               {
 | 
						|
                                   "account": {
 | 
						|
                                       "email": 'foo@example.com'
 | 
						|
                                   },
 | 
						|
                               },
 | 
						|
                           ],
 | 
						|
                           "owned_by_all_users":
 | 
						|
                           True,
 | 
						|
                       },
 | 
						|
                       {
 | 
						|
                           "code_owners": [
 | 
						|
                               {
 | 
						|
                                   "account": {
 | 
						|
                                       "email": 'bar@example.com'
 | 
						|
                                   },
 | 
						|
                               },
 | 
						|
                           ],
 | 
						|
                           "owned_by_all_users":
 | 
						|
                           False,
 | 
						|
                       },
 | 
						|
                   ]).start()
 | 
						|
        self.assertEqual(['foo@example.com', self.client.EVERYONE],
 | 
						|
                         self.client.ListOwners('foo.txt'))
 | 
						|
        self.assertEqual(['bar@example.com'], self.client.ListOwners('bar.txt'))
 | 
						|
 | 
						|
 | 
						|
class TestClient(owners_client.OwnersClient):
 | 
						|
    def __init__(self, owners_by_path):
 | 
						|
        super(TestClient, self).__init__()
 | 
						|
        self.owners_by_path = owners_by_path
 | 
						|
 | 
						|
    def ListOwners(self, path):
 | 
						|
        return self.owners_by_path[path]
 | 
						|
 | 
						|
 | 
						|
class OwnersClientTest(unittest.TestCase):
 | 
						|
    def setUp(self):
 | 
						|
        self.owners = {}
 | 
						|
        self.client = TestClient(self.owners)
 | 
						|
 | 
						|
    def testGetFilesApprovalStatus(self):
 | 
						|
        self.client.owners_by_path = {
 | 
						|
            'approved': ['approver@example.com'],
 | 
						|
            'pending': ['reviewer@example.com'],
 | 
						|
            'insufficient': ['insufficient@example.com'],
 | 
						|
            'everyone': [owners_client.OwnersClient.EVERYONE],
 | 
						|
        }
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.GetFilesApprovalStatus(
 | 
						|
                ['approved', 'pending', 'insufficient'],
 | 
						|
                ['approver@example.com'], ['reviewer@example.com']), {
 | 
						|
                    'approved': owners_client.OwnersClient.APPROVED,
 | 
						|
                    'pending': owners_client.OwnersClient.PENDING,
 | 
						|
                    'insufficient':
 | 
						|
                    owners_client.OwnersClient.INSUFFICIENT_REVIEWERS,
 | 
						|
                })
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.GetFilesApprovalStatus(['everyone'],
 | 
						|
                                               ['anyone@example.com'], []),
 | 
						|
            {'everyone': owners_client.OwnersClient.APPROVED})
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.GetFilesApprovalStatus(['everyone'], [],
 | 
						|
                                               ['anyone@example.com']),
 | 
						|
            {'everyone': owners_client.OwnersClient.PENDING})
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.GetFilesApprovalStatus(['everyone'], [], []),
 | 
						|
            {'everyone': owners_client.OwnersClient.INSUFFICIENT_REVIEWERS})
 | 
						|
 | 
						|
    def testScoreOwners(self):
 | 
						|
        self.client.owners_by_path = {'a': [alice, bob, chris]}
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.ScoreOwners(self.client.owners_by_path.keys()),
 | 
						|
            [alice, bob, chris])
 | 
						|
 | 
						|
        self.client.owners_by_path = {
 | 
						|
            'a': [alice, bob],
 | 
						|
            'b': [bob],
 | 
						|
            'c': [bob, chris]
 | 
						|
        }
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.ScoreOwners(self.client.owners_by_path.keys()),
 | 
						|
            [alice, bob, chris])
 | 
						|
 | 
						|
        self.client.owners_by_path = {
 | 
						|
            'a': [alice, bob],
 | 
						|
            'b': [bob],
 | 
						|
            'c': [bob, chris]
 | 
						|
        }
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.ScoreOwners(self.client.owners_by_path.keys(),
 | 
						|
                                    exclude=[chris]),
 | 
						|
            [alice, bob],
 | 
						|
        )
 | 
						|
 | 
						|
        self.client.owners_by_path = {
 | 
						|
            'a': [alice, bob, chris, dave],
 | 
						|
            'b': [chris, bob, dave],
 | 
						|
            'c': [chris, dave],
 | 
						|
            'd': [alice, chris, dave]
 | 
						|
        }
 | 
						|
        self.assertEqual(
 | 
						|
            self.client.ScoreOwners(self.client.owners_by_path.keys()),
 | 
						|
            [alice, chris, bob, dave])
 | 
						|
 | 
						|
    def assertSuggestsOwners(self, owners_by_path, exclude=None):
 | 
						|
        self.client.owners_by_path = owners_by_path
 | 
						|
        suggested = self.client.SuggestOwners(owners_by_path.keys(),
 | 
						|
                                              exclude=exclude)
 | 
						|
 | 
						|
        # Owners should appear only once
 | 
						|
        self.assertEqual(len(suggested), len(set(suggested)))
 | 
						|
 | 
						|
        # All paths should be covered.
 | 
						|
        suggested = set(suggested)
 | 
						|
        for owners in owners_by_path.values():
 | 
						|
            self.assertTrue(suggested & set(owners))
 | 
						|
 | 
						|
        # No excluded owners should be present.
 | 
						|
        if exclude:
 | 
						|
            for owner in suggested:
 | 
						|
                self.assertNotIn(owner, exclude)
 | 
						|
 | 
						|
    def testSuggestOwners(self):
 | 
						|
        self.assertSuggestsOwners({})
 | 
						|
        self.assertSuggestsOwners({'a': [alice]})
 | 
						|
        self.assertSuggestsOwners({'abcd': [alice, bob, chris, dave]})
 | 
						|
        self.assertSuggestsOwners({'abcd': [alice, bob, chris, dave]},
 | 
						|
                                  exclude=[alice, bob])
 | 
						|
        self.assertSuggestsOwners({
 | 
						|
            'ae': [alice, emily],
 | 
						|
            'be': [bob, emily],
 | 
						|
            'ce': [chris, emily],
 | 
						|
            'de': [dave, emily]
 | 
						|
        })
 | 
						|
        self.assertSuggestsOwners({
 | 
						|
            'ad': [alice, dave],
 | 
						|
            'cad': [chris, alice, dave],
 | 
						|
            'ead': [emily, alice, dave],
 | 
						|
            'bd': [bob, dave]
 | 
						|
        })
 | 
						|
        self.assertSuggestsOwners({
 | 
						|
            'a': [alice],
 | 
						|
            'b': [bob],
 | 
						|
            'c': [chris],
 | 
						|
            'ad': [alice, dave]
 | 
						|
        })
 | 
						|
        self.assertSuggestsOwners({
 | 
						|
            'abc': [alice, bob, chris],
 | 
						|
            'acb': [alice, chris, bob],
 | 
						|
            'bac': [bob, alice, chris],
 | 
						|
            'bca': [bob, chris, alice],
 | 
						|
            'cab': [chris, alice, bob],
 | 
						|
            'cba': [chris, bob, alice]
 | 
						|
        })
 | 
						|
 | 
						|
        # Check that we can handle a large amount of files with unrelated
 | 
						|
        # owners.
 | 
						|
        self.assertSuggestsOwners({str(x): [str(x)] for x in range(100)})
 | 
						|
 | 
						|
    def testBatchListOwners(self):
 | 
						|
        self.client.owners_by_path = {
 | 
						|
            'bar/everyone/foo.txt': [alice, bob],
 | 
						|
            'bar/everyone/bar.txt': [bob],
 | 
						|
            'bar/foo/': [bob, chris]
 | 
						|
        }
 | 
						|
 | 
						|
        self.assertEqual(
 | 
						|
            {
 | 
						|
                'bar/everyone/foo.txt': [alice, bob],
 | 
						|
                'bar/everyone/bar.txt': [bob],
 | 
						|
                'bar/foo/': [bob, chris]
 | 
						|
            },
 | 
						|
            self.client.BatchListOwners(
 | 
						|
                ['bar/everyone/foo.txt', 'bar/everyone/bar.txt', 'bar/foo/']))
 | 
						|
 | 
						|
 | 
						|
class GetCodeOwnersClientTest(unittest.TestCase):
 | 
						|
    def setUp(self):
 | 
						|
        mock.patch('gerrit_util.IsCodeOwnersEnabledOnHost').start()
 | 
						|
        self.addCleanup(mock.patch.stopall)
 | 
						|
 | 
						|
    def testGetCodeOwnersClient_CodeOwnersEnabled(self):
 | 
						|
        gerrit_util.IsCodeOwnersEnabledOnHost.return_value = True
 | 
						|
        self.assertIsInstance(
 | 
						|
            owners_client.GetCodeOwnersClient('host', 'project', 'branch'),
 | 
						|
            owners_client.GerritClient)
 | 
						|
 | 
						|
    def testGetCodeOwnersClient_CodeOwnersDisabled(self):
 | 
						|
        gerrit_util.IsCodeOwnersEnabledOnHost.return_value = False
 | 
						|
        with self.assertRaises(Exception):
 | 
						|
            owners_client.GetCodeOwnersClient('', '', '')
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    unittest.main()
 |