#!/usr/bin/python #pylint: disable-msg=C0111 # Copyright (c) 2014 The Chromium OS 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 common from autotest_lib.client.common_lib import global_config from autotest_lib.client.common_lib.test_utils import unittest from autotest_lib.frontend import setup_django_environment from autotest_lib.frontend.afe import frontend_test_utils from autotest_lib.frontend.afe import models from autotest_lib.scheduler import rdb_testing_utils from autotest_lib.scheduler import scheduler_models from autotest_lib.scheduler.shard import shard_client class ShardClientIntegrationTest(rdb_testing_utils.AbstractBaseRDBTester, unittest.TestCase): """Integration tests for the shard_client.""" def setup_global_config(self): """Mock out global_config for shard client creation.""" global_config.global_config.override_config_value( 'SHARD', 'is_slave_shard', 'True') global_config.global_config.override_config_value( 'SHARD', 'shard_hostname', 'host1') def initialize_shard_client(self): self.setup_global_config() return shard_client.get_shard_client() def testCompleteStatusBasic(self): """Test that complete jobs are uploaded properly.""" client = self.initialize_shard_client() job = self.create_job(deps=set(['a']), shard_hostname=client.hostname) scheduler_models.initialize() hqe = scheduler_models.HostQueueEntry.fetch( where='job_id = %s' % job.id)[0] # This should set both the shard_id and the complete bit. hqe.set_status('Completed') # Only incomplete jobs should be in known ids. job_ids, host_ids = client._get_known_ids() assert(job_ids == []) # Jobs that have successfully gone through a set_status should # be ready for upload. jobs = client._get_jobs_to_upload() assert(job.id in [j.id for j in jobs]) def testOnlyShardId(self): """Test that setting only the shardid prevents the job from upload.""" client = self.initialize_shard_client() job = self.create_job(deps=set(['a']), shard_hostname=client.hostname) scheduler_models.initialize() hqe = scheduler_models.HostQueueEntry.fetch( where='job_id = %s' % job.id)[0] def _local_update_field(hqe, field_name, value): """Turns update_field on the complete field into a no-op.""" if field_name == 'complete': return models.HostQueueEntry.objects.filter(id=hqe.id).update( **{field_name: value}) setattr(hqe, field_name, value) self.god.stub_with(scheduler_models.HostQueueEntry, 'update_field', _local_update_field) # This should only update the shard_id. hqe.set_status('Completed') # Retrieve the hqe along an independent code path so we're assured of # freshness, then make sure it has shard=None and an unset complete bit. modified_hqe = self.db_helper.get_hqes(job_id=job.id)[0] assert(modified_hqe.id == hqe.id and modified_hqe.complete == 0 and modified_hqe.job.shard == None) # Make sure the job with a shard but without complete is still # in known_ids. job_ids, host_ids = client._get_known_ids() assert(set(job_ids) == set([job.id])) # Make sure the job with a shard but without complete is not # in uploaded jobs. jobs = client._get_jobs_to_upload() assert(jobs == []) def testHostSerialization(self): """Test simple host serialization.""" client = self.initialize_shard_client() host = self.db_helper.create_host(name='test_host') serialized_host = host.serialize() models.Host.objects.all().delete() models.Host.deserialize(serialized_host) models.Host.objects.get(hostname='test_host') def testUserExists(self): """Test user related race conditions.""" client = self.initialize_shard_client() user = self.db_helper.create_user(name='test_user') serialized_user = user.serialize() # Master sends a user with the same login but different id serialized_user['id'] = '3' models.User.deserialize(serialized_user) models.User.objects.get(id=3, login='test_user') # Master sends a user with the same id, different login serialized_user['login'] = 'fake_user' models.User.deserialize(serialized_user) models.User.objects.get(id=3, login='fake_user') # Master sends a new user user = self.db_helper.create_user(name='new_user') serialized_user = user.serialize() models.User.objects.all().delete() models.User.deserialize(serialized_user) models.User.objects.get(login='new_user')