# 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/update_bundle.py."""

from pathlib import Path
import tempfile
import unittest

from pw_software_update import update_bundle
from pw_software_update.tuf_pb2 import SignedRootMetadata, TargetsMetadata


class TargetsFromDirectoryTest(unittest.TestCase):
    """Test turning a directory into TUF targets."""
    def test_excludes(self):
        """Checks that excludes are excluded."""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            bar_path = temp_root / 'bar.bin'
            baz_path = temp_root / 'baz.bin'
            qux_path = temp_root / 'qux.exe'
            for path in (foo_path, bar_path, baz_path, qux_path):
                path.touch()

            targets = update_bundle.targets_from_directory(
                temp_root, exclude=(Path('foo.bin'), Path('baz.bin')))

            self.assertNotIn('foo.bin', targets)
            self.assertEqual(bar_path, targets['bar.bin'])
            self.assertNotIn('baz.bin', targets)
            self.assertEqual(qux_path, targets['qux.exe'])

    def test_excludes_and_remapping(self):
        """Checks that remapping works, even in combination with excludes."""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            bar_path = temp_root / 'bar.bin'
            baz_path = temp_root / 'baz.bin'
            qux_path = temp_root / 'qux.exe'
            remap_paths = {
                Path('foo.bin'): 'main',
                Path('bar.bin'): 'backup',
                Path('baz.bin'): 'tertiary',
            }
            for path in (foo_path, bar_path, baz_path, qux_path):
                path.touch()

            targets = update_bundle.targets_from_directory(
                temp_root,
                exclude=(Path('qux.exe'), ),
                remap_paths=remap_paths)

            self.assertEqual(foo_path, targets['main'])
            self.assertEqual(bar_path, targets['backup'])
            self.assertEqual(baz_path, targets['tertiary'])
            self.assertNotIn('qux.exe', targets)

    def test_incomplete_remapping_logs(self):
        """Checks that incomplete remappings log warnings."""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            bar_path = temp_root / 'bar.bin'
            foo_path.touch()
            bar_path.touch()
            remap_paths = {Path('foo.bin'): 'main'}

            with self.assertLogs(level='WARNING') as log:
                update_bundle.targets_from_directory(
                    temp_root,
                    exclude=(Path('qux.exe'), ),
                    remap_paths=remap_paths)

                self.assertIn('Some remaps defined, but not "bar.bin"',
                              log.output[0])

    def test_remap_of_missing_file(self):
        """Checks that remapping a missing file raises an error."""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            foo_path.touch()
            remap_paths = {
                Path('foo.bin'): 'main',
                Path('bar.bin'): 'backup',
            }

            with self.assertRaises(FileNotFoundError):
                update_bundle.targets_from_directory(temp_root,
                                                     remap_paths=remap_paths)


class GenUnsignedUpdateBundleTest(unittest.TestCase):
    """Test the generation of unsigned update bundles."""
    def test_bundle_generation(self):
        """Tests basic creation of an UpdateBundle."""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            bar_path = temp_root / 'bar.bin'
            baz_path = temp_root / 'baz.bin'
            qux_path = temp_root / 'subdir' / 'qux.exe'
            foo_bytes = b'\xf0\x0b\xa4'
            bar_bytes = b'\x0b\xa4\x99'
            baz_bytes = b'\xba\x59\x06'
            qux_bytes = b'\x8a\xf3\x12'
            foo_path.write_bytes(foo_bytes)
            bar_path.write_bytes(bar_bytes)
            baz_path.write_bytes(baz_bytes)
            (temp_root / 'subdir').mkdir()
            qux_path.write_bytes(qux_bytes)
            targets = {
                foo_path: 'foo',
                bar_path: 'bar',
                baz_path: 'baz',
                qux_path: 'qux',
            }
            serialized_root_metadata_bytes = b'\x12\x34\x56\x78'

            bundle = update_bundle.gen_unsigned_update_bundle(
                targets,
                targets_metadata_version=42,
                root_metadata=SignedRootMetadata(
                    serialized_root_metadata=serialized_root_metadata_bytes))

            self.assertEqual(foo_bytes, bundle.target_payloads['foo'])
            self.assertEqual(bar_bytes, bundle.target_payloads['bar'])
            self.assertEqual(baz_bytes, bundle.target_payloads['baz'])
            self.assertEqual(qux_bytes, bundle.target_payloads['qux'])
            targets_metadata = TargetsMetadata.FromString(
                bundle.targets_metadata['targets'].serialized_targets_metadata)
            self.assertEqual(targets_metadata.common_metadata.version, 42)
            self.assertEqual(serialized_root_metadata_bytes,
                             bundle.root_metadata.serialized_root_metadata)

    def test_persist_to_disk(self):
        """Tests persisting the TUF repo to disk for debugging"""
        with tempfile.TemporaryDirectory() as tempdir_name:
            temp_root = Path(tempdir_name)
            foo_path = temp_root / 'foo.bin'
            bar_path = temp_root / 'bar.bin'
            baz_path = temp_root / 'baz.bin'
            qux_path = temp_root / 'subdir' / 'qux.exe'
            foo_bytes = b'\xf0\x0b\xa4'
            bar_bytes = b'\x0b\xa4\x99'
            baz_bytes = b'\xba\x59\x06'
            qux_bytes = b'\x8a\xf3\x12'
            foo_path.write_bytes(foo_bytes)
            bar_path.write_bytes(bar_bytes)
            baz_path.write_bytes(baz_bytes)
            (temp_root / 'subdir').mkdir()
            qux_path.write_bytes(qux_bytes)
            targets = {
                foo_path: 'foo',
                bar_path: 'bar',
                baz_path: 'baz',
                qux_path: 'subdir/qux',
            }
            persist_path = temp_root / 'persisted'

            update_bundle.gen_unsigned_update_bundle(targets,
                                                     persist=persist_path)

            self.assertEqual(foo_bytes, (persist_path / 'foo').read_bytes())
            self.assertEqual(bar_bytes, (persist_path / 'bar').read_bytes())
            self.assertEqual(baz_bytes, (persist_path / 'baz').read_bytes())
            self.assertEqual(qux_bytes,
                             (persist_path / 'subdir' / 'qux').read_bytes())


class ParseTargetArgTest(unittest.TestCase):
    """Test the parsing of target argument strings."""
    def test_valid_arg(self):
        """Checks that valid remap strings are parsed correctly."""
        file_path, target_name = update_bundle.parse_target_arg(
            'foo.bin > main')

        self.assertEqual(Path('foo.bin'), file_path)
        self.assertEqual('main', target_name)

    def test_invalid_arg_raises(self):
        """Checks that invalid remap string raise an error."""
        with self.assertRaises(ValueError):
            update_bundle.parse_target_arg('foo.bin main')


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