THRIFT-3221 Create a tool to audit network compatibility between two
.thrift files
Client: Compiler (general)
Patch: Sanjay Poojary <sanjay.pooj...@ni.com>, Ben Craig
<bencr...@apache.org>, and Zach Hindes <zach.hin...@ni.com>
This closes #541
Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/262cfb41
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/262cfb41
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/262cfb41
Branch: refs/heads/master
Commit: 262cfb4189f3b347f472dfe8b754861ba481c433
Parents: 384f976
Author: Ben Craig <bencr...@apache.org>
Authored: Wed Jul 8 20:37:15 2015 -0500
Committer: Ben Craig <bencr...@apache.org>
Committed: Wed Jul 8 20:37:15 2015 -0500
----------------------------------------------------------------------
compiler/cpp/CMakeLists.txt | 1 +
compiler/cpp/Makefile.am | 1 +
compiler/cpp/src/audit/readme.txt | 32 +++
compiler/cpp/src/audit/t_audit.cpp | 466 ++++++++++++++++++++++++++++++++
compiler/cpp/src/audit/t_audit.h | 11 +
compiler/cpp/src/main.cc | 199 ++++++++++----
compiler/cpp/src/parse/t_program.h | 3 +
test/audit/break1.thrift | 188 +++++++++++++
test/audit/break10.thrift | 190 +++++++++++++
test/audit/break11.thrift | 190 +++++++++++++
test/audit/break12.thrift | 191 +++++++++++++
test/audit/break13.thrift | 191 +++++++++++++
test/audit/break14.thrift | 190 +++++++++++++
test/audit/break15.thrift | 190 +++++++++++++
test/audit/break16.thrift | 191 +++++++++++++
test/audit/break17.thrift | 191 +++++++++++++
test/audit/break18.thrift | 191 +++++++++++++
test/audit/break19.thrift | 191 +++++++++++++
test/audit/break2.thrift | 190 +++++++++++++
test/audit/break20.thrift | 190 +++++++++++++
test/audit/break21.thrift | 190 +++++++++++++
test/audit/break22.thrift | 190 +++++++++++++
test/audit/break23.thrift | 192 +++++++++++++
test/audit/break24.thrift | 191 +++++++++++++
test/audit/break25.thrift | 191 +++++++++++++
test/audit/break26.thrift | 191 +++++++++++++
test/audit/break27.thrift | 190 +++++++++++++
test/audit/break28.thrift | 190 +++++++++++++
test/audit/break29.thrift | 191 +++++++++++++
test/audit/break3.thrift | 191 +++++++++++++
test/audit/break30.thrift | 190 +++++++++++++
test/audit/break31.thrift | 191 +++++++++++++
test/audit/break32.thrift | 191 +++++++++++++
test/audit/break33.thrift | 191 +++++++++++++
test/audit/break34.thrift | 192 +++++++++++++
test/audit/break4.thrift | 190 +++++++++++++
test/audit/break5.thrift | 190 +++++++++++++
test/audit/break6.thrift | 191 +++++++++++++
test/audit/break7.thrift | 190 +++++++++++++
test/audit/break8.thrift | 191 +++++++++++++
test/audit/break9.thrift | 190 +++++++++++++
test/audit/test.thrift | 189 +++++++++++++
test/audit/thrift_audit_test.pl | 261 ++++++++++++++++++
test/audit/warning.thrift | 190 +++++++++++++
44 files changed, 7785 insertions(+), 46 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt
index 01e229d..bc6591c 100644
--- a/compiler/cpp/CMakeLists.txt
+++ b/compiler/cpp/CMakeLists.txt
@@ -56,6 +56,7 @@ set( thrift_SOURCES
src/main.h
src/platform.h
src/md5.h
+ src/audit/t_audit.cpp
src/parse/t_doc.h
src/parse/t_type.h
src/parse/t_base_type.h
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/Makefile.am
----------------------------------------------------------------------
diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am
index 559a839..f5514d9 100644
--- a/compiler/cpp/Makefile.am
+++ b/compiler/cpp/Makefile.am
@@ -40,6 +40,7 @@ thrift_SOURCES = src/main.cc \
src/platform.h \
src/logging.h \
src/md5.h \
+ src/audit/t_audit.cpp \
src/parse/t_doc.h \
src/parse/t_type.h \
src/parse/t_base_type.h \
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/src/audit/readme.txt
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/audit/readme.txt
b/compiler/cpp/src/audit/readme.txt
new file mode 100644
index 0000000..f1c53e3
--- /dev/null
+++ b/compiler/cpp/src/audit/readme.txt
@@ -0,0 +1,32 @@
+Typical usage:
+ thrift.exe --audit <oldFile> <newFile>
+Example run:
+ > thrift.exe --audit test.thrift break1.thrift
+ [Thrift Audit Failure:break1.thrift] New Thrift File has
missing function base_function3
+ [Thrift Audit Warning:break1.thrift] Constant const3 has different value
+
+Problems that the audit tool can catch:
+Errors
+ Removing an enum value
+ Changing the type of a struct field
+ Changing the required-ness of a struct field
+ Removing a struct field
+ Adding a required struct field
+ Adding a struct field 'in the middle'. This usually indicates
an old ID has been recycled
+ Struct removed
+ Oneway-ness change
+ Return type change
+ Missing function
+ Missing service
+ Change in service inheritance
+Warnings
+ Removing a language namespace declaration
+ Changing a namespace
+ Changing an enum value's name
+ Removing an enum class
+ Default value changed
+ Struct field name change
+ Removed constant
+ Type of constant changed
+ Value of constant changed
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/src/audit/t_audit.cpp
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/audit/t_audit.cpp
b/compiler/cpp/src/audit/t_audit.cpp
new file mode 100644
index 0000000..afcbd5e
--- /dev/null
+++ b/compiler/cpp/src/audit/t_audit.cpp
@@ -0,0 +1,466 @@
+
+#include <cassert>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+// Careful: must include globals first for extern definitions
+#include "globals.h"
+
+#include "parse/t_program.h"
+#include "parse/t_scope.h"
+#include "parse/t_const.h"
+#include "parse/t_field.h"
+
+#include "version.h"
+
+#include "t_audit.h"
+
+extern int g_warn;
+extern std::string g_curpath;
+extern bool g_return_failure;
+
+void thrift_audit_warning(int level, const char* fmt, ...) {
+ if (g_warn < level) {
+ return;
+ }
+ va_list args;
+ printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ printf("\n");
+}
+
+void thrift_audit_failure(const char* fmt, ...) {
+ va_list args;
+ fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ g_return_failure = true;
+}
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram)
+{
+ const std::map<std::string, std::string>& newNamespaceMap =
newProgram->get_all_namespaces();
+ const std::map<std::string, std::string>& oldNamespaceMap =
oldProgram->get_all_namespaces();
+
+ for(std::map<std::string, std::string>::const_iterator
oldNamespaceMapIt = oldNamespaceMap.begin();
+ oldNamespaceMapIt != oldNamespaceMap.end();
+ oldNamespaceMapIt++)
+ {
+ std::map<std::string, std::string>::const_iterator
newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
+ if(newNamespaceMapIt == newNamespaceMap.end())
+ {
+ thrift_audit_warning(1, "Language %s not found in new
thrift file\n", (oldNamespaceMapIt->first).c_str());
+ }
+ else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
+ {
+ thrift_audit_warning(1, "Namespace %s changed in new
thrift file\n", (oldNamespaceMapIt->second).c_str());
+ }
+ }
+}
+
+void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
+{
+ const std::vector<t_enum_value*>& oldEnumValues =
oldEnum->get_constants();
+ for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt =
oldEnumValues.begin();
+ oldEnumValuesIt != oldEnumValues.end();
+ oldEnumValuesIt++)
+ {
+ int enumValue = (*oldEnumValuesIt)->get_value();
+ t_enum_value* newEnumValue =
newEnum->get_constant_by_value(enumValue);
+ if(newEnumValue != NULL)
+ {
+ std::string enumName = (*oldEnumValuesIt)->get_name();
+ if(enumName != newEnumValue->get_name())
+ {
+ thrift_audit_warning(1, "Name of the value %d changed
in enum %s\n", enumValue, oldEnum->get_name().c_str());
+ }
+ }
+ else
+ {
+ thrift_audit_failure("Enum value %d missing in %s\n",
enumValue, oldEnum->get_name().c_str());
+ }
+
+ }
+}
+
+void compare_enums(const std::vector<t_enum*>& newEnumList, const
std::vector<t_enum*>& oldEnumList)
+{
+ std::map<std::string,t_enum*> newEnumMap;
+ std::vector<t_enum*>::const_iterator newEnumIt;
+ for(newEnumIt = newEnumList.begin(); newEnumIt !=
newEnumList.end(); newEnumIt++)
+ {
+ newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
+ }
+ std::vector<t_enum*>::const_iterator oldEnumIt;
+ for(oldEnumIt = oldEnumList.begin(); oldEnumIt !=
oldEnumList.end(); oldEnumIt++)
+ {
+ std::map<std::string,t_enum*>::iterator newEnumMapIt;
+ newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
+
+ if(newEnumMapIt == newEnumMap.end())
+ {
+ thrift_audit_warning(1, "Enum %s not found in new thrift
file\n",(*oldEnumIt)->get_name().c_str());
+ }
+ else
+ {
+ compare_enum_values(newEnumMapIt->second, *oldEnumIt);
+ }
+ }
+}
+
+//This function returns 'true' if the two arguements are of same types.
+//Returns false if they are of different type
+bool compare_type(t_type* newType, t_type* oldType)
+{
+ //Comparing names of two types will work when the newType and
oldType are basic types or structs or enums.
+ //However, when they are containers, get_name() returns empty
for which we have to compare the type of
+ //their elements as well.
+ if((newType->get_name()).empty() && (oldType->get_name()).empty())
+ {
+
+ if(newType->is_list() && oldType->is_list())
+ {
+ t_type* newElementType = ((t_list*)newType)->get_elem_type();
+ t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
+ return compare_type(newElementType, oldElementType);
+ }
+ else if(newType->is_map() && oldType->is_map())
+ {
+ t_type* newKeyType = ((t_map*)newType)->get_key_type();
+ t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
+
+ t_type* newValType = ((t_map*)newType)->get_val_type();
+ t_type* oldValType = ((t_map*)oldType)->get_val_type();
+
+ return (compare_type(newKeyType, oldKeyType) &&
compare_type(newValType, oldValType));
+ }
+ else if(newType->is_set() && oldType->is_set())
+ {
+ t_type* newElementType = ((t_set*)newType)->get_elem_type();
+ t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
+ return compare_type(newElementType, oldElementType);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if(newType->get_name() == oldType->get_name())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool compare_pair(std::pair<t_const_value*, t_const_value*>
newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
+{
+ return compare_defaults(newMapPair.first, oldMapPair.first) &&
compare_defaults(newMapPair.second, oldMapPair.second);
+}
+
+// This function returns 'true' if the default values are same.
Returns false if they are different.
+bool compare_defaults(t_const_value* newStructDefault,
t_const_value* oldStructDefault)
+{
+ if(newStructDefault == NULL && oldStructDefault == NULL) return true;
+ else if(newStructDefault == NULL && oldStructDefault != NULL)
return false;
+ else if (newStructDefault != NULL && oldStructDefault == NULL)
return false;
+
+ if(newStructDefault->get_type() != oldStructDefault->get_type())
+ {
+ return false;
+ }
+
+ switch(newStructDefault->get_type())
+ {
+ case t_const_value::CV_INTEGER:
+ return (newStructDefault->get_integer() ==
oldStructDefault->get_integer());
+ case t_const_value::CV_DOUBLE:
+ return (newStructDefault->get_double() ==
oldStructDefault->get_double());
+ case t_const_value::CV_STRING:
+ return (newStructDefault->get_string() ==
oldStructDefault->get_string());
+ case t_const_value::CV_LIST:
+ {
+ const std::vector<t_const_value*>& oldDefaultList =
oldStructDefault->get_list();
+ const std::vector<t_const_value*>& newDefaultList =
newStructDefault->get_list();
+ bool defaultValuesCompare = (oldDefaultList.size() ==
newDefaultList.size());
+
+ return defaultValuesCompare &&
std::equal(newDefaultList.begin(), newDefaultList.end(),
oldDefaultList.begin(), compare_defaults);
+ }
+ case t_const_value::CV_MAP:
+ {
+ const std::map<t_const_value*, t_const_value*> newMap =
newStructDefault->get_map();
+ const std::map<t_const_value*, t_const_value*> oldMap =
oldStructDefault->get_map();
+
+ bool defaultValuesCompare = (oldMap.size() == newMap.size());
+
+ return defaultValuesCompare &&
std::equal(newMap.begin(), newMap.end(), oldMap.begin(),
compare_pair);
+ }
+ case t_const_value::CV_IDENTIFIER:
+ return (newStructDefault->get_identifier() ==
oldStructDefault->get_identifier());
+ default:
+ return false;
+ }
+
+}
+
+void compare_struct_field(t_field* newField, t_field* oldField,
std::string oldStructName)
+{
+ t_type* newFieldType = newField->get_type();
+ t_type* oldFieldType = oldField->get_type();
+ if(!compare_type(newFieldType, oldFieldType))
+ {
+ thrift_audit_failure("Struct Field Type Changed for Id = %d
in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+
+ // A Struct member can be optional if it is mentioned
explicitly, or if it is assigned with default values.
+ bool newStructFieldOptional = (newField->get_req() !=
t_field::T_REQUIRED);
+ bool oldStructFieldOptional = (oldField->get_req() !=
t_field::T_REQUIRED);
+
+ if(newStructFieldOptional != oldStructFieldOptional)
+ {
+ thrift_audit_failure("Struct Field Requiredness Changed for
Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+ if(newStructFieldOptional || oldStructFieldOptional)
+ {
+ if(!compare_defaults(newField->get_value(), oldField->get_value()))
+ {
+ thrift_audit_warning(1, "Default value changed for Id = %d
in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+ }
+
+ std::string fieldName = newField->get_name();
+ if(fieldName != oldField->get_name())
+ {
+ thrift_audit_warning(1, "Struct field name changed for Id =
%d in %s\n", newField->get_key(), oldStructName.c_str());
+ }
+
+}
+
+void compare_single_struct(t_struct* newStruct, t_struct*
oldStruct, const std::string& oldStructName = std::string())
+{
+ std::string structName = oldStructName.empty() ?
oldStruct->get_name() : oldStructName;
+ const std::vector<t_field*>& oldStructMembersInIdOrder =
oldStruct->get_sorted_members();
+ const std::vector<t_field*>& newStructMembersInIdOrder =
newStruct->get_sorted_members();
+ std::vector<t_field*>::const_iterator oldStructMemberIt =
oldStructMembersInIdOrder.begin();
+ std::vector<t_field*>::const_iterator newStructMemberIt =
newStructMembersInIdOrder.begin();
+
+ // Since we have the struct members in their ID order, comparing
their IDs can be done by traversing the two member
+ // lists together.
+ while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() &&
newStructMemberIt == newStructMembersInIdOrder.end()))
+ {
+ if(newStructMemberIt == newStructMembersInIdOrder.end() &&
oldStructMemberIt != oldStructMembersInIdOrder.end())
+ {
+ // A field ID has been removed from the end.
+ thrift_audit_failure("Struct Field removed for Id = %d in
%s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+ oldStructMemberIt++;
+ }
+ else if(newStructMemberIt != newStructMembersInIdOrder.end()
&& oldStructMemberIt == oldStructMembersInIdOrder.end())
+ {
+ //New field ID has been added to the end.
+ if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
+ {
+ thrift_audit_failure("Required Struct Field Added for
Id = %d in %s \n", (*newStructMemberIt)->get_key(),
structName.c_str());
+ }
+ newStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() ==
(*oldStructMemberIt)->get_key())
+ {
+ //Field ID found in both structs. Compare field types,
default values.
+ compare_struct_field(*newStructMemberIt,
*oldStructMemberIt, structName);
+
+ newStructMemberIt++;
+ oldStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() <
(*oldStructMemberIt)->get_key())
+ {
+ //New Field Id is inserted in between
+ //Adding fields to struct is fine, but adding them in the
middle is suspicious. Error!!
+ thrift_audit_failure("Struct field is added in the middle
with Id = %d in %s\n", (*newStructMemberIt)->get_key(),
structName.c_str());
+ newStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() >
(*oldStructMemberIt)->get_key())
+ {
+ //A field is deleted in newStruct.
+ thrift_audit_failure("Struct Field removed for Id = %d in
%s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+ oldStructMemberIt++;
+ }
+
+ }
+}
+
+void compare_structs(const std::vector<t_struct*>& newStructList,
const std::vector<t_struct*>& oldStructList)
+{
+ std::map<std::string,t_struct*> newStructMap;
+ std::vector<t_struct*>::const_iterator newStructListIt;
+ for(newStructListIt = newStructList.begin(); newStructListIt !=
newStructList.end(); newStructListIt++)
+ {
+ newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
+ }
+
+ std::vector<t_struct*>::const_iterator oldStructListIt;
+ for(oldStructListIt = oldStructList.begin(); oldStructListIt !=
oldStructList.end(); oldStructListIt++)
+ {
+ std::map<std::string, t_struct*>::iterator newStructMapIt;
+ newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
+ if(newStructMapIt == newStructMap.end())
+ {
+ thrift_audit_failure("Struct %s not found in new thrift
file\n", (*oldStructListIt)->get_name().c_str());
+ }
+ else
+ {
+ compare_single_struct(newStructMapIt->second, *oldStructListIt);
+ }
+ }
+
+}
+
+void compare_single_function(t_function* newFunction, t_function*
oldFunction)
+{
+ t_type* newFunctionReturnType = newFunction->get_returntype();
+
+ if(newFunction->is_oneway() != oldFunction->is_oneway())
+ {
+ thrift_audit_failure("Oneway attribute changed for function
%s\n",oldFunction->get_name().c_str());
+ }
+ if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
+ {
+ thrift_audit_failure("Return type changed for function
%s\n",oldFunction->get_name().c_str());
+ }
+
+ //Compare function arguments.
+ compare_single_struct(newFunction->get_arglist(),
oldFunction->get_arglist());
+ std::string exceptionName = oldFunction->get_name();
+ exceptionName += "_exception";
+ compare_single_struct(newFunction->get_xceptions(),
oldFunction->get_xceptions(), exceptionName);
+}
+
+void compare_functions(const std::vector<t_function*>&
newFunctionList, const std::vector<t_function*>& oldFunctionList)
+{
+ std::map<std::string, t_function*> newFunctionMap;
+ std::map<std::string, t_function*>::iterator newFunctionMapIt;
+ for(std::vector<t_function*>::const_iterator newFunctionIt =
newFunctionList.begin();
+ newFunctionIt != newFunctionList.end();
+ newFunctionIt++)
+ {
+ newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
+ }
+
+ for(std::vector<t_function*>::const_iterator oldFunctionIt =
oldFunctionList.begin();
+ oldFunctionIt != oldFunctionList.end();
+ oldFunctionIt++)
+ {
+ newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
+ if(newFunctionMapIt == newFunctionMap.end())
+ {
+ thrift_audit_failure("New Thrift File has missing function
%s\n",(*oldFunctionIt)->get_name().c_str());
+ continue;
+ }
+ else
+ {
+ //Function is found in both thrift files. Compare return
type and argument list
+ compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
+ }
+ }
+
+}
+
+void compare_services(const std::vector<t_service*>& newServices,
const std::vector<t_service*>& oldServices)
+{
+ std::vector<t_service*>::const_iterator oldServiceIt;
+
+ std::map<std::string, t_service*> newServiceMap;
+ for(std::vector<t_service*>::const_iterator newServiceIt =
newServices.begin();
+ newServiceIt != newServices.end();
+ newServiceIt++)
+ {
+ newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
+ }
+
+
+ for(oldServiceIt = oldServices.begin(); oldServiceIt !=
oldServices.end(); oldServiceIt++)
+ {
+ const std::string oldServiceName = (*oldServiceIt)->get_name();
+ std::map<std::string, t_service*>::iterator newServiceMapIt =
newServiceMap.find(oldServiceName);
+
+ if(newServiceMapIt == newServiceMap.end())
+ {
+ thrift_audit_failure("New Thrift file is missing a service
%s\n", oldServiceName.c_str());
+ }
+ else
+ {
+ t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
+ t_service* newServiceExtends =
(newServiceMapIt->second)->get_extends();
+
+ if(oldServiceExtends == NULL)
+ {
+ // It is fine to add extends. So if service in older
thrift did not have any extends, we are fine.
+ // DO Nothing
+ }
+ else if(oldServiceExtends != NULL && newServiceExtends == NULL)
+ {
+ thrift_audit_failure("Change in Service inheritance for
%s\n", oldServiceName.c_str());
+ }
+ else
+ {
+ std::string oldExtendsName = oldServiceExtends->get_name();
+ std::string newExtendsName = newServiceExtends->get_name();
+
+ if( newExtendsName != oldExtendsName)
+ {
+ thrift_audit_failure("Change in Service inheritance
for %s\n", oldServiceName.c_str());
+ }
+ }
+
+
compare_functions((newServiceMapIt->second)->get_functions(),
(*oldServiceIt)->get_functions());
+ }
+
+ }
+
+}
+
+void compare_consts(const std::vector<t_const*>& newConst, const
std::vector<t_const*>& oldConst)
+{
+ std::vector<t_const*>::const_iterator newConstIt;
+ std::vector<t_const*>::const_iterator oldConstIt;
+
+ std::map<std::string, t_const*> newConstMap;
+
+ for(newConstIt = newConst.begin(); newConstIt != newConst.end();
newConstIt++)
+ {
+ newConstMap[(*newConstIt)->get_name()] = *newConstIt;
+ }
+
+ std::map<std::string, t_const*>::const_iterator newConstMapIt;
+ for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end();
oldConstIt++)
+ {
+ newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
+ if(newConstMapIt == newConstMap.end())
+ {
+ thrift_audit_warning(1, "Constants Missing %s \n",
((*oldConstIt)->get_name()).c_str());
+ }
+ else if(!compare_type((newConstMapIt->second)->get_type(),
(*oldConstIt)->get_type()))
+ {
+ thrift_audit_warning(1, "Constant %s is of different type
\n", ((*oldConstIt)->get_name()).c_str());
+ }
+ else
if(!compare_defaults((newConstMapIt->second)->get_value(),
(*oldConstIt)->get_value()))
+ {
+ thrift_audit_warning(1, "Constant %s has different
value\n", ((*oldConstIt)->get_name()).c_str());
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/src/audit/t_audit.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/audit/t_audit.h
b/compiler/cpp/src/audit/t_audit.h
new file mode 100644
index 0000000..fd0013a
--- /dev/null
+++ b/compiler/cpp/src/audit/t_audit.h
@@ -0,0 +1,11 @@
+#ifndef T_AUDIT_H
+#define T_AUDIT_H
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram);
+void compare_enums(const std::vector<t_enum*>& newEnumList, const
std::vector<t_enum*>& oldEnumList);
+bool compare_defaults(t_const_value* newStructDefault,
t_const_value* oldStructDefault);
+void compare_structs(const std::vector<t_struct*>& newStructList,
const std::vector<t_struct*>& oldStructList);
+void compare_services(const std::vector<t_service*>& newServices,
const std::vector<t_service*>& oldServices);
+void compare_consts(const std::vector<t_const*>& newConst, const
std::vector<t_const*>& oldConst);
+
+#endif
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/src/main.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index 97d523e..a337cc6 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -51,6 +51,7 @@
#include "parse/t_program.h"
#include "parse/t_scope.h"
#include "generate/t_generator.h"
+#include "audit/t_audit.h"
#include "version.h"
@@ -169,6 +170,17 @@ int g_allow_64bit_consts = 0;
bool gen_recurse = false;
/**
+ * Flags to control thrift audit
+ */
+bool g_audit = false;
+
+/**
+ * Flag to control return status
+ */
+bool g_return_failure = false;
+bool g_audit_fatal = true;
+
+/**
* Win32 doesn't have realpath, so use fallback implementation in that case,
* otherwise this just calls through to realpath
*/
@@ -711,6 +723,13 @@ void help() {
fprintf(stderr, " Keys and values are options
passed to the generator.\n");
fprintf(stderr, " Many options will not require
values.\n");
fprintf(stderr, "\n");
+ fprintf(stderr, "Options related to audit operation\n");
+ fprintf(stderr, " --audit OldFile Old Thrift file to be
audited with 'file'\n");
+ fprintf(stderr, " -Iold dir Add a directory to the list of
directories\n");
+ fprintf(stderr, " searched for include directives
for old thrift file\n");
+ fprintf(stderr, " -Inew dir Add a directory to the list of
directories\n");
+ fprintf(stderr, " searched for include directives
for new thrift file\n");
+ fprintf(stderr, "\n");
fprintf(stderr, "Available generators (and options):\n");
t_generator_registry::gen_map_t gen_map =
t_generator_registry::get_generator_map();
@@ -1029,6 +1048,30 @@ void generate(t_program* program, const
vector<string>& generator_strings) {
}
}
+void audit(t_program* new_program, t_program* old_program, string
new_thrift_include_path, string old_thrift_include_path)
+{
+ vector<string> temp_incl_searchpath = g_incl_searchpath;
+ if(!old_thrift_include_path.empty()) {
+ g_incl_searchpath.push_back(old_thrift_include_path);
+ }
+
+ parse(old_program, NULL);
+
+ g_incl_searchpath = temp_incl_searchpath;
+ if(!new_thrift_include_path.empty()) {
+ g_incl_searchpath.push_back(new_thrift_include_path);
+ }
+
+ parse(new_program, NULL);
+
+ compare_namespace(new_program, old_program);
+ compare_services(new_program->get_services(),
old_program->get_services());
+ compare_enums(new_program->get_enums(), old_program->get_enums());
+ compare_structs(new_program->get_structs(), old_program->get_structs());
+ compare_structs(new_program->get_xceptions(),
old_program->get_xceptions());
+ compare_consts(new_program->get_consts(), old_program->get_consts());
+}
+
/**
* Parse it up.. then spit it back out, in pretty much every
language. Alright
* not that many languages, but the cool ones that we care about.
@@ -1049,6 +1092,9 @@ int main(int argc, char** argv) {
}
vector<string> generator_strings;
+ string old_thrift_include_path;
+ string new_thrift_include_path;
+ string old_input_file;
// Set the current path to a dummy value to make warning messages clearer.
g_curpath = "arguments";
@@ -1118,6 +1164,35 @@ int main(int argc, char** argv) {
#endif
if (!check_is_directory(out_path.c_str()))
return -1;
+ } else if (strcmp(arg, "-audit") == 0) {
+ g_audit = true;
+ arg = argv[++i];
+ if (arg == NULL) {
+ fprintf(stderr, "Missing old thrift file name for audit
operation\n");
+ usage();
+ }
+ char old_thrift_file_rp[THRIFT_PATH_MAX];
+
+ if (saferealpath(arg, old_thrift_file_rp) == NULL) {
+ failure("Could not open input file with realpath: %s", arg);
+ }
+ old_input_file = string(old_thrift_file_rp);
+ } else if(strcmp(arg, "-audit-nofatal") == 0){
+ g_audit_fatal = false;
+ } else if (strcmp(arg, "-Iold") == 0) {
+ arg = argv[++i];
+ if (arg == NULL) {
+ fprintf(stderr, "Missing Include directory for old thrift
file\n");
+ usage();
+ }
+ old_thrift_include_path = string(arg);
+ } else if (strcmp(arg, "-Inew") == 0) {
+ arg = argv[++i];
+ if(arg == NULL) {
+ fprintf(stderr, "Missing Include directory for new thrift file\n");
+ usage();
+ }
+ new_thrift_include_path = string(arg);
} else {
fprintf(stderr, "Unrecognized option: %s\n", arg);
usage();
@@ -1139,41 +1214,6 @@ int main(int argc, char** argv) {
exit(0);
}
- // You gotta generate something!
- if (generator_strings.empty()) {
- fprintf(stderr, "No output language(s) specified\n");
- usage();
- }
-
- // Real-pathify it
- char rp[THRIFT_PATH_MAX];
- if (argv[i] == NULL) {
- fprintf(stderr, "Missing file name\n");
- usage();
- }
- if (saferealpath(argv[i], rp) == NULL) {
- failure("Could not open input file with realpath: %s", argv[i]);
- }
- string input_file(rp);
-
- // Instance of the global parse tree
- t_program* program = new t_program(input_file);
- if (out_path.size()) {
- program->set_out_path(out_path, out_path_is_absolute);
- }
-
- // Compute the cpp include prefix.
- // infer this from the filename passed in
- string input_filename = argv[i];
- string include_prefix;
-
- string::size_type last_slash = string::npos;
- if ((last_slash = input_filename.rfind("/")) != string::npos) {
- include_prefix = input_filename.substr(0, last_slash);
- }
-
- program->set_include_prefix(include_prefix);
-
// Initialize global types
g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
@@ -1188,24 +1228,87 @@ int main(int argc, char** argv) {
g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
- // Parse it!
- parse(program, NULL);
+ if(g_audit)
+ {
+ // Audit operation
- // The current path is not really relevant when we are doing generation.
- // Reset the variable to make warning messages clearer.
- g_curpath = "generation";
- // Reset yylineno for the heck of it. Use 1 instead of 0 because
- // That is what shows up during argument parsing.
- yylineno = 1;
+ if (old_input_file.empty()) {
+ fprintf(stderr, "Missing file name of old thrift file for audit\n");
+ usage();
+ }
- // Generate it!
- generate(program, generator_strings);
+ char new_thrift_file_rp[THRIFT_PATH_MAX];
+ if (argv[i] == NULL) {
+ fprintf(stderr, "Missing file name of new thrift file for audit\n");
+ usage();
+ }
+ if (saferealpath(argv[i], new_thrift_file_rp) == NULL) {
+ failure("Could not open input file with realpath: %s", argv[i]);
+ }
+ string new_input_file(new_thrift_file_rp);
+
+ t_program new_program(new_input_file);
+ t_program old_program(old_input_file);
+
+ audit(&new_program, &old_program, new_thrift_include_path,
old_thrift_include_path);
+
+ } else {
+ // Generate options
+
+ // You gotta generate something!
+ if (generator_strings.empty()) {
+ fprintf(stderr, "No output language(s) specified\n");
+ usage();
+ }
+
+ // Real-pathify it
+ char rp[THRIFT_PATH_MAX];
+ if (argv[i] == NULL) {
+ fprintf(stderr, "Missing file name\n");
+ usage();
+ }
+ if (saferealpath(argv[i], rp) == NULL) {
+ failure("Could not open input file with realpath: %s", argv[i]);
+ }
+ string input_file(rp);
+
+ // Instance of the global parse tree
+ t_program* program = new t_program(input_file);
+ if (out_path.size()) {
+ program->set_out_path(out_path, out_path_is_absolute);
+ }
+
+ // Compute the cpp include prefix.
+ // infer this from the filename passed in
+ string input_filename = argv[i];
+ string include_prefix;
+
+ string::size_type last_slash = string::npos;
+ if ((last_slash = input_filename.rfind("/")) != string::npos) {
+ include_prefix = input_filename.substr(0, last_slash);
+ }
+
+ program->set_include_prefix(include_prefix);
+
+ // Parse it!
+ parse(program, NULL);
+
+ // The current path is not really relevant when we are doing generation.
+ // Reset the variable to make warning messages clearer.
+ g_curpath = "generation";
+ // Reset yylineno for the heck of it. Use 1 instead of 0 because
+ // That is what shows up during argument parsing.
+ yylineno = 1;
+
+ // Generate it!
+ generate(program, generator_strings);
+ delete program;
+ }
// Clean up. Who am I kidding... this program probably orphans heap memory
// all over the place, but who cares because it is about to exit and it is
// all referenced and used by this wacky parse tree up until now anyways.
- delete program;
delete g_type_void;
delete g_type_string;
delete g_type_bool;
@@ -1216,5 +1319,9 @@ int main(int argc, char** argv) {
delete g_type_double;
// Finished
+ if (g_return_failure && g_audit_fatal) {
+ exit(2);
+ }
+ // Finished
return 0;
}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/compiler/cpp/src/parse/t_program.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/parse/t_program.h
b/compiler/cpp/src/parse/t_program.h
index cfab691..556ee6c 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -321,6 +321,9 @@ public:
return std::string();
}
+ const std::map<std::string, std::string>& get_all_namespaces(){
+ return namespaces_;
+ }
// Language specific namespace / packaging
void add_cpp_include(std::string path) { cpp_includes_.push_back(path); }
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break1.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break1.thrift b/test/audit/break1.thrift
new file mode 100644
index 0000000..f77f672
--- /dev/null
+++ b/test/audit/break1.thrift
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//Thrift Method removed from service base.
+
+namespace cpp test
+
+//constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3= [23, 32],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break10.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break10.thrift b/test/audit/break10.thrift
new file mode 100644
index 0000000..00690aa
--- /dev/null
+++ b/test/audit/break10.thrift
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//break10 - Struct field removed from struct2 id =1
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break11.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break11.thrift b/test/audit/break11.thrift
new file mode 100644
index 0000000..a4e0a7d
--- /dev/null
+++ b/test/audit/break11.thrift
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//break11 - Struct field removed from struct3 id =7
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break12.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break12.thrift b/test/audit/break12.thrift
new file mode 100644
index 0000000..e5522ed
--- /dev/null
+++ b/test/audit/break12.thrift
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// derived1_function1 return type changed from enum1 to enum2
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum2 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break13.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break13.thrift b/test/audit/break13.thrift
new file mode 100644
index 0000000..66975cd
--- /dev/null
+++ b/test/audit/break13.thrift
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// derived1_function6 return type changed from struct1 to struct2
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct2 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break14.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break14.thrift b/test/audit/break14.thrift
new file mode 100644
index 0000000..4ccd503
--- /dev/null
+++ b/test/audit/break14.thrift
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// derived1_function6 return type changed from string to double
+
+namespace cpp test
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ double derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break15.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break15.thrift b/test/audit/break15.thrift
new file mode 100644
index 0000000..95f69e6
--- /dev/null
+++ b/test/audit/break15.thrift
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// break15 - derived2_function1 return type changed from list<i32>
to list<i16>
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i16> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break16.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break16.thrift b/test/audit/break16.thrift
new file mode 100644
index 0000000..cdcff7d
--- /dev/null
+++ b/test/audit/break16.thrift
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// break 16 - derived2_function5 return type changed from
map<test_enum1, test_enum2> to map<test_enum3, test_enum2>
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum3, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct2> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/262cfb41/test/audit/break17.thrift
----------------------------------------------------------------------
diff --git a/test/audit/break17.thrift b/test/audit/break17.thrift
new file mode 100644
index 0000000..353b142
--- /dev/null
+++ b/test/audit/break17.thrift
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//break17 - derived2_function6 return type changed from
map<struct1,struct2> to map<struct1, struct3>
+
+namespace cpp test
+
+//Constants
+const i32 const1 = 123;
+const double const2 = 23.3;
+const map<string,string> const3 = {"hello":"world", "thrift":"audit"};
+
+
+//Exception
+exception test_exception1 {
+ 1: i32 code;
+ 2: string json;
+}
+exception test_exception2 {
+ 1: i32 code;
+ 2: string json;
+}
+
+//Enums
+
+enum test_enum1 {
+ enum1_value0 = 0,
+ enum1_value1 = 1,
+ enum1_value2 = 2,
+ enum1_value5 = 5,
+ enum1_value7 = 7,
+ enum1_value8 = 8
+}
+
+enum test_enum2 {
+ enum2_value0 = 0,
+ enum2_value1 = 1,
+ enum2_value2 = 2,
+ enum2_value3 = 3
+}
+
+enum test_enum3 {
+ enum3_value1 = 0,
+ enum3_value2 = 1
+}
+
+struct test_struct1 {
+ 1: i16 struct1_member1,
+ 2: i32 struct1_member2,
+ 3: i64 struct1_member3,
+ 4: double struct1_member4 = 2.5,
+ 5: string struct1_member5 = "Audit test",
+ 6: bool struct1_member6,
+ 7: byte struct1_member7,
+ 8: binary struct1_member8,
+ 9: test_enum1 struct1_member9
+}
+
+struct test_struct2 {
+ 1: list<i16> struct2_member1,
+ 2: list<i32> struct2_member2,
+ 3: list<i64> struct2_member3 = [23, 32 ],
+ 4: list<double> struct2_member4,
+ 5: list<string> struct2_member5,
+ 6: list<bool> struct2_member6,
+ 7: list<byte> struct2_member7,
+ 8: list<binary> struct2_member8,
+ 9: list<test_enum1> struct2_member9
+}
+
+struct test_struct3 {
+ 1: map<i16, i32> struct3_member1 = {1:2, 3:4},
+ 2: map<i64, double> struct3_member2 = {10:1.1, 20:2.1},
+ 3: map<string, bool> struct3_member3,
+ 4: map<byte, test_enum1> struct3_member4,
+ 5: map<test_enum2, test_enum3 > struct3_member5,
+ 7: map<double, string> struct3_member7
+}
+
+struct test_struct4 {
+ 1: i32 struct4_member1,
+ 2: optional i32 struct4_member2
+}
+
+struct test_struct5{
+ 1: double struct5_member1,
+ 2: string struct5_member2 = "Thrift Audit Test"
+}
+struct test_struct6 {
+ 1: i32 struct6_member1,
+ 2: required i32 struct6_member2
+}
+
+service base {
+ oneway void base_oneway(
+ 1: i32 arg1),
+
+ void base_function1(
+ 1: i16 function1_arg1,
+ 2: i32 function1_arg2,
+ 3: i64 function1_arg3,
+ 4: double function1_arg4,
+ 5: string function1_arg5,
+ 6: bool function1_arg6,
+ 7: test_enum1 function1_arg7,
+ 8: test_struct1 function1_arg8),
+
+ void base_function2(
+ 1: list<i16> function2_arg1,
+ 2: list<i32> function2_arg2,
+ 3: list<i64> function2_arg3,
+ 4: list<double> function2_arg4,
+ 5: list<string> function2_arg5,
+ 6: list<bool> function2_arg6,
+ 7: list<byte> function2_arg7,
+ 8: list<test_enum1> function2_arg8,
+ 9: list<test_struct1> function2_arg9) throws (1:test_exception2 e),
+
+ void base_function3(),
+
+}
+
+service derived1 extends base {
+
+ test_enum1 derived1_function1(
+ 1: i64 function1_arg1,
+ 2: double function1_arg2,
+ 3: test_enum1 function1_arg3) throws (1:test_exception2 e),
+
+ i64 derived1_function2(
+ 1: list<i64> function2_arg1,
+ 2: list<double> function2_arg2,
+ 3: list<string> function2_arg3,
+ 4: list<byte> function2_arg4,
+ 5: list<test_enum1> function2_arg5) throws (1:test_exception2 e),
+
+ double derived1_function3(
+ 1: string function3_arg1,
+ 2: bool function3_arg2) throws (1:test_exception2 e),
+
+ string derived1_function4(
+ 1: string function4_arg1,
+ 2: bool function4_arg2) throws (1:test_exception2 e),
+
+
+ bool derived1_function5(
+ 1: map<i64, double> function5_arg1,
+ 2: map<string, bool> function5_arg2,
+ 3: map<test_enum1, test_enum2> function5_arg3) throws
(1:test_exception2 e),
+
+ test_struct1 derived1_function6(
+ 1: double function6_arg1) throws (1:test_exception2 e),
+}
+
+service derived2 extends base {
+
+ list<i32> derived2_function1(
+ 1: i32 function1_arg1) throws (1:test_exception2 e),
+
+ list<test_enum1> derived2_function2(
+ 1:i64 function2_arg2) throws (1:test_exception2 e),
+
+ list<test_struct1> derived2_function3(
+ 1:double function3_arg1) throws(1:test_exception2 e),
+
+ map<double, string> derived2_function4(
+ 1:string function4_arg1) throws(1:test_exception2 e),
+
+ map<test_enum1, test_enum2> derived2_function5(
+ 1:bool function5_arg1) throws(1:test_exception2 e),
+
+ map<test_struct1, test_struct3> derived2_function6(
+ 1:bool function6_arg1) throws(1:test_exception2 e),
+
+}