summaryrefslogtreecommitdiff
path: root/tests/conformance_upb.c
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2017-07-04 17:02:48 -0700
committerJoshua Haberman <jhaberman@gmail.com>2017-07-04 17:02:48 -0700
commit9cb10577fcefa3ed004e0bbdc61e6238e8137e3c (patch)
treee270ff7b0f782dadf2942f6816b071aa2a134e21 /tests/conformance_upb.c
parent76fcdd2ee92e8f7852f96ccd49fe776236ae4e60 (diff)
First version of a real C codegen for upb.
Also includes an implementation of the conformance tests to display what the API usage will be like. There is still a lot to do, and things that are broken (oneofs, repeated fields, etc), but it's a good start.
Diffstat (limited to 'tests/conformance_upb.c')
-rw-r--r--tests/conformance_upb.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c
new file mode 100644
index 0000000..9f83e80
--- /dev/null
+++ b/tests/conformance_upb.c
@@ -0,0 +1,162 @@
+/* This is a upb implementation of the upb conformance tests, see:
+ * https://github.com/google/protobuf/tree/master/conformance
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "conformance.upb.h"
+#include "google/protobuf/test_messages_proto3.upb.h"
+
+int test_count = 0;
+
+bool CheckedRead(int fd, void *buf, size_t len) {
+ size_t ofs = 0;
+ while (len > 0) {
+ ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+ if (bytes_read == 0) return false;
+
+ if (bytes_read < 0) {
+ perror("reading from test runner");
+ exit(1);
+ }
+
+ len -= bytes_read;
+ ofs += bytes_read;
+ }
+
+ return true;
+}
+
+void CheckedWrite(int fd, const void *buf, size_t len) {
+ if (write(fd, buf, len) != len) {
+ perror("writing to test runner");
+ exit(1);
+ }
+}
+
+void DoTest(
+ const conformance_ConformanceRequest* request,
+ conformance_ConformanceResponse *response,
+ upb_env *env) {
+ conformance_ConformanceResponse_new(env);
+ protobuf_test_messages_proto3_TestAllTypes *test_message;
+
+ switch (conformance_ConformanceRequest_payload_case(request)) {
+ case conformance_ConformanceRequest_payload_protobuf_payload:
+ test_message = protobuf_test_messages_proto3_TestAllTypes_parsenew(
+ conformance_ConformanceRequest_protobuf_payload(request), env);
+
+ if (!test_message) {
+ /* TODO(haberman): return details. */
+ static char msg[] = "Parse error (no more details available).";
+ conformance_ConformanceResponse_set_parse_error(
+ response, upb_stringview_make(msg, sizeof(msg)));
+ return;
+ }
+ break;
+
+ case conformance_ConformanceRequest_payload_json_payload: {
+ static char msg[] = "JSON support not yet implemented.";
+ conformance_ConformanceResponse_set_skipped(
+ response, upb_stringview_make(msg, sizeof(msg)));
+ return;
+ }
+
+ case conformance_ConformanceRequest_payload_NOT_SET:
+ fprintf(stderr, "conformance_upb: Request didn't have payload.");
+ exit(1);
+ }
+
+ switch (conformance_ConformanceRequest_requested_output_format(request)) {
+ case conformance_UNSPECIFIED:
+ fprintf(stderr, "conformance_upb: Unspecified output format.");
+ exit(1);
+
+ case conformance_PROTOBUF: {
+ size_t serialized_len;
+ char *serialized = protobuf_test_messages_proto3_TestAllTypes_serialize(
+ test_message, env, &serialized_len);
+ if (!serialized) {
+ fprintf(stderr, "conformance_upb: Error serialiing.");
+ exit(1);
+ }
+ conformance_ConformanceResponse_set_protobuf_payload(
+ response, upb_stringview_make(serialized, serialized_len));
+ break;
+ }
+
+ case conformance_JSON: {
+ static char msg[] = "JSON support not yet implemented.";
+ conformance_ConformanceResponse_set_skipped(
+ response, upb_stringview_make(msg, sizeof(msg)));
+ break;
+ }
+
+ default:
+ fprintf(stderr, "conformance_upb: Unknown output format: %d",
+ conformance_ConformanceRequest_requested_output_format(request));
+ exit(1);
+ }
+
+ return;
+}
+
+bool DoTestIo() {
+ upb_env env;
+ upb_status status;
+ char *serialized_input;
+ char *serialized_output;
+ uint32_t input_size;
+ size_t output_size;
+ conformance_ConformanceRequest *request;
+ conformance_ConformanceResponse *response;
+
+ if (!CheckedRead(STDIN_FILENO, &input_size, sizeof(uint32_t))) {
+ // EOF.
+ return false;
+ }
+
+ upb_env_init(&env);
+ upb_env_reporterrorsto(&env, &status);
+ serialized_input = upb_env_malloc(&env, input_size);
+
+ if (!CheckedRead(STDIN_FILENO, serialized_input, input_size)) {
+ fprintf(stderr, "conformance_upb: unexpected EOF on stdin.\n");
+ exit(1);
+ }
+
+ request = conformance_ConformanceRequest_parsenew(
+ upb_stringview_make(serialized_input, input_size), &env);
+ response = conformance_ConformanceResponse_new(&env);
+
+ if (request) {
+ DoTest(request, response, &env);
+ } else {
+ fprintf(stderr, "conformance_upb: parse of ConformanceRequest failed: %s\n",
+ upb_status_errmsg(&status));
+ }
+
+ serialized_output = conformance_ConformanceResponse_serialize(
+ response, &env, &output_size);
+
+ CheckedWrite(STDOUT_FILENO, &output_size, sizeof(uint32_t));
+ CheckedWrite(STDOUT_FILENO, serialized_output, output_size);
+
+ test_count++;
+
+ return true;
+}
+
+int main() {
+ while (1) {
+ if (!DoTestIo()) {
+ fprintf(stderr, "conformance_upb: received EOF from test runner "
+ "after %d tests, exiting\n", test_count);
+ return 0;
+ }
+ }
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback