From c51aaed2cdcf4b86577e7689ef594b6745a2a3c1 Mon Sep 17 00:00:00 2001 From: Vincent Parrett Date: Fri, 12 Dec 2014 11:18:27 +1100 Subject: [PATCH] Tidying up destruction of internals. --- DUnitX.TestFixture.pas | 15 +++++---- DUnitX.TestFramework.pas | 19 +++++++++-- DUnitX.TestRunner.pas | 24 +++++++------- DUnitX_XE7.groupproj | 28 ++++++++-------- Tests/DUnitX.Tests.Assert.pas | 1 + Tests/DUnitX.Tests.DUnitCompatibility.pas | 2 +- Tests/DUnitX.Tests.Example.pas | 9 +++++ Tests/DUnitX.Tests.IoC.pas | 40 +++++++++++++++-------- Tests/DUnitXTest_XE7.dpr | 4 +++ Tests/DUnitXTest_XE7.dproj | 18 +++++++--- 10 files changed, 107 insertions(+), 53 deletions(-) diff --git a/DUnitX.TestFixture.pas b/DUnitX.TestFixture.pas index 9f178b57..34290d19 100644 --- a/DUnitX.TestFixture.pas +++ b/DUnitX.TestFixture.pas @@ -121,6 +121,7 @@ TDUnitXTestFixture = class(TWeakReferencedObject, ITestFixture,ITestFixtureInf procedure SetTearDownFixtureMethod(const AMethodName : string; const AMethod : TTestMethod; const AIsDestructor : boolean); procedure SetTestInOwnThread(const value: Boolean); class constructor Create; + class destructor Destroy; public constructor Create(const AName : string; const ACategory : string; const AInstance : TObject);overload; constructor Create(const AName : string; const ACategory : string; const AClass : TClass);overload; @@ -218,7 +219,6 @@ constructor TDUnitXTestFixture.Create(const AName : string; const ACategory : st {$ENDIF} FFixtureInstance := FTestClass.Create; end; - end; destructor TDUnitXTestFixture.Destroy; @@ -416,12 +416,8 @@ function TDUnitXTestFixture.ITestFixtureInfo_GetTests: IList; procedure TDUnitXTestFixture.OnMethodExecuted(const AMethod: TTestMethod); begin - if FTearDownFixtureIsDestructor then - begin - if TMethod(AMethod).Code = TMethod(FTearDownFixtureMethod).Code then + if FTearDownFixtureIsDestructor and (TMethod(AMethod).Code = TMethod(FTearDownFixtureMethod).Code) then FFixtureInstance := nil; - end; - end; procedure TDUnitXTestFixture.SetEnabled(const value: Boolean); @@ -495,6 +491,12 @@ function TDUnitXTestFixture.AddTestCase(const ACaseName, AName: string; const AC FRttiContext := TRttiContext.Create; end; +class destructor TDUnitXTestFixture.Destroy; +begin + FRttiContext.Free; +end; + + constructor TDUnitXTestFixture.Create(const AName: string; const ACategory : string; const AInstance: TObject); begin FFixtureInstance := AInstance; @@ -517,5 +519,6 @@ function TDUnitXTestFixture.CreateTestFromTestCase(const ACaseInfo : TestCaseInf result.IgnoreMemoryLeaks := getIgnoreMemoryLeaksForMethod(AMethod); end; + end. diff --git a/DUnitX.TestFramework.pas b/DUnitX.TestFramework.pas index b7cd149e..7c7361a4 100644 --- a/DUnitX.TestFramework.pas +++ b/DUnitX.TestFramework.pas @@ -940,6 +940,7 @@ implementation DUnitX.MemoryLeakMonitor.Default, DUnitX.FixtureProviderPlugin, DUnitX.FilterBuilder, + DUnitX.WeakReference, Variants, Math, StrUtils, @@ -1884,9 +1885,12 @@ class procedure TDUnitX.CheckCommandLine; end; class function TDUnitX.CurrentRunner: ITestRunner; +var + ref : IWeakReference; begin - if not TDUnitXTestRunner.FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,result) then + if not TDUnitXTestRunner.FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,ref) then raise Exception.Create('No Runner found for current thread'); + result := ref.Data; end; @@ -1971,9 +1975,16 @@ procedure TTestFixtureHelper.Log(const msg: string); procedure TTestFixtureHelper.Log(const logType : TLogLevel; const msg: string); var runner : ITestRunner; + ref : IWeakReference; begin - if TDUnitXTestRunner.FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,runner) then - runner.Log(logType,msg) + if TDUnitXTestRunner.FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,ref) then + begin + runner := ref.Data; + if runner <> nil then + runner.Log(logType,msg) + else + System.Writeln(msg); + end else System.Writeln(msg); end; @@ -2036,4 +2047,6 @@ constructor CategoryAttribute.Create(const ACategory: string); initialization TDUnitX.RegisterPlugin(TDUnitXFixtureProviderPlugin.Create); +finalization + end. diff --git a/DUnitX.TestRunner.pas b/DUnitX.TestRunner.pas index 52c64dff..34a00638 100644 --- a/DUnitX.TestRunner.pas +++ b/DUnitX.TestRunner.pas @@ -46,11 +46,11 @@ interface type /// Note - we rely on the fact that there will only ever be 1 testrunner /// per thread, if this changes then handling of WriteLn will need to change - TDUnitXTestRunner = class(TInterfacedObject, ITestRunner) + TDUnitXTestRunner = class(TWeakReferencedObject, ITestRunner) private class var FRttiContext : TRttiContext; public class var - FActiveRunners : TDictionary; + FActiveRunners : TDictionary>; private FLoggers : TList; FUseRTTI : boolean; @@ -249,7 +249,7 @@ function TDUnitXTestRunner.BuildFixtures : IInterface; class constructor TDUnitXTestRunner.Create; begin FRttiContext := TRttiContext.Create; - FActiveRunners := TDictionary.Create; + FActiveRunners := TDictionary>.Create; end; function TDUnitXTestRunner.CheckMemoryAllocations(const test: ITest; out errorResult: ITestResult; const memoryAllocationProvider: IMemoryLeakMonitor): boolean; @@ -302,7 +302,7 @@ constructor TDUnitXTestRunner.Create(const AListener: ITestLogger); FLogMessages := TStringList.Create; MonitorEnter(TDUnitXTestRunner.FActiveRunners); try - TDUnitXTestRunner.FActiveRunners.Add(TThread.CurrentThread.ThreadID, Self); + TDUnitXTestRunner.FActiveRunners.Add(TThread.CurrentThread.ThreadID, TWeakReference.Create(Self)); finally MonitorExit(TDUnitXTestRunner.FActiveRunners); end; @@ -333,7 +333,6 @@ destructor TDUnitXTestRunner.Destroy; FLogMessages.Free; FLoggers.Free; FFixtureClasses.Free; - inherited; end; @@ -546,9 +545,12 @@ function TDUnitXTestRunner.ExecuteErrorResult( end; class function TDUnitXTestRunner.GetActiveRunner: ITestRunner; +var + ref : IWeakReference; begin result := nil; - FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,result) + if FActiveRunners.TryGetValue(TThread.CurrentThread.ThreadId,ref) then + result := ref.Data; end; function TDUnitXTestRunner.ExecuteFailureResult( @@ -627,13 +629,14 @@ function TDUnitXTestRunner.ExecuteSuccessfulResult(const context: ITestExecuteCo Result := TDUnitXTestResult.Create(test as ITestInfo, TTestResultType.Pass, message); end; -procedure TDUnitXTestRunner.ExecuteTearDownFixtureMethod( - const context: ITestExecuteContext; const threadId: Cardinal; - const fixture: ITestFixture); +procedure TDUnitXTestRunner.ExecuteTearDownFixtureMethod(const context: ITestExecuteContext; const threadId: Cardinal; const fixture: ITestFixture); +var + teardown : TTestMethod; begin try Self.Loggers_TeardownFixture(threadId, fixture as ITestFixtureInfo); - fixture.TearDownFixtureMethod; + tearDown := fixture.TearDownFixtureMethod; + tearDown(); fixture.OnMethodExecuted(fixture.TearDownFixtureMethod); except on e: Exception do @@ -810,7 +813,6 @@ procedure TDUnitXTestRunner.SetUseRTTI(const value: Boolean); procedure TDUnitXTestRunner.Status(const msg: string); begin Self.Log(TLogLevel.Information,msg); - end; procedure TDUnitXTestRunner.WriteLn; diff --git a/DUnitX_XE7.groupproj b/DUnitX_XE7.groupproj index 3b8a0c08..3d59fd3a 100644 --- a/DUnitX_XE7.groupproj +++ b/DUnitX_XE7.groupproj @@ -9,10 +9,10 @@ - + - + @@ -41,15 +41,6 @@ - - - - - - - - - @@ -59,14 +50,23 @@ + + + + + + + + + - + - + - + diff --git a/Tests/DUnitX.Tests.Assert.pas b/Tests/DUnitX.Tests.Assert.pas index 953ab2d6..d8e4ac21 100644 --- a/Tests/DUnitX.Tests.Assert.pas +++ b/Tests/DUnitX.Tests.Assert.pas @@ -231,6 +231,7 @@ procedure TTestsAssert.Fail_Throws_ETestFailure_Exception_With_Return_Address_Re end; Assert.WillRaise(MyProc, ETestFailure); + MyProc := nil; end; procedure TTestsAssert.Pass_Throws_ETestPass_Exception; diff --git a/Tests/DUnitX.Tests.DUnitCompatibility.pas b/Tests/DUnitX.Tests.DUnitCompatibility.pas index 3fbf3603..2cf44c94 100644 --- a/Tests/DUnitX.Tests.DUnitCompatibility.pas +++ b/Tests/DUnitX.Tests.DUnitCompatibility.pas @@ -80,8 +80,8 @@ procedure TMyDUnitTestSetUp.SetUp; procedure TMyDUnitTestSetup.TearDown; begin - inherited; FObject.Free; + inherited; end; initialization diff --git a/Tests/DUnitX.Tests.Example.pas b/Tests/DUnitX.Tests.Example.pas index 654904da..c8fecc98 100644 --- a/Tests/DUnitX.Tests.Example.pas +++ b/Tests/DUnitX.Tests.Example.pas @@ -99,6 +99,7 @@ TExampleFixture2 = class procedure SetupFixture; [Teardown] procedure TearDownFixture; + destructor Destroy;override; published procedure Published_Procedures_Are_Included_As_Tests; end; @@ -183,6 +184,7 @@ procedure TMyExampleTests.TestTwo; //CheckIs(x,TObject); //DUnit compatibility. TDUnitX.CurrentRunner.Status('hello world'); Assert.IsTrue(x is TObject); /// a bit pointless since it's strongly typed. + x.Free; end; procedure TMyExampleTests.TestTwoOne; @@ -194,10 +196,17 @@ procedure TMyExampleTests.TestTwoOne; //CheckIs(x,TObject); //DUnit compatibility. TDUnitX.CurrentRunner.Status('hello world'); Assert.IsTrue(x is TObject); /// a bit pointless since it's strongly typed. + x.Free; end; { TExampleFixture2 } +destructor TExampleFixture2.Destroy; +begin + + inherited; +end; + procedure TExampleFixture2.Published_Procedures_Are_Included_As_Tests; begin FPublished_Procedures_Are_Included_As_Tests_Called := True; diff --git a/Tests/DUnitX.Tests.IoC.pas b/Tests/DUnitX.Tests.IoC.pas index feef3c68..fa2bf820 100644 --- a/Tests/DUnitX.Tests.IoC.pas +++ b/Tests/DUnitX.Tests.IoC.pas @@ -46,9 +46,14 @@ interface end; TDUnitX_IoCTests = class + private + FContainer : TDUnitXIoC; public [SetupFixture] - procedure Setup; + procedure Setup; + + [TearDownFixture] + procedure TearDownFixture; {$IFDEF DELPHI_XE_UP} [Test] @@ -77,7 +82,9 @@ TFoo = class(TInterfacedObject,IFoo) procedure TDUnitX_IoCTests.Setup; begin - TDUnitXIoC.DefaultContainer.RegisterType( + FContainer := TDUnitXIoC.Create; + + FContainer.RegisterType( function : IFoo begin result := TFoo.Create; @@ -85,11 +92,11 @@ procedure TDUnitX_IoCTests.Setup; {$IFDEF DELPHI_XE_UP} //NOTE: DUnitX.IoC has details on why this is only available for XE up. - TDUnitXIoC.DefaultContainer.RegisterType('test'); + FContainer.RegisterType('test'); {$ENDIF} //singletons - TDUnitXIoC.DefaultContainer.RegisterType(true, + FContainer.RegisterType(true, function : IFoo begin result := TFoo.Create; @@ -98,17 +105,22 @@ procedure TDUnitX_IoCTests.Setup; {$IFDEF DELPHI_XE_UP} //NOTE: DUnitX.IoC has details on why this is only available for XE up. - TDUnitXIoC.DefaultContainer.RegisterType(true,'impl_singleton'); + FContainer.RegisterType(true,'impl_singleton'); {$ENDIF} end; +procedure TDUnitX_IoCTests.TearDownFixture; +begin + FContainer.Free; +end; + procedure TDUnitX_IoCTests.Test_Activator_Non_Singleton; var foo1 : IFoo; foo2 : IFoo; begin - foo1 := TDUnitXIoC.DefaultContainer.Resolve(); - foo2 := TDUnitXIoC.DefaultContainer.Resolve(); + foo1 := FContainer.Resolve(); + foo2 := FContainer.Resolve(); Assert.AreNotSame(foo1,foo2); end; @@ -118,13 +130,13 @@ procedure TDUnitX_IoCTests.Test_Activator_Singleton; foo1 : IFoo; foo2 : IFoo; begin - foo1 := TDUnitXIoC.DefaultContainer.Resolve('activator_singleton'); - foo2 := TDUnitXIoC.DefaultContainer.Resolve('activator_singleton'); + foo1 := FContainer.Resolve('activator_singleton'); + foo2 := FContainer.Resolve('activator_singleton'); Assert.AreSame(foo1,foo2); {$IFDEF DELPHI_XE_UP} //NOTE: DUnitX.IoC has details on why this is only available for XE up. - foo1 := TDUnitXIoC.DefaultContainer.Resolve('impl_singleton'); + foo1 := FContainer.Resolve('impl_singleton'); Assert.AreNotSame(foo1,foo2); {$ENDIF} end; @@ -136,8 +148,8 @@ procedure TDUnitX_IoCTests.Test_Implementation_Non_Singleton; foo1 : IFoo; foo2 : IFoo; begin - foo1 := TDUnitXIoC.DefaultContainer.Resolve('test'); - foo2 := TDUnitXIoC.DefaultContainer.Resolve('test'); + foo1 := FContainer.Resolve('test'); + foo2 := FContainer.Resolve('test'); Assert.AreNotSame(foo1,foo2); end; @@ -146,8 +158,8 @@ procedure TDUnitX_IoCTests.Test_Implementation_Singleton; foo1 : IFoo; foo2 : IFoo; begin - foo1 := TDUnitXIoC.DefaultContainer.Resolve('impl_singleton'); - foo2 := TDUnitXIoC.DefaultContainer.Resolve('impl_singleton'); + foo1 := FContainer.Resolve('impl_singleton'); + foo2 := FContainer.Resolve('impl_singleton'); Assert.AreSame(foo1,foo2); end; {$ENDIF} diff --git a/Tests/DUnitXTest_XE7.dpr b/Tests/DUnitXTest_XE7.dpr index 7df64efd..7fa71f89 100644 --- a/Tests/DUnitXTest_XE7.dpr +++ b/Tests/DUnitXTest_XE7.dpr @@ -73,6 +73,8 @@ begin //Run tests results := runner.Execute; + runner := nil; + {$IFDEF CI} if not results.AllPassed then System.ExitCode := 1; @@ -81,6 +83,8 @@ begin System.Write('Done.. press key to quit.'); System.Readln; {$ENDIF} + results := nil; + except on E: Exception do begin diff --git a/Tests/DUnitXTest_XE7.dproj b/Tests/DUnitXTest_XE7.dproj index 53652c17..b88a5944 100644 --- a/Tests/DUnitXTest_XE7.dproj +++ b/Tests/DUnitXTest_XE7.dproj @@ -29,6 +29,12 @@ Base true + + true + Cfg_2 + true + true + DUnitXTest_XE7 rtl;vcl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;vclie;webdsnap;inet;inetdbbde;inetdbxpress;soaprtl;DbxCommonDriver;DbxClientDriver;DBXInterBaseDriver;DBXMySQLDriver;dbexpress;dbxcds;FBDream2010;SynEdit_R2010;NxCommonRun;NxGridRun;KWizardD2010R;GFDLIB2009;dclRouteMapD2010;tb2k_d12;SpTBXLib_d12;dwWin7Controls_2010;IndyCore140;IndySystem140;IndyProtocols140;lmddocking11rt_140;lmdrtl11rt_140;RaizeComponentsVcl;FBMiscComponents;FBFormDesigner;FBSynEditHighlighters;VSPageR;madBasic_;madDisAsm_;madExcept_;adortl;TeeWorld814;TeeImage814;TeeLanguage814;TeePro814;TeeGL814;TeeUI814;TeeDB814;Tee814;VirtualTreesR;VSMessageAPIDesign;VSMessageAPIRun;$(DCC_UsePackage) @@ -57,6 +63,9 @@ 3 DEBUG;$(DCC_Define) + + DUNITX-DEBUG;$(DCC_Define) + MainSource @@ -167,10 +176,11 @@ - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components + Embarcadero Metropolis UI Live Tile Standard Components + Embarcadero C++Builder Office 2000 Servers Package + Embarcadero C++Builder Office XP Servers Package + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components