def test_ListItem_far_pointer(): seg0 = b('\x01\x00\x00\x00\x26\x00\x00\x00' # ptrlist '\x0d\x00\x00\x00\x12\x00\x00\x00' # ptr item 1 '\x0d\x00\x00\x00\x1a\x00\x00\x00' # ptr item 2 '\x0d\x00\x00\x00\x22\x00\x00\x00' # ptr item 3 '\x02\x00\x00\x00\x01\x00\x00\x00' # far ptr, segment=1, offset=0 'A' '\x00\x00\x00\x00\x00\x00\x00' # A 'B' 'C' '\x00\x00\x00\x00\x00\x00' # BC 'D' 'E' 'F' '\x00\x00\x00\x00\x00') # DEF # seg1 = b('\x01\x00\x00\x00\x2a\x00\x00\x00' # ptr item 4 'G' 'H' 'I' 'J' '\x00\x00\x00\x00') # GHIJ # buf = MultiSegment(seg0 + seg1, segment_offsets=(0, len(seg0))) blob = Struct.from_buffer(buf, 0, data_size=0, ptrs_size=1) item_type = ListItemType(PrimitiveItemType(Types.int8)) lst = blob._read_list(0, item_type) ghij = lst[3] assert list(ghij) == [ord('G'), ord('H'), ord('I'), ord('J'), 0]
def _load_buffer_multiple_segments(f, n): # slow path for the multiple-segments case # # 1. read the size of each segment fmt = '<' + 'I' * n size = struct.calcsize(fmt) buf = f.read(size) if len(buf) < size: raise ValueError("Unexpected EOF when reading the header") segments = struct.unpack(fmt, buf) # # 2. add enough padding so that the message starts at word boundary bytes_read = 4 + n * 4 # 4 bytes for the n, plus 4 bytes for each segment if bytes_read % 8 != 0: padding = 8 - (bytes_read % 8) f.read(padding) # # 3. read the body of the message message_lenght = sum(segments) * 8 buf = f.read(message_lenght) if len(buf) < message_lenght: raise ValueError("Unexpected EOF: expected %d bytes, got only %s. " "Segments size: %s" % (message_lenght, len(buf), segments)) # # 4. precompute the offset of each segment starting from the beginning of buf segment_offsets = [] segment_offsets.append(0) offset = 0 for size in segments[:-1]: offset += size * 8 segment_offsets.append(offset) # # 5. we are finally done :) return MultiSegment(buf, tuple(segment_offsets))
def test_TextItem_far_pointer(): seg0 = b('\x01\x00\x00\x00\x26\x00\x00\x00' # ptrlist '\x0d\x00\x00\x00\x12\x00\x00\x00' # ptr item 1 '\x0d\x00\x00\x00\x1a\x00\x00\x00' # ptr item 2 '\x0d\x00\x00\x00\x22\x00\x00\x00' # ptr item 3 '\x02\x00\x00\x00\x01\x00\x00\x00' # far ptr, segment=1, offset=0 'A' '\x00\x00\x00\x00\x00\x00\x00' # A 'B' 'C' '\x00\x00\x00\x00\x00\x00' # BC 'D' 'E' 'F' '\x00\x00\x00\x00\x00') # DEF # seg1 = b('\x01\x00\x00\x00\x2a\x00\x00\x00' # ptr item 4 'G' 'H' 'I' 'J' '\x00\x00\x00\x00') # GHIJ # buf = MultiSegment(seg0 + seg1, segment_offsets=(0, len(seg0))) blob = Struct.from_buffer(buf, 0, data_size=0, ptrs_size=1) lst = blob._read_list(0, TextItemType(Types.text)) assert list(lst) == [b'A', b'BC', b'DEF', b'GHIJ']
def test_far_pointer(self): ## struct Point { ## x @0 :Int64; ## y @1 :Int64; ## } seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x00\x00\x00\x00\x00\x00\x01\x00' # ptr (0, 1) to A '\x0a\x00\x00\x00\x01\x00\x00\x00' ) # far pointer to B: segment=1, offset=1 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # random data '\x00\x00\x00\x00\x02\x00\x00\x00' # ptr to B {x, y} '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 # src_seg = MultiSegment(seg0 + seg1, segment_offsets=(0, 24)) dstsize = 16 dst = self.copy_struct_segment(src_seg, offset=8, data_size=0, ptrs_size=1, bufsize=dstsize) assert dst == b('\x00\x00\x00\x00\x00\x00\x01\x00' # root ptr (0, 1) '\x00\x00\x00\x00\x00\x00\x01\x00' # ptr to A (0, 1) '\x00\x00\x00\x00\x02\x00\x00\x00' # ptr to B {x, y} '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2
def test_far_pointer_1(): # test for far pointer with landing_pad==0 # see also test_list.test_far_pointer_1 seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0e\x00\x00\x00\x02\x00\x00\x00' ) # far ptr: pad=1, segment=2, offset=1 # ==> 2nd line of seg2 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 seg2 = b( '\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x0a\x00\x00\x00\x01\x00\x00\x00' # far ptr: pad=0, segment=1, offset=1 # ==> 2nd line of seg1 '\x00\x00\x00\x00\x02\x00\x00\x00' ) # tag: struct,offset=0,data=2,ptrs=0 # buf = MultiSegment(seg0 + seg1 + seg2, segment_offsets=(0, len(seg0), len(seg0 + seg1))) blob = Struct.from_buffer(buf, 8, data_size=0, ptrs_size=1) p = blob._read_struct(0, Struct) assert p._read_primitive(0, Types.int64.ifmt) == 1 assert p._read_primitive(8, Types.int64.ifmt) == 2
def test_MultiSegment_pickle(): import cPickle as pickle buf = MultiSegment('hello', (1, 2, 3)) # buf2 = pickle.loads(pickle.dumps(buf)) assert buf2.buf == 'hello' assert buf2.segment_offsets == (1, 2, 3) # buf2 = pickle.loads(pickle.dumps(buf, pickle.HIGHEST_PROTOCOL)) assert buf2.buf == 'hello' assert buf2.segment_offsets == (1, 2, 3)
def test_far_pointer(self): ## struct Point { ## x @0 :Int64; ## y @1 :Int64; ## } seg0 = b('\x02\x00\x00\x00\x01\x00\x00\x00' ) # far pointer: segment=1, offset=0 seg1 = b('\x00\x00\x00\x00\x02\x00\x00\x00' # ptr to {x, y} '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 seg = MultiSegment(seg0 + seg1, segment_offsets=(0, 8)) end = self.endof(seg, offset=0, data_size=0, ptrs_size=1) assert end == -1
def test_far_pointer(): # see also test_list.test_far_pointer seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0a\x00\x00\x00\x01\x00\x00\x00') # far pointer: segment=1, offset=1 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # random data '\x00\x00\x00\x00\x02\x00\x00\x00' # ptr to {x, y} '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 # buf = MultiSegment(seg0+seg1, segment_offsets=(0, 16)) blob = Struct.from_buffer(buf, 8, data_size=0, ptrs_size=1) p = blob._read_struct(0, Struct) assert p._read_data(0, Types.int64.ifmt) == 1 assert p._read_data(8, Types.int64.ifmt) == 2
def test_far_pointer_0(): # see also test_blob.test_far_pointer_0 seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0a\x00\x00\x00\x01\x00\x00\x00') # far pointer: segment=1, offset=1 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # random data '\x01\x00\x00\x00\x25\x00\x00\x00' # ptrlist '\x01\x00\x00\x00\x00\x00\x00\x00' # 1 '\x02\x00\x00\x00\x00\x00\x00\x00' # 2 '\x03\x00\x00\x00\x00\x00\x00\x00' # 3 '\x04\x00\x00\x00\x00\x00\x00\x00') # 4 buf = MultiSegment(seg0+seg1, segment_offsets=(0, 16)) blob = Struct.from_buffer(buf, 8, data_size=0, ptrs_size=1) lst = blob._read_list(0, PrimitiveItemType(Types.int64)) assert lst == [1, 2, 3, 4]
def test_raw_dumps_loads_multi_segment(): seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0a\x00\x00\x00\x01\x00\x00\x00') # far pointer: segment=1, offset=1 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # random data '\x00\x00\x00\x00\x02\x00\x00\x00' # ptr to {x, y} '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 # buf = MultiSegment(seg0+seg1, segment_offsets=(0, 16)) obj = Struct.from_buffer(buf, 8, data_size=0, ptrs_size=1) # mydump = obj._raw_dumps() obj2 = Struct._raw_loads(mydump) # p = obj2._read_struct(0, Struct) assert p._read_primitive(0, Types.int64.ifmt) == 1 assert p._read_primitive(8, Types.int64.ifmt) == 2
def _raw_loads(cls, s): """ Load an object which was saved by _raw_dumps """ args = marshal.loads(s) header, clsname, buf, segment_offsets, offset, data_size, ptrs_size = args assert header == 'capnpy raw dump' if clsname != cls.__name__: warnings.warn("The raw dump says it's a %s, but we are loading it " "as a %s" % (clsname, cls.__name__)) # if segment_offsets is None: seg = Segment(buf) else: seg = MultiSegment(buf, segment_offsets) self = cls.__new__(cls) self._init_from_buffer(seg, offset, data_size, ptrs_size) return self
def test_declare_const_multi_segment(self): schema = """ @0xbf5147cbbecf40c1; struct Point { x @0 :Int64; y @1 :Int64; } struct Root { p @0 :Point; } """ mod = self.compile(schema) # # create a multi-segment Root object. We don't have a builtin way to # do it inside capnpy, so we need to do it manually seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0e\x00\x00\x00\x02\x00\x00\x00') # far ptr: pad=1, segment=2, ofs=1 # ==> 2nd line of seg2 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x01\x00\x00\x00\x00\x00\x00\x00' # x == 1 '\x02\x00\x00\x00\x00\x00\x00\x00') # y == 2 seg2 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x0a\x00\x00\x00\x01\x00\x00\x00' # far ptr: pad=0, segment=1, ofs=1 # ==> 2nd line of seg1 '\x00\x00\x00\x00\x02\x00\x00\x00') # tag: struct,ofs=0,data=2,ptrs=0 seg = MultiSegment(seg0+seg1+seg2, segment_offsets=(0, len(seg0), len(seg0+seg1))) myroot = mod.Root.from_buffer(seg, 8, data_size=0, ptrs_size=1) assert myroot.p.x == 1 assert myroot.p.y == 2 # # now, we call ModuleGenerator.declare_const on "myroot": then we # eval() the source code and check that the new "declared" constant is # still readable m = capnpy.get_reflection_data(mod).m src = m.declare_const('Root', myroot) d = {'Root': mod.Root, '_MultiSegment': MultiSegment} newroot = eval(src, d) assert newroot.p.x == 1 assert newroot.p.y == 2
def test_far_pointer_1(): # see also test_blob.test_far_pointer_1 seg0 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # some garbage '\x0e\x00\x00\x00\x02\x00\x00\x00') # far ptr: pad=1, segment=2, offset=1 # ==> 2nd line of seg2 seg1 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x01\x00\x00\x00\x00\x00\x00\x00' # 1 '\x02\x00\x00\x00\x00\x00\x00\x00' # 2 '\x03\x00\x00\x00\x00\x00\x00\x00' # 3 '\x04\x00\x00\x00\x00\x00\x00\x00') # 4 seg2 = b('\x00\x00\x00\x00\x00\x00\x00\x00' # garbage '\x0a\x00\x00\x00\x01\x00\x00\x00' # far ptr: pad=0, segment=1, offset=1 # ==> 2nd line of seg1 '\x01\x00\x00\x00\x25\x00\x00\x00') # tag: ptrlist buf = MultiSegment(seg0+seg1+seg2, segment_offsets=(0, len(seg0), len(seg0+seg1))) blob = Struct.from_buffer(buf, 8, data_size=0, ptrs_size=1) lst = blob._read_list(0, PrimitiveItemType(Types.int64)) assert lst == [1, 2, 3, 4]