[IMP] runbot: refactor tests

A lot of things have to be mocked during runbot tests, as a consequence,
a lot of patch decorators accumulate in a big stack uppon some tests
methods.

Also, a lot of mocks are used multiple times among tests.

With this commit, a new RunbotClass is added that comes with patches
ready to be started. A start_patcher helper method is available to start
a patch and add the appropriate stop in a cleanup.

Also, when a build is created in the tests, the _get_params method is
always called, resulting in an annoying git warning.

With this commit, a create_build method is added on the test class, that
way the _get_params is always mocked when a build is created.
This commit is contained in:
Christophe Monniez 2019-11-10 17:16:41 +01:00
parent 7d1283492b
commit 73f720a55c
16 changed files with 251 additions and 253 deletions

View File

@ -63,10 +63,14 @@ def now():
def grep(filename, string):
if os.path.isfile(filename):
return open(filename).read().find(string) != -1
return find(filename, string) != -1
return False
def find(filename, string):
return open(filename).read().find(string)
def uniq_list(l):
return OrderedDict.fromkeys(l).keys()

View File

@ -14,7 +14,7 @@ import datetime
import io
import json
import logging
import os
from .common import os
import shutil
import subprocess
import time

View File

@ -2,14 +2,13 @@
import fnmatch
import glob
import logging
import os
import pwd
import re
import shutil
import subprocess
import time
import datetime
from ..common import dt2time, fqdn, now, grep, uniq_list, local_pgadmin_cursor, s2human, Commit, dest_reg
from ..common import dt2time, fqdn, now, grep, uniq_list, local_pgadmin_cursor, s2human, Commit, dest_reg, os
from ..container import docker_build, docker_stop, docker_is_running, Command
from odoo.addons.runbot.models.repo import RunbotException
from odoo import models, fields, api
@ -382,10 +381,7 @@ class runbot_build(models.Model):
def _get_params(self):
message = False
try:
message = self.repo_id._git(['show', '-s', self.name])
except CalledProcessError:
pass # todo remove this try catch and make correct patch for _git
message = self.repo_id._git(['show', '-s', self.name])
params = defaultdict(lambda: defaultdict(str))
if message:
regex = re.compile(r'^[\t ]*Runbot-dependency: ([A-Za-z0-9\-_]+/[A-Za-z0-9\-_]+):([0-9A-Fa-f\-]*) *(#.*)?$', re.M) # dep:repo:hash #comment

View File

@ -1,11 +1,10 @@
import base64
import glob
import logging
import os
import re
import shlex
import time
from ..common import now, grep, time2str, rfind, Commit, s2human
from ..common import now, grep, time2str, rfind, Commit, s2human, os
from ..container import docker_run, docker_get_gateway_ip, Command
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError

View File

@ -3,7 +3,6 @@ import datetime
import dateutil
import json
import logging
import os
import random
import re
import requests
@ -18,7 +17,7 @@ from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from odoo import models, fields, api, registry
from odoo.modules.module import get_module_resource
from odoo.tools import config
from ..common import fqdn, dt2time, Commit, dest_reg
from ..common import fqdn, dt2time, Commit, dest_reg, os
from ..container import docker_ps, docker_stop
from psycopg2.extensions import TransactionRollbackError
_logger = logging.getLogger(__name__)
@ -538,6 +537,7 @@ class runbot_repo(models.Model):
"""This method have to be called from a dedicated cron on a runbot
in charge of orchestration.
"""
if hostname != fqdn():
return 'Not for me'
@ -558,8 +558,10 @@ class runbot_repo(models.Model):
""" This method have to be called from a dedicated cron
created on each runbot instance.
"""
if hostname != fqdn():
return 'Not for me'
host = self.env['runbot.host']._get_current()
host.set_psql_conn_count()
host.last_start_loop = fields.Datetime.now()

View File

@ -1,3 +1,4 @@
from . import common
from . import test_repo
from . import test_build_error
from . import test_branch

55
runbot/tests/common.py Normal file
View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase
from unittest.mock import patch
class Dummy():
...
class RunbotCase(TransactionCase):
def setUp(self):
super(RunbotCase, self).setUp()
self.Build = self.env['runbot.build']
self.Repo = self.env['runbot.repo']
self.Branch = self.env['runbot.branch']
self.patchers = {}
def git_side_effect(cmd):
if cmd[:2] == ['show', '-s'] or cmd[:3] == ['show', '--pretty="%H -- %s"', '-s']:
return 'commit message for %s' % cmd[-1]
if cmd[:2] == ['cat-file', '-e']:
return True
else:
print('Unsupported mock command %s' % cmd)
self.start_patcher('git_patcher', 'odoo.addons.runbot.models.repo.runbot_repo._git', side_effect=git_side_effect)
self.start_patcher('fqdn_patcher', 'odoo.addons.runbot.common.socket.getfqdn', 'host.runbot.com')
self.start_patcher('find_patcher', 'odoo.addons.runbot.common.find', 0)
self.start_patcher('github_patcher', 'odoo.addons.runbot.models.repo.runbot_repo._github', {})
self.start_patcher('is_on_remote_patcher', 'odoo.addons.runbot.models.branch.runbot_branch._is_on_remote', True)
self.start_patcher('repo_root_patcher', 'odoo.addons.runbot.models.repo.runbot_repo._root', '/tmp/runbot_test/static')
self.start_patcher('makedirs', 'odoo.addons.runbot.common.os.makedirs', True)
self.start_patcher('mkdir', 'odoo.addons.runbot.common.os.mkdir', True)
self.start_patcher('local_pgadmin_cursor', 'odoo.addons.runbot.common.local_pgadmin_cursor', False) # avoid to create databases
self.start_patcher('isdir', 'odoo.addons.runbot.common.os.path.isdir', True)
self.start_patcher('isfile', 'odoo.addons.runbot.common.os.path.isfile', True)
self.start_patcher('docker_run', 'odoo.addons.runbot.models.build_config.docker_run')
self.start_patcher('docker_ps', 'odoo.addons.runbot.models.repo.docker_ps', [])
self.start_patcher('docker_stop', 'odoo.addons.runbot.models.repo.docker_stop')
def start_patcher(self, patcher_name, patcher_path, return_value=Dummy, side_effect=Dummy):
patcher = patch(patcher_path)
if not hasattr(patcher, 'is_local'):
res = patcher.start()
self.addCleanup(patcher.stop)
self.patchers[patcher_name] = res
if side_effect != Dummy:
res.side_effect = side_effect
elif return_value != Dummy:
res.return_value = return_value
def create_build(self, vals):
return self.Build.create(vals)

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
class Test_Branch(common.TransactionCase):
class Test_Branch(RunbotCase):
def setUp(self):
super(Test_Branch, self).setUp()
@ -24,8 +25,8 @@ class Test_Branch(common.TransactionCase):
self.assertEqual(branch.branch_url, 'https://example.com/foo/bar/tree/master')
self.assertEqual(branch.config_id, self.env.ref('runbot.runbot_build_config_default'))
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_pull_request(self, mock_github):
def test_pull_request(self):
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
'head' : {'label': 'foo-dev:bar_branch'},
'base' : {'ref': 'master'},

