# Copyright (c) 2009-2021, Google LLC
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Google LLC nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


"""A bare-bones unit test that doesn't load any generated code."""


import unittest
from google.protobuf.pyext import _message
from google.protobuf.internal import api_implementation
from google.protobuf import unittest_pb2
from google.protobuf import map_unittest_pb2
from google.protobuf import descriptor_pool
from google.protobuf import text_format
from google.protobuf import message_factory
from google.protobuf import message
from google.protobuf.internal import factory_test1_pb2
from google.protobuf.internal import factory_test2_pb2
from google.protobuf.internal import more_extensions_pb2
from google.protobuf import descriptor_pb2

class TestMessageExtension(unittest.TestCase):

    def test_descriptor_pool(self):
        serialized_desc = b'\n\ntest.proto\"\x0e\n\x02M1*\x08\x08\x01\x10\x80\x80\x80\x80\x02:\x15\n\x08test_ext\x12\x03.M1\x18\x01 \x01(\x05'
        pool = _message.DescriptorPool()
        file_desc = pool.AddSerializedFile(serialized_desc)
        self.assertEqual("test.proto", file_desc.name)
        ext_desc = pool.FindExtensionByName("test_ext")
        self.assertEqual(1, ext_desc.number)

        # Test object cache: repeatedly retrieving the same descriptor
        # should result in the same object
        self.assertIs(ext_desc, pool.FindExtensionByName("test_ext"))


    def test_lib_is_upb(self):
        # Ensure we are not pulling in a different protobuf library on the
        # system.
        print(_message._IS_UPB)
        self.assertTrue(_message._IS_UPB)
        self.assertEqual(api_implementation.Type(), "cpp")

    def test_repeated_field_slice_delete(self):
        def test_slice(start, end, step):
            vals = list(range(20))
            message = unittest_pb2.TestAllTypes(repeated_int32=vals)
            del vals[start:end:step]
            del message.repeated_int32[start:end:step]
            self.assertEqual(vals, list(message.repeated_int32))
        test_slice(3, 11, 1)
        test_slice(3, 11, 2)
        test_slice(3, 11, 3)
        test_slice(11, 3, -1)
        test_slice(11, 3, -2)
        test_slice(11, 3, -3)
        test_slice(10, 25, 4)
    
    def testExtensionsErrors(self):
        msg = unittest_pb2.TestAllTypes()
        self.assertRaises(AttributeError, getattr, msg, 'Extensions')
    
    def testClearStubMapField(self):
        msg = map_unittest_pb2.TestMapSubmessage()
        int32_map = msg.test_map.map_int32_int32
        msg.test_map.ClearField("map_int32_int32")
        int32_map[123] = 456
        self.assertEqual(0, msg.test_map.ByteSize())

    def testClearReifiedMapField(self):
        msg = map_unittest_pb2.TestMap()
        int32_map = msg.map_int32_int32
        int32_map[123] = 456
        msg.ClearField("map_int32_int32")
        int32_map[111] = 222
        self.assertEqual(0, msg.ByteSize())

    def testClearStubRepeatedField(self):
        msg = unittest_pb2.NestedTestAllTypes()
        int32_array = msg.payload.repeated_int32
        msg.payload.ClearField("repeated_int32")
        int32_array.append(123)
        self.assertEqual(0, msg.payload.ByteSize())

    def testClearReifiedRepeatdField(self):
        msg = unittest_pb2.TestAllTypes()
        int32_array = msg.repeated_int32
        int32_array.append(123)
        self.assertNotEqual(0, msg.ByteSize())
        msg.ClearField("repeated_int32")
        int32_array.append(123)
        self.assertEqual(0, msg.ByteSize())

    def testFloatPrinting(self):
        message = unittest_pb2.TestAllTypes()
        message.optional_float = -0.0
        self.assertEqual(str(message), 'optional_float: -0\n')

class OversizeProtosTest(unittest.TestCase):
  def setUp(self):
    msg = unittest_pb2.NestedTestAllTypes()
    m = msg
    for i in range(101):
      m = m.child
    m.Clear()
    self.p_serialized = msg.SerializeToString()
    
  def testAssertOversizeProto(self):
    from google.protobuf.pyext._message import SetAllowOversizeProtos
    SetAllowOversizeProtos(False)
    q = unittest_pb2.NestedTestAllTypes()
    with self.assertRaises(message.DecodeError):
      q.ParseFromString(self.p_serialized)
      print(q)
  
  def testSucceedOversizeProto(self):
    from google.protobuf.pyext._message import SetAllowOversizeProtos
    SetAllowOversizeProtos(True)
    q = unittest_pb2.NestedTestAllTypes()
    q.ParseFromString(self.p_serialized)

  def testExtensionIter(self):
    extendee_proto = more_extensions_pb2.ExtendedMessage()

    extension_int32 = more_extensions_pb2.optional_int_extension
    extendee_proto.Extensions[extension_int32] = 23

    extension_repeated = more_extensions_pb2.repeated_int_extension
    extendee_proto.Extensions[extension_repeated].append(11)

    extension_msg = more_extensions_pb2.optional_message_extension
    extendee_proto.Extensions[extension_msg].foreign_message_int = 56

    # Set some normal fields.
    extendee_proto.optional_int32 = 1
    extendee_proto.repeated_string.append('hi')

    expected = {
        extension_int32: True,
        extension_msg: True,
        extension_repeated: True
    }
    count = 0
    for item in extendee_proto.Extensions:
      del expected[item]
      self.assertIn(item, extendee_proto.Extensions)
      count += 1
    self.assertEqual(count, 3)
    self.assertEqual(len(expected), 0)
  
  def testIsInitializedStub(self):
    proto = unittest_pb2.TestRequiredForeign()
    self.assertTrue(proto.IsInitialized())
    self.assertFalse(proto.optional_message.IsInitialized())
    errors = []
    self.assertFalse(proto.optional_message.IsInitialized(errors))
    self.assertEqual(['a', 'b', 'c'], errors)
    self.assertRaises(message.EncodeError, proto.optional_message.SerializeToString)

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