This is an automated email from the ASF dual-hosted git repository.

jensg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/thrift.git


The following commit(s) were added to refs/heads/master by this push:
     new ec57271  THRIFT-5251 StringUtils<T>.ToString() raises an exception for 
enum values outside range Client: Delphi Patch: Jens Geyer
ec57271 is described below

commit ec57271d5b90ba06eaad99dda26dc0af9bd2af71
Author: Jens Geyer <[email protected]>
AuthorDate: Mon Jul 13 21:15:31 2020 +0200

    THRIFT-5251 StringUtils<T>.ToString() raises an exception for enum values 
outside range
    Client: Delphi
    Patch: Jens Geyer
---
 lib/delphi/src/Thrift.Utils.pas                    | 12 +++
 lib/delphi/test/typeregistry/Test.EnumToString.pas | 93 ++++++++++++++++++++++
 ...{TestTypeRegistry.dpr => Test.TypeRegistry.pas} | 40 +++++-----
 lib/delphi/test/typeregistry/TestTypeRegistry.dpr  | 57 +++----------
 4 files changed, 136 insertions(+), 66 deletions(-)

diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas
index bc9b460..bfd020e 100644
--- a/lib/delphi/src/Thrift.Utils.pas
+++ b/lib/delphi/src/Thrift.Utils.pas
@@ -313,6 +313,7 @@ begin
   pType := PTypeInfo(TypeInfo(T));
   if Assigned(pType) then begin
     case pType^.Kind of
+
       tkInterface : begin
         pIntf := PInterface(@value);
         if Supports( pIntf^, ISupportsToString, stos) then begin
@@ -320,6 +321,17 @@ begin
           Exit;
         end;
       end;
+
+      tkEnumeration : begin
+        case SizeOf(value) of
+          1 : begin result := EnumUtils<T>.ToString( PShortInt(@value)^);  
Exit; end;
+          2 : begin result := EnumUtils<T>.ToString( PSmallInt(@value)^);  
Exit; end;
+          4 : begin result := EnumUtils<T>.ToString( PLongInt(@value)^);  
Exit; end;
+        else
+          ASSERT(FALSE); // in theory, this should not happen
+        end;
+      end;
+
     end;
   end;
 
diff --git a/lib/delphi/test/typeregistry/Test.EnumToString.pas 
b/lib/delphi/test/typeregistry/Test.EnumToString.pas
new file mode 100644
index 0000000..a3d095d
--- /dev/null
+++ b/lib/delphi/test/typeregistry/Test.EnumToString.pas
@@ -0,0 +1,93 @@
+(*
+ * 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.
+ *)
+
+unit Test.EnumToString;
+
+interface
+
+uses
+  Classes, SysUtils,
+  Thrift.Utils,
+  DebugProtoTest;
+
+
+procedure RunTest;
+
+
+implementation
+
+{$SCOPEDENUMS ON}
+
+type
+  TIrregularEnum = (  // has gaps and/or does not start at zero
+    FiveHundretOne = 501,
+    FiveHundretTwo = 502,
+    FiveHundretFive = 505
+  );
+
+  TRegularEnum = (  // starts at zero, no gaps, no duplicates
+    One,
+    Two,
+    Three
+  );
+
+
+procedure IrregularEnumToString;
+// TIrregularEnum does not run from 0 to N, so we don't have RTTI for it
+// Search for "E2134: Type has no typeinfo" message to get the details
+// Unfortunately, this also means that StringUtils<T>.ToString() does not work 
for enums w/o RTTI
+var value : Integer;
+    sA,sB : string;
+begin
+  for value := Pred(Ord(Low(TIrregularEnum))) to 
Succ(Ord(High(TIrregularEnum))) do begin
+    sA := EnumUtils<TIrregularEnum>.ToString(Ord(value));               // 
much more reliable
+    sB := StringUtils<TIrregularEnum>.ToString(TIrregularEnum(value));  // 
does not really work
+    WriteLn( '- TIrregularEnum('+IntToStr(value)+'): EnumUtils => ',sA,', 
StringUtils => ', sB);
+  end;
+end;
+
+
+procedure RegularEnumToString;
+// Regular enums have RTTI and work like a charm
+var value : Integer;
+    sA,sB : string;
+begin
+  for value := Pred(Ord(Low(TRegularEnum))) to Succ(Ord(High(TRegularEnum))) 
do begin
+    sA := EnumUtils<TRegularEnum>.ToString(Ord(value));
+    sB := StringUtils<TRegularEnum>.ToString(TRegularEnum(value));
+    if sA = sB  // both are expected to work with regular enums
+    then WriteLn( '- TRegularEnum('+IntToStr(value)+'): ',sA,' = ', sB)
+    else raise Exception.Create( 'Test failed: '+sA+' <> '+sB);
+  end;
+end;
+
+
+procedure RunTest;
+begin
+  Writeln('Testing enum utils ...');
+
+  RegularEnumToString;
+  IrregularEnumToString;
+
+  Writeln;
+end;
+
+
+end.
+
diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr 
b/lib/delphi/test/typeregistry/Test.TypeRegistry.pas
similarity index 68%
copy from lib/delphi/test/typeregistry/TestTypeRegistry.dpr
copy to lib/delphi/test/typeregistry/Test.TypeRegistry.pas
index 31c0fb2..96e30d8 100644
--- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
+++ b/lib/delphi/test/typeregistry/Test.TypeRegistry.pas
@@ -17,34 +17,31 @@
  * under the License.
  *)
 
