TEST(WireFormat, CopyStruct) { Session ctx1, ctx2; setupStruct(&ctx1.capn); checkStruct(&ctx1.capn); capn_ptr root = capn_root(&ctx2.capn); EXPECT_EQ(0, capn_setp(root, 0, capn_getp(capn_root(&ctx1.capn), 0, 1))); checkStruct(&ctx2.capn); }
TEST(Schema, ReadSimple) { struct capn ctx; ASSERT_EQ(0, capn_init_mem(&ctx, simple_schema, sizeof(simple_schema), 0)); CodeGeneratorRequest_ptr root = {capn_getp(capn_root(&ctx), 0, 1)}; EXPECT_EQ(CAPN_STRUCT, root.p.type); struct CodeGeneratorRequest req; read_CodeGeneratorRequest(&req, root); for (size_t i = 0; i < req.nodes.p.len; i++) { } }
static int capn_write_mem_packed(struct capn *c, uint8_t *p, size_t sz) { struct capn_segment *seg; struct capn_ptr root; uint32_t headerlen; size_t headersz, datasz = 0; uint32_t *header; struct capn_stream z; int ret; root = capn_root(c); header_calc(c, &headerlen, &headersz); header = (uint32_t*) (p + headersz + 2); /* must reserve two bytes for worst case expansion */ if (sz < headersz*2 + 2) /* We must have space for temporary writing of header to deflate */ return -1; ret = header_render(c, root.seg, header, headerlen, &datasz); if (ret != 0) return -1; memset(&z, 0, sizeof(z)); z.next_in = (uint8_t *)header; z.avail_in = headersz; z.next_out = p; z.avail_out = sz; // pack the headers ret = capn_deflate(&z); if (ret != 0 || z.avail_in != 0) return -1; for (seg = root.seg; seg; seg = seg->next) { z.next_in = (uint8_t *)seg->data; z.avail_in = seg->len; ret = capn_deflate(&z); if (ret != 0 || z.avail_in != 0) return -1; } return sz - z.avail_out; }
TEST(WireFormat, SimpleRawDataStruct) { AlignedData<2> data = {{ // Struct ref, offset = 1, dataSize = 1, referenceCount = 0 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Content for the data segment. 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }}; struct capn_segment seg; memset(&seg, 0, sizeof(seg)); seg.data = (char*) data.bytes; seg.len = seg.cap = sizeof(data.bytes); struct capn ctx; memset(&ctx, 0, sizeof(ctx)); capn_append_segment(&ctx, &seg); EXPECT_EQ(&seg, ctx.seglist); EXPECT_EQ(&seg, ctx.lastseg); EXPECT_EQ(&seg.hdr, ctx.segtree); EXPECT_EQ(1, ctx.segnum); EXPECT_EQ(0, seg.id); struct capn_ptr ptr = capn_getp(capn_root(&ctx), 0, 1); EXPECT_EQ(CAPN_STRUCT, ptr.type); EXPECT_EQ(8, ptr.datasz); EXPECT_EQ(0, ptr.ptrs); EXPECT_EQ(UINT64_C(0xefcdab8967452301), capn_read64(ptr, 0)); EXPECT_EQ(UINT64_C(0), capn_read64(ptr, 8)); EXPECT_EQ(UINT32_C(0x67452301), capn_read32(ptr, 0)); EXPECT_EQ(UINT32_C(0xefcdab89), capn_read32(ptr, 4)); EXPECT_EQ(UINT32_C(0), capn_read32(ptr, 8)); EXPECT_EQ(UINT16_C(0x2301), capn_read16(ptr, 0)); EXPECT_EQ(UINT16_C(0x6745), capn_read16(ptr, 2)); EXPECT_EQ(UINT16_C(0xab89), capn_read16(ptr, 4)); EXPECT_EQ(UINT16_C(0xefcd), capn_read16(ptr, 6)); EXPECT_EQ(UINT16_C(0), capn_read16(ptr, 8)); }
int capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed) { struct capn_segment *seg; struct capn_ptr root; uint32_t headerlen; size_t headersz, datasz = 0; uint32_t *header; int ret; if (c->segnum == 0) return -1; if (packed) return capn_write_mem_packed(c, p, sz); root = capn_root(c); header_calc(c, &headerlen, &headersz); header = (uint32_t*) p; if (sz < headersz) return -1; ret = header_render(c, root.seg, header, headerlen, &datasz); if (ret != 0) return -1; if (sz < headersz + datasz) return -1; p += headersz; for (seg = root.seg; seg; seg = seg->next) { memcpy(p, seg->data, seg->len); p += seg->len; } return headersz+datasz; }
static void setupStruct(struct capn *ctx) { struct capn_ptr root = capn_root(ctx); ASSERT_EQ(CAPN_PTR_LIST, root.type); ASSERT_EQ(1, root.len); struct capn_ptr ptr = capn_new_struct(root.seg, 16, 6); ASSERT_EQ(CAPN_STRUCT, ptr.type); EXPECT_EQ(16, ptr.datasz); EXPECT_EQ(6, ptr.ptrs); EXPECT_EQ(0, capn_setp(root, 0, ptr)); EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); EXPECT_EQ(0, capn_write32(ptr, 8, UINT32_C(0x20212223))); EXPECT_EQ(0, capn_write16(ptr, 12, UINT16_C(0x3031))); EXPECT_EQ(0, capn_write8(ptr, 14, 0x40)); EXPECT_EQ(0, capn_write8(ptr, 15, (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2))); capn_ptr subStruct = capn_new_struct(ptr.seg, 8, 0); ASSERT_EQ(CAPN_STRUCT, subStruct.type); EXPECT_EQ(8, subStruct.datasz); EXPECT_EQ(0, subStruct.ptrs); EXPECT_EQ(0, capn_write32(subStruct, 0, 123)); EXPECT_NE(0, capn_write32(subStruct, 8, 124)); EXPECT_EQ(0, capn_setp(ptr, 0, subStruct)); capn_list32 list32 = capn_new_list32(ptr.seg, 3); capn_list64 list64 = {list32.p}; ASSERT_EQ(CAPN_LIST, list32.p.type); EXPECT_EQ(3, list32.p.len); EXPECT_EQ(4, list32.p.datasz); EXPECT_EQ(0, capn_set32(list32, 0, 200)); EXPECT_EQ(0, capn_set32(list32, 1, 201)); EXPECT_EQ(0, capn_set32(list32, 2, 202)); EXPECT_NE(0, capn_set32(list32, 3, 203)); EXPECT_NE(0, capn_set64(list64, 0, 405)); EXPECT_EQ(0, capn_setp(ptr, 1, list32.p)); capn_ptr list = capn_new_list(ptr.seg, 4, 4, 1); ASSERT_EQ(CAPN_LIST, list.type); ASSERT_EQ(1, list.is_composite_list); EXPECT_EQ(4, list.len); EXPECT_EQ(8, list.datasz); EXPECT_EQ(1, list.ptrs); EXPECT_EQ(0, capn_setp(ptr, 2, list)); for (int i = 0; i < 4; i++) { capn_ptr element = capn_getp(list, i, 1); ASSERT_EQ(CAPN_STRUCT, element.type); EXPECT_EQ(1, element.is_list_member); EXPECT_EQ(8, element.datasz); EXPECT_EQ(1, element.ptrs); EXPECT_EQ(0, capn_write32(element, 0, 300+i)); capn_ptr subelement = capn_new_struct(element.seg, 8, 0); ASSERT_EQ(CAPN_STRUCT, subelement.type); EXPECT_EQ(8, subelement.datasz); EXPECT_EQ(0, subelement.ptrs); EXPECT_EQ(0, capn_write32(subelement, 0, 400+i)); EXPECT_EQ(0, capn_setp(element, 0, subelement)); } list = capn_new_ptr_list(ptr.seg, 5); ASSERT_EQ(CAPN_PTR_LIST, list.type); EXPECT_EQ(5, list.len); EXPECT_EQ(0, capn_setp(ptr, 3, list)); for (int i = 0; i < 5; i++) { capn_list16 element = capn_new_list16(list.seg, i+1); ASSERT_EQ(CAPN_LIST, element.p.type); EXPECT_EQ(i+1, element.p.len); EXPECT_EQ(2, element.p.datasz); EXPECT_EQ(0, element.p.ptrs); EXPECT_EQ(0, capn_setp(list, i, element.p)); for (int j = 0; j <= i; j++) { EXPECT_EQ(0, capn_set16(element, j, 500+j)); } } capn_ptr recurse = capn_new_struct(ptr.seg, 0, 2); EXPECT_EQ(CAPN_STRUCT, recurse.type); EXPECT_EQ(0, recurse.datasz); EXPECT_EQ(2, recurse.ptrs); EXPECT_EQ(0, capn_setp(recurse, 0, recurse)); EXPECT_EQ(0, capn_setp(ptr, 4, recurse)); }
static void checkStruct(struct capn *ctx) { capn_ptr ptr = capn_getp(capn_root(ctx), 0, 1); EXPECT_EQ(CAPN_STRUCT, ptr.type); EXPECT_EQ(16, ptr.datasz); EXPECT_EQ(6, ptr.ptrs); EXPECT_EQ(UINT64_C(0x1011121314151617), capn_read64(ptr, 0)); EXPECT_EQ(UINT32_C(0x20212223), capn_read32(ptr, 8)); EXPECT_EQ(0x3031, capn_read16(ptr, 12)); EXPECT_EQ(0x40, capn_read8(ptr, 14)); EXPECT_EQ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 2), capn_read8(ptr, 15)); capn_ptr subStruct = capn_getp(ptr, 0, 1); EXPECT_EQ(CAPN_STRUCT, subStruct.type); EXPECT_EQ(8, subStruct.datasz); EXPECT_EQ(0, subStruct.ptrs); EXPECT_EQ(123, capn_read32(subStruct, 0)); capn_list32 list32 = {capn_getp(ptr, 1, 1)}; capn_list8 list8 = {list32.p}; capn_list16 list16 = {list32.p}; capn_list64 list64 = {list32.p}; EXPECT_EQ(CAPN_LIST, list32.p.type); EXPECT_EQ(3, list32.p.len); EXPECT_EQ(4, list32.p.datasz); EXPECT_EQ(0, list32.p.ptrs); EXPECT_EQ(200, capn_get32(list32, 0)); EXPECT_EQ(201, capn_get32(list32, 1)); EXPECT_EQ(202, capn_get32(list32, 2)); EXPECT_EQ(0, capn_get32(list32, 3)); EXPECT_EQ(0, capn_get64(list64, 0)); EXPECT_EQ(201, capn_get8(list8, 1)); EXPECT_EQ(202, capn_get16(list16, 2)); capn_ptr list = capn_getp(ptr, 2, 1); EXPECT_EQ(CAPN_LIST, list.type); EXPECT_EQ(1, list.is_composite_list); EXPECT_EQ(4, list.len); EXPECT_EQ(8, list.datasz); EXPECT_EQ(1, list.ptrs); for (int i = 0; i < 4; i++) { capn_ptr element = capn_getp(list, i, 1); EXPECT_EQ(CAPN_STRUCT, element.type); EXPECT_EQ(1, element.is_list_member); EXPECT_EQ(8, element.datasz); EXPECT_EQ(1, element.ptrs); EXPECT_EQ(300+i, capn_read32(element,0)); capn_ptr subelement = capn_getp(element, 0, 1); EXPECT_EQ(CAPN_STRUCT, subelement.type); EXPECT_EQ(8, subelement.datasz); EXPECT_EQ(0, subelement.ptrs); EXPECT_EQ(400+i, capn_read32(subelement, 0)); } list = capn_getp(ptr, 3, 1); EXPECT_EQ(CAPN_PTR_LIST, list.type); EXPECT_EQ(5, list.len); for (int i = 0; i < 5; i++) { capn_list16 element = {capn_getp(list, i, 1)}; EXPECT_EQ(CAPN_LIST, element.p.type); EXPECT_EQ(i+1, element.p.len); EXPECT_EQ(2, element.p.datasz); EXPECT_EQ(0, element.p.ptrs); for (int j = 0; j <= i; j++) { EXPECT_EQ(500+j, capn_get16(element, j)); } } capn_ptr recurse = capn_getp(ptr, 4, 1); EXPECT_EQ(CAPN_STRUCT, recurse.type); EXPECT_EQ(0, recurse.datasz); EXPECT_EQ(2, recurse.ptrs); capn_ptr recurse_mbr = capn_getp(recurse, 0, 1); EXPECT_EQ(CAPN_STRUCT, recurse_mbr.type); EXPECT_EQ(0, recurse_mbr.datasz); EXPECT_EQ(2, recurse_mbr.ptrs); EXPECT_EQ(recurse.seg, recurse_mbr.seg); EXPECT_EQ(recurse.data, recurse_mbr.data); EXPECT_EQ(CAPN_NULL, capn_getp(recurse, 1, 1).type); }
int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, void *p, size_t count), int fd, int packed) { unsigned char buf[4096]; struct capn_segment *seg; struct capn_ptr root; uint32_t headerlen; size_t headersz, datasz = 0; int ret; struct capn_stream z; unsigned char *p; if (c->segnum == 0) return -1; root = capn_root(c); header_calc(c, &headerlen, &headersz); if (sizeof(buf) < headersz) return -1; ret = header_render(c, root.seg, (uint32_t*)buf, headerlen, &datasz); if (ret != 0) return -1; if (packed) { const int headerrem = sizeof(buf) - headersz; const int maxpack = headersz + 2; if (headerrem < maxpack) return -1; memset(&z, 0, sizeof(z)); z.next_in = buf; z.avail_in = headersz; z.next_out = buf + headersz; z.avail_out = headerrem; ret = capn_deflate(&z); if (ret != 0) return -1; p = buf + headersz; headersz = headerrem - z.avail_out; } else { p = buf; } ret = _write_fd(write_fd, fd, p, headersz); if (ret < 0) return -1; datasz = headersz; for (seg = root.seg; seg; seg = seg->next) { size_t bufsz; if (packed) { memset(&z, 0, sizeof(z)); z.next_in = (uint8_t*)seg->data; z.avail_in = seg->len; z.next_out = buf; z.avail_out = sizeof(buf); ret = capn_deflate(&z); if (ret != 0) return -1; p = buf; bufsz = sizeof(buf) - z.avail_out; } else { p = (uint8_t*)seg->data; bufsz = seg->len; } ret = _write_fd(write_fd, fd, p, bufsz); if (ret < 0) return -1; datasz += bufsz; } return datasz; }