def testKickTestPlan_withError(self, create_test_run, set_test_run_state):
    """Tests that errors are handled when kicking off a test plan."""
    test = ndb_models.Test(id='test_id')
    test_run_config = ndb_models.TestRunConfig(
        test_key=test.key, cluster='cluster', run_target='run_target')
    test_plan = ndb_models.TestPlan(
        name='test_plan', test_run_configs=[test_run_config, test_run_config])
    test_plan.put()
    # First test run created successfully, but second fails even with retries
    test_run = ndb_models.TestRun(id='test_run_id')
    create_test_run.side_effect = (
        [test_run] +
        test_plan_kicker.MAX_RETRY_COUNT * [RuntimeError('test_run_error')])

    # Retries a few times before canceling test run and raising exception
    with self.assertRaises(RuntimeError):
      test_plan_kicker.KickTestPlan(test_plan.key.id())
    self.assertEqual(create_test_run.call_count,
                     1 + test_plan_kicker.MAX_RETRY_COUNT)
    set_test_run_state.assert_called_once_with('test_run_id',
                                               ndb_models.TestRunState.CANCELED)
    # Stores the canceled test run key and the error message
    status = ndb_models.TestPlanStatus.query(ancestor=test_plan.key).get()
    self.assertEqual(status.last_run_keys, [test_run.key])
    self.assertEqual(status.last_run_error, 'test_run_error')
예제 #2
0
def _CreateMockTestPlan(name, cron_exp='0 * * * *', test_run_configs=None):
    """Creates a mock test plan."""
    test_plan = ndb_models.TestPlan(name=name,
                                    cron_exp=cron_exp,
                                    test_run_configs=test_run_configs or [])
    test_plan.put()
    return test_plan
 def testScheduleCronKick_noCronExpression(self):
   """Tests that test plan without cron expressions do not get scheduled."""
   test_plan = ndb_models.TestPlan(name='test_plan')
   test_plan.put()
   test_plan_kicker.ScheduleCronKick(test_plan.key.id())
   # No tasks scheduled
   tasks = self.mock_task_scheduler.GetTasks(
       queue_names=[test_plan_kicker.TEST_PLAN_KICKER_QUEUE])
   self.assertEmpty(tasks)
 def testScheduleCronKick_invalidTimezone(self):
   """Tests that test plan with invalid timezones do not get scheduled."""
   test_plan = ndb_models.TestPlan(
       name='test_plan', cron_exp='0 0 * * *', cron_exp_timezone='INVALID')
   test_plan.put()
   test_plan_kicker.ScheduleCronKick(test_plan.key.id())
   # No tasks scheduled
   tasks = self.mock_task_scheduler.GetTasks(
       queue_names=[test_plan_kicker.TEST_PLAN_KICKER_QUEUE])
   self.assertEmpty(tasks)
  def testKickTestPlan_invalidTask(self):
    """Tests that a test plan kick is skipped if the task is invalid."""
    test_plan = ndb_models.TestPlan(name='test_plan')
    test_plan.put()
    ndb_models.TestPlanStatus(
        parent=test_plan.key, next_run_task_name='task_name').put()

    executed = test_plan_kicker.KickTestPlan(
        test_plan.key.id(), task_name='invalid_task_name')
    self.assertFalse(executed)
 def _CreateMockTestPlan(self,
                         configs,
                         device_action_keys=None,
                         test_resource_pipes=None):
     """Creates a mock ndb_models.TestPlan object."""
     test_plan = ndb_models.TestPlan(
         test_run_configs=configs,
         name='name',
         before_device_action_keys=device_action_keys,
         test_resource_pipes=test_resource_pipes)
     test_plan.put()
     return test_plan
  def testCheckTestPlanNextRuns(self, get_current_time, schedule_cron_kick):
    now = datetime.datetime(1970, 1, 1, 0, 30, 0)
    get_current_time.return_value = now
    test_plan = ndb_models.TestPlan(name='foo', cron_exp='0 0 * * *')
    test_plan.put()
    test_plan_status = ndb_models.TestPlanStatus(
        parent=test_plan.key,
        next_run_time=datetime.datetime(1970, 1, 1, 0, 0, 0))
    test_plan_status.put()

    test_plan_kicker.CheckTestPlanNextRuns()

    schedule_cron_kick.assert_called_with(test_plan.key.id(), next_run_time=now)
  def testKickTestPlan(self, create_test_run):
    """Tests that a test plan can be kicked off."""
    test = ndb_models.Test(id='test_id')
    test_device_action = ndb_models.DeviceAction(id='test_device_action')
    test_run_action = ndb_models.TestRunAction(id='test_run_action')
    # Create a test plan with multiple resources and actions
    test_plan = ndb_models.TestPlan(
        name='test_plan',
        labels=['label'],
        cron_exp='0 0 * * *',
        test_run_configs=[
            ndb_models.TestRunConfig(
                test_key=test.key,
                cluster='cluster',
                run_target='run_target',
                before_device_action_keys=[test_device_action.key],
                test_run_action_refs=[
                    ndb_models.TestRunActionRef(action_key=test_run_action.key),
                ],
                test_resource_objs=[
                    ndb_models.TestResourceObj(name='res_1', url='url_1')]),
        ])
    test_plan.put()
    # Test run will be created successfully
    test_run = ndb_models.TestRun(id='test_run_id')
    create_test_run.return_value = test_run

    executed = test_plan_kicker.KickTestPlan(test_plan.key.id())
    self.assertTrue(executed)

    # Test run is created with the right test and test plan components
    create_test_run.assert_called_with(
        labels=['label'],
        test_plan_key=test_plan.key,
        test_run_config=ndb_models.TestRunConfig(
            test_key=test.key,
            cluster='cluster',
            run_target='run_target',
            before_device_action_keys=[test_device_action.key],
            test_run_action_refs=[
                ndb_models.TestRunActionRef(action_key=test_run_action.key),
            ],
            test_resource_objs=[
                ndb_models.TestResourceObj(name='res_1', url='url_1')
            ]),
        )
    # Test run key is stored in the test plan status
    status = ndb_models.TestPlanStatus.query(ancestor=test_plan.key).get()
    self.assertEqual(status.last_run_keys, [test_run.key])
