unit Antlr.Runtime.Tools.Tests;
{

  Delphi DUnit Test Case
  ----------------------
  This unit contains a skeleton test case class generated by the Test Case Wizard.
  Modify the generated code to correctly setup and call the methods from the unit
  being tested.

}

interface

uses
  SysUtils,
  TestFramework,
  Generics.Defaults,
  Generics.Collections,
  Antlr.Runtime.Tools;

type
  // Test methods for class IANTLRString
  TestIANTLRString = class(TTestCase)
  strict private
    FIANTLRString: IANTLRString;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestGetValue;
    procedure TestSetValue;
  end;

  // Test methods for class TANTLRString
  TestTANTLRString = class(TTestCase)
  strict private
    FANTLRString: TANTLRString;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestToString;
  end;

  // Test methods for class ICloneable
  TestICloneable = class(TTestCase)
  strict private
    FICloneable: ICloneable;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestClone;
  end;

  // Test methods for class IList
  TestIList = class(TTestCase)
  strict private
    FIList: IList<Integer>;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestGetCapacity;
    procedure TestSetCapacity;
    procedure TestGetCount;
    procedure TestSetCount;
    procedure TestGetItem;
    procedure TestSetItem;
    procedure TestAdd;
    procedure TestAddRange;
    procedure TestInsert;
    procedure TestRemove;
    procedure TestDelete;
    procedure TestDeleteRange;
    procedure TestClear;
    procedure TestContains;
    procedure TestIndexOf;
  end;

  // Test methods for class IDictionary
  TestIDictionary = class(TTestCase)
  strict private
    FIDictionary: IDictionary<String, Integer>;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestGetItem;
    procedure TestSetItem;
    procedure TestGetCount;
    procedure TestAdd;
    procedure TestRemove;
    procedure TestTryGetValue;
    procedure TestContainsKey;
    procedure TestContainsValue;
    procedure TestEnumeration;
  end;

  // Test methods for record TLocalStorage
  TestTLocalStorage = class(TTestCase)
  published
    procedure TestLocalIntegerStorage;
    procedure TestLocalInterfaceStorage;
  end;

implementation

type
  IFoo = interface(IANTLRInterface)
  ['{48E3FC72-4E63-46D8-8450-A561ECF76995}']
    function GetValue: String;
    procedure SetValue(const V: String);
    property Value: String read GetValue write SetValue;
  end;

  TFoo = class(TANTLRObject, ICloneable, IFoo)
    FValue: String;
    function GetValue: String;
    procedure SetValue(const V: String);
    function Clone: IANTLRInterface;
  end;

function TFoo.GetValue: String;
begin
  Result := FValue;
end;

procedure TFoo.SetValue(const V: String);
begin
  FValue := V;
end;

function TFoo.Clone: IANTLRInterface;
var
  Foo: IFoo;
begin
  Foo := TFoo.Create;
  Foo.Value := FValue;
  Result := Foo;
end;

procedure TestIANTLRString.SetUp;
begin
  FIANTLRString := TANTLRString.Create('foo');
end;

procedure TestIANTLRString.TearDown;
begin
  FIANTLRString := nil;
end;

procedure TestIANTLRString.TestGetValue;
var
  ReturnValue: string;
begin
  ReturnValue := FIANTLRString.GetValue;
  CheckEquals(ReturnValue,'foo');
end;

procedure TestIANTLRString.TestSetValue;
var
  Value: string;
begin
  Value := 'bar';
  FIANTLRString.SetValue(Value);
  CheckEquals(FIANTLRString.Value,'bar');
end;

procedure TestTANTLRString.SetUp;
begin
  FANTLRString := TANTLRString.Create('foo');
end;

procedure TestTANTLRString.TearDown;
begin
  FANTLRString.Free;
  FANTLRString := nil;
end;

procedure TestTANTLRString.TestToString;
var
  ReturnValue: string;
begin
  ReturnValue := FANTLRString.ToString;
  CheckEquals(ReturnValue,'foo');
end;

procedure TestICloneable.SetUp;
var
  Foo: IFoo;
begin
  Foo := TFoo.Create;
  Foo.Value := 'original';
  FICloneable := Foo as ICloneable;
end;

procedure TestICloneable.TearDown;
begin
  FICloneable := nil;
end;

procedure TestICloneable.TestClone;
var
  ReturnValue: IANTLRInterface;
begin
  ReturnValue := FICloneable.Clone;
  Check(Supports(ReturnValue, IFoo));
  CheckEquals((ReturnValue as IFoo).Value,(FICloneable as IFoo).Value);
end;

procedure TestIList.SetUp;
begin
  FIList := TList<Integer>.Create;
end;

procedure TestIList.TearDown;
begin
  FIList := nil;
end;

procedure TestIList.TestGetCapacity;
var
  ReturnValue: Integer;
