Browse Source

* Added JSON fpcunit helper

Michaël Van Canneyt 2 years ago
parent
commit
ba15672a44
2 changed files with 410 additions and 0 deletions
  1. 7 0
      packages/fcl-json/fpmake.pp
  2. 403 0
      packages/fcl-json/src/jsonfpcunit.pp

+ 7 - 0
packages/fcl-json/fpmake.pp

@@ -20,6 +20,7 @@ begin
     P.Version:='3.3.1';
     P.Dependencies.Add('fcl-base');
     P.Dependencies.Add('rtl-objpas');
+    P.Dependencies.Add('fcl-fpcunit');
     P.Author := 'Michael van Canneyt';
     P.License := 'LGPL with modification, ';
     P.HomepageURL := 'www.freepascal.org';
@@ -42,6 +43,12 @@ begin
       AddUnit('fpjson');
       AddUnit('jsonparser');
      end;
+    T:=P.Targets.AddUnit('jsonfpcunit.pp');
+    T.ResourceStrings:=true;
+    with T.Dependencies do
+      begin
+      AddUnit('fpjson');
+     end;
         
     T:=P.Targets.AddUnit('jsonparser.pp');
     T.ResourceStrings:=true;

+ 403 - 0
packages/fcl-json/src/jsonfpcunit.pp

