import pytest

from mock import patch
from tempfile import NamedTemporaryFile

from util.config.validators import ConfigValidationException
from util.config.validators.validate_ssl import SSLValidator, SSL_FILENAMES
from test.test_ssl_util import generate_test_cert

from test.fixtures import *

@pytest.mark.parametrize('unvalidated_config', [
  ({}),
  ({'PREFERRED_URL_SCHEME': 'http'}),
  ({'PREFERRED_URL_SCHEME': 'https', 'EXTERNAL_TLS_TERMINATION': True}),
])
def test_skip_validate_ssl(unvalidated_config, app):
  validator = SSLValidator()
  validator.validate(unvalidated_config, None, None)


@pytest.mark.parametrize('cert, expected_error, error_message', [
  ('invalidcert', ConfigValidationException, 'Could not load SSL certificate: no start line'),
  (generate_test_cert(hostname='someserver'), None, None),
  (generate_test_cert(hostname='invalidserver'), ConfigValidationException,
   'Supported names "invalidserver" in SSL cert do not match server hostname "someserver"'),
])
def test_validate_ssl(cert, expected_error, error_message, app):
  with NamedTemporaryFile(delete=False) as cert_file:
    cert_file.write(cert[0])
    cert_file.seek(0)

    with NamedTemporaryFile(delete=False) as key_file:
      key_file.write(cert[1])
      key_file.seek(0)

    def return_true(filename):
      return True

    def get_volume_file(filename):
      if filename == SSL_FILENAMES[0]:
        return open(cert_file.name)

      if filename == SSL_FILENAMES[1]:
        return open(key_file.name)

      return None

    config = {
      'PREFERRED_URL_SCHEME': 'https',
      'SERVER_HOSTNAME': 'someserver',
    }

    with patch('app.config_provider.volume_file_exists', return_true):
      with patch('app.config_provider.get_volume_file', get_volume_file):
        validator = SSLValidator()

        if expected_error is not None:
          with pytest.raises(expected_error) as ipe:
            validator.validate(config, None, None)

          assert ipe.value.message == error_message
        else:
          validator.validate(config, None, None)