begin
  FIList.Capacity := 100;
  ReturnValue := FIList.GetCapacity;
  CheckEquals(ReturnValue,100);
end;

procedure TestIList.TestSetCapacity;
var
  Value: Integer;
begin
  Value := 100;
  FIList.SetCapacity(Value);
  CheckEquals(FIList.Capacity,100);
end;

procedure TestIList.TestGetCount;
var
  ReturnValue: Integer;
begin
  FIList.Clear;
  FIList.Add(123);
  ReturnValue := FIList.GetCount;
  CheckEquals(ReturnValue,1);
end;

procedure TestIList.TestSetCount;
var
  Value: Integer;
begin
  Value := 4;
  FIList.SetCount(Value);
  CheckEquals(FIList.Count,4);
end;

procedure TestIList.TestGetItem;
var
  ReturnValue: Integer;
  Index: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Index := 2;
  ReturnValue := FIList.GetItem(Index);
  CheckEquals(ReturnValue,300);
end;

procedure TestIList.TestSetItem;
var
  Value: Integer;
  Index: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Index := 3;
  Value := 333;
  FIList.SetItem(Index, Value);
  CheckEquals(FIList.Items[3],333);
end;

procedure TestIList.TestAdd;
var
  ReturnValue: Integer;
  Value: Integer;
begin
  FIList.Clear;
  Value := 3;
  ReturnValue := FIList.Add(Value);
  CheckEquals(ReturnValue,0);
end;

procedure TestIList.TestAddRange;
var
  Values: array [0..3] of Integer;
begin
  FIList.Clear;
  Values[0] := 111;
  Values[1] := 222;
  Values[2] := 333;
  Values[3] := 444;
  FIList.AddRange(Values);
  CheckEquals(FIList[0],111);
  CheckEquals(FIList[1],222);
  CheckEquals(FIList[2],333);
  CheckEquals(FIList[3],444);
end;

procedure TestIList.TestInsert;
var
  Value: Integer;
  Index: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Index := 2;
  Value := 250;
  FIList.Insert(Index, Value);
  CheckEquals(FIList[1],200);
  CheckEquals(FIList[2],250);
  CheckEquals(FIList[3],300);
end;

procedure TestIList.TestRemove;
var
  ReturnValue: Integer;
  Value: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Value := 300;
  ReturnValue := FIList.Remove(Value);
  CheckEquals(ReturnValue,2);
end;

procedure TestIList.TestDelete;
var
  Index: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Index := 2;
  FIList.Delete(Index);
  CheckEquals(FIList[2],400);
end;

procedure TestIList.TestDeleteRange;
var
  ACount: Integer;
  AIndex: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  AIndex := 1;
  ACount := 2;
  FIList.DeleteRange(AIndex, ACount);
  CheckEquals(FIlist[0],100);
  CheckEquals(FIlist[1],400);
end;

procedure TestIList.TestClear;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  FIList.Clear;
  CheckEquals(FIList.Count,0);
end;

procedure TestIList.TestContains;
var
  ReturnValue: Boolean;
  Value: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Value := 200;
  ReturnValue := FIList.Contains(Value);
  CheckTrue(ReturnValue);
  Value := 250;
  ReturnValue := FIList.Contains(Value);
  CheckFalse(ReturnValue);
end;

procedure TestIList.TestIndexOf;
var
  ReturnValue: Integer;
  Value: Integer;
begin
  FIList.Clear;
  FIList.Add(100);
  FIList.Add(200);
  FIList.Add(300);
  FIList.Add(400);
  Value := 300;
  ReturnValue := FIList.IndexOf(Value);
  CheckEquals(ReturnValue,2);
  Value := 301;
  ReturnValue := FIList.IndexOf(Value);
  CheckEquals(ReturnValue,-1);
end;

procedure TestIDictionary.SetUp;
begin
  FIDictionary := TDictionary<String, Integer>.Create;
  FIDictionary.Add('Foo',1);
  FIDictionary.Add('Bar',3);
  FIDictionary.Add('Baz',7);
  FIDictionary.Add('Zip',7);
end;

procedure TestIDictionary.TearDown;
begin
  FIDictionary := nil;
end;

procedure TestIDictionary.TestGetItem;
var
  ReturnValue: Integer;
  Key: String;
begin
  Key := 'Baz';
  ReturnValue := FIDictionary.GetItem(Key);
  CheckEquals(ReturnValue,7);
end;

procedure TestIDictionary.TestSetItem;
var
  Value: Integer;
  Key: String;
begin
  Key := 'Bar';
  Value := 20;
  FIDictionary.SetItem(Key, Value);
  CheckEquals(FIDictionary['Bar'],20);
end;

procedure TestIDictionary.TestGetCount;
var
  ReturnValue: Integer;
