XPInterfacedObjectTests.pas
上传用户:yjb1804
上传日期:2021-01-30
资源大小:3105k
文件大小:13k
源码类别:

Email服务器

开发平台:

Delphi

  1. unit XPInterfacedObjectTests;
  2. interface
  3. uses
  4.   XPInterfacedObject,
  5.   TestFrameWork;
  6. type
  7.   IXPCrackedInterface = interface(IInterface)
  8.     ['{2ECEC777-1C1B-4797-8916-4D7139BA4392}']
  9.     function RefCount: integer;
  10.   end;
  11.   TXPInterfacedObjectTests = class(TTestCase)
  12.   private
  13.     FDelegator: IXPCrackedInterface;
  14.     FContained: IInterface;
  15.     FXPContained: IXPCrackedInterface;
  16.     FCleverDelegator: IInterface;
  17.   protected
  18.     procedure SetUp; override;
  19.     procedure TearDown; override;
  20.   published
  21.     // Test methods
  22.     procedure TestQueryInterface;
  23.     procedure Test_AddRef;
  24.     procedure Test_AddRefXP;
  25.     procedure Test_Release;
  26.     procedure TestCreate;
  27.     procedure TestCreateXP;
  28.     procedure TestDestroy;
  29.     procedure TestDelegation;
  30.     procedure TestIntrospective;
  31.   end;
  32. implementation
  33. uses
  34.   SysUtils;
  35. type
  36.   // Access FRefCount
  37.   TCrackedInterface = class(TInterfacedObject, IXPCrackedInterface)
  38.   protected
  39.     function RefCount: integer;
  40.   public
  41.     destructor Destroy; override;
  42.   end;
  43.   TXPCrackedInterface = class(TXPInterfacedObject, IXPCrackedInterface)
  44.   protected
  45.     function RefCount: integer;
  46.   public
  47.     destructor Destroy; override;
  48.   end;
  49.   IA = interface
  50.     ['{CEBA0535-4909-4605-8AFC-844092A36D47}']
  51.     function A: integer;
  52.   end;
  53.   IB = interface
  54.     ['{121BAA8A-A52B-4FA1-9729-3A8E744E1F41}']
  55.     function B: integer;
  56.   end;
  57.   IC = interface
  58.     ['{AA3CCF11-704B-414D-B6F5-514493D09D38}']
  59.     function C: integer;
  60.   end;
  61.   ID = interface
  62.     ['{B028B140-AFB2-49D8-9A71-CE82555080DA}']
  63.     function D: integer;
  64.   end;
  65.   TClever = class(TInterfacedObject, IA, IB)
  66.   protected
  67.     function A: integer;
  68.     function B: integer;
  69.   end;
  70.   TUnOwnedDelegatee = class(TInterfacedObject, IC)
  71.   protected
  72.     function C: integer;
  73.   end;
  74.   TOwnedDelegatee = class(TXPInterfacedObject, ID)
  75.   protected
  76.     function D: integer;
  77.   end;
  78.   TDelegator = class (TCrackedInterface, IC, ID)
  79.   private
  80.     FUnOwned: TUnOwnedDelegatee;
  81.     FOwned: TOwnedDelegatee;
  82.   protected
  83.     property UnOwned: TUnOwnedDelegatee
  84.       read FUnOwned implements IC;
  85.     property Owned: TOwnedDelegatee
  86.       read FOwned implements ID;
  87.   public
  88.     constructor Create;
  89.     destructor Destroy; override;
  90.     procedure SetIntrospective(Value: boolean);
  91.   end;
  92. { TXPInterfacedObjectTests }
  93. procedure TXPInterfacedObjectTests.SetUp;
  94. begin
  95.   inherited;
  96.   FDelegator := TCrackedInterface.Create;
  97.   FCleverDelegator := TClever.Create;
  98. end;
  99. procedure TXPInterfacedObjectTests.TearDown;
  100. begin
  101.   FXPContained := nil;
  102.   FContained := nil;
  103.   FDelegator := nil;
  104.   FCleverDelegator := nil;
  105.   inherited;
  106. end;
  107. procedure TXPInterfacedObjectTests.Test_AddRef;
  108. begin
  109.   // Memory leak created here, as there is no way to call FContained destructor
  110.   FContained := TXPInterfacedObject.Create(FDelegator);
  111.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned construction');
  112.   FContained._AddRef;
  113.   CheckEquals(3, FDelegator.RefCount, 'Bad rc after owned addref');
  114.   FContained._AddRef;
  115.   CheckEquals(4, FDelegator.RefCount, 'Bad rc after second owned addref');
  116.   FContained._Release;
  117.   FContained._Release;
  118. end;
  119. procedure TXPInterfacedObjectTests.Test_Release;
  120. begin
  121.   // Memory leak created here, as there is no way to call FContained destructor
  122.   FContained := TXPInterfacedObject.Create(FDelegator);
  123.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned construction');
  124.   FContained._AddRef;
  125.   CheckEquals(3, FDelegator.RefCount, 'Bad rc after owned addref');
  126.   FContained._AddRef;
  127.   CheckEquals(4, FDelegator.RefCount, 'Bad rc after owned second addref');
  128.   FContained._Release;
  129.   CheckEquals(3, FDelegator.RefCount, 'Bad rc after owned release');
  130.   FContained._Release;
  131.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned second release');
  132.   FContained := nil;
  133.   CheckEquals(1, FDelegator.RefCount, 'Bad rc after owned nil''d');
  134. end;
  135. procedure TXPInterfacedObjectTests.TestCreate;
  136. begin
  137.   CheckEquals(1, FDelegator.RefCount, 'Initial rc for Delegator');
  138.   FContained := TXPInterfacedObject.Create;
  139.   CheckEquals(1, FDelegator.RefCount, 'Bad rc after default construction');
  140.   FContained := TXPInterfacedObject.Create(nil);
  141.   CheckEquals(1, FDelegator.RefCount, 'Bad rc after nil construction');
  142.   // Memory leak created here, as there is no way to call FContained destructor
  143.   FContained := TXPInterfacedObject.Create(FDelegator);
  144.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned construction');
  145. end;
  146. procedure TXPInterfacedObjectTests.TestDestroy;
  147. begin
  148.   // Memory leak created here, as there is no way to call FContained destructor
  149.   FContained := TXPInterfacedObject.Create(FDelegator);
  150.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned construction');
  151.   FContained := nil;
  152.   CheckEquals(1, FDelegator.RefCount, 'Bad rc after owned destruction');
  153. end;
  154. procedure TXPInterfacedObjectTests.TestQueryInterface;
  155. var
  156.   A: IA;
  157.   B: IB;
  158. begin
  159.   // Memory leak created here, as there is no way to call FContained destructor
  160.   FContained := TXPInterfacedObject.Create(FCleverDelegator);
  161.   Check(SysUtils.Supports(FContained, IA, A), 'Not finding IA through owned');
  162.   CheckEquals(1, A.A, 'queried IA.A failed');
  163.   CheckEquals(1, (FContained as IA).A, '(FContained as IA).A failed');
  164.   Check(SysUtils.Supports(FContained, IB, B), 'Not finding IB through owned');
  165.   CheckEquals(2, B.B, 'queried IB.B failed');
  166.   CheckEquals(2, (FContained as IB).B, '(FContained as IB).B failed');
  167.   // Drop reference to container and query containers interfaces through
  168.   // contained reference
  169.   A := nil;
  170.   B := nil;
  171.   FCleverDelegator := nil;
  172.   Check(SysUtils.Supports(FContained, IA, A),
  173.     'Not finding IA through owned after container released');
  174.   CheckEquals(1, A.A, 'queried IA.A failed  after container released');
  175.   CheckEquals(1, (FContained as IA).A,
  176.     '(FContained as IA).A failed  after container released');
  177.   Check(SysUtils.Supports(FContained, IB, B),
  178.     'Not finding IB through owned  after container released');
  179.   CheckEquals(2, B.B, 'queried IB.B failed  after container released');
  180.   CheckEquals(2, (FContained as IB).B,
  181.     '(FContained as IB).B failed  after container released');
  182. end;
  183. procedure TXPInterfacedObjectTests.TestCreateXP;
  184. begin
  185.   FXPContained := TXPCrackedInterface.Create;
  186.   CheckEquals(1, FXPContained.RefCount, 'Initial rc for unowned xp');
  187.   FXPContained := nil;
  188.   FXPContained := TXPCrackedInterface.Create(nil);
  189.   CheckEquals(1, FXPContained.RefCount, 'Initial rc for unowned (nil) xp');
  190.   FXPContained := nil;
  191.   FXPContained := TXPCrackedInterface.Create;
  192.   CheckEquals(1, FXPContained.RefCount, 'Initial rc for unowned xp');
  193.   FXPContained := TXPCrackedInterface.Create(nil);
  194.   CheckEquals(1, FXPContained.RefCount,
  195.     'Initial rc for unowned (nil) xp - no intervening nil');
  196.   FXPContained := nil;
  197.   CheckEquals(1, FDelegator.RefCount, 'Initial rc for Delegator');
  198.   // Memory leak created here, as there is no way to call FXPContained
  199.   // destructor
  200.   FXPContained := TXPCrackedInterface.Create(FDelegator);
  201.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned xp construction');
  202.   CheckEquals(1, FXPContained.RefCount, 'Initial rc for owned xp');
  203.   // Memory leak created here, as there is no way to call FContained destructor
  204.   FContained := TXPInterfacedObject.Create(FDelegator);
  205.   CheckEquals(3, FDelegator.RefCount,
  206.     'Bad rc after owned construction with xp on board');
  207.   CheckEquals(1, FXPContained.RefCount,
  208.     'Bad rc for owned xp afer owned added to delegator');
  209.   FContained := nil;
  210.   CheckEquals(2, FDelegator.RefCount,
  211.     'Bad rc after owned nil''d with xp on board');
  212.   CheckEquals(1, FXPContained.RefCount,
  213.     'Bad rc for owned xp after owned nil''d with xp on board');
  214. end;
  215. procedure TXPInterfacedObjectTests.Test_AddRefXP;
  216. begin
  217.   // Memory leak created here, as there is no way to call FXPContained
  218.   // destructor
  219.   FXPContained := TXPCrackedInterface.Create(FDelegator);
  220.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned construction');
  221.   CheckEquals(1, FXPContained.RefCount, 'Initial rc for owned xp');
  222.   FXPContained._AddRef;
  223.   CheckEquals(3, FDelegator.RefCount, 'Bad rc after owned addref');
  224.   CheckEquals(2, FXPContained.RefCount, 'Bad rc for addref''d xp');
  225.   FXPContained._AddRef;
  226.   CheckEquals(4, FDelegator.RefCount, 'Bad rc after second owned addref');
  227.   CheckEquals(3, FXPContained.RefCount, 'Bad rc for second addref''d xp');
  228.   FXPContained._Release;
  229.   CheckEquals(3, FDelegator.RefCount, 'Bad rc after owned released xp');
  230.   CheckEquals(2, FXPContained.RefCount, 'Bad rc for released xp');
  231.   FXPContained._Release;
  232.   CheckEquals(2, FDelegator.RefCount, 'Bad rc after owned second released xp');
  233.   CheckEquals(1, FXPContained.RefCount, 'Bad rc for second released xp');
  234. end;
  235. procedure TXPInterfacedObjectTests.TestDelegation;
  236. var
  237.   Delegator: IXPCrackedInterface;
  238.   Unowned: IC;
  239.   Owned: ID;
  240. begin
  241.   Delegator := TDelegator.Create;
  242.   CheckEquals(1, Delegator.RefCount, 'Delegator rc after construction');
  243.   Check(SysUtils.Supports(Delegator, IC, Unowned), '1st query for unowned');
  244.   CheckEquals(1, Delegator.RefCount, 'Delegator rc after querying for unowned');
  245.   CheckEquals(3, Unowned.C, 'Called method on IC interface');
  246.   Unowned := nil;
  247. {
  248.   // Uncomment this to see an invalid pointer op, since we have just destroyed
  249.   // the implementing object for IC, and now have a dangling reference within
  250.   // the TDelegator container
  251.   Check(SysUtils.Supports(Delegator, IC, Unowned),
  252.     'query for unowned after reference released');
  253. }
  254.   CheckEquals(1, Delegator.RefCount, 'Delegator rc after unowned released');
  255.   Check(SysUtils.Supports(Delegator, ID, Owned), '1st query for owned');
  256.   CheckEquals(2, Delegator.RefCount, 'Delegator rc after querying for owned');
  257.   CheckEquals(4, Owned.D, 'Called method on ID interface');
  258.   Owned := nil;
  259.   CheckEquals(1, Delegator.RefCount, 'Delegator rc after owned released');
  260.   // Try op that fails for Unowned - fetch owned ref again
  261.   Check(SysUtils.Supports(Delegator, ID, Owned), '2nd query for owned');
  262.   CheckEquals(2, Delegator.RefCount, 'Delegator rc after 2nd query for owned');
  263.   CheckEquals(4, Owned.D, 'Called method on ID interface after 2nd query');
  264. end;
  265. procedure TXPInterfacedObjectTests.TestIntrospective;
  266. var
  267.   Delegator: TDelegator;
  268.   Cracked: IXPCrackedInterface;
  269.   Owned: ID;
  270. begin
  271.   Delegator := TDelegator.Create;
  272.   CheckEquals(0, Delegator.RefCount, 'Delegator rc after construction');
  273.   Check(SysUtils.Supports(TObject(Delegator), ID, Owned), '1st query for owned');
  274.   CheckEquals(1, Delegator.RefCount, 'Delegator rc after querying for owned');
  275.   CheckEquals(4, Owned.D, 'Called method on ID interface');
  276.   // default introspective setting
  277.   Check(SysUtils.Supports(Owned, IXPCrackedInterface, Cracked),
  278.     'query for delegator interface through owned');
  279.   CheckEquals(2, Delegator.RefCount,
  280.     'Delegator rc after query for delegator interface through owned');
  281.   // true introspective setting
  282.   Delegator.SetIntrospective(true);
  283.   Check(not SysUtils.Supports(Owned, IXPCrackedInterface, Cracked),
  284.     'query for delegator interface through owned with introspective true');
  285.   // false introspective setting
  286.   Delegator.SetIntrospective(false);
  287.   Check(SysUtils.Supports(Owned, IXPCrackedInterface, Cracked),
  288.     'query for delegator interface through owned with introspective false');
  289.   CheckEquals(2, Delegator.RefCount,
  290.     'Delegator rc after query for delegator interface through owned (false)');
  291.   Cracked := nil;
  292.   CheckEquals(1, Delegator.RefCount,
  293.     'Delegator rc after Cracked = nil');
  294.   Owned := nil;
  295. end;
  296. { TCrackedInterface }
  297. destructor TCrackedInterface.Destroy;
  298. begin
  299.   inherited;
  300. end;
  301. function TCrackedInterface.RefCount: integer;
  302. begin
  303.   Result := FRefCount;
  304. end;
  305. { TXPCrackedInterface }
  306. destructor TXPCrackedInterface.Destroy;
  307. begin
  308.   inherited;
  309. end;
  310. function TXPCrackedInterface.RefCount: integer;
  311. begin
  312.   Result := FRefCount;
  313. end;
  314. { TClever }
  315. function TClever.A: integer;
  316. begin
  317.   Result := 1;
  318. end;
  319. function TClever.B: integer;
  320. begin
  321.   Result := 2;
  322. end;
  323. { TDelegator }
  324. constructor TDelegator.Create;
  325. begin
  326.   inherited;
  327.   FUnOwned := TUnOwnedDelegatee.Create;
  328.   FOwned := TOwnedDelegatee.Create(self);
  329. end;
  330. destructor TDelegator.Destroy;
  331. begin
  332.   // We are not knocking off FUnowned as this will be destroyed through
  333.   // releasing a reference in the test
  334.   FOwned.Free;
  335.   inherited;
  336. end;
  337. procedure TDelegator.SetIntrospective(Value: boolean);
  338. begin
  339.   FOwned.Introspective := Value;
  340. end;
  341. { TUnOwnedDelegatee }
  342. function TUnOwnedDelegatee.C: integer;
  343. begin
  344.   Result := 3;
  345. end;
  346. { TOwnedDelegatee }
  347. function TOwnedDelegatee.D: integer;
  348. begin
  349.   Result := 4;
  350. end;
  351. initialization
  352.   TestFramework.RegisterTest('XPInterfacedObjectTests Suite',
  353.     TXPInterfacedObjectTests.Suite);
  354. end.