@@ -0,0 +1,403 @@
+{
+    This file is part of the Free Component Library
+
+    JSON Data unit test helper
+    Copyright (c) 2023 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit jsonfpcunit;
+
+{$mode objfpc}
+{$H+}
+{$modeswitch typehelpers}
+
+interface
+
+uses
+  Classes, SysUtils, fpjson, fpcunit;
+
+Type
+
+  { TTestJSONHelper }
+
+  TTestJSONHelper = Class helper for TAssert
+    // JSON Tests
+    class Procedure AssertEquals(const Msg : String; AExpected,AActual : TJSONType); overload;
+    // Check D has the correct type.
+    class Procedure AssertJSONType(D: TJSONData; AExpected : TJSONType);
+    class Procedure AssertJSONType(const Msg : String; D: TJSONData; AExpected : TJSONType) ;
+    // Check D is a Null value and return the value
+    class function AssertJSONNull(D: TJSONData) : TJSONNull;
+    class function AssertJSONNull(Const Msg : String; D: TJSONData) : TJSONNull;
+    // Check D is a TJSONArray value and return the value. If element count is specified, the array element count is checked.
+    class Function AssertJSONArray(D: TJSONData; AElementCount : Integer = -1) : TJSONArray;
+    class Function AssertJSONArray(Const Msg : String; D: TJSONData; AElementCount : Integer = -1) : TJSONArray;
+    // Check Src is an object, and has element of given name and type
+    class function AssertJSONElement(Src: TJSONData; const Msg, aName: String; aType: TJSONtype): TJSONData;
+    // Check D is a boolean with given value. Return typed json value
+    class function AssertJSONBoolean(D: TJSONData; AValue: Boolean) : TJSONBoolean;
+    class function AssertJSONBoolean(Const Msg : String; D: TJSONData; AValue: Boolean) : TJSONBoolean;
+    // Check D is an integer with given value. Return typed json value
+    class function AssertJSONInteger(D: TJSONData; AValue: Integer) : TJSONNumber;
+    class function AssertJSONInteger(Const Msg : String; D: TJSONData; AValue: Integer) : TJSONNumber;
+    // Check D is a float with given value. Return typed json value
+    class function AssertJSONFloat(D: TJSONData; AValue: Double) : TJSONNumber;
+    class function AssertJSONFloat(Const Msg : String; D: TJSONData; AValue: Double) : TJSONNumber;
+    // Check D is a string with given value. Return typed json value
+    class Function AssertJSONString(D: TJSONData; const AValue: TJSONStringType) : TJSONString;
+    class Function AssertJSONString(Const Msg : String; D: TJSONData; const AValue: TJSONStringType) : TJSONString;
+    // Check D is a string with given value. Return typed json value.
+    class Function AssertJSONObject(D: TJSONData) : TJSONObject;
+    class Function AssertJSONObject(Const Msg : String; D: TJSONData) : TJSONObject;
+
+    // Checks for object members
+
+    // Check D is an object and contains an object value named aName. Return the value
+    class Function AssertJSONObject(D: TJSONData; const AName : string) : TJSONObject;
+    class Function AssertJSONObject(Const Msg : String; D: TJSONData; const AName : string) : TJSONObject;
+    // Check D is an object and contains a boolean value named aName with given value. Return the value
+    class function AssertJSONBoolean(D: TJSONData; const AName: String; AValue: Boolean) : TJSONBoolean;
+    class function AssertJSONBoolean(Const Msg : String; D: TJSONData; const AName: String; AValue: Boolean) : TJSONBoolean;
+    // Check D is an object and contains a null value named aName. Return the value
+    class function AssertJSONNull(D: TJSONData; const AName: String) : TJSONNull;
+    class function AssertJSONNull(Const Msg : String; D: TJSONData; const AName: String) : TJSONNull;
+    // Check D is an object and contains an integer value named aName with given value. Return the value
+    class function AssertJSONInteger(D: TJSONData; const AName: String; AValue: Integer) : TJSONNumber;
+    class function AssertJSONInteger(Const Msg : String; D: TJSONData; const AName: String; AValue: Integer) : TJSONNumber;
+    // Check D is an object and contains an int64 value named aName with given value. Return the value
+    class function AssertJSONInt64(D: TJSONData; const AName: String; AValue: Int64) : TJSONNumber;
+    class function AssertJSONInt64(Const Msg : String; D: TJSONData; const AName: String; AValue: Int64) : TJSONNumber;
+    // Check D is an object and contains a float value named aName with given value. Return the value
+    class function AssertJSONFloat(D: TJSONData;  const AName: String; AValue: Double) : TJSONNumber;
+    class function AssertJSONFloat(Const Msg : String; D: TJSONData;  const AName: String; AValue: Double) : TJSONNumber;
+    // Check D is an object and contains a string value named aName with given value. Return the value
+    class Function AssertJSONString(D: TJSONData; const AName: String; AValue: TJSONStringType) : TJSONString;
+    class Function AssertJSONString(Const Msg : String; D: TJSONData; const AName: String; AValue: TJSONStringType) : TJSONString;
+    // Check D is an object and contains an array value named aName with given element count. Return the value
+    class Function AssertJSONArray(D: TJSONData; const AName: String; AElementCount : Integer = -1) : TJSONArray;
+    class Function AssertJSONArray(Const Msg : String; D: TJSONData; const AName: String; AElementCount : Integer = -1) : TJSONArray;
+    // Check D is an object and has NO member
+    class Procedure AssertJSONNoMember(D: TJSONData; const AName: String);
+   end;
+
+
+implementation
+
+uses typinfo;
+
+resourcestring
+  SDataNotNull = ': Data is not null';
+  SDataHasCorrectType = '%s: Data has correct type';
+  SJSONTest = 'JSON test';
+  SCorrectArrayElementCount = '%s: Correct element count for array';
+  SCorrectDataValue = ': Correct value for data';
+  SIsJSONObject = ': Source is JSONObject';
+  SHaveElementCalled = '%s: Have element called %s';
+  SCorrectElementType = '%s: Element %s has correct type';
+  SCorrectElementValue = '%s: Correct value for element %s';
+  SCorrectArrayNamesElementCount = '%s: Correct array element "%s" count';
+  SUnexpectedValue = 'Expected no element called %s but found element of type %s with value %s';
+
+class procedure TTestJSONHelper.AssertEquals(const Msg: String; AExpected,
+  AActual: TJSONType);
+begin
+  AssertEquals(Msg,GetEnumName(Typeinfo(TJSONType),Ord(AExpected)),
+                   GetEnumName(Typeinfo(TJSONType),Ord(AActual)));
+end;
+
+class procedure TTestJSONHelper.AssertJSONType(const Msg: String; D: TJSONData;
+  AExpected: TJSONType);
+
+begin
+  AssertNotNull(Msg+SDataNotNull,D);
+  AssertEquals(Format(SDataHasCorrectType, [Msg]), AExpected, D.JSONType);
+end;
+
+class function TTestJSONHelper.AssertJSONNull(D: TJSONData): TJSONNull;
+begin
+  Result:=AssertJSONNull('',D);
+end;
+
+class function TTestJSONHelper.AssertJSONArray(D: TJSONData;
+  AElementCount: Integer): TJSONArray;
+begin
+  Result:=AssertJSONArray('',D,AElementCount);
+end;
+
+class function TTestJSONHelper.AssertJSONBoolean(D: TJSONData; AValue: Boolean
+  ): TJSONBoolean;
+begin
+  Result:=AssertJSONBoolean('',D,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONInteger(D: TJSONData; AValue: Integer
+  ): TJSONNumber;
+begin
+  Result:=AssertJSONInteger('',D,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONFloat(D: TJSONData; AValue: Double
+  ): TJSONNumber;
+begin
+  Result:=AssertJSONFloat('',D,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONString(D: TJSONData;
+  const AValue: TJSONStringType): TJSONString;
+begin
+  Result:=AssertJSONString('',D,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONObject(D: TJSONData): TJSONObject;
+begin
+  Result:=AssertJSONObject('',D);
+end;
+
+class function TTestJSONHelper.AssertJSONObject(D: TJSONData; const AName: string
+  ): TJSONObject;
+begin
+  Result:=AssertJSONObject('',D,AName);
+end;
+
+class function TTestJSONHelper.AssertJSONBoolean(D: TJSONData; const AName: String;
+  AValue: Boolean): TJSONBoolean;
+begin
+  Result:=AssertJSONBoolean('',D,AName,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONNull(D: TJSONData; const AName: String
+  ): TJSONNull;
+begin
+  Result:=AssertJSONNull('',D,AName);
+end;
+
+class function TTestJSONHelper.AssertJSONInteger(D: TJSONData; const AName: String;
+  AValue: Integer): TJSONNumber;
+begin
+  Result:=AssertJSONInteger('',D,AName,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONInt64(D: TJSONData; const AName: String;
+  AValue: Int64): TJSONNumber;
+begin
+  Result:=AssertJSONInt64('',D,AName,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONFloat(D: TJSONData; const AName: String;
+  AValue: Double): TJSONNumber;
+begin
+  Result:=AssertJSONFloat('',D,AName,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONString(D: TJSONData; const AName: String;
+  AValue: TJSONStringType): TJSONString;
+begin
+  Result:=AssertJSONString('',D,AName,AValue);
+end;
+
+class function TTestJSONHelper.AssertJSONArray(D: TJSONData; const AName: String;
+  AElementCount: Integer): TJSONArray;
+begin
+  Result:=AssertJSONArray('',D,AName,AElementCount);
+end;
+
+class procedure TTestJSONHelper.AssertJSONType(D: TJSONData;
+  AExpected: TJSONType);
+begin
+  AssertJSONType(SJSONTest, D, AExpected);
+end;
+
+class function TTestJSONHelper.AssertJSONNull(const Msg: String; D: TJSONData
+  ): TJSONNull;
+begin
+  AssertJSONType(Msg,D,jtNull);
+  Result:=TJSONNull(D);
+end;
+
+class function TTestJSONHelper.AssertJSONArray(const Msg: String; D: TJSONData;
+  AElementCount: Integer): TJSONArray;
+
+begin
+  Result:=Nil;
+  AssertJSONType(Msg,D,jtArray);
+  Result:=TJSONArray(D);
+  if AElementCount>=0 then
+    AssertEquals(Format(SCorrectArrayElementCount, [Msg]), AElementCount,
+      D.Count);
+end;
+
+class function TTestJSONHelper.AssertJSONBoolean(const Msg: String;
+  D: TJSONData; AValue: Boolean): TJSONBoolean;
+
+begin
+  AssertJSONType(Msg,D,jtBoolean);
+  Result:=TJSONBoolean(D);
+  AssertEquals(Msg+SCorrectDataValue, AValue, D.AsBoolean);
+end;
+
+class function TTestJSONHelper.AssertJSONInteger(const Msg: String;
+  D: TJSONData; AValue: Integer): TJSONNumber;
+
+begin
+  AssertJSONType(Msg,D,jtNumber);
+  Result:=TJSONNumber(D);
+  AssertEquals(Msg+SCorrectDataValue,AValue,D.AsInteger);
+end;
+
+class function TTestJSONHelper.AssertJSONFloat(const Msg: String; D: TJSONData;
+  AValue: Double): TJSONNumber;
+begin
+  AssertJSONType(Msg,D,jtNumber);
+  Result:=TJSONNumber(D);
+  AssertEquals(Msg+SCorrectDataValue,AValue,D.AsFloat);
+end;
+
+class function TTestJSONHelper.AssertJSONString(const Msg: String;
+  D: TJSONData; const AValue: TJSONStringType): TJSONString;
+
+begin
+  AssertJSONType(Msg,D,jtString);
+  Result:=TJSONString(D);
+  AssertEquals(Msg+SCorrectDataValue,AValue,D.AsString);
+end;
+
+class function TTestJSONHelper.AssertJSONObject(const Msg: String; D: TJSONData
+  ): TJSONObject;
+begin
+  AssertJSONType(Msg+SIsJSONObject, D, jtObject);
+  Result:=TJSONObject(D);
+end;
+
+class function TTestJSONHelper.AssertJSONObject(const Msg: String;
+  D: TJSONData; const AName: string): TJSONObject;
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtObject);
+  Result:=TJSONObject(SD);
+end;
+
+class function TTestJSONHelper.AssertJSONBoolean(const Msg: String;
+  D: TJSONData; const AName: String; AValue: Boolean): TJSONBoolean;
+
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtBoolean);
+  Result:=TJSONBoolean(SD);
+  AssertEquals(Format(SCorrectElementValue, [Msg, AName]),AValue,SD.AsBoolean);
+end;
+
+class function TTestJSONHelper.AssertJSONNull(const Msg: String; D: TJSONData;
+  const AName: String): TJSONNull;
+
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtNull);
+  Result:=TJSONNull(SD);
+end;
+
+class function TTestJSONHelper.AssertJSONInteger(const Msg: String;
+  D: TJSONData; const AName: String; AValue: Integer): TJSONNumber;
+
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtNumber);
+  Result:=TJSONNumber(SD);
+  AssertEquals(Format(SCorrectElementValue, [Msg, AName]),AValue,SD.AsInteger);
+end;
+
+class function TTestJSONHelper.AssertJSONInt64(const Msg: String; D: TJSONData;
+  const AName: String; AValue: Int64): TJSONNumber;
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtNumber);
+  Result:=TJSONNumber(SD);
+  AssertEquals(Format(SCorrectElementValue, [Msg, AName]),AValue,SD.AsInt64);
+end;
+
+class function TTestJSONHelper.AssertJSONFloat(const Msg: String; D: TJSONData;
+  const AName: String; AValue: Double): TJSONNumber;
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtNumber);
+  Result:=TJSONNumber(SD);
+  AssertEquals(Format(SCorrectElementValue, [Msg, AName]),AValue,SD.AsFloat);
+end;
+
+class function TTestJSONHelper.AssertJSONElement(Src : TJSONData; const Msg,aName : String; aType : TJSONtype) : TJSONData;
+
+begin
+  Result:=Nil;
+  AssertJSONObject(Msg,Src);
+  AssertJSONType(Msg+SIsJSONObject,Src,jtObject);
+  Result:=TJSONObject(Src).Find(AName);
+  AssertNotNull(Format(SHaveElementCalled, [Msg,AName]),Result);
+  AssertJSONType(Format(SCorrectElementType,[Msg,aName]),Result,aType);
+end;
+
+class function TTestJSONHelper.AssertJSONString(const Msg: String;
+  D: TJSONData; const AName: String; AValue: TJSONStringType): TJSONString;
+
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtString);
+  Result:=TJSONString(SD);
+  AssertEquals(Format(SCorrectElementValue, [Msg, AName]), AValue, SD.AsString);
+end;
+
+class function TTestJSONHelper.AssertJSONArray(const Msg: String; D: TJSONData;
+  const AName: String; AElementCount: Integer): TJSONArray;
+
+Var
+  SD : TJSONData;
+
+begin
+  Result:=Nil;
+  SD:=AssertJSONElement(D,Msg,aName,jtArray);
+  Result:=TJSONArray(SD);
+  if AElementCount>=0 then
+    AssertEquals(Format(SCorrectArrayNamesElementCount, [Msg, AName]),
+      AElementCount, SD.Count);
+end;
+
+class procedure TTestJSONHelper.AssertJSONNoMember(D: TJSONData; const AName: String);
+
+Var
+  SD : TJSONData;
+
+begin
+  AssertJSONType(SIsJSONObject,D,jtObject);
+  SD:=TJSONObject(D).Find(AName);
+  if (SD<>Nil) then
+    Fail(Format(SUnexpectedValue,[AName,GetEnumName(Typeinfo(TJSONType),Ord(SD.JSONType)),SD.AsJSON]));
+end;
+
+end.
+