Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.6 KiB
165 lines
4.6 KiB
/* 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 <stdio.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 ((size_t)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 const 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 const 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.\n"); |
|
return; |
|
} |
|
|
|
switch (conformance_ConformanceRequest_requested_output_format(request)) { |
|
case conformance_UNSPECIFIED: |
|
fprintf(stderr, "conformance_upb: Unspecified output format.\n"); |
|
exit(1); |
|
|
|
case conformance_PROTOBUF: { |
|
size_t serialized_len; |
|
char *serialized = protobuf_test_messages_proto3_TestAllTypes_serialize( |
|
test_message, env, &serialized_len); |
|
if (!serialized) { |
|
static const char msg[] = "Error serializing."; |
|
conformance_ConformanceResponse_set_serialize_error( |
|
response, upb_stringview_make(msg, sizeof(msg))); |
|
return; |
|
} |
|
conformance_ConformanceResponse_set_protobuf_payload( |
|
response, upb_stringview_make(serialized, serialized_len)); |
|
break; |
|
} |
|
|
|
case conformance_JSON: { |
|
static const 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\n", |
|
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; |
|
} |
|
} |
|
}
|
|
|