grpc 第三方依赖 就是grpc的 third_party 文件夹
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.
 
 
 
 
 
 

157 lines
6.0 KiB

#include <functional>
#include <iostream>
#if defined(WIN32)
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#endif
#include "validate/validate.h"
#include "tests/harness/cases/bool.pb.h"
#include "tests/harness/cases/bool.pb.validate.h"
#include "tests/harness/cases/bytes.pb.h"
#include "tests/harness/cases/bytes.pb.validate.h"
#include "tests/harness/cases/enums.pb.h"
#include "tests/harness/cases/enums.pb.validate.h"
#include "tests/harness/cases/filename-with-dash.pb.h"
#include "tests/harness/cases/filename-with-dash.pb.validate.h"
#include "tests/harness/cases/maps.pb.h"
#include "tests/harness/cases/maps.pb.validate.h"
#include "tests/harness/cases/messages.pb.h"
#include "tests/harness/cases/messages.pb.validate.h"
#include "tests/harness/cases/numbers.pb.h"
#include "tests/harness/cases/numbers.pb.validate.h"
#include "tests/harness/cases/oneofs.pb.h"
#include "tests/harness/cases/oneofs.pb.validate.h"
#include "tests/harness/cases/repeated.pb.h"
#include "tests/harness/cases/repeated.pb.validate.h"
#include "tests/harness/cases/strings.pb.h"
#include "tests/harness/cases/strings.pb.validate.h"
#include "tests/harness/cases/wkt_any.pb.h"
#include "tests/harness/cases/wkt_any.pb.validate.h"
#include "tests/harness/cases/wkt_duration.pb.h"
#include "tests/harness/cases/wkt_duration.pb.validate.h"
#include "tests/harness/cases/wkt_timestamp.pb.h"
#include "tests/harness/cases/wkt_timestamp.pb.validate.h"
#include "tests/harness/cases/wkt_wrappers.pb.h"
#include "tests/harness/cases/wkt_wrappers.pb.validate.h"
#include "tests/harness/cases/kitchen_sink.pb.h"
#include "tests/harness/cases/kitchen_sink.pb.validate.h"
#include "tests/harness/harness.pb.h"
namespace {
using tests::harness::TestCase;
using tests::harness::TestResult;
using google::protobuf::Any;
std::ostream& operator<<(std::ostream& out, const TestResult& result) {
if (result.reasons_size() > 0) {
out << "valid: " << result.valid() << " reason: '" << result.reasons(0) << "'"
<< std::endl;
} else {
out << "valid: " << result.valid() << " reason: unknown"
<< std::endl;
}
return out;
}
void WriteTestResultAndExit(const TestResult& result) {
if (!result.SerializeToOstream(&std::cout)) {
std::cerr << "could not martial response: ";
std::cerr << result << std::endl;
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void ExitIfFailed(bool succeeded, const pgv::ValidationMsg& err_msg) {
if (succeeded) {
return;
}
TestResult result;
result.set_error(true);
result.add_reasons(pgv::String(err_msg));
WriteTestResultAndExit(result);
}
std::function<TestResult()> GetValidationCheck(const Any& msg) {
// This macro is intended to be called once for each message type with the
// fully-qualified class name passed in as the only argument CLS. It checks
// whether the msg argument above can be unpacked as a CLS. If so, it returns
// a lambda that, when called, unpacks the message and validates it as a CLS.
// This is here to work around the lack of duck-typing in C++, and because the
// validation function can't be specified as a virtual method on the
// google::protobuf::Message class.
#define TRY_RETURN_VALIDATE_CALLABLE(CLS) \
if (msg.Is<CLS>() && !msg.Is<::tests::harness::cases::MessageIgnored>()) { \
return [msg] () { \
pgv::ValidationMsg err_msg; \
TestResult result; \
CLS unpacked; \
msg.UnpackTo(&unpacked); \
try { \
result.set_valid(Validate(unpacked, &err_msg)); \
result.add_reasons(std::move(err_msg)); \
} catch (pgv::UnimplementedException& e) { \
/* don't fail for unimplemented validations */ \
result.set_valid(false); \
result.set_allowfailure(true); \
result.add_reasons(e.what()); \
} \
return result; \
}; \
}
// These macros are defined in the various validation headers and call the
// above macro once for each message class in the header.
X_TESTS_HARNESS_CASES_BOOL(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_BYTES(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_ENUMS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_MAPS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_MESSAGES(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_NUMBERS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_ONEOFS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_REPEATED(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_STRINGS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_WKT_ANY(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_WKT_DURATION(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_WKT_TIMESTAMP(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_WKT_WRAPPERS(TRY_RETURN_VALIDATE_CALLABLE)
X_TESTS_HARNESS_CASES_KITCHEN_SINK(TRY_RETURN_VALIDATE_CALLABLE)
// TODO(akonradi) add macros as the C++ validation code gets fleshed out for
// more field types.
#undef TRY_RETURN_VALIDATE_CALLABLE
// TODO(akonradi) remove this once all C++ validation code is done
return []() {
TestResult result;
result.set_valid(false);
result.set_allowfailure(true);
result.add_reasons("not implemented");
return result;
};
}
} // namespace
int main() {
TestCase test_case;
#if defined(WIN32)
// need to explicitly set the stdin file mode to binary on Windows
ExitIfFailed(_setmode(_fileno(stdin), _O_BINARY) != -1, "failed to set stdin to binary mode");
#endif
ExitIfFailed(test_case.ParseFromIstream(&std::cin), "failed to parse TestCase");
auto validate_fn = GetValidationCheck(test_case.message());
WriteTestResultAndExit(validate_fn());
return 0;
}