#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 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.
# pylint: disable=unused-argument

"""Unit tests for ConfigFS data file generator."""

from __future__ import print_function

import functools
import json
import os
import struct
import subprocess
import tempfile
import configfs

from chromite.lib import cros_test_lib
from chromite.lib import osutils

this_dir = os.path.dirname(__file__)


def TestConfigs(*args):
  """Wrapper function for tests which use configs from libcros_config/

  Use like so:
  @TestConfigs('test.json', [any other files you want...])
  def testFoo(self, config_filename, config, output_dir):
    # do something!
    pass
  """
  def _Decorator(method):
    @functools.wraps(method)
    def _Wrapper(self):
      for filename in args:
        with open(os.path.join(this_dir, '../test_data', filename)) as f:
          config = json.load(f)

        with tempfile.TemporaryDirectory(prefix='test.') as output_dir:
          squashfs_img = os.path.join(output_dir, 'configfs.img')
          configfs.GenerateConfigFSData(config, squashfs_img)
          subprocess.run(['unsquashfs', squashfs_img], check=True,
                         cwd=output_dir, stdout=subprocess.PIPE)
          method(self, filename, config, output_dir)
    return _Wrapper
  return _Decorator


class ConfigFSTests(cros_test_lib.TestCase):
  """Tests for ConfigFS."""

  def testSerialize(self):
    self.assertEqual(configfs.Serialize(True), b'true')
    self.assertEqual(configfs.Serialize(False), b'false')
    self.assertEqual(configfs.Serialize(10), b'10')
    self.assertEqual(configfs.Serialize('hello💩'), b'hello\xf0\x9f\x92\xa9')
    self.assertEqual(configfs.Serialize(b'\xff\xff\xff'), b'\xff\xff\xff')

  @TestConfigs('test.json', 'test_arm.json')
  def testConfigV1FileStructure(self, filename, config, output_dir):
    def _CheckConfigRec(config, path):
      if isinstance(config, dict):
        iterator = config.items()
      elif isinstance(config, list):
        iterator = enumerate(config)
      else:
        self.assertTrue(os.path.isfile(path))
        self.assertEqual(osutils.ReadFile(path, mode='rb'),
                         configfs.Serialize(config))
        return
      self.assertTrue(os.path.isdir(path))
      for name, entry in iterator:
        childpath = os.path.join(path, str(name))
        _CheckConfigRec(entry, childpath)
    _CheckConfigRec(config, os.path.join(output_dir, 'squashfs-root/v1'))

  # TODO(jrosenth): remove once we've fully moved over to struct-based
  # identity.
  @TestConfigs('test.json', 'test_arm.json')
  def testConfigV1IdentityJson(self, filename, config, output_dir):
    identity_path = os.path.join(output_dir, 'squashfs-root/v1/identity.json')
    self.assertTrue(os.path.isfile(identity_path))
    with open(identity_path) as f:
      identity_data = json.load(f)
    for device_config, identity_config in zip(
        config['chromeos']['configs'], identity_data['chromeos']['configs']):
      self.assertEqual(set(identity_config.keys()), {'identity'})
      self.assertEqual(device_config['identity'], identity_config['identity'])

  def testConfigIdentityStructSizes(self):
    self.assertEqual(struct.calcsize(configfs.HEADER_FORMAT), 16)
    self.assertEqual(struct.calcsize(configfs.ENTRY_FORMAT), 16)

  @TestConfigs('test.json', 'test_arm.json')
  def testConfigIdentityV0(self, filename, config, output_dir):
    device_configs = config['chromeos']['configs']
    identity_path = os.path.join(output_dir, 'squashfs-root/identity.bin')
    identity_bin = osutils.ReadFile(identity_path, mode='rb')
    version, identity_type, entry_count = struct.unpack_from(
        configfs.HEADER_FORMAT, identity_bin)
    offset = struct.calcsize(configfs.HEADER_FORMAT)
    identity_type = configfs.IdentityType(identity_type)

    self.assertEqual(version, configfs.STRUCT_VERSION)
    if 'arm' in filename:
      self.assertEqual(identity_type, configfs.IdentityType.ARM)
    else:
      self.assertEqual(identity_type, configfs.IdentityType.X86)
    self.assertEqual(len(device_configs), entry_count)

    # Get an entry from the string table.
    def _GetString(offset):
      base = (struct.calcsize(configfs.HEADER_FORMAT)
              + struct.calcsize(configfs.ENTRY_FORMAT) * entry_count)
      string, _, _ = identity_bin[base + offset:].partition(b'\000')
      return string.decode('utf-8')

    for device in device_configs:
      flags, model_match_offset, sku_id, whitelabel_offset = struct.unpack_from(
          configfs.ENTRY_FORMAT, identity_bin, offset=offset)
      offset += struct.calcsize(configfs.ENTRY_FORMAT)

      if identity_type == configfs.IdentityType.X86:
        self.assertEqual(
            flags & configfs.EntryFlags.USES_FIRMWARE_NAME.value, 0)
      else:
        self.assertEqual(
            flags & configfs.EntryFlags.IS_X86_LEGACY_CUSTOMIZATION_ID.value, 0)

      if 'smbios-name-match' in device['identity']:
        self.assertEqual(flags & configfs.EntryFlags.HAS_SMBIOS_NAME.value,
                         configfs.EntryFlags.HAS_SMBIOS_NAME.value)
        self.assertEqual(identity_type, configfs.IdentityType.X86)
        self.assertEqual(_GetString(model_match_offset),
                         device['identity']['smbios-name-match'].lower())

      if 'device-tree-compatible-match' in device['identity']:
        self.assertEqual(identity_type, configfs.IdentityType.ARM)
        self.assertEqual(
            _GetString(model_match_offset),
            device['identity']['device-tree-compatible-match'].lower())

      if 'firmware-name' in device['identity']:
        self.assertEqual(flags & configfs.EntryFlags.USES_FIRMWARE_NAME.value,
                         configfs.EntryFlags.USES_FIRMWARE_NAME.value)
        self.assertEqual(identity_type, configfs.IdentityType.ARM)
        self.assertEqual(_GetString(model_match_offset),
                         device['identity']['firmware-name'].lower())
      else:
        self.assertEqual(
            flags & configfs.EntryFlags.USES_FIRMWARE_NAME.value, 0)

      if 'sku-id' in device['identity']:
        self.assertEqual(flags & configfs.EntryFlags.HAS_SKU_ID.value,
                         configfs.EntryFlags.HAS_SKU_ID.value)
        self.assertEqual(sku_id, device['identity']['sku-id'])
      else:
        self.assertEqual(flags & configfs.EntryFlags.HAS_SKU_ID.value, 0)

      if 'whitelabel-tag' in device['identity']:
        self.assertEqual(flags & configfs.EntryFlags.HAS_WHITELABEL.value,
                         configfs.EntryFlags.HAS_WHITELABEL.value)
        self.assertEqual(_GetString(whitelabel_offset),
                         device['identity']['whitelabel-tag'].lower())
      else:
        self.assertEqual(
            flags & configfs.EntryFlags.HAS_WHITELABEL.value, 0)

      if 'customization-id' in device['identity']:
        self.assertEqual(
            flags & configfs.EntryFlags.IS_X86_LEGACY_CUSTOMIZATION_ID.value,
            configfs.EntryFlags.IS_X86_LEGACY_CUSTOMIZATION_ID.value)
        self.assertEqual(_GetString(whitelabel_offset),
                         device['identity']['customization-id'].lower())
      else:
        self.assertEqual(
            flags & configfs.EntryFlags.IS_X86_LEGACY_CUSTOMIZATION_ID.value, 0)

if __name__ == '__main__':
  cros_test_lib.main(module=__name__)