예제 #9
0
    def Get(self, request):
        """Fetches a test plan.

    Parameters:
      test_plan_id: Test plan ID, or zero for an empty test plan
    """
        if request.test_plan_id == '0':
            # For ID 0, return an empty test plan object to use as a template in UI.
            test_plan = ndb_models.TestPlan(id=0, name='')
        else:
            test_plan = mtt_messages.ConvertToKey(ndb_models.TestPlan,
                                                  request.test_plan_id).get()
        if not test_plan:
            raise endpoints.NotFoundException('No test plan with ID %s' %
                                              request.test_plan_id)
        return mtt_messages.Convert(test_plan, mtt_messages.TestPlan)
예제 #10
0
def _TestPlanMessageConverter(msg):
  return ndb_models.TestPlan(
      key=ConvertToKeyOrNone(ndb_models.TestPlan, getattr(msg, 'id')),
      name=msg.name,
      labels=msg.labels,
      cron_exp=msg.cron_exp,
      cron_exp_timezone=msg.cron_exp_timezone,
      test_run_configs=ConvertList(
          msg.test_run_configs, ndb_models.TestRunConfig),
      test_resource_pipes=ConvertList(
          msg.test_resource_pipes, ndb_models.TestResourcePipe),
      before_device_action_keys=[
          ConvertToKeyOrNone(ndb_models.DeviceAction, device_action_id)
          for device_action_id in msg.before_device_action_ids
      ],
      test_run_action_refs=ConvertList(
          msg.test_run_action_refs, ndb_models.TestRunActionRef))
  def testScheduleCronKick_withTimezone(self, get_current_time):
    """Tests that test plans can be scheduled relative to a timezone."""
    # Create test plan that runs every day at midnight in PT
    test_plan = ndb_models.TestPlan(
        name='test_plan',
        cron_exp='0 0 * * *',
        cron_exp_timezone='America/Los_Angeles')
    test_plan.put()
    # Current time is 12:30 AM UTC and next run time is midnight PT (8 AM UTC)
    get_current_time.return_value = datetime.datetime(1970, 1, 1, 0, 30, 0)
    next_run_time = pytz.UTC.localize(datetime.datetime(1970, 1, 1, 8, 0, 0))

    test_plan_kicker.ScheduleCronKick(test_plan.key.id())

    tasks = self.mock_task_scheduler.GetTasks(
        queue_names=[test_plan_kicker.TEST_PLAN_KICKER_QUEUE])
    self.assertLen(tasks, 1)
    self.assertEqual(next_run_time, tasks[0].eta)
  def testScheduleCronKick(self, get_current_time):
    """Tests that test plans can be scheduled."""
    # Create test plan that runs every day at midnight
    test_plan = ndb_models.TestPlan(name='test_plan', cron_exp='0 0 * * *')
    test_plan.put()
    test_plan_id = test_plan.key.id()
    # Current time is 12:30 AM UTC and next run time is the following midnight
    get_current_time.return_value = datetime.datetime(1970, 1, 1, 0, 30, 0)
    next_run_time = pytz.UTC.localize(datetime.datetime(1970, 1, 2, 0, 0, 0))

    test_plan_kicker.ScheduleCronKick(test_plan_id)

    tasks = self.mock_task_scheduler.GetTasks(
        queue_names=[test_plan_kicker.TEST_PLAN_KICKER_QUEUE])
    self.assertLen(tasks, 1)
    self.assertEqual(next_run_time, tasks[0].eta)
    data = json.loads(tasks[0].payload)
    self.assertEqual(test_plan_id, data['test_plan_id'])
 def setUp(self):
     super(TfcEventHandlerTest, self).setUp()
     self.mock_test = ndb_models.Test(name='test',
                                      command='command',
                                      result_file='result_file')
     self.mock_test.put()
     self.mock_test_plan = ndb_models.TestPlan(name='plan')
     self.mock_test_plan.put()
     self.mock_test_run = ndb_models.TestRun(
         test_plan_key=self.mock_test_plan.key,
         test_run_config=ndb_models.TestRunConfig(
             test_key=self.mock_test.key,
             run_target='run_target',
             command='mock test run command',
             retry_command='mock test run retry command'),
         test=self.mock_test,
         request_id='request_id',
         state=ndb_models.TestRunState.UNKNOWN)
     self.mock_test_run.put()
  def testKickTestPlan_withRetry(self, create_test_run):
    """Tests that a test plan kick operations can be retried."""
    test = ndb_models.Test(id='test_id')
    test_run_config = ndb_models.TestRunConfig(
        test_key=test.key, cluster='cluster', run_target='run_target')
    test_plan = ndb_models.TestPlan(
        name='test_plan', test_run_configs=[test_run_config])
    test_plan.put()
    # First test run creation fails, but second attempt succeeds
    test_run = ndb_models.TestRun(id='test_run_id')
    create_test_run.side_effect = [RuntimeError('test_run_error'), test_run]

    executed = test_plan_kicker.KickTestPlan(test_plan.key.id())
    self.assertTrue(executed)

    # Create test run operation retried until successful
    self.assertEqual(create_test_run.call_count, 2)
    status = ndb_models.TestPlanStatus.query(ancestor=test_plan.key).get()
    # Test run key stored and error message is empty
    self.assertEqual(status.last_run_keys, [test_run.key])
    self.assertIsNone(status.last_run_error)
 def testKickTestPlan_notFound(self):
   """Tests that a test plan kick is skipped if the plan is not found."""
   test_plan = ndb_models.TestPlan(id='unknown')
   executed = test_plan_kicker.KickTestPlan(test_plan.key.id())
   self.assertFalse(executed)