import pytest from panda3d import core import tempfile import sys # Fixtures for generating interesting datagrams (and verification functions) on # the fly... @pytest.fixture(scope='module', params=[False, True], ids=['stdfloat_float', 'stdfloat_double']) def datagram_small(request): """Returns a small datagram, along with a verification function.""" dg = core.Datagram() dg.set_stdfloat_double(request.param) dg.add_uint8(3) dg.add_uint16(14159) dg.add_uint32(0xDEADBEEF) dg.add_uint64(0x0123456789ABCDEF) dg.add_int8(-77) dg.add_int16(-1) dg.add_int32(-972965890) dg.add_int64(-1001001001001001) dg.add_string('this is a string') dg.add_string32('this is another string') dg.add_string('this is yet a third string') dg.add_blob(b'blob data \x00\xf2\xa0\x00\x00') dg.add_blob32(b'\xc9\x8f\x00 test blob32') dg.add_stdfloat(800.2) dg.add_stdfloat(3.1415926) dg.add_stdfloat(2.7182818) def readback_function(dgi): assert dgi.get_remaining_size() > 0 assert dgi.get_uint8() == 3 assert dgi.get_uint16() == 14159 assert dgi.get_uint32() == 0xDEADBEEF assert dgi.get_uint64() == 0x0123456789ABCDEF assert dgi.get_int8() == -77 assert dgi.get_int16() == -1 assert dgi.get_int32() == -972965890 assert dgi.get_int64() == -1001001001001001 assert dgi.get_string() == 'this is a string' assert dgi.get_string32() == 'this is another string' assert dgi.get_string() == 'this is yet a third string' assert dgi.get_blob() == b'blob data \x00\xf2\xa0\x00\x00' assert dgi.get_blob32() == b'\xc9\x8f\x00 test blob32' assert dgi.get_stdfloat() == pytest.approx(800.2) assert dgi.get_stdfloat() == pytest.approx(3.1415926) assert dgi.get_stdfloat() == pytest.approx(2.7182818) assert dgi.get_remaining_size() == 0 return dg, readback_function @pytest.fixture(scope='module') def datagram_large(): """Returns a big datagram, along with a verification function.""" dg = core.Datagram() for x in range(2000000): dg.add_uint32(x) dg.add_string('the magic words are squeamish ossifrage') def readback_function(dgi): assert dgi.get_remaining_size() > 0 for x in range(2000000): assert dgi.get_uint32() == x assert dgi.get_string() == 'the magic words are squeamish ossifrage' assert dgi.get_remaining_size() == 0 return dg, readback_function def test_datagram_bytes(): """Tests that we can put and get a bytes object on Datagram.""" dg = core.Datagram(b'abc\x00') dg.append_data(b'\xff123') assert bytes(dg) == b'abc\x00\xff123' dgi = core.DatagramIterator(dg) dgi.get_remaining_bytes() == b'abc\x00\xff123' def test_datagram_get_message(): dg = core.Datagram(b'abc\x00') dg.append_data(b'\xff123') assert dg.get_message() == b'abc\x00\xff123' def test_datagram_pickle(): import pickle dg = core.Datagram() assert pickle.loads(pickle.dumps(dg, -1)) == dg dg = core.Datagram(b'abc\x00') assert pickle.loads(pickle.dumps(dg, -1)) == dg def test_datagram_cow(): dg1 = core.Datagram() dg1.append_data(b'1234') dg2 = core.Datagram(dg1) dg2.append_data(b'5678') assert dg1.get_message() == b'1234' assert dg2.get_message() == b'12345678' def test_iterator(datagram_small): """This tests Datagram/DatagramIterator, and sort of serves as a self-check of the test fixtures too.""" dg, verify = datagram_small dgi = core.DatagramIterator(dg) verify(dgi) # This tests the copy constructor: def test_copy(datagram_small): dg, verify = datagram_small dg2 = core.Datagram(dg) dgi = core.DatagramIterator(dg2) verify(dgi) def test_assign(datagram_small): dg, verify = datagram_small dg2 = core.Datagram() dg2.assign(dg) dgi = core.DatagramIterator(dg2) verify(dgi) # These test DatagramInputFile/DatagramOutputFile: def do_file_test(dg, verify, filename): dof = core.DatagramOutputFile() dof.open(filename) dof.put_datagram(dg) dof.close() dg2 = core.Datagram() dif = core.DatagramInputFile() dif.open(filename) assert dif.get_datagram(dg2) dif.close() # This is normally saved by the DatagramOutputFile header. We cheat here. dg2.set_stdfloat_double(dg.get_stdfloat_double()) dgi = core.DatagramIterator(dg2) verify(dgi) def test_file_small(datagram_small): """This tests DatagramOutputFile/DatagramInputFile on small datagrams.""" dg, verify = datagram_small file = tempfile.NamedTemporaryFile(suffix='.bin') filename = core.Filename.from_os_specific(file.name) filename.make_true_case() do_file_test(dg, verify, filename) @pytest.mark.skipif(sys.platform == "emscripten", reason="Low-memory environment") def test_file_large(datagram_large): """This tests DatagramOutputFile/DatagramInputFile on very large datagrams.""" dg, verify = datagram_large file = tempfile.NamedTemporaryFile(suffix='.bin') filename = core.Filename.from_os_specific(file.name) filename.make_true_case() do_file_test(dg, verify, filename) def test_file_corrupt(datagram_small): """This tests DatagramInputFile's handling of a corrupt size header.""" dg, verify = datagram_small file = tempfile.NamedTemporaryFile(suffix='.bin') filename = core.Filename.from_os_specific(file.name) filename.make_true_case() dof = core.DatagramOutputFile() dof.open(filename) dof.put_datagram(dg) dof.close() # Corrupt the size header to 1GB file.seek(0) file.write(b'\xFF\xFF\xFF\x4F') file.flush() dg2 = core.Datagram() dif = core.DatagramInputFile() dif.open(filename) assert not dif.get_datagram(dg2) dif.close() # Truncate the file for size in [12, 8, 4, 3, 2, 1, 0]: file.truncate(size) dg2 = core.Datagram() dif = core.DatagramInputFile() dif.open(filename) assert not dif.get_datagram(dg2) dif.close() # Should we test that dg2 is unmodified?