mirror of
https://github.com/zap-proto/c.git
synced 2026-10-30 15:05:52 +00:00
Finish the capnp->ZAP rebrand for the shared runtime and make the build
configure and pass on a clean checkout.
Runtime file rename (history-preserving git mv) + every reference updated
in one pass:
lib/capn.c -> lib/zap.c
lib/capn-malloc.c -> lib/zap-malloc.c
lib/capn-stream.c -> lib/zap-stream.c
lib/capn-list.inc -> lib/zap-list.inc
tests/capn-test.cpp -> tests/zap-test.cpp
tests/capn-stream-test.cpp -> tests/zap-stream-test.cpp
Updated #include directives (zap.c's 4 SZ-templated zap-list.inc includes,
the two unity-build test includes), file banner comments, and the
meson/autotools targets (test target capn-test -> zap-test, with the
matching automake zap_test_* variables and the libzap source list).
The upstream `capn_`/`CAPN_` C ABI (struct capn, capn_get, ...) is left
intact: it is the original MIT library's neutral symbol prefix, not a
capnp/Cap'n Proto brand token, and renaming it would break the generated
*.zap.c/*.zap.h and the runtime shared into the lua binding.
Build fixes:
- example-test.cpp wrote to a fixed relative path ("tests/...out"), which
fails under `meson test` (cwd is the build dir). Use tmpfile() so the
test is cwd-independent and leaves no artifact.
- CI workflow: trigger on main (default branch was renamed master->main),
run the renamed zap-test binary, drop EOL ubuntu-20.04, pin checkout@v4.
Dependency bump (in-major): gtest wrap 1.13.0-1 -> 1.17.0-4. gtest >=1.14
requires C++17, so bump the test C++ standard c++14 -> c++17 in meson.build
and Makefile.am (the runtime stays c99; C++ is test-only).
Verified: meson setup build && ninja builds libzap + zapc-c + zap-test
clean; zap-test passes 24/24; `meson test` green (1/1). autoreconf
generates configure and automake accepts the renamed targets.
167 lines
4.8 KiB
C++
167 lines
4.8 KiB
C++
/* example-test.cpp
|
|
*
|
|
* Some simple examples using c-zap.
|
|
*
|
|
* Based on the canonical addressbook.zap example schema.
|
|
*
|
|
* Copyright (C) 2017 Alex Helfet
|
|
*
|
|
* This software may be modified and distributed under the terms
|
|
* of the MIT license. See the LICENSE file for details.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <cstdint>
|
|
|
|
#include "zap_c.h"
|
|
#include "addressbook.zap.h"
|
|
|
|
static capn_text chars_to_text(const char *chars) {
|
|
return (capn_text) {
|
|
.len = (int) strlen(chars),
|
|
.str = chars,
|
|
.seg = NULL,
|
|
};
|
|
}
|
|
|
|
// EXPECT_CAPN_TEXT_EQ arguments:
|
|
// const char * expected
|
|
// capn_text t
|
|
#define EXPECT_CAPN_TEXT_EQ(expected, t) \
|
|
do { \
|
|
EXPECT_EQ(strlen((expected)), (uint32_t) (t).len); \
|
|
EXPECT_STREQ((expected), (t).str); \
|
|
} while(0);
|
|
|
|
|
|
// Demonstrates serializing an object tree to a byte array, then deserializing it
|
|
// back into an object tree and asserting on the expected values therein.
|
|
//
|
|
// This example uses generated read_*, write_*, get_*, set_* functions
|
|
// to deserialize into structs.
|
|
TEST(Examples, RoundTripPerson) {
|
|
uint8_t buf[4096];
|
|
ssize_t sz = 0;
|
|
|
|
const char *name = "Firstname Lastname";
|
|
const char *email = "[email protected]";
|
|
const char *school = "of life";
|
|
|
|
{
|
|
struct capn c;
|
|
capn_init_malloc(&c);
|
|
capn_ptr cr = capn_root(&c);
|
|
struct capn_segment *cs = cr.seg;
|
|
|
|
// Set initial object in `p`.
|
|
struct Person p = {
|
|
.id = 17,
|
|
.name = chars_to_text(name),
|
|
.email = chars_to_text(email),
|
|
};
|
|
p.employment_which = Person_employment_school;
|
|
p.employment.school = chars_to_text(school);
|
|
|
|
p.phones = new_Person_PhoneNumber_list(cs, 2);
|
|
struct Person_PhoneNumber pn0 = {
|
|
.number = chars_to_text("123"),
|
|
.type = Person_PhoneNumber_Type_work,
|
|
};
|
|
set_Person_PhoneNumber(&pn0, p.phones, 0);
|
|
struct Person_PhoneNumber pn1 = {
|
|
.number = chars_to_text("234"),
|
|
.type = Person_PhoneNumber_Type_home,
|
|
};
|
|
set_Person_PhoneNumber(&pn1, p.phones, 1);
|
|
|
|
Person_ptr pp = new_Person(cs);
|
|
write_Person(&p, pp);
|
|
int setp_ret = capn_setp(capn_root(&c), 0, pp.p);
|
|
ASSERT_EQ(0, setp_ret);
|
|
sz = capn_write_mem(&c, buf, sizeof(buf), 0 /* packed */);
|
|
capn_free(&c);
|
|
}
|
|
|
|
{
|
|
// Demonstrate writing the serialized object to a FILE*. Use tmpfile() so the
|
|
// test does not depend on the working directory (meson runs it from the build
|
|
// dir) and leaves no artifact behind.
|
|
FILE *f = tmpfile();
|
|
ASSERT_NE(f, (void*)0);
|
|
fwrite(buf, 1 /* size */, sz /* count */, f);
|
|
int close_ret = fclose(f);
|
|
ASSERT_EQ(0, close_ret);
|
|
}
|
|
|
|
{
|
|
// Deserialize `buf[0..sz-1]` to `rp`.
|
|
struct capn rc;
|
|
int init_mem_ret = capn_init_mem(&rc, buf, sz, 0 /* packed */);
|
|
ASSERT_EQ(0, init_mem_ret);
|
|
Person_ptr rroot;
|
|
struct Person rp;
|
|
rroot.p = capn_getp(capn_root(&rc), 0 /* off */, 1 /* resolve */);
|
|
read_Person(&rp, rroot);
|
|
|
|
// Assert deserialized values in `rp`
|
|
EXPECT_EQ(rp.id, (uint32_t) 17);
|
|
EXPECT_CAPN_TEXT_EQ(name, rp.name);
|
|
EXPECT_CAPN_TEXT_EQ(email, rp.email);
|
|
|
|
EXPECT_EQ(rp.employment_which, Person_employment_school);
|
|
EXPECT_CAPN_TEXT_EQ(school, rp.employment.school);
|
|
|
|
EXPECT_EQ(2, capn_len(rp.phones));
|
|
|
|
struct Person_PhoneNumber rpn0;
|
|
get_Person_PhoneNumber(&rpn0, rp.phones, 0);
|
|
EXPECT_CAPN_TEXT_EQ("123", rpn0.number);
|
|
EXPECT_EQ(rpn0.type, Person_PhoneNumber_Type_work);
|
|
|
|
struct Person_PhoneNumber rpn1;
|
|
get_Person_PhoneNumber(&rpn1, rp.phones, 1);
|
|
EXPECT_CAPN_TEXT_EQ("234", rpn1.number);
|
|
EXPECT_EQ(rpn1.type, Person_PhoneNumber_Type_home);
|
|
|
|
capn_free(&rc);
|
|
}
|
|
}
|
|
|
|
// Demonstrate accessing serialized objects using accessor functions without
|
|
// first copying values into structs.
|
|
TEST(Examples, PersonWithAccessors) {
|
|
struct capn c;
|
|
capn_init_malloc(&c);
|
|
capn_ptr cr = capn_root(&c);
|
|
struct capn_segment *cs = cr.seg;
|
|
|
|
// Set fields with set_ accessors.
|
|
Person_ptr pp = new_Person(cs);
|
|
{
|
|
Person_set_id(pp, 17);
|
|
|
|
capn_text name = chars_to_text("Name");
|
|
EXPECT_CAPN_TEXT_EQ("Name", name);
|
|
Person_set_name(pp, name);
|
|
|
|
Person_PhoneNumber_list pnl = new_Person_PhoneNumber_list(cs, 1);
|
|
Person_set_phones(pp, pnl);
|
|
Person_PhoneNumber_ptr pn0;
|
|
pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */);
|
|
Person_PhoneNumber_set_type(pn0, Person_PhoneNumber_Type_home);
|
|
}
|
|
|
|
// Assert field values returned by get_ accessors.
|
|
{
|
|
EXPECT_EQ(Person_get_id(pp), 17);
|
|
EXPECT_CAPN_TEXT_EQ("Name", Person_get_name(pp));
|
|
|
|
Person_PhoneNumber_list pnl = Person_get_phones(pp);
|
|
Person_PhoneNumber_ptr pn0;
|
|
pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */);
|
|
EXPECT_EQ(Person_PhoneNumber_Type_home, Person_PhoneNumber_get_type(pn0));
|
|
}
|
|
|
|
capn_free(&c);
|
|
}
|