# -*- coding: utf-8 -*-
# Copyright 2019 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.

"""Unittests for trigger_cr50_signing.py."""

from __future__ import print_function

import json

import mock

from chromite.scripts import trigger_cr50_signing as trigger
from chromite.api.gen.chromiumos import common_pb2
from chromite.api.gen.chromiumos import sign_image_pb2
from chromite.lib import cros_logging as logging
from chromite.lib import cros_test_lib

# pylint: disable=protected-access

class TestLaunchOne(cros_test_lib.RunCommandTempDirTestCase):
  """Tests for the LaunchOne function."""

  def setUp(self):
    self.log_info = self.PatchObject(logging, 'info')
    self.properties = {'keyset': 'test-keyest'}
    self.json_prop = json.dumps(self.properties)

  def testDryRunOnlyLogs(self):
    """Test that dry_run=True results in only a log message."""
    trigger.LaunchOne(True, 'chromeos/packaging/test', self.properties)
    self.assertEqual(0, self.rc.call_count)
    self.log_info.assert_called_once()

  def testCallsRun(self):
    """Test that dry_run=False calls run()."""
    trigger.LaunchOne(False, 'chromeos/packaging/test', self.properties)
    self.log_info.assert_not_called()
    self.assertEqual(
        [mock.call(
            ['bb', 'add', '-p', '@/dev/stdin', 'chromeos/packaging/test'],
            input=self.json_prop, log_output=True)],
        self.rc.call_args_list)


class TestMain(cros_test_lib.RunCommandTempDirTestCase):
  """Tests for the main function."""

  def setUp(self):
    self.log_error = self.PatchObject(logging, 'error')

  def testMinimal(self):
    """Test minimal instructions."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset']
    self.assertEqual(0, trigger.main(args))
    launch.assert_called_once_with(
        False, trigger.CR50_PRODUCTION_JOB, {
            'archive': 'gs://test/file.bin',
            'build_target': {'name': 'unknown'},
            'channel': common_pb2.CHANNEL_UNSPECIFIED,
            'cr50_instructions': {
                'target': sign_image_pb2.Cr50Instructions.UNSPECIFIED},
            'image_type': common_pb2.CR50_FIRMWARE,
            'keyset': 'test-keyset',
            'signer_type': sign_image_pb2.SIGNER_DEV})

  def testPropertiesCorrect(self):
    """Test minimal instructions."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    archive = 'gs://test/file.bin'
    keyset = 'keyset'
    channel = 'canary'
    build_target = 'board'
    target = 'prepvt'
    signer = 'production'
    image = 'cr50_firmware'

    args = ['--archive', archive, '--keyset', keyset, '--channel', channel,
            '--build-target', build_target, '--target', target,
            '--signer-type', signer, '--image-type', image]
    self.assertEqual(0, trigger.main(args))
    launch.assert_called_once_with(
        False, trigger.CR50_PRODUCTION_JOB, {
            'archive': archive,
            'build_target': {'name': build_target},
            'channel': trigger._channels[channel],
            'cr50_instructions': {'target': trigger._target_types[target]},
            'image_type': trigger._image_types[image],
            'keyset': keyset,
            'signer_type': trigger._signer_types[signer]})

  def testStaging(self):
    """Test --staging works."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--staging']
    self.assertEqual(0, trigger.main(args))
    launch.assert_called_once_with(
        False, trigger.CR50_STAGING_JOB, {
            'archive': 'gs://test/file.bin',
            'build_target': {'name': 'unknown'},
            'channel': common_pb2.CHANNEL_UNSPECIFIED,
            'cr50_instructions': {
                'target': sign_image_pb2.Cr50Instructions.UNSPECIFIED},
            'image_type': common_pb2.CR50_FIRMWARE,
            'keyset': 'test-keyset',
            'signer_type': sign_image_pb2.SIGNER_DEV})

  def testDryRun(self):
    """Test --dry-run works."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--dry-run']
    self.assertEqual(0, trigger.main(args))
    launch.assert_called_once_with(
        True, trigger.CR50_PRODUCTION_JOB, {
            'archive': 'gs://test/file.bin',
            'build_target': {'name': 'unknown'},
            'channel': common_pb2.CHANNEL_UNSPECIFIED,
            'cr50_instructions': {
                'target': sign_image_pb2.Cr50Instructions.UNSPECIFIED},
            'image_type': common_pb2.CR50_FIRMWARE,
            'keyset': 'test-keyset',
            'signer_type': sign_image_pb2.SIGNER_DEV})

  def testNodeLockedCatchesBadDeviceId(self):
    """Test --target node_locked catches bad --device-id."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--target', 'node_locked', '--device-id', '12345678-9ABCDEFG',
            '--dev01', '-1', '0x1234']
    self.assertEqual(1, trigger.main(args))
    launch.assert_not_called()
    self.assertEqual(1, self.log_error.call_count)

  def testNodeLockedRequiresDeviceId(self):
    """Test --target node_locked requires --device-id."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--target', 'node_locked']
    self.assertEqual(1, trigger.main(args))
    launch.assert_not_called()
    self.assertEqual(1, self.log_error.call_count)

  def testDeviceIdRequiresNodeLocked(self):
    """Test --device_id is rejected if not node_locked."""
    launch = self.PatchObject(trigger, 'LaunchOne')
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--target', 'general_release', '--dev01', '1', '0x1234']
    self.assertEqual(1, trigger.main(args))
    launch.assert_not_called()
    self.assertEqual(1, self.log_error.call_count)

  def testNodeLockedLaunchesMultiple(self):
    """Test --target node_locked launches multiple jobs."""
    # Do not mock LaunchOne, so that we can grab the input= passed to run().
    args = ['--archive', 'gs://test/file.bin', '--keyset', 'test-keyset',
            '--target', 'node_locked', '--dev01', '1', '0x1234',
            '--dev01', '2', '33']
    self.assertEqual(0, trigger.main(args))
    self.log_error.assert_not_called()
    expected_properties = [
        {'archive': 'gs://test/file.bin', 'build_target': {'name': 'unknown'},
         'channel': 0,
         'cr50_instructions': {'target': trigger._target_types['node_locked'],
                               'device_id': '00000001-00001234'},
         'signer_type': sign_image_pb2.SIGNER_DEV,
         'image_type': common_pb2.CR50_FIRMWARE, 'keyset': 'test-keyset'},
        {'archive': 'gs://test/file.bin', 'build_target': {'name': 'unknown'},
         'channel': 0,
         'cr50_instructions': {'target': trigger._target_types['node_locked'],
                               'device_id': '00000002-00000021'},
         'signer_type': sign_image_pb2.SIGNER_DEV,
         'image_type': common_pb2.CR50_FIRMWARE, 'keyset': 'test-keyset'}]
    # Check the calls in two parts, since we need to convert the json string
    # back to a dict.
    self.assertEqual(self.rc.call_args_list, [
        mock.call(
            ['bb', 'add', '-p', '@/dev/stdin', trigger.CR50_PRODUCTION_JOB],
            log_output=True, input=mock.ANY) for _ in expected_properties])
    self.assertEqual(
        expected_properties,
        [json.loads(x[1]['input']) for x in self.rc.call_args_list])
