⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xpobservertests.pas

📁 For Delphi的单元测试工具DUnit的源代码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    '2: subject rc after first observer added again');
  CheckEquals(2, FObserver.RefCount,
    '2: observer rc after attempting to add itself again');
  CheckEquals(1, ASubject.ObserverCount,
    '2: observer count after first observer added again');

  ASubject := nil;
  CheckEquals(1, FObserver.RefCount, 'observer rc after subject is destroyed');
end;

procedure TXPSubjectTests.TestCreate;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(1, ASubject.RefCount, 'sole reference on construction');
end;

procedure TXPSubjectTests.TestDeleteObserver;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(1, ASubject.RefCount, 'sole reference on construction');
  CheckEquals(0, ASubject.Count, 'empty observer count on construction');

  Check(not ASubject.DeleteObserver(nil), 'delete nil observer on empty');

  FObserver.Subject := ASubject;
  CheckEquals(2, ASubject.RefCount, 'subject rc after assignment');
  Check(ASubject.InsertObserver(0, FObserver, ASubject),
    'insert observer into subject');
  CheckEquals(2, FObserver.RefCount, 'observer rc after registration');

  Check(not ASubject.DeleteObserver(nil), 'delete nil observer on non-empty');
  CheckEquals(2, FObserver.RefCount, 'observer rc after delete nil observer');
  Check(not ASubject.DeleteObserver(FObserver, pointer(1)),
    'delete observer with wrong context');
  CheckEquals(2, FObserver.RefCount,
    'observer rc after delete observer with wrong context');
  Check(ASubject.DeleteObserver(FObserver),
    'delete observer with right context');
  CheckEquals(1, FObserver.RefCount,
    'observer rc after delete observer with right context');
  CheckEquals(1, ASubject.RefCount,
    'subject rc after delete observer callback');

  Check(not ASubject.DeleteObserver(FObserver),
    'delete deleted observer with right context');
  Check(not ASubject.DeleteObserver(nil),
    'delete nil observer on empty after filling');
end;

procedure TXPSubjectTests.TestDeleteObservers;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(1, ASubject.RefCount, 'sole reference on construction');
  CheckEquals(0, ASubject.Count, 'empty observer count on construction');

  ASubject.DeleteObservers;
  CheckEquals(1, ASubject.RefCount,
    'rc after delete observers without observers');
  CheckEquals(0, ASubject.Count,
    'observer count after delete observers without observers');

  FObserver.Subject := ASubject;
  Check(ASubject.InsertObserver(0, FObserver, ASubject),
    'insert observer into subject');
  CheckEquals(2, FObserver.RefCount,
    'observer rc after registration');

  FObserver2.Subject := ASubject;
  Check(ASubject.InsertObserver(0, FObserver2, ASubject),
    'insert observer 2 into subject');
  CheckEquals(2, FObserver2.RefCount, 'observer 2 rc after registration');

  FObserver3.Subject := ASubject;
  Check(ASubject.InsertObserver(0, FObserver3, ASubject),
    'insert observer 3 into subject');
  CheckEquals(2, FObserver3.RefCount, 'observer 3 rc after registration');

  CheckEquals(3, ASubject.Count, 'observer count after 3 registrations');
  CheckEquals(4, ASubject.RefCount, 'subject rc after 3 registrations');

  ASubject.DeleteObservers;
  CheckEquals(0, ASubject.Count, 'observer count after delete observers');
  CheckEquals(1, ASubject.RefCount, 'subject rc after delete observers');
  CheckEquals(1, FObserver.RefCount, 'observer rc after delete observers');
  CheckEquals(1, FObserver2.RefCount, 'observer 2 rc after delete observers');
  CheckEquals(1, FObserver3.RefCount, 'observer 3 rc after delete observers');
end;

procedure TXPSubjectTests.TestInsertObserver;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(1, ASubject.RefCount, 'sole reference on construction');
  CheckEquals(0, ASubject.Count, 'empty observer count on construction');
  CheckEquals(1, FObserver.RefCount, 'rc observer on construction');

  FObserver.Subject := ASubject;
  CheckEquals(2, ASubject.RefCount, 'subject rc after assignment');
  CheckEquals(1, FObserver.RefCount, 'observer rc after assignment');
  Check(not ASubject.InsertObserver(-1, FObserver, ASubject),
    'insert lower bound error');
  Check(not ASubject.InsertObserver(1, FObserver, ASubject),
    'insert upper bound error');
  Check(ASubject.InsertObserver(0, FObserver, ASubject),
    'insert into empty subject');
  CheckEquals(1, ASubject.Count, 'observer count after registration');
  CheckEquals(2, FObserver.RefCount, 'observer rc after registration');

  FObserver2.Subject := ASubject;
  CheckEquals(3, ASubject.RefCount, 'subject rc after second assignment');
  CheckEquals(1, FObserver2.RefCount, 'observer2 rc after assignment');
  Check(not ASubject.InsertObserver(-1, FObserver2, ASubject),
    'insert 2 lower bound error');
  Check(not ASubject.InsertObserver(2, FObserver2, ASubject),
    'insert 2 upper bound error');
  Check(ASubject.InsertObserver(0, FObserver2, ASubject),
    'insert into start of non-empty subject');
  CheckEquals(2, ASubject.Count, 'observer count after second registration');
  CheckEquals(2, FObserver2.RefCount, 'observer2 rc after registration');

  FObserver3.Subject := ASubject;
  CheckEquals(4, ASubject.RefCount, 'subject rc after third assignment');
  CheckEquals(1, FObserver3.RefCount, 'observer3 rc after assignment');
  Check(not ASubject.InsertObserver(-1, FObserver3, ASubject),
    'insert 3 lower bound error');
  Check(not ASubject.InsertObserver(3, FObserver3, ASubject),
    'insert 3 upper bound error');
  Check(ASubject.InsertObserver(2, FObserver3, ASubject),
    'insert into end of non-empty subject');
  CheckEquals(3, ASubject.Count,
    'observer count after third registration');
  CheckEquals(2, FObserver2.RefCount, 'observer3 rc after registration');

  FObserver4.Subject := ASubject;
  CheckEquals(5, ASubject.RefCount, 'subject rc after fourth assignment');
  CheckEquals(1, FObserver4.RefCount, 'observer4 rc after assignment');
  Check(not ASubject.InsertObserver(-1, FObserver4, ASubject),
    'insert 4 lower bound error');
  Check(not ASubject.InsertObserver(4, FObserver4, ASubject),
    'insert 4 upper bound error');
  Check(ASubject.InsertObserver(2, FObserver4, ASubject),
    'insert into middle of non-empty subject');
  CheckEquals(4, ASubject.Count,
    'observer count after fourth registration');
  CheckEquals(2, FObserver4.RefCount, 'observer4 rc after registration');

  Check(not ASubject.InsertObserver(-1, FObserver3, ASubject),
    'insert 5 lower bound error with current member');
  Check(not ASubject.InsertObserver(5, FObserver3, ASubject),
    'insert 5 upper bound error with current member');
  Check(not ASubject.InsertObserver(0, FObserver3, ASubject),
    'insert 5 at 0 with found current member');
  Check(not ASubject.InsertObserver(1, FObserver3, ASubject),
    'insert 5 at 1 with found current member');
  Check(not ASubject.InsertObserver(2, FObserver3, ASubject),
    'insert 5 at 2 with found current member');
  Check(not ASubject.InsertObserver(3, FObserver3, ASubject),
    'insert 5 at 3 with found current member');
  Check(not ASubject.InsertObserver(4, FObserver3, ASubject),
    'insert 5 at 4 with found current member');

  ASubject := nil;
  CheckEquals(1, FObserver.RefCount, 'observer 1 rc after subject nil''d');
  CheckEquals(1, FObserver2.RefCount, 'observer 2 rc after subject nil''d');
  CheckEquals(1, FObserver3.RefCount, 'observer 3 rc after subject nil''d');
  CheckEquals(1, FObserver4.RefCount, 'observer 4 rc after subject nil''d');
end;

procedure TXPSubjectTests.TestObserverCount;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(0, ASubject.ObserverCount,
    'empty observer count on construction');
  CheckEquals(1, FObserver.RefCount, 'observer rc before acquiring subject');
  FObserver.Subject := ASubject;
  Check(ASubject.AddObserver(FObserver, ASubject),
    '1: adding first observer to subject') ;
  CheckEquals(2, ASubject.RefCount, '1: subject rc after first observer');
  CheckEquals(2, FObserver.RefCount, '1: observer rc after acquiring subject');
  CheckEquals(1, ASubject.ObserverCount,
    '1: observer count after first observer');
  CheckEquals(1, FObserver2.RefCount,
    '1: observer rc before acquiring subject');
  FObserver2.Subject := ASubject;
  Check(ASubject.AddObserver(FObserver2, ASubject),
    '1: adding second observer to subject');
  CheckEquals(3, ASubject.RefCount, '1: subject rc after second observer');
  CheckEquals(2, FObserver2.RefCount,
    '1: second observer rc after acquiring subject');
  CheckEquals(2, ASubject.ObserverCount,
    '1: observer count after second observer');
  Check(ASubject.DeleteObserver(FObserver2),
    '1: deleting second observer from subject');
  CheckEquals(2, ASubject.RefCount,
    '1: subject rc after deleting second observer');
  CheckEquals(1, FObserver2.RefCount,
    '1: second observer rc after detaching from subject');
  CheckEquals(1, ASubject.ObserverCount,
    '1: observer count after deleting second observer');
  CheckEquals(2, FObserver.RefCount,
    '1: observer rc after detaching first observer from subject');
  Check(ASubject.DeleteObserver(FObserver),
    '1: deleting second observer from subject');
  CheckEquals(1, ASubject.RefCount,
    '1: subject rc after deleting first observer');
  CheckEquals(1, FObserver.RefCount,
    '1: first observer rc after detaching from subject');
  CheckEquals(0, ASubject.ObserverCount,
    '1: observer count after deleting first observer');
  CheckEquals(1, FObserver2.RefCount,
    '1: second observer rc after first observer detached from subject');

  // Repeat but reverse removal order

  FObserver.Subject := ASubject;
  Check(ASubject.AddObserver(FObserver, ASubject),
    '2: adding first observer to subject');
  CheckEquals(2, ASubject.RefCount, '2: subject rc after first observer');
  CheckEquals(2, FObserver.RefCount, '2: observer rc after acquiring subject');
  CheckEquals(1, ASubject.ObserverCount,
    '2: observer count after first observer');
  CheckEquals(1, FObserver2.RefCount,
    '2: observer rc before acquiring subject');
  FObserver2.Subject := ASubject;
  Check(ASubject.AddObserver(FObserver2, ASubject),
    '2: adding second observer to subject');
  CheckEquals(3, ASubject.RefCount, '2: subject rc after second observer');
  CheckEquals(2, FObserver2.RefCount,
    '2: second observer rc after acquiring subject');
  CheckEquals(2, ASubject.ObserverCount,
    '2: observer count after second observer');
  Check(ASubject.DeleteObserver(FObserver),
    '2: deleting first observer from subject');
  CheckEquals(2, ASubject.RefCount,
    '2: subject rc after deleting first observer');
  CheckEquals(1, FObserver.RefCount,
    '2: observer rc after detaching from subject');
  CheckEquals(1, ASubject.ObserverCount,
    '2: observer count after deleting first observer');
  CheckEquals(2, FObserver2.RefCount,
    '2: second observer rc after first observer detached from subject');
  Check(ASubject.DeleteObserver(FObserver2),
    '2: deleting second observer from subject');
  CheckEquals(1, ASubject.RefCount,
    '2: subject rc after deleting second observer');
  CheckEquals(1, FObserver2.RefCount,
    '2: second observer rc after detaching from subject');
  CheckEquals(0, ASubject.ObserverCount,
    '2: observer count after deleting second observer');
  CheckEquals(1, FObserver.RefCount,
    '2: first observer rc after detaching second observer from subject');

  // Try repeated deletion

  Check(not ASubject.DeleteObserver(FObserver2),
    '2: deleting second observer (again) from subject');
  CheckEquals(1, ASubject.RefCount,
    '2: subject rc after second attempt to delete second observer');
  CheckEquals(1, FObserver2.RefCount,
    '2: second observer rc after second attempt to detach from subject');
  CheckEquals(0, ASubject.ObserverCount,
    '2: observer count after attempting  second deletion of second observer');
  CheckEquals(1, FObserver.RefCount,
    '2: observer rc after attempting to detach second observer from subject');
end;

procedure TXPSubjectTests.SetUp;
begin
  inherited;
  FObserver := TCrackedObserver.Create;
  FObserver2 := TCrackedObserver.Create;
  FObserver3 := TCrackedObserver.Create;
  FObserver4 := TCrackedObserver.Create;
end;

procedure TXPSubjectTests.TearDown;
begin
  FObserver := nil;
  FObserver2 := nil;
  FObserver3 := nil;
  FObserver4 := nil;
  inherited;
end;

procedure TXPSubjectTests.TestGetObserver;
var
  ASubject: IXPCrackedSubject;

begin
  ASubject := TCrackedSubject.Create;
  CheckEquals(1, ASubject.RefCount, 'subject rc count on construction');
  CheckEquals(0, ASubject.ObserverCount,
    'empty observer count on construction');
  Check(ASubject.Observers[0] = nil, 'observers[0] on empty subject');
  CheckEquals(1, ASubject.RefCount,
    'subject rc count after observers[0] on empty subject');
  Check(ASubject.Observers[-1] = nil, 'observers[-1] on empty subject');
  CheckEquals(1, ASubject.RefCount,
    'subject rc count after observers[-1] on empty subject');
  Check(ASubject.Observers[1] = nil, 'observers[1] on empty subject');
  CheckEquals(1, ASubject.RefCount,
    'subject rc count after observers[1] on empty subject');

  // Add an observer

  CheckEquals(1, FObserver.RefCount, 'observer rc before acquiring subject');
  FObserver.Subject := ASubject;
  Check(ASubject.AddObserver(FObserver, ASubject),
    '1: adding first observer to subject') ;
  CheckEquals(2, ASubject.RefCount, '1: subject rc after first observer');
  CheckEquals(2, FObserver.RefCount, '1: observer rc after acquiring subject');
  CheckEquals(1, ASubject.ObserverCount,
    '1: observer count after first observer');
  Check(ASubject.Observers[0] <> nil, 'observers[0] non-nil on empty subject');
  // temporary interface created in above comparison not released until
  // procedure scope exited
  CheckEquals(3, FObserver.RefCount,
    'observer rc after observers[0] non-nil comparison');
  CheckEquals(1, FObserver2.RefCount, 'observer 2 rc before re-assignment');
  FObserver2 := FObserver;
  // temporary still present in rc after copy
  CheckEquals(4, FObserver2.RefCount, 'observer 2 rc after re-assignment');
  CheckEquals(4, FObserver.RefCount, 'observer rc after copying to observer 2');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -