| #!/usr/bin/perl -w |
| |
| # 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. |
| |
| |
| #break1 - Thrift method removed from service base |
| #break2 - Struct field changed in test_struct1(i16 to i32) |
| #break3 - Struct field changed in test_struct1(enum1 to enum2) |
| #break4 - Field type changed in test_struct1(bool to string) |
| #break5- member field type changed in test_struct1(bool to list<bool>) |
| #break6- Field type changed in test_struct2 (list<double> to list<i16>) |
| #break7 - requiredness removed in struct6 |
| #break8 - requiredness addedd in struct5 |
| #break9 - Struct field removed from struct1 |
| #break10 - Struct field removed from struct2 id = 1 |
| #break11 - Struct field removed from struct3 last id |
| #break12 - derived1_function1 return type changed from enum1 to enum2 |
| #break13 - derived1_function6 return type changed from struct1 to struct2 |
| #break14 - derived1_function4 return type changed from string to double |
| #break15 - derived2_function1 return type changed from list<i32> to list<i16> |
| #break16 - derived2_function5 return type changed from map<test_enum1,test_enum2> to map<test_enum3, test_enum2> |
| #break17 - derived2_function6 return type changed from map<struct1,struct2> to map<struct1, struct3> |
| #break18- oneway removed from base_oneway |
| #break19 - oneway added to base_function1 |
| #break20 - first enum value removed from enum1 |
| #break21- last enum value removed from enum2 |
| #break22 - in-between enum value removed from enum1 |
| #break23 - required struct field added to struct4 |
| #break24 - removed inheritance of derived1. |
| #break25 - changed inheritance of derived2. |
| #break26 - Field type changed in base_function1 argument id=3 |
| #break27 - argument changed base_function2 list<enum1> to list<enum3> id =8 |
| #break28- derived1_function5 arguement type changed map<i64, double> to list<i64> |
| #break29 - base_function2 arguemnt type changed list<string> to string |
| #break30- derived1_function6 argument changed struct1 to map<struct1,struct1> |
| #break31 - Exception removed to base_function2 |
| #break32- Exception1 field type changed for id =1 |
| #break33 - derived1_function1 exception type changed. |
| #break34 - Field added to struct with Field ID being in between two existing field IDs |
| |
| #warning.thrift |
| #Changing defaults |
| #Id=1 struct5 |
| #id=2 struct5 |
| #id=4 struct2(list<double>) |
| #id=3 struct2(list<i64> default values removed) |
| #id 4 struct1 change in double value |
| #id 5 struct1 (default string value removed) |
| #id=1 struct3 (change in map values) |
| #id2 struct3 (change in map keys) |
| |
| #change in inheritance for derived1 and derived2 |
| |
| #change in struct field names |
| #id9 struct1 |
| #id2 struct2 |
| |
| use strict; |
| use warnings; |
| use Getopt::Std; |
| |
| # globals |
| my $gArguments = ""; # arguments that will be passed to AuditTool |
| my $gAuditToolPath = ""; |
| my $gPreviousThriftPath; # previous thrift path |
| my $gCurrentThriftPath; # current thrift path |
| my $gThriftFileFolder; |
| my $gBreakingFilesCount =34; |
| |
| my $gVerbose = 0; |
| #functions |
| sub auditBreakingChanges; |
| sub auditNonBreakingChanges; |
| |
| main(); |
| |
| sub main |
| { |
| parseOptions(); |
| auditBreakingChanges(); |
| auditNonBreakingChanges(); |
| } |
| |
| sub parseOptions |
| { |
| my %options = (); |
| if ( getopts ('vf:o:t:',\%options) ) |
| { |
| # current (new) thrift folder |
| if ($options{'f'}) |
| { |
| $gThriftFileFolder = $options{'f'}; |
| $gPreviousThriftPath = $gThriftFileFolder."/test.thrift"; |
| } |
| else |
| { |
| die "Missing Folder containing thrift files\n"; |
| } |
| |
| if($options{'t'}) |
| { |
| $gAuditToolPath = $options{'t'}; |
| } |
| else |
| { |
| die "Audit Tool Path required \n"; |
| } |
| |
| if ($options{'v'}) |
| { |
| $gVerbose = 1; |
| } |
| |
| } |
| } |
| |
| sub auditBreakingChanges |
| { |
| my $breakingFileBaseName = $gThriftFileFolder."/break"; |
| my $newThriftFile; |
| for(my $i=1; $i <= $gBreakingFilesCount; $i++) |
| { |
| $newThriftFile = $breakingFileBaseName."$i.thrift"; |
| my $arguments = $gPreviousThriftPath." ".$newThriftFile; |
| my ($exitCode, $output) = callThriftAuditTool($arguments); |
| print $output if $gVerbose eq 1; |
| |
| if($exitCode == 1) |
| { |
| # thrift_audit returns 1 when it is not able to find files or other non-audit failures |
| print "exiting with exit code =1 i = ".$i."\n"; |
| print $output; |
| exit $exitCode; |
| } |
| if($exitCode != 2) |
| { |
| # thrift-audit return 2 for audit failures. So for Breaking changes we should get 2 as return value. |
| print $output; |
| die "\nTEST FAILURE: Breaking Change not detected for thrift file $newThriftFile, code=$exitCode \n"; |
| } |
| if(index($output,getMessageSubString("break$i")) == -1) |
| { |
| #Audit tool detected failure, but not the expected one. The change in breaking thrift file does not match getMessageSubString() |
| print $output; |
| die "\nTest FAILURE: Audit tool detected failure, but not the expected one!\n"; |
| } |
| else |
| { |
| #Thrift audit tool has detected audit failure and has returned exited to status code 2 |
| print "Test Pass: Audit Failure detected for thrift file break$i.thrift \n"; |
| } |
| } |
| |
| } |
| |
| sub auditNonBreakingChanges |
| { |
| my $breakingFileBaseName = $gThriftFileFolder."/warning"; |
| my $newThriftFile; |
| $newThriftFile = $breakingFileBaseName.".thrift"; |
| my $arguments = $gPreviousThriftPath." ".$newThriftFile; |
| my ($exitCode, $output) = callThriftAuditTool($arguments); |
| print $output if $gVerbose eq 1; |
| |
| if($exitCode == 1) |
| { |
| # thrift_audit returns 1 when it is not able to find files or other non-audit failures |
| print "exiting with exit code = 1 for file warning.thrift\n"; |
| exit $exitCode; |
| } |
| elsif($exitCode != 0) |
| { |
| # thrift-audit return 0 if there are no audit failures. |
| die "\nTEST FAILURE: Non Breaking changes returned failure for thrift file $newThriftFile \n"; |
| } |
| else |
| { |
| #Thrift audit tool has exited with status 0. |
| print "Test Pass: Audit tool exits with success for warnings \n"; |
| } |
| |
| |
| } |
| |
| # ----------------------------------------------------------------------------------------------------- |
| # call thriftAuditTool script |
| sub callThriftAuditTool ( $ ) |
| { |
| my $args = shift; |
| |
| my $command = "$gAuditToolPath --audit $args"; |
| my $output = `$command 2>&1`; |
| my $exitCode = $? >> 8; |
| |
| return ($exitCode,$output); |
| } |
| |
| sub getMessageSubString( $ ) |
| { |
| my $fileName = shift; |
| my %lookupTable = ( |
| "break1" => "base_function3", |
| "break2" => "test_struct1", |
| "break3" => "test_struct1", |
| "break4" => "test_struct1", |
| "break5" => "test_struct1", |
| "break6" => "test_struct2", |
| "break7" => "test_struct6", |
| "break8" => "test_struct5", |
| "break9" => "test_struct1", |
| "break10" => "test_struct2", |
| "break11" => "test_struct3", |
| "break12" => "derived1_function1", |
| "break13" => "derived1_function6", |
| "break14" => "derived1_function4", |
| "break15" => "derived2_function1", |
| "break16" => "derived2_function5", |
| "break17" => "derived2_function6", |
| "break18" => "base_oneway", |
| "break19" => "base_function1", |
| "break20" => "test_enum1", |
| "break21" => "test_enum2", |
| "break22" => "test_enum1", |
| "break23" => "test_struct4", |
| "break24" => "derived1", |
| "break25" => "derived2", |
| "break26" => "base_function1", |
| "break27" => "base_function2_args", |
| "break28" => "derived1_function5_args", |
| "break29" => "base_function2_args", |
| "break30" => "derived1_function6", |
| "break31" => "base_function2_exception", |
| "break32" => "test_exception1", |
| "break33" => "derived1_function1_exception", |
| "break34" => "test_struct3", |
| ); |
| if (not exists $lookupTable{ $fileName }) |
| { |
| print "in the null case\n"; |
| return "NULL"; |
| } |
| |
| my $retval = $lookupTable{ $fileName }; |
| print "$fileName => $retval\n"; |
| return $lookupTable{ $fileName }; |
| } |