Commit ef7894e2 authored by Josh Haberman's avatar Josh Haberman

Make conformance tests more strict about the failure list.

The failure lists were falling out of date because the
tests would pass even if people forgot to remove failures
from the list.
parent 20b53254
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <string> #include <string>
#include <fstream>
#include "conformance.pb.h" #include "conformance.pb.h"
#include "conformance_test.h" #include "conformance_test.h"
...@@ -575,24 +576,41 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) { ...@@ -575,24 +576,41 @@ void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
} }
} }
void ConformanceTestSuite::SetFailureList(const vector<string>& failure_list) { void ConformanceTestSuite::SetFailureList(const string& filename,
const vector<string>& failure_list) {
failure_list_filename_ = filename;
expected_to_fail_.clear(); expected_to_fail_.clear();
std::copy(failure_list.begin(), failure_list.end(), std::copy(failure_list.begin(), failure_list.end(),
std::inserter(expected_to_fail_, expected_to_fail_.end())); std::inserter(expected_to_fail_, expected_to_fail_.end()));
} }
bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check, bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
const char* msg) { const std::string& write_to_file,
const std::string& msg) {
if (set_to_check.empty()) { if (set_to_check.empty()) {
return true; return true;
} else { } else {
StringAppendF(&output_, "\n"); StringAppendF(&output_, "\n");
StringAppendF(&output_, "%s:\n", msg); StringAppendF(&output_, "%s\n\n", msg.c_str());
for (set<string>::const_iterator iter = set_to_check.begin(); for (set<string>::const_iterator iter = set_to_check.begin();
iter != set_to_check.end(); ++iter) { iter != set_to_check.end(); ++iter) {
StringAppendF(&output_, " %s\n", iter->c_str()); StringAppendF(&output_, " %s\n", iter->c_str());
} }
StringAppendF(&output_, "\n"); StringAppendF(&output_, "\n");
if (!write_to_file.empty()) {
std::ofstream os(write_to_file);
if (os) {
for (set<string>::const_iterator iter = set_to_check.begin();
iter != set_to_check.end(); ++iter) {
os << *iter << "\n";
}
} else {
StringAppendF(&output_, "Failed to open file: %s\n",
write_to_file.c_str());
}
}
return false; return false;
} }
} }
...@@ -1965,27 +1983,34 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, ...@@ -1965,27 +1983,34 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
)"); )");
bool ok = true; bool ok = true;
if (!CheckSetEmpty(expected_to_fail_, if (!CheckSetEmpty(expected_to_fail_, "nonexistent_tests.txt",
"These tests were listed in the failure list, but they " "These tests were listed in the failure list, but they "
"don't exist. Remove them from the failure list")) { "don't exist. Remove them from the failure list by "
"running:\n"
" ./update_failure_list.py " + failure_list_filename_ +
" --remove nonexistent_tests.txt")) {
ok = false; ok = false;
} }
if (!CheckSetEmpty(unexpected_failing_tests_, if (!CheckSetEmpty(unexpected_failing_tests_, "failing_tests.txt",
"These tests failed. If they can't be fixed right now, " "These tests failed. If they can't be fixed right now, "
"you can add them to the failure list so the overall " "you can add them to the failure list so the overall "
"suite can succeed")) { "suite can succeed. Add them to the failure list by "
"running:\n"
" ./update_failure_list.py " + failure_list_filename_ +
" --add failing_tests.txt")) {
ok = false;
}
if (!CheckSetEmpty(unexpected_succeeding_tests_, "succeeding_tests.txt",
"These tests succeeded, even though they were listed in "
"the failure list. Remove them from the failure list "
"by running:\n"
" ./update_failure_list.py " + failure_list_filename_ +
" --remove succeeding_tests.txt")) {
ok = false; ok = false;
} }
// Sometimes the testee may be fixed before we update the failure list (e.g.,
// the testee is from a different component). We warn about this case but
// don't consider it an overall test failure.
CheckSetEmpty(unexpected_succeeding_tests_,
"These tests succeeded, even though they were listed in "
"the failure list. Remove them from the failure list");
if (verbose_) { if (verbose_) {
CheckSetEmpty(skipped_, CheckSetEmpty(skipped_, "",
"These tests were skipped (probably because support for some " "These tests were skipped (probably because support for some "
"features is not implemented)"); "features is not implemented)");
} }
......
...@@ -98,7 +98,11 @@ class ConformanceTestSuite { ...@@ -98,7 +98,11 @@ class ConformanceTestSuite {
// Sets the list of tests that are expected to fail when RunSuite() is called. // Sets the list of tests that are expected to fail when RunSuite() is called.
// RunSuite() will fail unless the set of failing tests is exactly the same // RunSuite() will fail unless the set of failing tests is exactly the same
// as this list. // as this list.
void SetFailureList(const std::vector<std::string>& failure_list); //
// The filename here is *only* used to create/format useful error messages for
// how to update the failure list. We do NOT read this file at all.
void SetFailureList(const std::string& filename,
const std::vector<std::string>& failure_list);
// Run all the conformance tests against the given test runner. // Run all the conformance tests against the given test runner.
// Test output will be stored in "output". // Test output will be stored in "output".
...@@ -143,12 +147,14 @@ class ConformanceTestSuite { ...@@ -143,12 +147,14 @@ class ConformanceTestSuite {
void ExpectHardParseFailureForProto(const std::string& proto, void ExpectHardParseFailureForProto(const std::string& proto,
const std::string& test_name); const std::string& test_name);
void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type);
bool CheckSetEmpty(const set<string>& set_to_check, const char* msg); bool CheckSetEmpty(const set<string>& set_to_check,
const std::string& write_to_file, const std::string& msg);
ConformanceTestRunner* runner_; ConformanceTestRunner* runner_;
int successes_; int successes_;
int expected_failures_; int expected_failures_;
bool verbose_; bool verbose_;
std::string output_; std::string output_;
std::string failure_list_filename_;
// The set of test names that are expected to fail in this run, but haven't // The set of test names that are expected to fail in this run, but haven't
// failed yet. // failed yet.
......
...@@ -280,11 +280,13 @@ int main(int argc, char *argv[]) { ...@@ -280,11 +280,13 @@ int main(int argc, char *argv[]) {
char *program; char *program;
google::protobuf::ConformanceTestSuite suite; google::protobuf::ConformanceTestSuite suite;
string failure_list_filename;
vector<string> failure_list; vector<string> failure_list;
for (int arg = 1; arg < argc; ++arg) { for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], "--failure_list") == 0) { if (strcmp(argv[arg], "--failure_list") == 0) {
if (++arg == argc) UsageError(); if (++arg == argc) UsageError();
failure_list_filename = argv[arg];
ParseFailureList(argv[arg], &failure_list); ParseFailureList(argv[arg], &failure_list);
} else if (strcmp(argv[arg], "--verbose") == 0) { } else if (strcmp(argv[arg], "--verbose") == 0) {
suite.SetVerbose(true); suite.SetVerbose(true);
...@@ -300,7 +302,7 @@ int main(int argc, char *argv[]) { ...@@ -300,7 +302,7 @@ int main(int argc, char *argv[]) {
} }
} }
suite.SetFailureList(failure_list); suite.SetFailureList(failure_list_filename, failure_list);
ForkPipeRunner runner(program); ForkPipeRunner runner(program);
std::string output; std::string output;
......
...@@ -12,21 +12,11 @@ FieldMaskPathsDontRoundTrip.JsonOutput ...@@ -12,21 +12,11 @@ FieldMaskPathsDontRoundTrip.JsonOutput
FieldMaskTooManyUnderscore.JsonOutput FieldMaskTooManyUnderscore.JsonOutput
JsonInput.AnyUnorderedTypeTag.JsonOutput JsonInput.AnyUnorderedTypeTag.JsonOutput
JsonInput.AnyUnorderedTypeTag.ProtobufOutput JsonInput.AnyUnorderedTypeTag.ProtobufOutput
JsonInput.AnyWithValueForInteger.JsonOutput
JsonInput.AnyWithValueForInteger.ProtobufOutput
JsonInput.AnyWithValueForJsonObject.JsonOutput
JsonInput.AnyWithValueForJsonObject.ProtobufOutput
JsonInput.BoolFieldDoubleQuotedFalse JsonInput.BoolFieldDoubleQuotedFalse
JsonInput.BoolFieldDoubleQuotedTrue JsonInput.BoolFieldDoubleQuotedTrue
JsonInput.BoolFieldIntegerOne
JsonInput.BoolFieldIntegerZero
JsonInput.BytesFieldInvalidBase64Characters
JsonInput.BytesFieldNoPadding JsonInput.BytesFieldNoPadding
JsonInput.DoubleFieldTooSmall JsonInput.DoubleFieldTooSmall
JsonInput.DurationHasZeroFractionalDigit.Validator JsonInput.DurationHasZeroFractionalDigit.Validator
JsonInput.DurationJsonInputTooLarge
JsonInput.DurationJsonInputTooSmall
JsonInput.DurationMissingS
JsonInput.EnumFieldUnknownValue.Validator JsonInput.EnumFieldUnknownValue.Validator
JsonInput.FieldMaskInvalidCharacter JsonInput.FieldMaskInvalidCharacter
JsonInput.FieldNameDuplicate JsonInput.FieldNameDuplicate
...@@ -36,58 +26,12 @@ JsonInput.FieldNameInLowerCamelCase.Validator ...@@ -36,58 +26,12 @@ JsonInput.FieldNameInLowerCamelCase.Validator
JsonInput.FieldNameInSnakeCase.JsonOutput JsonInput.FieldNameInSnakeCase.JsonOutput
JsonInput.FieldNameInSnakeCase.ProtobufOutput JsonInput.FieldNameInSnakeCase.ProtobufOutput
JsonInput.FieldNameNotQuoted JsonInput.FieldNameNotQuoted
JsonInput.FloatFieldTooLarge
JsonInput.FloatFieldTooSmall
JsonInput.Int32FieldLeadingSpace
JsonInput.Int32FieldLeadingZero
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
JsonInput.Int32FieldMinValue.JsonOutput
JsonInput.Int32FieldMinValue.ProtobufOutput
JsonInput.Int32FieldNegativeWithLeadingZero
JsonInput.Int32FieldNotInteger
JsonInput.Int32FieldNotNumber
JsonInput.Int32FieldTooLarge
JsonInput.Int32FieldTooSmall
JsonInput.Int32FieldTrailingSpace
JsonInput.Int64FieldNotInteger
JsonInput.Int64FieldNotNumber
JsonInput.Int64FieldTooLarge
JsonInput.Int64FieldTooSmall
JsonInput.MapFieldValueIsNull JsonInput.MapFieldValueIsNull
JsonInput.OneofFieldDuplicate
JsonInput.RepeatedFieldMessageElementIsNull JsonInput.RepeatedFieldMessageElementIsNull
JsonInput.RepeatedFieldPrimitiveElementIsNull JsonInput.RepeatedFieldPrimitiveElementIsNull
JsonInput.RepeatedFieldTrailingComma JsonInput.RepeatedFieldTrailingComma
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotMessage
JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotString
JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotBool
JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotString
JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotMessage
JsonInput.StringFieldNotAString
JsonInput.StringFieldSurrogateInWrongOrder
JsonInput.StringFieldSurrogatePair.JsonOutput
JsonInput.StringFieldSurrogatePair.ProtobufOutput
JsonInput.StringFieldUnpairedHighSurrogate
JsonInput.StringFieldUnpairedLowSurrogate
JsonInput.StringFieldUppercaseEscapeLetter JsonInput.StringFieldUppercaseEscapeLetter
JsonInput.TimestampJsonInputLowercaseT
JsonInput.TimestampJsonInputLowercaseZ
JsonInput.TimestampJsonInputMissingT
JsonInput.TimestampJsonInputMissingZ
JsonInput.TimestampJsonInputTooLarge
JsonInput.TimestampJsonInputTooSmall
JsonInput.TrailingCommaInAnObject JsonInput.TrailingCommaInAnObject
JsonInput.Uint32FieldNotInteger
JsonInput.Uint32FieldNotNumber
JsonInput.Uint32FieldTooLarge
JsonInput.Uint64FieldNotInteger
JsonInput.Uint64FieldNotNumber
JsonInput.Uint64FieldTooLarge
JsonInput.WrapperTypesWithNullValue.JsonOutput JsonInput.WrapperTypesWithNullValue.JsonOutput
JsonInput.WrapperTypesWithNullValue.ProtobufOutput JsonInput.WrapperTypesWithNullValue.ProtobufOutput
ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
...@@ -102,5 +46,3 @@ ProtobufInput.PrematureEofInPackedField.SINT64 ...@@ -102,5 +46,3 @@ ProtobufInput.PrematureEofInPackedField.SINT64
ProtobufInput.PrematureEofInPackedField.UINT32 ProtobufInput.PrematureEofInPackedField.UINT32
ProtobufInput.PrematureEofInPackedField.UINT64 ProtobufInput.PrematureEofInPackedField.UINT64
ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
TimestampProtoInputTooLarge.JsonOutput
TimestampProtoInputTooSmall.JsonOutput
...@@ -8,8 +8,6 @@ FieldMaskNumbersDontRoundTrip.JsonOutput ...@@ -8,8 +8,6 @@ FieldMaskNumbersDontRoundTrip.JsonOutput
FieldMaskPathsDontRoundTrip.JsonOutput FieldMaskPathsDontRoundTrip.JsonOutput
FieldMaskTooManyUnderscore.JsonOutput FieldMaskTooManyUnderscore.JsonOutput
JsonInput.AnyWithFieldMask.ProtobufOutput JsonInput.AnyWithFieldMask.ProtobufOutput
JsonInput.AnyWithValueForInteger.JsonOutput
JsonInput.AnyWithValueForJsonObject.JsonOutput
JsonInput.BoolFieldAllCapitalFalse JsonInput.BoolFieldAllCapitalFalse
JsonInput.BoolFieldAllCapitalTrue JsonInput.BoolFieldAllCapitalTrue
JsonInput.BoolFieldCamelCaseFalse JsonInput.BoolFieldCamelCaseFalse
...@@ -30,8 +28,6 @@ JsonInput.FloatFieldInfinityNotQuoted ...@@ -30,8 +28,6 @@ JsonInput.FloatFieldInfinityNotQuoted
JsonInput.FloatFieldNanNotQuoted JsonInput.FloatFieldNanNotQuoted
JsonInput.FloatFieldNegativeInfinityNotQuoted JsonInput.FloatFieldNegativeInfinityNotQuoted
JsonInput.Int32FieldLeadingZero JsonInput.Int32FieldLeadingZero
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinValue.JsonOutput
JsonInput.Int32FieldNegativeWithLeadingZero JsonInput.Int32FieldNegativeWithLeadingZero
JsonInput.Int32FieldPlusSign JsonInput.Int32FieldPlusSign
JsonInput.Int32MapFieldKeyNotQuoted JsonInput.Int32MapFieldKeyNotQuoted
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment