text: # encoding: utf-8
  
  from __future__ import unicode_literals
  
  import unittest
  
  import mock
  
  from mopidy import config
  
  from tests import path_to_data_dir
  
  
  class LoadConfigTest(unittest.TestCase):
      def test_load_nothing(self):
          self.assertEqual({}, config._load([], [], []))
  
      def test_load_single_default(self):
          default = b'[foo]\nbar = baz'
          expected = {'foo': {'bar': 'baz'}}
          result = config._load([], [default], [])
          self.assertEqual(expected, result)
  
      def test_unicode_default(self):
          default = '[foo]\nbar = æøå'
          expected = {'foo': {'bar': 'æøå'.encode('utf-8')}}
          result = config._load([], [default], [])
          self.assertEqual(expected, result)
  
      def test_load_defaults(self):
          default1 = b'[foo]\nbar = baz'
          default2 = b'[foo2]\n'
          expected = {'foo': {'bar': 'baz'}, 'foo2': {}}
          result = config._load([], [default1, default2], [])
          self.assertEqual(expected, result)
  
      def test_load_single_override(self):
          override = ('foo', 'bar', 'baz')
          expected = {'foo': {'bar': 'baz'}}
          result = config._load([], [], [override])
          self.assertEqual(expected, result)
  
      def test_load_overrides(self):
          override1 = ('foo', 'bar', 'baz')
          override2 = ('foo2', 'bar', 'baz')
          expected = {'foo': {'bar': 'baz'}, 'foo2': {'bar': 'baz'}}
          result = config._load([], [], [override1, override2])
          self.assertEqual(expected, result)
  
      def test_load_single_file(self):
          file1 = path_to_data_dir('file1.conf')
          expected = {'foo': {'bar': 'baz'}}
          result = config._load([file1], [], [])
          self.assertEqual(expected, result)
  
      def test_load_files(self):
          file1 = path_to_data_dir('file1.conf')
          file2 = path_to_data_dir('file2.conf')
          expected = {'foo': {'bar': 'baz'}, 'foo2': {'bar': 'baz'}}
          result = config._load([file1, file2], [], [])
          self.assertEqual(expected, result)
  
      def test_load_file_with_utf8(self):
          expected = {'foo': {'bar': 'æøå'.encode('utf-8')}}
          result = config._load([path_to_data_dir('file3.conf')], [], [])
          self.assertEqual(expected, result)
  
      def test_load_file_with_error(self):
          expected = {'foo': {'bar': 'baz'}}
          result = config._load([path_to_data_dir('file4.conf')], [], [])
          self.assertEqual(expected, result)
  
  
  class ValidateTest(unittest.TestCase):
      def setUp(self):
          self.schema = config.ConfigSchema('foo')
          self.schema['bar'] = config.ConfigValue()
  
      def test_empty_config_no_schemas(self):
          conf, errors = config._validate({}, [])
          self.assertEqual({}, conf)
          self.assertEqual({}, errors)
  
      def test_config_no_schemas(self):
          raw_config = {'foo': {'bar': 'baz'}}
          conf, errors = config._validate(raw_config, [])
          self.assertEqual({}, conf)
          self.assertEqual({}, errors)
  
      def test_empty_config_single_schema(self):
          conf, errors = config._validate({}, [self.schema])
          self.assertEqual({'foo': {'bar': None}}, conf)
          self.assertEqual({'foo': {'bar': 'config key not found.'}}, errors)
  
      def test_config_single_schema(self):
          raw_config = {'foo': {'bar': 'baz'}}
          conf, errors = config._validate(raw_config, [self.schema])
          self.assertEqual({'foo': {'bar': 'baz'}}, conf)
          self.assertEqual({}, errors)
  
      def test_config_single_schema_config_error(self):
          raw_config = {'foo': {'bar': 'baz'}}
          self.schema['bar'] = mock.Mock()
          self.schema['bar'].deserialize.side_effect = ValueError('bad')
          conf, errors = config._validate(raw_config, [self.schema])
          self.assertEqual({'foo': {'bar': None}}, conf)
          self.assertEqual({'foo': {'bar': 'bad'}}, errors)
  
      # TODO: add more tests
  
  
  INPUT_CONFIG = """# comments before first section should work
  
  [section] anything goes ; after the [] block it seems.
  ; this is a valid comment
  this-should-equal-baz = baz ; as this is a comment
  this-should-equal-everything = baz # as this is not a comment
  
  # this is also a comment ; and the next line should be a blank comment.
  ;
  # foo # = should all be treated as a comment."""
  
  PROCESSED_CONFIG = """[__COMMENTS__]
  __HASH0__ = comments before first section should work
  __BLANK1__ =
  [section]
  __SECTION2__ = anything goes
  __INLINE3__ = after the [] block it seems.
  __SEMICOLON4__ = this is a valid comment
  this-should-equal-baz = baz
  __INLINE5__ = as this is a comment
  this-should-equal-everything = baz # as this is not a comment
  __BLANK6__ =
  __HASH7__ = this is also a comment
  __INLINE8__ = and the next line should be a blank comment.
  __SEMICOLON9__ =
  __HASH10__ = foo # = should all be treated as a comment."""
  
  
  class PreProcessorTest(unittest.TestCase):
      maxDiff = None  # Show entire diff.
  
      def test_empty_config(self):
          result = config._preprocess('')
          self.assertEqual(result, '[__COMMENTS__]')
  
      def test_plain_section(self):
          result = config._preprocess('[section]\nfoo = bar')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   'foo = bar')
  
      def test_initial_comments(self):
          result = config._preprocess('; foobar')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '__SEMICOLON0__ = foobar')
  
          result = config._preprocess('# foobar')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '__HASH0__ = foobar')
  
          result = config._preprocess('; foo\n# bar')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '__SEMICOLON0__ = foo\n'
                                   '__HASH1__ = bar')
  
      def test_initial_comment_inline_handling(self):
          result = config._preprocess('; foo ; bar ; baz')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '__SEMICOLON0__ = foo\n'
                                   '__INLINE1__ = bar\n'
                                   '__INLINE2__ = baz')
  
      def test_inline_semicolon_comment(self):
          result = config._preprocess('[section]\nfoo = bar ; baz')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   'foo = bar\n'
                                   '__INLINE0__ = baz')
  
      def test_no_inline_hash_comment(self):
          result = config._preprocess('[section]\nfoo = bar # baz')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   'foo = bar # baz')
  
      def test_section_extra_text(self):
          result = config._preprocess('[section] foobar')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   '__SECTION0__ = foobar')
  
      def test_section_extra_text_inline_semicolon(self):
          result = config._preprocess('[section] foobar ; baz')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   '__SECTION0__ = foobar\n'
                                   '__INLINE1__ = baz')
  
      def test_conversion(self):
          """Tests all of the above cases at once."""
          result = config._preprocess(INPUT_CONFIG)
          self.assertEqual(result, PROCESSED_CONFIG)
  
  
  class PostProcessorTest(unittest.TestCase):
      maxDiff = None  # Show entire diff.
  
      def test_empty_config(self):
          result = config._postprocess('[__COMMENTS__]')
          self.assertEqual(result, '')
  
      def test_plain_section(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '[section]\n'
                                       'foo = bar')
          self.assertEqual(result, '[section]\nfoo = bar')
  
      def test_initial_comments(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '__SEMICOLON0__ = foobar')
          self.assertEqual(result, '; foobar')
  
          result = config._postprocess('[__COMMENTS__]\n'
                                       '__HASH0__ = foobar')
          self.assertEqual(result, '# foobar')
  
          result = config._postprocess('[__COMMENTS__]\n'
                                       '__SEMICOLON0__ = foo\n'
                                       '__HASH1__ = bar')
          self.assertEqual(result, '; foo\n# bar')
  
      def test_initial_comment_inline_handling(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '__SEMICOLON0__ = foo\n'
                                       '__INLINE1__ = bar\n'
                                       '__INLINE2__ = baz')
          self.assertEqual(result, '; foo ; bar ; baz')
  
      def test_inline_semicolon_comment(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '[section]\n'
                                       'foo = bar\n'
                                       '__INLINE0__ = baz')
          self.assertEqual(result, '[section]\nfoo = bar ; baz')
  
      def test_no_inline_hash_comment(self):
          result = config._preprocess('[section]\nfoo = bar # baz')
          self.assertEqual(result, '[__COMMENTS__]\n'
                                   '[section]\n'
                                   'foo = bar # baz')
  
      def test_section_extra_text(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '[section]\n'
                                       '__SECTION0__ = foobar')
          self.assertEqual(result, '[section] foobar')
  
      def test_section_extra_text_inline_semicolon(self):
          result = config._postprocess('[__COMMENTS__]\n'
                                       '[section]\n'
                                       '__SECTION0__ = foobar\n'
                                       '__INLINE1__ = baz')
          self.assertEqual(result, '[section] foobar ; baz')
  
      def test_conversion(self):
          result = config._postprocess(PROCESSED_CONFIG)
          self.assertEqual(result, INPUT_CONFIG)
  