test_datagram.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import pytest
  2. from panda3d import core
  3. import tempfile
  4. import sys
  5. # Fixtures for generating interesting datagrams (and verification functions) on
  6. # the fly...
  7. @pytest.fixture(scope='module',
  8. params=[False, True],
  9. ids=['stdfloat_float', 'stdfloat_double'])
  10. def datagram_small(request):
  11. """Returns a small datagram, along with a verification function."""
  12. dg = core.Datagram()
  13. dg.set_stdfloat_double(request.param)
  14. dg.add_uint8(3)
  15. dg.add_uint16(14159)
  16. dg.add_uint32(0xDEADBEEF)
  17. dg.add_uint64(0x0123456789ABCDEF)
  18. dg.add_int8(-77)
  19. dg.add_int16(-1)
  20. dg.add_int32(-972965890)
  21. dg.add_int64(-1001001001001001)
  22. dg.add_string('this is a string')
  23. dg.add_string32('this is another string')
  24. dg.add_string('this is yet a third string')
  25. dg.add_blob(b'blob data \x00\xf2\xa0\x00\x00')
  26. dg.add_blob32(b'\xc9\x8f\x00 test blob32')
  27. dg.add_stdfloat(800.2)
  28. dg.add_stdfloat(3.1415926)
  29. dg.add_stdfloat(2.7182818)
  30. def readback_function(dgi):
  31. assert dgi.get_remaining_size() > 0
  32. assert dgi.get_uint8() == 3
  33. assert dgi.get_uint16() == 14159
  34. assert dgi.get_uint32() == 0xDEADBEEF
  35. assert dgi.get_uint64() == 0x0123456789ABCDEF
  36. assert dgi.get_int8() == -77
  37. assert dgi.get_int16() == -1
  38. assert dgi.get_int32() == -972965890
  39. assert dgi.get_int64() == -1001001001001001
  40. assert dgi.get_string() == 'this is a string'
  41. assert dgi.get_string32() == 'this is another string'
  42. assert dgi.get_string() == 'this is yet a third string'
  43. assert dgi.get_blob() == b'blob data \x00\xf2\xa0\x00\x00'
  44. assert dgi.get_blob32() == b'\xc9\x8f\x00 test blob32'
  45. assert dgi.get_stdfloat() == pytest.approx(800.2)
  46. assert dgi.get_stdfloat() == pytest.approx(3.1415926)
  47. assert dgi.get_stdfloat() == pytest.approx(2.7182818)
  48. assert dgi.get_remaining_size() == 0
  49. return dg, readback_function
  50. @pytest.fixture(scope='module')
  51. def datagram_large():
  52. """Returns a big datagram, along with a verification function."""
  53. dg = core.Datagram()
  54. for x in range(2000000):
  55. dg.add_uint32(x)
  56. dg.add_string('the magic words are squeamish ossifrage')
  57. def readback_function(dgi):
  58. assert dgi.get_remaining_size() > 0
  59. for x in range(2000000):
  60. assert dgi.get_uint32() == x
  61. assert dgi.get_string() == 'the magic words are squeamish ossifrage'
  62. assert dgi.get_remaining_size() == 0
  63. return dg, readback_function
  64. def test_datagram_bytes():
  65. """Tests that we can put and get a bytes object on Datagram."""
  66. dg = core.Datagram(b'abc\x00')
  67. dg.append_data(b'\xff123')
  68. assert bytes(dg) == b'abc\x00\xff123'
  69. dgi = core.DatagramIterator(dg)
  70. dgi.get_remaining_bytes() == b'abc\x00\xff123'
  71. def test_datagram_get_message():
  72. dg = core.Datagram(b'abc\x00')
  73. dg.append_data(b'\xff123')
  74. assert dg.get_message() == b'abc\x00\xff123'
  75. def test_datagram_pickle():
  76. import pickle
  77. dg = core.Datagram()
  78. assert pickle.loads(pickle.dumps(dg, -1)) == dg
  79. dg = core.Datagram(b'abc\x00')
  80. assert pickle.loads(pickle.dumps(dg, -1)) == dg
  81. def test_datagram_cow():
  82. dg1 = core.Datagram()
  83. dg1.append_data(b'1234')
  84. dg2 = core.Datagram(dg1)
  85. dg2.append_data(b'5678')
  86. assert dg1.get_message() == b'1234'
  87. assert dg2.get_message() == b'12345678'
  88. def test_iterator(datagram_small):
  89. """This tests Datagram/DatagramIterator, and sort of serves as a self-check
  90. of the test fixtures too."""
  91. dg, verify = datagram_small
  92. dgi = core.DatagramIterator(dg)
  93. verify(dgi)
  94. # This tests the copy constructor:
  95. def test_copy(datagram_small):
  96. dg, verify = datagram_small
  97. dg2 = core.Datagram(dg)
  98. dgi = core.DatagramIterator(dg2)
  99. verify(dgi)
  100. def test_assign(datagram_small):
  101. dg, verify = datagram_small
  102. dg2 = core.Datagram()
  103. dg2.assign(dg)
  104. dgi = core.DatagramIterator(dg2)
  105. verify(dgi)
  106. # These test DatagramInputFile/DatagramOutputFile:
  107. def do_file_test(dg, verify, filename):
  108. dof = core.DatagramOutputFile()
  109. dof.open(filename)
  110. dof.put_datagram(dg)
  111. dof.close()
  112. dg2 = core.Datagram()
  113. dif = core.DatagramInputFile()
  114. dif.open(filename)
  115. assert dif.get_datagram(dg2)
  116. dif.close()
  117. # This is normally saved by the DatagramOutputFile header. We cheat here.
  118. dg2.set_stdfloat_double(dg.get_stdfloat_double())
  119. dgi = core.DatagramIterator(dg2)
  120. verify(dgi)
  121. def test_file_small(datagram_small):
  122. """This tests DatagramOutputFile/DatagramInputFile on small datagrams."""
  123. dg, verify = datagram_small
  124. file = tempfile.NamedTemporaryFile(suffix='.bin')
  125. filename = core.Filename.from_os_specific(file.name)
  126. filename.make_true_case()
  127. do_file_test(dg, verify, filename)
  128. @pytest.mark.skipif(sys.platform == "emscripten", reason="Low-memory environment")
  129. def test_file_large(datagram_large):
  130. """This tests DatagramOutputFile/DatagramInputFile on very large datagrams."""
  131. dg, verify = datagram_large
  132. file = tempfile.NamedTemporaryFile(suffix='.bin')
  133. filename = core.Filename.from_os_specific(file.name)
  134. filename.make_true_case()
  135. do_file_test(dg, verify, filename)
  136. def test_file_corrupt(datagram_small):
  137. """This tests DatagramInputFile's handling of a corrupt size header."""
  138. dg, verify = datagram_small
  139. file = tempfile.NamedTemporaryFile(suffix='.bin')
  140. filename = core.Filename.from_os_specific(file.name)
  141. filename.make_true_case()
  142. dof = core.DatagramOutputFile()
  143. dof.open(filename)
  144. dof.put_datagram(dg)
  145. dof.close()
  146. # Corrupt the size header to 1GB
  147. file.seek(0)
  148. file.write(b'\xFF\xFF\xFF\x4F')
  149. file.flush()
  150. dg2 = core.Datagram()
  151. dif = core.DatagramInputFile()
  152. dif.open(filename)
  153. assert not dif.get_datagram(dg2)
  154. dif.close()
  155. # Truncate the file
  156. for size in [12, 8, 4, 3, 2, 1, 0]:
  157. file.truncate(size)
  158. dg2 = core.Datagram()
  159. dif = core.DatagramInputFile()
  160. dif.open(filename)
  161. assert not dif.get_datagram(dg2)
  162. dif.close()
  163. # Should we test that dg2 is unmodified?