View File

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
def rev_parse(repo, branch_name):
"""
@ -12,13 +14,11 @@ def rev_parse(repo, branch_name):
head_hash = 'rp_%s_%s_head' % (repo.name.split(':')[1], branch_name.split('/')[-1])
return head_hash
class Test_Build(common.TransactionCase):
class Test_Build(RunbotCase):
def setUp(self):
super(Test_Build, self).setUp()
self.Repo = self.env['runbot.repo']
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar', 'server_files': 'server.py', 'addons_paths': 'addons,core/addons'})
self.Branch = self.env['runbot.branch']
self.branch = self.Branch.create({
'repo_id': self.repo.id,
'name': 'refs/heads/master'
@ -31,11 +31,9 @@ class Test_Build(common.TransactionCase):
'repo_id': self.repo.id,
'name': 'refs/heads/11.0'
})
self.Build = self.env['runbot.build']
@patch('odoo.addons.runbot.models.build.fqdn')
def test_base_fields(self, mock_fqdn):
build = self.Build.create({
def test_base_fields(self):
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -47,14 +45,14 @@ class Test_Build(common.TransactionCase):
self.assertEqual(build.dest, '%05d-master-deadbe' % build.id)
# Test domain compute with fqdn and ir.config_parameter
mock_fqdn.return_value = 'runbot98.nowhere.org'
self.patchers['fqdn_patcher'].return_value = 'runbot98.nowhere.org'
self.env['ir.config_parameter'].sudo().set_param('runbot.runbot_domain', False)
self.assertEqual(build.domain, 'runbot98.nowhere.org:1234')
self.env['ir.config_parameter'].set_param('runbot.runbot_domain', 'runbot99.example.org')
build._compute_domain()
self.assertEqual(build.domain, 'runbot99.example.org:1234')
other = self.Build.create({
other = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '5678',
@ -71,11 +69,9 @@ class Test_Build(common.TransactionCase):
builds.write({'local_state': 'duplicate'})
@patch('odoo.addons.runbot.models.build.runbot_build._get_repo_available_modules')
@patch('odoo.addons.runbot.models.build.runbot_build._get_params')
@patch('odoo.addons.runbot.models.build.fqdn')
def test_filter_modules(self, mock_fqdn, mock_get_params, mock_get_repo_mods):
def test_filter_modules(self, mock_get_repo_mods):
""" test module filtering """
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -99,15 +95,11 @@ class Test_Build(common.TransactionCase):
modules_to_test = build._get_modules_to_test(self, modules_patterns='*, -hw_*, hw_explicit')
self.assertEqual(modules_to_test, sorted(['good_module', 'bad_module', 'other_good', 'l10n_be', 'hwgood', 'hw_explicit', 'other_mod_1', 'other_mod_2']))
@patch('odoo.addons.runbot.models.build.os.path.isfile')
@patch('odoo.addons.runbot.models.build.os.mkdir')
@patch('odoo.addons.runbot.models.build.grep')
def test_build_cmd_log_db(self, mock_grep, mock_mkdir, mock_is_file):
def test_build_cmd_log_db(self, ):
""" test that the logdb connection URI is taken from the .odoorc file """
mock_is_file.return_value = True
uri = 'postgres://someone:pass@somewhere.com/db'
self.env['ir.config_parameter'].sudo().set_param("runbot.runbot_logdb_uri", uri)
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -115,15 +107,9 @@ class Test_Build(common.TransactionCase):
cmd = build._cmd(py_version=3)
self.assertIn('log-db = %s' % uri, cmd.get_config())
@patch('odoo.addons.runbot.models.build.os.path.isdir')
@patch('odoo.addons.runbot.models.build.os.path.isfile')
@patch('odoo.addons.runbot.models.build.os.mkdir')
@patch('odoo.addons.runbot.models.build.grep')
def test_build_cmd_server_path_no_dep(self, mock_grep, mock_mkdir, mock_is_file, mock_is_dir):
def test_build_cmd_server_path_no_dep(self):
""" test that the server path and addons path """
mock_is_file.return_value = True
mock_is_dir.return_value = True
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -135,19 +121,15 @@ class Test_Build(common.TransactionCase):
addons_path_pos = cmd.index('--addons-path') + 1
self.assertEqual(cmd[addons_path_pos], 'bar/addons,bar/core/addons')
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
@patch('odoo.addons.runbot.models.build.os.path.isdir')
@patch('odoo.addons.runbot.models.build.os.path.isfile')
@patch('odoo.addons.runbot.models.build.os.mkdir')
@patch('odoo.addons.runbot.models.build.grep')
def test_build_cmd_server_path_with_dep(self, mock_grep, mock_mkdir, mock_is_file, mock_is_dir, mock_is_on_remote):
def test_build_cmd_server_path_with_dep(self):
""" test that the server path and addons path """
def is_file(file):
self.assertIn(file, [
'/tmp/runbot_test/static/sources/bar-ent/d0d0caca0000ffffffffffffffffffffffffffff/requirements.txt',
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/requirements.txt',
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/server.py'
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/server.py',
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/openerp/tools/config.py'
])
if file == '/tmp/runbot_test/static/sources/bar-ent/d0d0caca0000ffffffffffffffffffffffffffff/requirements.txt':
return False
@ -162,9 +144,9 @@ class Test_Build(common.TransactionCase):
self.assertTrue(any([path in file for path in paths])) # checking that addons path existence check looks ok
return True
mock_is_file.side_effect = is_file
mock_is_dir.side_effect = is_dir
mock_is_on_remote.return_value = True
self.patchers['isfile'].side_effect = is_file
self.patchers['isdir'].side_effect = is_dir
repo_ent = self.env['runbot.repo'].create({
'name': 'bla@example.com:foo/bar-ent',
'server_files': '',
@ -181,7 +163,7 @@ class Test_Build(common.TransactionCase):
return 'dfdfcfcf0000ffffffffffffffffffffffffffff'
with patch('odoo.addons.runbot.models.repo.runbot_repo._git_rev_parse', new=rev_parse):
build = self.Build.create({
build = self.create_build({
'branch_id': enterprise_branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -193,26 +175,21 @@ class Test_Build(common.TransactionCase):
self.assertEqual('bar/server.py', cmd[1])
self.assertEqual('python3', cmd[0])
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
@patch('odoo.addons.runbot.models.build.os.path.isdir')
@patch('odoo.addons.runbot.models.build.os.path.isfile')
@patch('odoo.addons.runbot.models.build.os.mkdir')
@patch('odoo.addons.runbot.models.build.grep')
def test_build_cmd_server_path_with_dep_collision(self, mock_grep, mock_mkdir, mock_is_file, mock_is_dir, mock_is_on_remote):
def test_build_cmd_server_path_with_dep_collision(self):
""" test that the server path and addons path """
def is_file(file):
self.assertIn(file, [
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/requirements.txt',
'/tmp/runbot_test/static/sources/bar/d0d0caca0000ffffffffffffffffffffffffffff/requirements.txt',
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/server.py'])
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/server.py',
'/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/openerp/tools/config.py'
])
if file == '/tmp/runbot_test/static/sources/bar/dfdfcfcf0000ffffffffffffffffffffffffffff/requirements.txt':
return False
return True
mock_is_file.side_effect = is_file
mock_is_dir.return_value = True
mock_is_on_remote.return_value = True
self.patchers['isfile'].side_effect = is_file
repo_ent = self.env['runbot.repo'].create({
'name': 'bla@example.com:foo-ent/bar',
'server_files': '',
@ -229,7 +206,7 @@ class Test_Build(common.TransactionCase):
return 'dfdfcfcf0000ffffffffffffffffffffffffffff'
with patch('odoo.addons.runbot.models.repo.runbot_repo._git_rev_parse', new=rev_parse):
build = self.Build.create({
build = self.create_build({
'branch_id': enterprise_branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -243,7 +220,7 @@ class Test_Build(common.TransactionCase):
def test_build_config_from_branch_default(self):
"""test build config_id is computed from branch default config_id"""
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
@ -252,7 +229,7 @@ class Test_Build(common.TransactionCase):
def test_build_config_from_branch_testing(self):
"""test build config_id is computed from branch"""
self.branch.config_id = self.env.ref('runbot.runbot_build_config_default_no_run')
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
@ -261,7 +238,7 @@ class Test_Build(common.TransactionCase):
def test_build_from_branch_no_build(self):
"""test build is not even created when branch no_build is True"""
self.branch.no_build = True
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
@ -270,7 +247,7 @@ class Test_Build(common.TransactionCase):
def test_build_config_can_be_set(self):
"""test build config_id can be set to something different than the one on the branch"""
self.branch.config_id = self.env.ref('runbot.runbot_build_config_default')
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'config_id': self.env.ref('runbot.runbot_build_config_default_no_run').id
@ -280,7 +257,7 @@ class Test_Build(common.TransactionCase):
@patch('odoo.addons.runbot.models.build._logger')
def test_build_skip(self, mock_logger):
"""test build is skipped"""
build = self.Build.create({
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -289,7 +266,7 @@ class Test_Build(common.TransactionCase):
self.assertEqual(build.local_state, 'done')
self.assertEqual(build.local_result, 'skipped')
other_build = self.Build.create({
other_build = self.create_build({
'branch_id': self.branch.id,
'name': 'deadbeef0000ffffffffffffffffffffffffffff',
'port': '1234',
@ -302,13 +279,12 @@ class Test_Build(common.TransactionCase):
def test_ask_kill_duplicate(self):
""" Test that the _ask_kill method works on duplicate"""
#mock_is_on_remote.return_value = True
build1 = self.Build.create({
build1 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
build2 = self.Build.create({
build2 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
@ -320,30 +296,30 @@ class Test_Build(common.TransactionCase):
self.assertEqual(build1.local_result, 'skipped', 'A killed pending duplicate build should mark the real build as skipped')
def test_children(self):
build1 = self.Build.create({
build1 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
build1_1 = self.Build.create({
build1_1 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'parent_id': build1.id,
'hidden': True,
'extra_params': '2', # avoid duplicate
})
build1_2 = self.Build.create({
build1_2 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'parent_id': build1.id,
'extra_params': '3',
})
build1_1_1 = self.Build.create({
build1_1_1 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'parent_id': build1_1.id,
'extra_params': '4',
})
build1_1_2 = self.Build.create({
build1_1_2 = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'parent_id': build1_1.id,
@ -408,17 +384,17 @@ class Test_Build(common.TransactionCase):
assert_state(0, 0, 0, 'done', build1_1_2)
def test_duplicate_childrens(self):
build_old = self.Build.create({
build_old = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'extra_params': '0',
})
build_parent = self.Build.create({
build_parent = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'extra_params': '1',
})
build_child = self.Build.create({
build_child = self.create_build({
'branch_id': self.branch_10.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'parent_id': build_parent.id,
@ -431,7 +407,8 @@ class Test_Build(common.TransactionCase):
self.assertEqual(build_parent.nb_testing, 0)
self.assertEqual(build_parent.global_state, 'done')
class TestClosestBranch(common.TransactionCase):
class TestClosestBranch(RunbotCase):
def branch_description(self, branch):
branch_type = 'pull' if 'pull' in branch.name else 'branch'
@ -453,7 +430,7 @@ class TestClosestBranch(common.TransactionCase):
}
for b1, b2 in [(branch1, branch2), (branch2, branch1)]:
hash = '%s%s' % (b1.name, b2.name)
build1 = self.Build.create({
build1 = self.create_build({
'branch_id': b1.id,
'name': hash,
})
@ -461,7 +438,7 @@ class TestClosestBranch(common.TransactionCase):
if b1_closest:
self.assertClosest(b1, closest[b1])
build2 = self.Build.create({
build2 = self.create_build({
'branch_id': b2.id,
'name': hash,
})
@ -533,10 +510,10 @@ class TestClosestBranch(common.TransactionCase):
self.Build = self.env['runbot.build']
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_pr_is_duplicate(self, mock_github):
def test_pr_is_duplicate(self):
""" test PR is a duplicate of a dev branch build """
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
'head': {'label': 'odoo-dev:10.0-fix-thing-moc'},
'base': {'ref': '10.0'},
@ -553,10 +530,8 @@ class TestClosestBranch(common.TransactionCase):
})
self.assertDuplicate(dev_branch, pr)
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_closest_branch_01(self, mock_is_on_remote):
def test_closest_branch_01(self):
""" test find a matching branch in a target repo based on branch name """
mock_is_on_remote.return_value = True
self.Branch.create({
'repo_id': self.community_dev_repo.id,
@ -569,10 +544,10 @@ class TestClosestBranch(common.TransactionCase):
self.assertEqual((addons_branch, 'exact'), addons_branch._get_closest_branch(self.enterprise_dev_repo.id))
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_closest_branch_02(self, mock_github):
def test_closest_branch_02(self):
""" test find two matching PR having the same head name """
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
# "head label" is the repo:branch where the PR comes from
# "base ref" is the target of the PR
@ -601,13 +576,11 @@ class TestClosestBranch(common.TransactionCase):
})
self.assertEqual((community_branch, 'exact PR'), enterprise_pr._get_closest_branch(self.community_repo.id))
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_closest_branch_02_improved(self, mock_is_on_remote, mock_github):
def test_closest_branch_02_improved(self):
""" test that a PR in enterprise with a matching PR in Community
uses the matching one"""
mock_is_on_remote.return_value = True
mock_github = self.patchers['github_patcher']
com_dev_branch = self.Branch.create({
'repo_id': self.community_dev_repo.id,
@ -656,22 +629,18 @@ class TestClosestBranch(common.TransactionCase):
(com_dev_branch, 'exact PR')
)
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_closest_branch_03(self, mock_is_on_remote):
def test_closest_branch_03(self):
""" test find a branch based on dashed prefix"""
mock_is_on_remote.return_value = True
addons_branch = self.Branch.create({
'repo_id': self.enterprise_dev_repo.id,
'name': 'refs/heads/10.0-fix-blah-blah-moc'
})
self.assertEqual((self.branch_odoo_10, 'prefix'), addons_branch._get_closest_branch(self.community_repo.id))
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_closest_branch_03_05(self, mock_is_on_remote, mock_github):
def test_closest_branch_03_05(self):
""" test that a PR in enterprise without a matching PR in Community
and no branch in community"""
mock_is_on_remote.return_value = True
mock_github = self.patchers['github_patcher']
# comm_repo = self.repo
# self.repo.write({'token': 1})
@ -715,12 +684,10 @@ class TestClosestBranch(common.TransactionCase):
(com_branch, 'prefix'),
)
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_closest_branch_04(self, mock_is_on_remote, mock_github):
def test_closest_branch_04(self):
""" test that a PR in enterprise without a matching PR in Community
uses the corresponding exact branch in community"""
mock_is_on_remote.return_value = True
mock_github = self.patchers['github_patcher']
com_dev_branch = self.Branch.create({
'repo_id': self.community_dev_repo.id,
@ -753,9 +720,9 @@ class TestClosestBranch(common.TransactionCase):
(com_dev_branch, 'no PR')
)
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_closest_branch_05(self, mock_github):
def test_closest_branch_05(self):
""" test last resort value """
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
'head': {'label': 'foo-dev:bar_branch'},
'base': {'ref': '10.0'},
@ -786,10 +753,8 @@ class TestClosestBranch(common.TransactionCase):
})
self.assertEqual((self.branch_odoo_master, 'default'), addons_branch._get_closest_branch(self.community_repo.id))
@patch('odoo.addons.runbot.models.branch.runbot_branch._is_on_remote')
def test_no_duplicate_update(self, mock_is_on_remote):
def test_no_duplicate_update(self):
"""push a dev branch in enterprise with same head as sticky, but with a matching branch in community"""
mock_is_on_remote.return_value = True
community_sticky_branch = self.Branch.create({
'repo_id': self.community_repo.id,
'name': 'refs/heads/saas-12.2',
@ -811,7 +776,7 @@ class TestClosestBranch(common.TransactionCase):
# we shouldn't have duplicate since community_dev_branch exists
with patch('odoo.addons.runbot.models.repo.runbot_repo._git_rev_parse', new=rev_parse):
# lets create an old enterprise build
self.Build.create({
self.create_build({
'branch_id': enterprise_sticky_branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})
@ -822,9 +787,9 @@ class TestClosestBranch(common.TransactionCase):
(community_dev_branch, 'exact'),
)
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_external_pr_closest_branch(self, mock_github):
def test_external_pr_closest_branch(self):
""" test last resort value target_name"""
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
'head': {'label': 'external_repo:11.0-fix'},
'base': {'ref': '11.0'},
@ -838,9 +803,9 @@ class TestClosestBranch(common.TransactionCase):
closest_branch = enterprise_pr._get_closest_branch(dependency_repo.id)
self.assertEqual(enterprise_pr._get_closest_branch(dependency_repo.id), (self.branch_odoo_11, 'pr_target'))
@patch('odoo.addons.runbot.models.repo.runbot_repo._github')
def test_external_pr_with_comunity_pr_closest_branch(self, mock_github):
def test_external_pr_with_comunity_pr_closest_branch(self):
""" test matching external pr """
mock_github = self.patchers['github_patcher']
mock_github.return_value = {
'head': {'label': 'external_dev_repo:11.0-fix'},
'base': {'ref': '11.0'},
@ -860,7 +825,7 @@ class TestClosestBranch(common.TransactionCase):
'name': 'refs/pull/123'
})
with patch('odoo.addons.runbot.models.repo.runbot_repo._git_rev_parse', new=rev_parse):
build = self.Build.create({
build = self.create_build({
'branch_id': enterprise_pr.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
})

View File

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*-
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
class TestBuildConfigStep(common.TransactionCase):
class TestBuildConfigStep(RunbotCase):
def setUp(self):
super(TestBuildConfigStep, self).setUp()
self.Repo = self.env['runbot.repo']
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
self.Branch = self.env['runbot.branch']
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar', 'server_files': 'server.py'})
self.branch = self.Branch.create({
'repo_id': self.repo.id,
'name': 'refs/heads/master'
@ -31,6 +29,9 @@ class TestBuildConfigStep(common.TransactionCase):
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',
})
self.start_patcher('_local_pg_createdb', 'odoo.addons.runbot.models.build.runbot_build._local_pg_createdb', True)
self.start_patcher('_get_py_version', 'odoo.addons.runbot.models.build.runbot_build._get_py_version', 3)
def test_config_step_create_results(self):
""" Test child builds are taken into account"""
@ -81,50 +82,48 @@ class TestBuildConfigStep(common.TransactionCase):
self.assertFalse(self.parent_build.global_result)
@patch('odoo.addons.runbot.models.build.runbot_build._local_pg_createdb')
@patch('odoo.addons.runbot.models.build.runbot_build._get_server_info')
@patch('odoo.addons.runbot.models.build.runbot_build._get_addons_path')
@patch('odoo.addons.runbot.models.build.runbot_build._get_py_version')
@patch('odoo.addons.runbot.models.build.runbot_build._server')
@patch('odoo.addons.runbot.models.build.runbot_build._checkout')
@patch('odoo.addons.runbot.models.build_config.docker_run')
def test_coverage(self, mock_docker_run, mock_checkout, mock_server, mock_get_py_version, mock_get_addons_path, mock_get_server_info, mock_local_pg_createdb):
def test_coverage(self, mock_checkout):
config_step = self.ConfigStep.create({
'name': 'coverage',
'job_type': 'install_odoo',
'coverage': True
})
mock_checkout.return_value = {}
mock_server.return_value = 'bar'
mock_get_py_version.return_value = '3'
mock_get_addons_path.return_value = ['bar/addons']
mock_get_server_info.return_value = (self.parent_build._get_all_commit()[0], 'server.py')
mock_local_pg_createdb.return_value = True
def docker_run(cmd, log_path, build_dir, *args, **kwargs):
cmds = cmd.split(' && ')
self.assertEqual(cmds[0], 'sudo pip3 install -r bar/requirements.txt')
self.assertEqual(cmds[1].split(' bar/server.py')[0], 'python3 -m coverage run --branch --source /data/build --omit *__manifest__.py')
self.assertEqual(cmds[2].split(' ; ')[0], 'python3 -m coverage html -d /data/build/coverage --ignore-errors')
self.assertEqual(cmds[2].split(' ; ')[1], 'pg_dump %s-coverage > /data/build/logs/%s-coverage//dump.sql' % (self.parent_build.dest, self.parent_build.dest))
def docker_run(cmd, log_path, *args, **kwargs):
cmds = cmd.build().split(' && ')
dest = self.parent_build.dest
self.assertEqual(cmd.pres, [['sudo', 'pip3', 'install', '-r', 'bar/requirements.txt']])
self.assertEqual(cmd.cmd[:10], ['python3', '-m', 'coverage', 'run', '--branch', '--source', '/data/build', '--omit', '*__manifest__.py', 'bar/server.py'])
#['bar/server.py', '--addons-path', 'bar', '--no-xmlrpcs', '--no-netrpc', '-d', '08732-master-d0d0ca-coverage', '--test-enable', '--stop-after-init', '--log-level=test', '--max-cron-threads=0']
self.assertEqual(cmd.posts, [['python3', '-m', 'coverage', 'html', '-d', '/data/build/coverage', '--ignore-errors']])
self.assertEqual(log_path, 'dev/null/logpath')
mock_docker_run.side_effect = docker_run
self.patchers['docker_run'].side_effect = docker_run
config_step._run_odoo_install(self.parent_build, 'dev/null/logpath')
@patch('odoo.addons.runbot.models.build.runbot_build._checkout')
def test_dump(self, mock_checkout):
config_step = self.ConfigStep.create({
'name': 'all',
'job_type': 'install_odoo',
})
def docker_run(cmd, log_path, *args, **kwargs):
dest = self.parent_build.dest
self.assertEqual(cmd.cmd[:2], ['python3', 'bar/server.py'])
self.assertEqual(cmd.finals[0], ['pg_dump', '%s-all' % dest, '>', '/data/build/logs/%s-all//dump.sql' % dest])
self.assertEqual(cmd.finals[1], ['cp', '-r', '/data/build/datadir/filestore/%s-all' % dest, '/data/build/logs/%s-all//filestore/' % dest])
self.assertEqual(cmd.finals[2], ['cd', '/data/build/logs/%s-all/' % dest, '&&', 'zip', '-rmq9', '/data/build/logs/%s-all.zip' % dest, '*'])
self.assertEqual(log_path, 'dev/null/logpath')
self.patchers['docker_run'].side_effect = docker_run
config_step._run_odoo_install(self.parent_build, 'dev/null/logpath')
@patch('odoo.addons.runbot.models.build.runbot_build._local_pg_createdb')
@patch('odoo.addons.runbot.models.build.runbot_build._get_server_info')
@patch('odoo.addons.runbot.models.build.runbot_build._get_addons_path')
@patch('odoo.addons.runbot.models.build.runbot_build._get_py_version')
@patch('odoo.addons.runbot.models.build.runbot_build._server')
@patch('odoo.addons.runbot.models.build.runbot_build._checkout')
@patch('odoo.addons.runbot.models.build_config.docker_run')
@patch('odoo.addons.runbot.models.build_config.grep')
def test_install_tags(self, mock_grep, mock_docker_run, mock_checkout, mock_server, mock_get_py_version, mock_get_addons_path, mock_get_server_info, mock_local_pg_createdb):
def test_install_tags(self, mock_checkout):
config_step = self.ConfigStep.create({
'name': 'all',
'job_type': 'install_odoo',
@ -137,29 +136,22 @@ class TestBuildConfigStep(common.TransactionCase):
'test_tags': ':otherclass.othertest'
})
mock_checkout.return_value = {}
mock_server.return_value = 'bar'
mock_get_py_version.return_value = '3'
mock_get_addons_path.return_value = ['bar/addons']
mock_get_server_info.return_value = (self.parent_build._get_all_commit()[0], 'server.py')
mock_local_pg_createdb.return_value = True
mock_grep.return_value = True
def docker_run(cmd, log_path, build_dir, *args, **kwargs):
cmds = cmd.split(' && ')
def docker_run(cmd, *args, **kwargs):
cmds = cmd.build().split(' && ')
self.assertEqual(cmds[1].split(' bar/server.py')[0], 'python3')
tags = cmds[1].split('--test-tags ')[1].split(' ')[0]
self.assertEqual(tags, '/module,:class.method')
mock_docker_run.side_effect = docker_run
self.patchers['docker_run'].side_effect = docker_run
config_step._run_odoo_install(self.parent_build, 'dev/null/logpath')
config_step.enable_auto_tags =True
def docker_run(cmd, log_path, build_dir, *args, **kwargs):
cmds = cmd.split(' && ')
config_step.enable_auto_tags = True
def docker_run2(cmd, *args, **kwargs):
cmds = cmd.build().split(' && ')
self.assertEqual(cmds[1].split(' bar/server.py')[0], 'python3')
tags = cmds[1].split('--test-tags ')[1].split(' ')[0]
self.assertEqual(tags, '/module,:class.method,-:otherclass.othertest')
mock_docker_run.side_effect = docker_run
self.patchers['docker_run'].side_effect = docker_run2
config_step._run_odoo_install(self.parent_build, 'dev/null/logpath')

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
RTE_ERROR = """FAIL: TestUiTranslate.test_admin_tour_rte_translator
Traceback (most recent call last):
@ -14,9 +15,10 @@ AssertionError: The test code "odoo.startTour('rte_translator')" failed
Tour rte_translator failed at step click language dropdown (trigger: .js_language_selector .dropdown-toggle)
"""
class TestBuildError(common.TransactionCase):
def create_build(self, vals):
class TestBuildError(RunbotCase):
def create_test_build(self, vals):
create_vals = {
'branch_id': self.branch.id,
'name': 'deadbeaf0000ffffffffffffffffffffffffffff',
@ -24,11 +26,10 @@ class TestBuildError(common.TransactionCase):
'local_result': 'ok'
}
create_vals.update(vals)
return self.Build.create(create_vals)
return self.create_build(create_vals)
@patch('odoo.addons.runbot.models.build.runbot_build._get_params')
def setUp(self, mock_get_params):
def setUp(self):
super(TestBuildError, self).setUp()
repo = self.env['runbot.repo'].create({'name': 'bla@example.com:foo/bar'})
self.branch = self.env['runbot.branch'].create({
@ -36,14 +37,12 @@ class TestBuildError(common.TransactionCase):
'name': 'refs/heads/master'
})
self.Build = self.env['runbot.build']
self.BuildError = self.env['runbot.build.error']
@patch('odoo.addons.runbot.models.build.runbot_build._get_params')
def test_build_scan(self, mock_get_params):
def test_build_scan(self):
IrLog = self.env['ir.logging']
ko_build = self.create_build({'local_result': 'ko'})
ok_build = self.create_build({'local_result': 'ok'})
ko_build = self.create_test_build({'local_result': 'ko'})
ok_build = self.create_test_build({'local_result': 'ok'})
log = {'message': RTE_ERROR,
'build_id': ko_build.id,
@ -66,24 +65,24 @@ class TestBuildError(common.TransactionCase):
self.assertFalse(self.BuildError.search([('build_ids','in', [ok_build.id])]), 'A successful build should not associated to a runbot.build.error')
# Test that build with same error is added to the errors
ko_build_same_error = self.create_build({'local_result': 'ko'})
ko_build_same_error = self.create_test_build({'local_result': 'ko'})
log.update({'build_id': ko_build_same_error.id})
IrLog.create(log)
ko_build_same_error._parse_logs()
self.assertIn(ko_build_same_error, build_error.build_ids, 'The parsed build should be added to the existing runbot.build.error')
# Test that line numbers does not interfere with error recognition
ko_build_diff_number = self.create_build({'local_result': 'ko'})
ko_build_diff_number = self.create_test_build({'local_result': 'ko'})
rte_diff_numbers = RTE_ERROR.replace('89','100').replace('1062','1000').replace('1046', '4610')
log.update({'build_id': ko_build_diff_number.id, 'message': rte_diff_numbers})
IrLog.create(log)
ko_build_diff_number._parse_logs()
self.assertIn(ko_build_diff_number, build_error.build_ids, 'The parsed build with different line numbers in error should be added to the runbot.build.error')
# Test that when an error re-appears after the bug has been fixed,
# a new build error is created, with the old one linked
build_error.active = False
ko_build_new = self.create_build({'local_result': 'ko'})
ko_build_new = self.create_test_build({'local_result': 'ko'})
log.update({'build_id': ko_build_new.id})
IrLog.create(log)
ko_build_new._parse_logs()
@ -92,10 +91,9 @@ class TestBuildError(common.TransactionCase):
self.assertIn(ko_build_new, new_build_error.build_ids, 'The parsed build with a re-apearing error should generate a new runbot.build.error')
self.assertIn(build_error, new_build_error.error_history_ids, 'The old error should appear in history')
@patch('odoo.addons.runbot.models.build.runbot_build._get_params')
def test_build_error_links(self, mock_get_params):
build_a = self.create_build({'local_result': 'ko'})
build_b = self.create_build({'local_result': 'ko'})
def test_build_error_links(self):
build_a = self.create_test_build({'local_result': 'ko'})
build_b = self.create_test_build({'local_result': 'ko'})
error_a = self.env['runbot.build.error'].create({
'content': 'foo',

View File

@ -1,13 +1,14 @@
# -*- coding: utf-8 -*-
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
class Test_Cron(common.TransactionCase):
class Test_Cron(RunbotCase):
def setUp(self):
super(Test_Cron, self).setUp()
self.Repo = self.env['runbot.repo']
self.start_patcher('_get_cron_period', 'odoo.addons.runbot.models.repo.runbot_repo._get_cron_period', 2)
@patch('odoo.addons.runbot.models.repo.config.get')
def test_cron_period(self, mock_config_get):
@ -19,53 +20,43 @@ class Test_Cron(common.TransactionCase):
for i in range(200):
self.assertLess(period, 400)
@patch('odoo.addons.runbot.models.repo.fqdn')
def test_crons_returns(self, mock_fqdn):
def test_crons_returns(self):
""" test that cron_fetch_and_schedule and _cron_fetch_and_build
return directly when called on wrong host
"""
mock_fqdn.return_value = 'runboty.foo.com'
ret = self.Repo._cron_fetch_and_schedule('runbotx.foo.com')
self.assertEqual(ret, 'Not for me')
ret = self.Repo._cron_fetch_and_build('runbotx.foo.com')
self.assertEqual(ret, 'Not for me')
@patch('odoo.addons.runbot.models.repo.runbot_repo._get_cron_period')
@patch('odoo.addons.runbot.models.repo.runbot_repo._create_pending_builds')
@patch('odoo.addons.runbot.models.repo.runbot_repo._update')
@patch('odoo.addons.runbot.models.repo.fqdn')
def test_cron_schedule(self, mock_fqdn, mock_update, mock_create, mock_cron_period):
def test_cron_schedule(self, mock_update, mock_create):
""" test that cron_fetch_and_schedule do its work """
mock_fqdn.return_value = 'runbotx.foo.com'
mock_cron_period.return_value = 2
self.env['ir.config_parameter'].sudo().set_param('runbot.runbot_update_frequency', 1)
self.Repo.create({'name': '/path/somewhere/disabled.git', 'mode': 'disabled'}) # create a disabled
self.Repo.search([]).write({'mode': 'disabled'}) # disable all depo, in case we have existing ones
local_repo = self.Repo.create({'name': '/path/somewhere/rep.git'}) # create active repo
ret = self.Repo._cron_fetch_and_schedule('runbotx.foo.com')
ret = self.Repo._cron_fetch_and_schedule('host.runbot.com')
self.assertEqual(None, ret)
mock_update.assert_called_with(force=False)
mock_create.assert_called_with()
@patch('odoo.addons.runbot.models.host.fqdn')
@patch('odoo.addons.runbot.models.repo.runbot_repo._get_cron_period')
@patch('odoo.addons.runbot.models.repo.runbot_repo._reload_nginx')
@patch('odoo.addons.runbot.models.repo.runbot_repo._scheduler')
@patch('odoo.addons.runbot.models.repo.fqdn')
def test_cron_build(self, mock_fqdn, mock_scheduler, mock_reload, mock_cron_period, mock_host_fqdn):
def test_cron_build(self, mock_scheduler, mock_reload):
""" test that cron_fetch_and_build do its work """
hostname = 'runbotx.foo.com'
mock_fqdn.return_value = mock_host_fqdn.return_value = hostname
mock_cron_period.return_value = 2
hostname = 'host.runbot.com'
self.env['ir.config_parameter'].sudo().set_param('runbot.runbot_update_frequency', 1)
self.Repo.create({'name': '/path/somewhere/disabled.git', 'mode': 'disabled'}) # create a disabled
self.Repo.search([]).write({'mode': 'disabled'}) # disable all depo, in case we have existing ones
local_repo = self.Repo.create({'name': '/path/somewhere/rep.git'}) # create active repo
ret = self.Repo._cron_fetch_and_build('runbotx.foo.com')
ret = self.Repo._cron_fetch_and_build(hostname)
self.assertEqual(None, ret)
mock_scheduler.assert_called()
self.assertTrue(mock_reload.called)
host = self.env['runbot.host'].search([('name', '=', 'runbotx.foo.com')])
host = self.env['runbot.host'].search([('name', '=', hostname)])
self.assertEqual(host.name, hostname, 'A new host should have been created')
self.assertGreater(host.psql_conn_count, 0, 'A least one connection should exist on the current psql instance')

View File

@ -1,15 +1,14 @@
# -*- coding: utf-8 -*-
from unittest.mock import patch
from odoo.tests import common
from .common import RunbotCase
class TestIrLogging(common.TransactionCase):
class TestIrLogging(RunbotCase):
def setUp(self):
super(TestIrLogging, self).setUp()
self.Repo = self.env['runbot.repo']
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar', 'server_files': 'server.py', 'addons_paths': 'addons,core/addons'})
self.Branch = self.env['runbot.branch']
self.branch = self.Branch.create({
'repo_id': self.repo.id,
'name': 'refs/heads/master'
@ -26,10 +25,8 @@ class TestIrLogging(common.TransactionCase):
VALUES (NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s)
""", val)
@patch('odoo.addons.runbot.models.build.runbot_build._get_params')
@patch('odoo.addons.runbot.models.build.fqdn')
def test_ir_logging(self, mock_fqdn, mock_get_params):
build = self.Build.create({
def test_ir_logging(self):
build = self.create_build({
'branch_id': self.branch.id,
'name': 'd0d0caca0000ffffffffffffffffffffffffffff',
'port': '1234',

View File

@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
from itertools import cycle
from unittest.mock import patch
from werkzeug.wrappers import Response
from odoo.tests import common
from odoo.addons.runbot.controllers import frontend
from .common import RunbotCase
class Test_Frontend(common.HttpCase):
class Test_Frontend(RunbotCase):
def setUp(self):
super(Test_Frontend, self).setUp()

View File

@ -2,22 +2,22 @@
import datetime
from unittest import skip
from unittest.mock import patch, Mock
from odoo.tests import common
from odoo.tests import common, TransactionCase
import logging
import odoo
import time
import datetime
from .common import RunbotCase
_logger = logging.getLogger(__name__)
class Test_Repo(common.TransactionCase):
class Test_Repo(RunbotCase):
def setUp(self):
super(Test_Repo, self).setUp()
self.Repo = self.env['runbot.repo']
self.commit_list = []
self.mock_root = self.patchers['repo_root_patcher']
def mock_git_helper(self):
"""Helper that returns a mock for repo._git()"""
@ -26,9 +26,8 @@ class Test_Repo(common.TransactionCase):
return '\n'.join(['\0'.join(commit_fields) for commit_fields in self.commit_list])
return mock_git
@patch('odoo.addons.runbot.models.repo.runbot_repo._root')
def test_base_fields(self, mock_root):
mock_root.return_value = '/tmp/static'
def test_base_fields(self):
self.mock_root.return_value = '/tmp/static'
repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
self.assertEqual(repo.path, '/tmp/static/repo/bla_example.com_foo_bar')
@ -41,13 +40,12 @@ class Test_Repo(common.TransactionCase):
local_repo = self.Repo.create({'name': '/path/somewhere/rep.git'})
self.assertEqual(local_repo.short_name, 'somewhere/rep')
@patch('odoo.addons.runbot.models.repo.runbot_repo._root')
@patch('odoo.addons.runbot.models.repo.runbot_repo._get_fetch_head_time')
def test_repo_create_pending_builds(self, mock_fetch_head_time, mock_root):
def test_repo_create_pending_builds(self, mock_fetch_head_time):
""" Test that when finding new refs in a repo, the missing branches
are created and new builds are created in pending state
"""
mock_root.return_value = '/tmp/static'
self.mock_root.return_value = '/tmp/static'
repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
# create another repo and branch to ensure there is no mismatch
@ -152,8 +150,7 @@ class Test_Repo(common.TransactionCase):
@skip('This test is for performances. It needs a lot of real branches in DB to mean something')
@patch('odoo.addons.runbot.models.repo.runbot_repo._root')
def test_repo_perf_find_new_commits(self, mock_root):
def test_repo_perf_find_new_commits(self):
mock_root.return_value = '/tmp/static'
repo = self.env['runbot.repo'].search([('name', '=', 'blabla')])
@ -179,9 +176,11 @@ class Test_Repo(common.TransactionCase):
_logger.info('Create pending builds took: %ssec', (time.time() - inserted_time))
class Test_Github(TransactionCase):
def test_github(self):
""" Test different github responses or failures"""
repo = self.Repo.create({'name': 'bla@example.com:foo/foo'})
repo = self.env['runbot.repo'].create({'name': 'bla@example.com:foo/foo'})
self.assertEqual(repo._github('/repos/:owner/:repo/statuses/abcdef', dict(), ignore_errors=True), None, 'A repo without token should return None')
repo.token = 'abc'
with patch('odoo.addons.runbot.models.repo.requests.Session') as mock_session:
@ -204,22 +203,23 @@ class Test_Repo(common.TransactionCase):
self.assertEqual(2, mock_session.return_value.post.call_count, "_github method should try two times by default")
class Test_Repo_Scheduler(common.TransactionCase):
@patch('odoo.addons.runbot.models.repo.runbot_repo._root')
def setUp(self, mock_root):
class Test_Repo_Scheduler(RunbotCase):
def setUp(self ):
# as the _scheduler method commits, we need to protect the database
registry = odoo.registry()
registry.enter_test_mode()
self.addCleanup(registry.leave_test_mode)
super(Test_Repo_Scheduler, self).setUp()
self.fqdn_patcher = patch('odoo.addons.runbot.models.host.fqdn')
mock_root = self.patchers['repo_root_patcher']
mock_root.return_value = '/tmp/static'
self.Repo_model = self.env['runbot.repo']
self.Branch_model = self.env['runbot.branch']
self.foo_repo = self.Repo_model.create({'name': 'bla@example.com:foo/bar'})
self.foo_branch = self.Branch_model.create({
self.foo_repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
self.foo_branch = self.Branch.create({
'repo_id': self.foo_repo.id,
'name': 'refs/head/foo'
})
@ -227,26 +227,23 @@ class Test_Repo_Scheduler(common.TransactionCase):
@patch('odoo.addons.runbot.models.build.runbot_build._reap')
@patch('odoo.addons.runbot.models.build.runbot_build._kill')
@patch('odoo.addons.runbot.models.build.runbot_build._schedule')
@patch('odoo.addons.runbot.models.host.fqdn')
def test_repo_scheduler(self, mock_fqdn, mock_schedule, mock_kill, mock_reap):
mock_fqdn.return_value = 'test_host'
def test_repo_scheduler(self, mock_schedule, mock_kill, mock_reap):
self.env['ir.config_parameter'].set_param('runbot.runbot_workers', 6)
Build_model = self.env['runbot.build']
builds = []
# create 6 builds that are testing on the host to verify that
# workers are not overfilled
for build_name in ['a', 'b', 'c', 'd', 'e', 'f']:
build = Build_model.create({
build = self.create_build({
'branch_id': self.foo_branch.id,
'name': build_name,
'port': '1234',
'build_type': 'normal',
'local_state': 'testing',
'host': 'test_host'
'host': 'host.runbot.com'
})
builds.append(build)
# now the pending build that should stay unasigned
scheduled_build = Build_model.create({
scheduled_build = self.create_build({
'branch_id': self.foo_branch.id,
'name': 'sched_build',
'port': '1234',
@ -255,7 +252,7 @@ class Test_Repo_Scheduler(common.TransactionCase):
})
builds.append(scheduled_build)
# create the build that should be assigned once a slot is available
build = Build_model.create({
build = self.create_build({
'branch_id': self.foo_branch.id,
'name': 'foobuild',
'port': '1234',
@ -272,10 +269,10 @@ class Test_Repo_Scheduler(common.TransactionCase):
self.assertFalse(scheduled_build.host)
# give some room for the pending build
Build_model.search([('name', '=', 'a')]).write({'local_state': 'done'})
self.Build.search([('name', '=', 'a')]).write({'local_state': 'done'})
self.foo_repo._scheduler()
build.invalidate_cache()
scheduled_build.invalidate_cache()
self.assertEqual(build.host, 'test_host')
self.assertEqual(build.host, 'host.runbot.com')
self.assertFalse(scheduled_build.host)

View File

@ -3,9 +3,10 @@ import datetime
from unittest.mock import patch
from odoo.tests import common
import odoo
from .common import RunbotCase
class TestSchedule(common.TransactionCase):
class TestSchedule(RunbotCase):
def setUp(self):
# entering test mode to avoid that the _schedule method commits records
@ -13,19 +14,16 @@ class TestSchedule(common.TransactionCase):
registry.enter_test_mode()
self.addCleanup(registry.leave_test_mode)
super(TestSchedule, self).setUp()
self.Repo = self.env['runbot.repo']
self.repo = self.Repo.create({'name': 'bla@example.com:foo/bar'})
self.Branch = self.env['runbot.branch']
self.branch = self.Branch.create({
'repo_id': self.repo.id,
'name': 'refs/heads/master'
})
self.Build = self.env['runbot.build']
@patch('odoo.addons.runbot.models.build.os.makedirs')
@patch('odoo.addons.runbot.models.build.os.path.getmtime')
@patch('odoo.addons.runbot.models.build.docker_is_running')
def test_schedule_mark_done(self, mock_running, mock_getmtime, mock_makedirs):
def test_schedule_mark_done(self, mock_running, mock_getmtime):
""" Test that results are set even when job_30_run is skipped """
job_end_time = datetime.datetime.now()
mock_getmtime.return_value = job_end_time.timestamp()