#
# Copyright 2008 The ndb Authors. All Rights Reserved.
#
# 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
#
#     http://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.

"""Tests for metadata.py."""

from .google_imports import namespace_manager

from .google_test_imports import unittest

from . import context
from . import metadata
from . import model
from . import tasklets
from . import test_utils


class MetadataTests(test_utils.NDBTest):

  def setUp(self):
    super(MetadataTests, self).setUp()

    class Foo(model.Model):
      name = model.StringProperty()
      age = model.IntegerProperty()
    self.Foo = Foo

    class Bar(model.Model):
      name = model.StringProperty()
      rate = model.IntegerProperty()
    self.Bar = Bar

    class Ext(model.Expando):
      pass
    self.Ext = Ext
    namespace_manager.set_namespace('')  # Always start in default ns.
    # Turn on caching to make sure we don't cache metadata
    opts = context.ContextOptions(use_cache=True, use_memcache=True)
    tasklets.set_context(tasklets.make_context(config=opts))

  the_module = metadata

  def testGetNamespaces(self):
    self.assertEqual([], metadata.get_namespaces())
    self.Foo().put()
    self.assertEqual([''], metadata.get_namespaces())
    self.assertEqual([], metadata.get_namespaces(None, ''))
    for ns in 'x', 'xyzzy', 'y', 'z':
      namespace_manager.set_namespace(ns)
      self.Foo().put()
    self.assertEqual(['', 'x', 'xyzzy', 'y', 'z'], metadata.get_namespaces())
    self.assertEqual(['x', 'xyzzy'], metadata.get_namespaces('x', 'y'))

  def testGetKinds(self):
    self.assertEqual([], metadata.get_kinds())
    self.Foo().put()
    self.Bar().put()
    self.Ext().put()
    self.assertEqual(['Bar', 'Ext', 'Foo'], metadata.get_kinds())
    self.assertEqual(['Bar', 'Ext'], metadata.get_kinds('A', 'F'))
    self.assertEqual([], metadata.get_kinds(None, ''))
    namespace_manager.set_namespace('x')
    self.assertEqual([], metadata.get_kinds())
    self.Foo().put()
    self.assertEqual(['Foo'], metadata.get_kinds())

  def testGetPropertiesOfKind(self):
    self.Foo().put()
    self.assertEqual(['age', 'name'], metadata.get_properties_of_kind('Foo'))
    self.assertEqual(['age'], metadata.get_properties_of_kind('Foo', 'a', 'h'))
    self.assertEqual([], metadata.get_properties_of_kind('Foo', None, ''))
    e = self.Ext()
    e.foo = 1
    e.bar = 2
    e.put()
    self.assertEqual(['bar', 'foo'], metadata.get_properties_of_kind('Ext'))
    namespace_manager.set_namespace('x')
    e = self.Ext()
    e.one = 1
    e.two = 2
    e.put()
    self.assertEqual(['one', 'two'], metadata.get_properties_of_kind('Ext'))

  def testGetRepresentationsOfKind(self):
    e = self.Ext()
    e.foo = 1
    e.bar = 'a'
    e.put()
    self.assertEqual({'foo': ['INT64'], 'bar': ['STRING']},
                     metadata.get_representations_of_kind('Ext'))
    self.assertEqual({'bar': ['STRING']},
                     metadata.get_representations_of_kind('Ext', 'a', 'e'))
    self.assertEqual({},
                     metadata.get_representations_of_kind('Ext', None, ''))
    f = self.Ext()
    f.foo = 'x'
    f.bar = 2
    f.put()
    self.assertEqual({'foo': ['INT64', 'STRING'],
                      'bar': ['INT64', 'STRING']},
                     metadata.get_representations_of_kind('Ext'))

  def testDirectPropertyQueries(self):
    e = self.Ext()
    e.foo = 1
    e.bar = 'a'
    e.put()
    f = self.Foo(name='a', age=42)
    f.put()
    q = metadata.Property.query()
    res = q.fetch()
    self.assertEqual([('Ext', 'bar'), ('Ext', 'foo'),
                      ('Foo', 'age'), ('Foo', 'name')],
                     [(p.kind_name, p.property_name) for p in res])

  def testEntityGroup(self):
    """Test for EntityGroup class."""
    self.HRTest()
    foo_e = self.Foo(age=11)
    foo_e.put()
    egfoo_k = metadata.EntityGroup.key_for_entity_group(foo_e.key)

    v1 = egfoo_k.get().version
    self.assertTrue(v1 > 0)

    child_e = self.Foo(age=22, parent=foo_e.key)
    child_e.put()
    self.assertEquals(egfoo_k,
                      metadata.EntityGroup.key_for_entity_group(child_e.key))

    self.assertTrue(egfoo_k.get().version > v1)

  def testGetEntityGroupVersion(self):
    """Test for get_entity_group_version function."""
    self.HRTest()
    foo_e = self.Foo(age=11)
    foo_e.put()
    self.assertTrue(metadata.get_entity_group_version(foo_e.key) > 0)


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