# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Unit tests for pw_software_update.remote_sign module."""

import os
from pathlib import Path
import tempfile
import textwrap
import unittest
from unittest import mock

from google.cloud.storage import Blob  # type: ignore
from google.cloud.storage.bucket import Bucket  # type: ignore

from pw_software_update import remote_sign

# inclusive-language: disable
FAKE_BUILDER_KEY = textwrap.dedent("""\
    -----BEGIN RSA PRIVATE KEY-----
    MIIEpAIBAAKCAQEA4qEQSHM0QpWEhTvhWMBahS7wbTIihaiRpUQC8+hEkmHhoJQy
    zaNR3CKdYWnJ1bAjdBT1HTHznbYSBasFAUKPiB16K/akuKSPnwHG9OM6+8Psw7lt
    GLP2jP65HE4a8n9lGas399xIK4hxZJkV2BXocociXVEVB3nzzNk1AQZdJxik/ToL
    MYC2EKTu1kdt+OLl56/O1Mq9p8V7u2G1l8fqHtJi4Z34LzUzIoyFf7+bSmZBcHG1
    F/QdjbHb4temShDzptOM1VfXZchYTDVnbNsmR7TP2B857agog4rhqtVlPvHqFial
    WEU1WmAQz+oYqtRikUVWHq10SACxo6MFoM7LqQIDAQABAoIBAQCjrdoZyYLUGDLn
    G1FtDTgTesxQwWXnjNDsQMu1J2rnImSX2pE6rhtAV4u9QG9ys01X2I8Tr/EYVdh8
    WYE64LzTfR6ww+lCJjBIkjsEwVznWyEUV0bxEYEfYhWF2O9jdxkoyd2ZWXKSZnAn
    TN1W/LOui+UI6re6d5zatYGvpM4AnlMTmwcO5aPQqTZMBOqJQZgEgyyHH2DZpIRI
    L7dG/k9Y/ML4T+hSVvi84+NS7GyTajPtaNRoVnlwr9+QVKplIgT8ZSqAF7unBsmF
    +s/U+TCFKq0pOhamOVz8eVd/uusy0d7a2oomtKoIzcPd74J5KZMub8izmEOwp5TZ
    17rsBDuVAoGBAPJMv737tYf5T5ihwEJ84OWxq3qLwWSoNwezOF3iWi4r42+QoqsC
    F0dLlgTmsafNTwVP1ztoeGvvezXSUfKfMTjjaZDRB226gwW7+eZ0MbrVcEnI9wm5
    K9MOWut40KsoAHHGs5sLyAtIENwnPAkPQPwPxmEcUxJJZwI/Rq78zR1bAoGBAO9x
    fAi9M8VdbV3r/l1SnExRlTu2gp9Rv02Zy78HVOWEWdEn6mhG3to5mXsHNIQwLulQ
    jm/hBSme5g4xbSCL/qCqRkc1rRautq/W50G8h7S3+KFGdnzXdEYnEh4oh5t5PJtA
    LHWc2WhTe5bsBNwOR1xQ8bEm+V/lf4Fbq+jOcjZLAoGBALzKgDwPfApOf2512c/0
    bWeLYAlEC5PaXcZqJmlAjPOczsGG+Lg2EN1ET8fR2Gre1ctVwmZPqESxfFcbYS6i
    S0AAMajcteURhjVZmgWuU3E4DR3wsEurNDJm5QDEShKSQIZmRFtyepQPutNO3sBQ
    WloMEI5p+3AsMU7W7sQ5xbgxAoGABWwAbwI5xeJTs6jAXcSdHW1Lf8qmMo1bU5qD
    7pNv7LKOhhntSOcx7KcZPpvvKH8e0NGuKAJkZ4jdlLyxx+bjoSe556rjfHwATwMC
    wY5PVFxGGQDLdhA65cvEsUIhr/eS08EkQJWIpsAdMFGv2nvISeLbVjOXugAsXvWA
    cwkZtPkCgYBQJPRCGBz73lBFB16oYJR6AnC32nf0WbrnMLFwMejUrsTLN6M72axw
    bWFpW7rWV7ldSgxKJ6ucKWl78uUMUnkM+CGPt5WJiisZXM2X1Q8+V7fmdAtK/AFj
    /tbEFpftkCyIM1nGZwZ/ziPF4n5hzGGF6w/ZMWZkwFZlqxlejK9IfQ==
    -----END RSA PRIVATE KEY-----
""")

FAKE_BUILDER_PUBLIC_KEY = textwrap.dedent("""\
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4qEQSHM0QpWEhTvhWMBa
    hS7wbTIihaiRpUQC8+hEkmHhoJQyzaNR3CKdYWnJ1bAjdBT1HTHznbYSBasFAUKP
    iB16K/akuKSPnwHG9OM6+8Psw7ltGLP2jP65HE4a8n9lGas399xIK4hxZJkV2BXo
    cociXVEVB3nzzNk1AQZdJxik/ToLMYC2EKTu1kdt+OLl56/O1Mq9p8V7u2G1l8fq
    HtJi4Z34LzUzIoyFf7+bSmZBcHG1F/QdjbHb4temShDzptOM1VfXZchYTDVnbNsm
    R7TP2B857agog4rhqtVlPvHqFialWEU1WmAQz+oYqtRikUVWHq10SACxo6MFoM7L
    qQIDAQAB
    -----END PUBLIC KEY-----
""")

# inclusive-language: enable


# TODO(b/235240430): Improve unit test coverage.
class PathSigningTest(unittest.TestCase):
    """Tests the signing of bundles by path."""
    @classmethod
    def setUpClass(cls):
        cls.tempdir = tempfile.mkdtemp()

        cls.builder_key = Path(cls.tempdir) / 'fake_builder_key'
        cls.builder_key.write_text(FAKE_BUILDER_KEY)

        cls.builder_pub_key = Path(cls.tempdir) / 'fake_builder_pub_key.pem'
        cls.builder_pub_key.write_text(FAKE_BUILDER_PUBLIC_KEY)

        cls.bundle = Path(cls.tempdir) / 'fake_bundle'
        cls.bundle.write_bytes(b'FAKE BUNDLE CONTENTS\n')

    def test_bundle_blob_uploads(self):
        """Signing should upload the bundle, pub key, and signing request."""
        mock_blob = mock.create_autospec(Blob, instance=True)
        mock_blob.exists = mock.MagicMock(return_value=False)
        mock_in_bucket = mock.create_autospec(Bucket, instance=True)
        mock_in_bucket.blob = mock.MagicMock(return_value=mock_blob)
        mock_out_bucket = mock.create_autospec(Bucket, instance=True)
        mock_out_bucket.name = 'fake_out_bucket'
        client = remote_sign.RemoteSignClient(input_bucket=mock_in_bucket,
                                              output_bucket=mock_out_bucket)

        client.sign(self.bundle,
                    signing_key_name='fake_key',
                    builder_key=self.builder_key,
                    builder_public_key=self.builder_pub_key,
                    request_blob_name='signing_request.json',
                    timeout_s=0.1)

        mock_blob.upload_from_filename.assert_has_calls([
            mock.call(os.path.join(self.tempdir, 'fake_bundle')),
            mock.call(os.path.join(self.tempdir, 'fake_builder_pub_key.pem')),
        ],
                                                        any_order=True)
        mock_blob.upload_from_string.assert_called_once()


if __name__ == '__main__':
    unittest.main()
