"""Tests for config."""

import os
import sys
import unittest

# Allow imports to be rooted in continuous-tests/ folder
sys.path.insert(
    0,
    os.path.realpath(
        os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)))

# pylint: disable=wrong-import-position
from cq.appengine.genfiles import build_config_pb2

import google.protobuf.text_format

_BUILD_RULES_RELPATH = 'configs/{env}/build_rules.protoascii'
_BUILD_DETAILS_RELPATH = 'configs/{env}/build_details.protoascii'


def GetBuildRules(build_config_env):
  """Returns the BuildRules proto."""
  build_rules = build_config_pb2.BuildRules()
  build_rules_path = os.path.join(
      os.path.dirname(__file__),
      _BUILD_RULES_RELPATH.format(env=build_config_env))
  with open(build_rules_path) as f:
    google.protobuf.text_format.Merge(f.read(), build_rules)
  return build_rules


def GetBuildDetails(build_config_env):
  """Returns the BuildDetails proto."""
  build_details = build_config_pb2.BuildDetails()
  build_details_path = os.path.join(
      os.path.dirname(__file__),
      _BUILD_DETAILS_RELPATH.format(env=build_config_env))
  with open(build_details_path) as f:
    google.protobuf.text_format.Merge(f.read(), build_details)
  return build_details

# Use a wrapping class so the test runner does not mistakenly try to run
# tests on ConfigTest, which is not a fully-implemented test class
class BaseTestCases:
  class ConfigTest(unittest.TestCase):
    """A class to test a build config.

    Note: The |self.env| property is initialized externally to this class. This
    class will be setup twice, once with the staging config and once with the
    prod config.
    """
    env = None

    @property
    def build_rules_proto(self):
      return GetBuildRules(self.env)

    @property
    def build_details_proto(self):
      return GetBuildDetails(self.env)

    def testParseBuildRules(self):
      """Tests the build_rules config is a valid proto."""
      self.assertTrue(self.build_rules_proto)

    def testParseBuildDetails(self):
      """Tests the build_details config is a valid proto."""
      self.assertTrue(self.build_details_proto)

    def testOnlySupportedGobHosts(self):
      """Tests that only supported gob_hosts are used."""
      supported_hosts = {
          'caraway-internal',
          'chrome-internal',
          'eureka-internal',
          'eureka-partner',
          'eureka-staging-internal',
          'libassistant-internal',
          'nest-camera-internal',
          'nest-internal',
          'team',
      }
      for rule in self.build_rules_proto.build_rules:
        self.assertIn(rule.gob_host, supported_hosts)

    def testEveryBuildRuleHasAMatchingBuildDetail(self):
      """Test that every build in a build_rule has a matching build_detail."""

      referenced_builds = set()
      for rule in self.build_rules_proto.build_rules:
        referenced_builds.update(rule.builds)
        referenced_builds.update(rule.presubmit_builds)
        for build_set in rule.build_sets:
          referenced_builds.update(
              self.build_rules_proto.build_sets[build_set].builds)

      build_detail_builds = set()
      for build_name in self.build_details_proto.build_details:
        build_detail_builds.add(build_name)

      # Note that it is acceptable for there to be extra build_details, since
      # that is how a build is enabled for manually scheduling.
      missing_build_details = referenced_builds - build_detail_builds
      self.assertFalse(missing_build_details)

    def testScheduleValid(self):
      for build, detail in self.build_details_proto.build_details.items():
        if detail.schedule.min_branch and detail.schedule.max_branch:
          self.assertLess(
              detail.schedule.min_branch, detail.schedule.max_branch,
              'Branch range ({} < {}) for {} is invalid'.format(
                  detail.schedule.min_branch, detail.schedule.max_branch, build
              )
          )
        if detail.schedule.master_only and detail.schedule.release_only:
          raise AssertionError(
              'Can only set master only or release only for {}'.format(build)
          )

    def testHasRequiredFields(self):
      for name, detail in self.build_details_proto.build_details.items():
        self.assertTrue(
            detail.HasField('config'),
            f'{name} must have oneof field config set.')
        which_config = detail.WhichOneof('config')
        if which_config == 'device_tests':
          self.assertGreater(
              len(detail.device_tests.test_groups),
              0,
              f'{name} must have at least one test_group')
          self.assertTrue(
              detail.device_tests.HasField('depends_on'),
              f'{name} must have a depends_on set')
          self.assertGreater(
              len(detail.device_tests.depends_on),
              0,
              f'{name} must have a non-empty depends_on')
        elif which_config == 'cast_build':
          self.assertTrue(
              detail.cast_build.HasField('recipe'),
              f'{name} must have a recipe set')
          self.assertGreater(
              len(detail.cast_build.recipe),
              0,
              f'{name} must have a non-empty recipe')
        elif which_config == 'jenkins_job':
          self.assertTrue(
              detail.jenkins_job.HasField('job_name'),
              f'{name} must have a job_name set')
          self.assertGreater(
              len(detail.jenkins_job.job_name),
              0,
              f'{name} must have a non-empty job_name')


class ProdConfigTest(BaseTestCases.ConfigTest):
  env = "prod"


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