Browse Source

+ add a test for Variant dispatch and the generated call description format (this is for the previous three fixes)

git-svn-id: trunk@49481 -
svenbarth 4 years ago
parent
commit
e89e87372e
2 changed files with 148 additions and 0 deletions
  1. 1 0
      .gitattributes
  2. 147 0
      tests/test/tcustomvar1.pp

+ 1 - 0
.gitattributes

@@ -15010,6 +15010,7 @@ tests/test/tcustomattr6.pp svneol=native#text/pascal
 tests/test/tcustomattr7.pp svneol=native#text/pascal
 tests/test/tcustomattr7.pp svneol=native#text/pascal
 tests/test/tcustomattr8.pp svneol=native#text/pascal
 tests/test/tcustomattr8.pp svneol=native#text/pascal
 tests/test/tcustomattr9.pp svneol=native#text/pascal
 tests/test/tcustomattr9.pp svneol=native#text/pascal
+tests/test/tcustomvar1.pp svneol=native#text/pascal
 tests/test/tdefault1.pp svneol=native#text/pascal
 tests/test/tdefault1.pp svneol=native#text/pascal
 tests/test/tdefault10.pp svneol=native#text/pascal
 tests/test/tdefault10.pp svneol=native#text/pascal
 tests/test/tdefault11.pp svneol=native#text/pascal
 tests/test/tdefault11.pp svneol=native#text/pascal

+ 147 - 0
tests/test/tcustomvar1.pp

@@ -0,0 +1,147 @@
+program tcustomvar1;
+
+{$APPTYPE CONSOLE}
+{$MODE Delphi}
+
+uses
+  Variants, SysUtils;
+
+type
+  TSampleVariant = class(TCustomVariantType)
+  protected
+    procedure DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer); override;
+  public
+    procedure Clear(var V: TVarData); override;
+    procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean ); override;
+  end;
+
+procedure TSampleVariant.Clear(var V: TVarData);
+begin
+  V.VType:=varEmpty;
+end;
+
+procedure TSampleVariant.Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean);
+begin
+  if Indirect and VarDataIsByRef(Source) then
+    VarDataCopyNoInd(Dest, Source)
+  else with Dest do
+    VType:=Source.VType;
+end;
+
+var
+  funcname: String;
+  argnames: array of String;
+  argtypes: array of Byte;
+  argvalues: array of Variant;
+
+procedure TSampleVariant.DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer);
+var
+  n: AnsiString;
+  nptr: PChar;
+  arg: Pointer;
+  t: Byte;
+  i: LongInt;
+  v: Variant;
+begin
+  nptr := PChar(@CallDesc^.argtypes[CallDesc^.argcount]);
+  n := StrPas(nptr);
+  if n <> funcname then begin
+    Writeln('Func name: got: ', n, ', expected: ', funcname);
+    Halt(1);
+  end;
+  if Length(argnames) <> CallDesc^.namedargcount then
+    Halt(1);
+  nptr := nptr + Length(n) + 1;
+  arg := Params;
+  for i := 0 to CallDesc^.namedargcount - 1 do begin
+    n := StrPas(nptr);
+    if n <> argnames[i] then begin
+      Writeln('Arg ', i, ': got: ', n, ', expected: ', argnames[i]);
+      Halt(1);
+    end;
+    if CallDesc^.argtypes[i] <> argtypes[i] then begin
+      Writeln('Arg ', i, ' type: got: ', CallDesc^.ArgTypes[i], ', expected: ', argtypes[i]);
+      Halt(1);
+    end;
+    t := argtypes[i] and $7f;
+    if argtypes[i] and $80 <> 0 then begin
+      TVarData(v).VType := t or varByRef;
+      TVarData(v).VPointer := PPointer(arg)^;
+    end else begin
+      TVarData(v).VType := t;
+      case t of
+        varSingle,
+        varSmallint,
+        varInteger,
+        varLongWord,
+        varBoolean,
+        varShortInt,
+        varByte,
+        varWord:
+          TVarData(v).VInteger := PInteger(arg)^;
+        else
+          TVarData(v).VAny := PPointer(arg)^;
+      end;
+    end;
+    if v <> argvalues[i] then begin
+      Writeln('Arg ', i, ' value: got: ', String(v), ', expected: ', String(argvalues[i]));
+      Halt(1);
+    end;
+    nptr := nptr + Length(n) + 1;
+    arg := PByte(arg) + SizeOf(Pointer);
+    { unset so that VarClear doesn't try to free the constant WideChar }
+    TVarData(v).vtype:=varEmpty;
+  end;
+end;
+
+function ConvertArgType(aType: Word): Byte;
+var
+  ref: Boolean;
+begin
+  ref := (aType and varByRef) <> 0;
+  aType := aType and not varByRef;
+  case aType of
+    varString:
+      Result := varOleStr;
+    otherwise
+      Result := aType;
+  end;
+  if ref then
+    Result := Result or $80;
+end;
+
+var
+  SampleVariant: TSampleVariant;
+  v, v1: Variant;
+
+begin
+  SampleVariant:=TSampleVariant.Create;
+  TVarData(v).VType:=SampleVariant.VarType;
+
+  funcname := 'SomeProc';
+  SetLength(argnames, 0);
+  v.SomeProc;
+
+  funcname := 'SomeFunc';
+  SetLength(argnames, 0);
+  v1 := v.SomeFunc;
+
+  funcname := 'Begin';
+  SetLength(argnames, 2);
+  SetLength(argtypes, 2);
+  SetLength(argvalues, 2);
+  { the parameters are passed right-to-left }
+  argnames[1] := 'Date';
+  argnames[0] := 'Foobar';
+  argvalues[1] := 42;
+  argvalues[0] := 'Hello';
+  argtypes[1] := ConvertArgType(TVarData(argvalues[1]).VType);
+  argtypes[0] := ConvertArgType(TVarData(argvalues[0]).VType);
+  v.&Begin(Date:=42,Foobar:='Hello');
+
+  funcname := '_';
+  SetLength(argnames, 0);
+  v._;
+
+  writeln('ok');
+end.