begin
  ReturnValue := FIDictionary.GetCount;
  CheckEquals(ReturnValue,4);
end;

procedure TestIDictionary.TestAdd;
var
  Value: Integer;
  Key: String;
begin
  Key := 'Key';
  Value := -1;
  FIDictionary.Add(Key, Value);
  CheckEquals(FIDictionary['Key'],-1);
end;

procedure TestIDictionary.TestRemove;
var
  Key: String;
begin
  Key := 'Bar';
  FIDictionary.Remove(Key);
  CheckEquals(FIDictionary.Count,3);
end;

procedure TestIDictionary.TestTryGetValue;
var
  ReturnValue: Boolean;
  Value: Integer;
  Key: String;
begin
  Key := 'Zip';
  ReturnValue := FIDictionary.TryGetValue(Key, Value);
  CheckTrue(ReturnValue);
  CheckEquals(Value,7);

  Key := 'Oops';
  ReturnValue := FIDictionary.TryGetValue(Key, Value);
  CheckFalse(ReturnValue);
end;

procedure TestIDictionary.TestContainsKey;
var
  ReturnValue: Boolean;
  Key: String;
begin
  Key := 'Foo';
  ReturnValue := FIDictionary.ContainsKey(Key);
  CheckTrue(ReturnValue);

  Key := 'foo';
  ReturnValue := FIDictionary.ContainsKey(Key);
  CheckFalse(ReturnValue);
end;

procedure TestIDictionary.TestContainsValue;
var
  ReturnValue: Boolean;
  Value: Integer;
begin
  Value := 3;
  ReturnValue := FIDictionary.ContainsValue(Value);
  CheckTrue(ReturnValue);

  Value := 2;
  ReturnValue := FIDictionary.ContainsValue(Value);
  CheckFalse(ReturnValue);
end;

procedure TestIDictionary.TestEnumeration;
var
  Pair: TPair<String, Integer>;
  Foo, Bar, Baz, Zip: Boolean;
begin
  Foo := False;
  Bar := False;
  Baz := False;
  Zip := False;

  for Pair in FIDictionary do
  begin
    if (Pair.Key = 'Foo') then
    begin
      Foo := True;
      CheckEquals(Pair.Value, 1);
    end
    else
    if (Pair.Key = 'Bar') then
    begin
      Bar := True;
      CheckEquals(Pair.Value, 3);
    end
    else
    if (Pair.Key = 'Baz') then
    begin
      Baz := True;
      CheckEquals(Pair.Value, 7);
    end
    else
    if (Pair.Key = 'Zip') then
    begin
      Zip := True;
      CheckEquals(Pair.Value, 7);
    end
    else
      Check(False, 'Unknown key in dictionary');
  end;
  CheckTrue(Foo);
  CheckTrue(Bar);
  CheckTrue(Baz);
  CheckTrue(Zip);
end;

{ TestTLocalStorage }

procedure TestTLocalStorage.TestLocalIntegerStorage;
var
  Locals: TLocalStorage;
begin
  Locals.Initialize;
  try
    Locals.AsInteger['x'] := 2;
    Locals.AsInteger['X'] := 3;
    CheckEquals(2, Locals.AsInteger['x']);
    CheckEquals(3, Locals.AsInteger['X']);
    CheckEquals(0, Locals.AsInteger['y']);
    Locals.AsInteger['X'] := Locals.AsInteger['x'] * 2;
    CheckEquals(4, Locals.AsInteger['X']);
    CheckEquals(2, Locals.Count);
  finally
    Locals.Finalize;
  end;
end;

procedure TestTLocalStorage.TestLocalInterfaceStorage;
var
  Locals: TLocalStorage;
begin
  Locals.Initialize;
  try
    { Local variable Z is never accessed again. We add it to check that there
      will be no memory leak. }
    Locals['Z'] := TANTLRString.Create('Value Z');

    Locals['x'] := TANTLRString.Create('Value x');
    Locals['X'] := TANTLRString.Create('Value X');
    CheckEquals('Value x', (Locals['x'] as IANTLRString).Value);
    CheckEquals('Value X', (Locals['X'] as IANTLRString).Value);
    Check(Locals['y'] = nil);

    Locals['X'] := TANTLRString.Create(
      (Locals['X'] as IANTLRString).Value + ' Update');
    CheckEquals('Value X Update', (Locals['X'] as IANTLRString).Value);
    CheckEquals(3, Locals.Count);
  finally
    Locals.Finalize;
  end;
end;

initialization
  // Register any test cases with the test runner
  RegisterTest(TestIANTLRString.Suite);
  RegisterTest(TestTANTLRString.Suite);
  RegisterTest(TestICloneable.Suite);
  RegisterTest(TestIList.Suite);
  RegisterTest(TestIDictionary.Suite);
  RegisterTest(TestTLocalStorage.Suite);
end.