-program TestTypeRegistry;
+unit Test.TypeRegistry;
 
-{$APPTYPE CONSOLE}
+interface
 
 uses
-  Classes, Windows, SysUtils, Generics.Collections, TypInfo,
-  Thrift in '..\..\src\Thrift.pas',
-  Thrift.Transport in '..\..\src\Thrift.Transport.pas',
-  Thrift.Exception in '..\..\src\Thrift.Exception.pas',
-  Thrift.Socket in '..\..\src\Thrift.Socket.pas',
-  Thrift.Protocol in '..\..\src\Thrift.Protocol.pas',
-  Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas',
-  Thrift.Collections in '..\..\src\Thrift.Collections.pas',
-  Thrift.Configuration in '..\..\src\Thrift.Configuration.pas',
-  Thrift.Server in '..\..\src\Thrift.Server.pas',
-  Thrift.Utils in '..\..\src\Thrift.Utils.pas',
-  Thrift.Serializer in '..\..\src\Thrift.Serializer.pas',
-  Thrift.Stream in '..\..\src\Thrift.Stream.pas',
-  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
-  Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
+  Classes, SysUtils, TypInfo,
+  Thrift,
+  Thrift.TypeRegistry,
   DebugProtoTest;
 
+
+procedure RunTest;
+
+
+implementation
+
+
 type
   Tester<T : IInterface> = class
   public
     class procedure Test;
   end;
 
+
+
 class procedure Tester<T>.Test;
 var instance : T;
     name : string;
@@ -59,8 +56,11 @@ begin
   end;
 end;
 
+
+procedure RunTest;
 begin
-  Writeln('Testing ...');
+  Writeln('Testing type registry ...');
+
   Tester<IDoubles>.Test;
   Tester<IOneOfEach>.Test;
   Tester<IBonk>.Test;
@@ -85,7 +85,9 @@ begin
   Tester<IBigFieldIdStruct>.Test;
   Tester<IBreaksRubyCompactProtocol>.Test;
   Tester<ITupleProtocolTestStruct>.Test;
-  Writeln('Completed.');
+
+  Writeln;
+end;
 
 
 end.
diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr 
b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
index 31c0fb2..2896bbf 100644
--- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
+++ b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
@@ -37,56 +37,19 @@ uses
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
   Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
-  DebugProtoTest;
+  Thrift.Test, // in 'gen-delphi\Thrift.Test.pas',
+  Test.TypeRegistry,
+  Test.EnumToString;
 
-type
-  Tester<T : IInterface> = class
-  public
-    class procedure Test;
-  end;
-
-class procedure Tester<T>.Test;
-var instance : T;
-    name : string;
-begin
-  instance := TypeRegistry.Construct<T>;
-  name := GetTypeName(TypeInfo(T));
-  if instance <> nil
-  then Writeln( name, ' = ok')
-  else begin
-    Writeln( name, ' = failed');
-    raise Exception.Create( 'Test with '+name+' failed!');
-  end;
-end;
 
 begin
-  Writeln('Testing ...');
-  Tester<IDoubles>.Test;
-  Tester<IOneOfEach>.Test;
-  Tester<IBonk>.Test;
-  Tester<INesting>.Test;
-  Tester<IHolyMoley>.Test;
-  Tester<IBackwards>.Test;
-  Tester<IEmpty>.Test;
-  Tester<IWrapper>.Test;
-  Tester<IRandomStuff>.Test;
-  Tester<IBase64>.Test;
-  Tester<ICompactProtoTestStruct>.Test;
-  Tester<ISingleMapTestStruct>.Test;
-  Tester<IBlowUp>.Test;
-  Tester<IReverseOrderStruct>.Test;
-  Tester<IStructWithSomeEnum>.Test;
-  Tester<ITestUnion>.Test;
-  Tester<ITestUnionMinusStringField>.Test;
-  Tester<IComparableUnion>.Test;
-  Tester<IStructWithAUnion>.Test;
-  Tester<IPrimitiveThenStruct>.Test;
-  Tester<IStructWithASomemap>.Test;
-  Tester<IBigFieldIdStruct>.Test;
-  Tester<IBreaksRubyCompactProtocol>.Test;
-  Tester<ITupleProtocolTestStruct>.Test;
-  Writeln('Completed.');
-
+  try
+    Test.TypeRegistry.RunTest;
+    Test.EnumToString.RunTest;
 
+    Writeln('Completed.');
+  except
+    on e:Exception do Writeln(e.ClassName,': ',e.Message);
+  end;
 end.
 

Reply via email to