[NUI] Add DisposeTest, Add DebugFileLogging Test
authordongsug.song <dongsug.song@samsung.com>
Fri, 28 Jan 2022 11:56:44 +0000 (20:56 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 8 Feb 2022 04:41:28 +0000 (13:41 +0900)
- fix the bug that TextRunner was not working properly.
- change the TextRunner to executed one by one by using EventThread trigger.
- previously, it was reculsively executed in one timer callback.
- this means it accumulated call stack very much.

src/Tizen.NUI/src/internal/Common/DebugFileLogging.cs [new file with mode: 0755]
src/Tizen.NUI/src/internal/Common/DisposeQueue.cs
src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs
src/Tizen.NUI/src/public/Common/BaseHandle.cs
test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/Program.cs
test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/etc/DisposeTest.cs [new file with mode: 0644]
test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/internal/TSView.cs [moved from test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/TSView.cs with 100% similarity]
test/Tizen.NUI.Devel.Tests.Ubuntu/nunit.framework/TUnit/TAsyncThreadMgr.cs
test/Tizen.NUI.Devel.Tests.Ubuntu/nunit.framework/TUnit/TLogger.cs
test/Tizen.NUI.Devel.Tests.Ubuntu/nunitlite/TUnit/TRunner.cs

diff --git a/src/Tizen.NUI/src/internal/Common/DebugFileLogging.cs b/src/Tizen.NUI/src/internal/Common/DebugFileLogging.cs
new file mode 100755 (executable)
index 0000000..7183da4
--- /dev/null
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright(c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using global::System;
+using global::System.IO;
+using global::System.Diagnostics;
+
+namespace Tizen.NUI
+{
+    internal class DebugFileLogging
+    {
+        #region Constant Fields
+        private const string logFolderPath = "/home/ssong2best/Downloads/0128/";//"/run/user/5001/nui/"; //need fix as for target (tv, ubuntu, and etc)
+        #endregion //Constant Fields
+
+        #region Fields
+        public static DebugFileLogging Instance => instance;
+        private static readonly DebugFileLogging instance = new DebugFileLogging();
+        private string filePath;
+        private FileStream file;
+        #endregion //Fields
+
+        #region Constructors
+        private DebugFileLogging()
+        {
+            Directory.CreateDirectory(logFolderPath);
+
+            var id = Process.GetCurrentProcess().Id;
+            filePath = logFolderPath + id.ToString();
+            file = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
+        }
+        #endregion //Constructors
+
+        #region Methods
+        [Conditional("NUI_DEBUG_ON")]
+        internal void WriteLog(string log)
+        {
+            TimeSpan curr = DateTime.Now.TimeOfDay;
+
+            FileStream file = new FileStream(filePath, FileMode.Append, FileAccess.Write);
+            StreamWriter write = new StreamWriter(file);
+            var time = String.Format("[{0,-13}] ", curr.TotalMilliseconds);
+            write.WriteLine(time + log);
+            write.Close();
+        }
+        #endregion //Methods
+    }
+}
index 6bb216a..71ec436 100755 (executable)
@@ -53,6 +53,8 @@ namespace Tizen.NUI
                 disposeQueueProcessDisposablesDelegate = new EventThreadCallback.CallbackDelegate(ProcessDisposables);
                 eventThreadCallback = new EventThreadCallback(disposeQueueProcessDisposablesDelegate);
                 isCalled = true;
+
+                DebugFileLogging.Instance.WriteLog("DiposeTest START");
             }
         }
 
@@ -76,6 +78,7 @@ namespace Tizen.NUI
                 foreach (IDisposable disposable in disposables)
                 {
                     disposable.Dispose();
+                    DebugFileLogging.Instance.WriteLog($"disposable.Dispose(); type={disposable.GetType().FullName}, hash={disposable.GetHashCode()}");
                 }
                 disposables.Clear();
             }
index f9b752e..29ca704 100755 (executable)
@@ -1150,19 +1150,16 @@ namespace Tizen.NUI.BaseComponents
                 return;
             }
 
-#if NUI_DEBUG_ON
-            NUILog.Debug($"[Dispose] View.Dispose({type}) START");
-            NUILog.Debug($"[Dispose] type:{GetType()} copyNativeHandle:{GetBaseHandleCPtrHandleRef.Handle.ToString("X8")}");
+            DebugFileLogging.Instance.WriteLog($"View.Dispose({type}) START");
+            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{GetBaseHandleCPtrHandleRef.Handle.ToString("X8")}");
             if(HasBody())
             {
-                NUILog.Debug($"[Dispose] ID:{Interop.Actor.GetId(GetBaseHandleCPtrHandleRef)} Name:{Interop.Actor.GetName(GetBaseHandleCPtrHandleRef)}");
+                DebugFileLogging.Instance.WriteLog($"ID:{Interop.Actor.GetId(GetBaseHandleCPtrHandleRef)} Name:{Interop.Actor.GetName(GetBaseHandleCPtrHandleRef)}");
             }
             else
             {
-                NUILog.Debug($"has no native body!");
+                DebugFileLogging.Instance.WriteLog($"has no native body!");
             }
-#endif
-
 
             //_mergedStyle = null;
 
index 9842020..c033810 100644 (file)
@@ -50,10 +50,6 @@ namespace Tizen.NUI
         //A Flag to check who called Dispose(). (By User or DisposeQueue)
         private bool isDisposeQueued = false;
 
-#if NUI_DEBUG_ON
-        private static int debuggingCount = 0;
-#endif
-
         /// <summary>
         /// Create an instance of BaseHandle.
         /// </summary>
@@ -78,7 +74,7 @@ namespace Tizen.NUI
             //to catch derived classes dali native exceptions
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
 
-            NUILog.Debug($"[Dispose] BaseHandle.contructor with cMemeryOwn:{cMemoryOwn} START");
+            DebugFileLogging.Instance.WriteLog($"BaseHandle.contructor with cMemeryOwn:{cMemoryOwn} START");
 
             registerMe = swigCMemOwn = cMemoryOwn;
             swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
@@ -92,22 +88,18 @@ namespace Tizen.NUI
                 Registry.Register(this);
             }
 
-#if NUI_DEBUG_ON
-            NUILog.Debug($"[Dispose] type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-
-            debuggingCount++;
+            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
             if (this is BaseComponents.View view)
             {
-                NUILog.Debug($"[Dispose] ID:{view.ID} Name:{view.Name} debuggingCount:{debuggingCount}");
+                  DebugFileLogging.Instance.WriteLog($"ID:{view.ID} Name:{view.Name}");
             }
-            NUILog.Debug($"[Dispose] BaseHandle.contructor with cMemeryOwn END");
-            NUILog.Debug($"=============================");
-#endif
+            DebugFileLogging.Instance.WriteLog($" BaseHandle.contructor with cMemeryOwn END");
+            DebugFileLogging.Instance.WriteLog($"=============================");
         }
 
         internal BaseHandle(global::System.IntPtr cPtr)
         {
-            NUILog.Debug($"[Dispose] BaseHandle.contructor START");
+            DebugFileLogging.Instance.WriteLog($"BaseHandle.contructor START");
 
             registerMe = swigCMemOwn = true;
 
@@ -123,18 +115,13 @@ namespace Tizen.NUI
                 Registry.Register(this);
             }
 
-#if NUI_DEBUG_ON
-            NUILog.Debug($"[Dispose] type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-
-            debuggingCount++;
+            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
             if (this is BaseComponents.View view)
             {
-                NUILog.Debug($"[Dispose] ID:{view.ID} Name:{view.Name} debuggingCount:{debuggingCount}");
+                DebugFileLogging.Instance.WriteLog($"ID:{view.ID} Name:{view.Name}");
             }
-            NUILog.Debug($"[Dispose] BaseHandle.contructor END");
-            NUILog.Debug($"=============================");
-#endif
-
+            DebugFileLogging.Instance.WriteLog($"BaseHandle.contructor END");
+            DebugFileLogging.Instance.WriteLog($"=============================");
         }
 
         /// <summary>
@@ -366,13 +353,17 @@ namespace Tizen.NUI
                     var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
                     var me = this.GetType().FullName;
 
+                    DebugFileLogging.Instance.WriteLog("[NUI][BaseHandle] This API called from separate thread. This API must be called from MainThread. \n" +
+                        $" process:{process} thread:{thread}, disposing:{disposing}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n");
+
                     throw new global::System.InvalidOperationException("[NUI][BaseHandle] This API called from separate thread. This API must be called from MainThread. \n" +
                         $" process:{process} thread:{thread}, disposing:{disposing}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n");
                 }
 
                 if (isDisposeQueued)
                 {
-                    Tizen.Log.Fatal("NUI", $"should not be here! (dead code) this will be removed!");
+                    DebugFileLogging.Instance.WriteLog($"should not be here! (dead code) this will be removed!");
+
                     throw new global::System.Exception($"[NUI] should not be here! (dead code) this will be removed!");
                     Dispose(DisposeTypes.Implicit);
                 }
@@ -533,7 +524,7 @@ namespace Tizen.NUI
                 return;
             }
 
-            NUILog.Debug($"[Dispose] BaseHandle.Dispose({type}) START");
+            DebugFileLogging.Instance.WriteLog($"BaseHandle.Dispose({type}) START");
 
             if (type == DisposeTypes.Explicit)
             {
@@ -553,10 +544,8 @@ namespace Tizen.NUI
                 Registry.Unregister(this);
             }
 
-#if NUI_DEBUG_ON
-            debuggingCount--;
-            NUILog.Debug($"[Dispose] swigCMemOwn:{swigCMemOwn} debuggingCount:{debuggingCount} type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-#endif
+            DebugFileLogging.Instance.WriteLog($"swigCMemOwn:{swigCMemOwn} type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
+
             // this is temporary test code. will be removed laster
             {
                 if (swigCPtr.Handle != IntPtr.Zero && swigCPtrCopy.Handle != IntPtr.Zero)
@@ -577,6 +566,10 @@ namespace Tizen.NUI
                         tmp.Dispose();
                         if (refCnt > 2)
                         {
+                            DebugFileLogging.Instance.WriteLog($"[ERR] reference count is over than 2. Could be a memory leak. Need to check! \n" +
+                                $" process:{process} thread:{thread}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me} \n" +
+                                $" disposeType:{type}, name:{name}, daliID:{daliId}, hash:{hash}, refCnt:{refCnt}");
+
                             Log.Error("NUI", $"[ERR] reference count is over than 2. Could be a memory leak. Need to check! \n" +
                                 $" process:{process} thread:{thread}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me} \n" +
                                 $" disposeType:{type}, name:{name}, daliID:{daliId}, hash:{hash}, refCnt:{refCnt}");
@@ -597,6 +590,7 @@ namespace Tizen.NUI
             else
             {
                 var me = this.GetType().FullName;
+                DebugFileLogging.Instance.WriteLog($"[ERR] SwigCPtr is NULL, need to check! me:{me}");
                 Log.Error("NUI", $"[ERR] SwigCPtr is NULL, need to check! me:{me}");
             }
 
@@ -609,6 +603,7 @@ namespace Tizen.NUI
             else
             {
                 var me = this.GetType().FullName;
+                DebugFileLogging.Instance.WriteLog($"[ERR] swigCPtrCopy is NULL, need to check! me:{me}");
                 Log.Error("NUI", $"[ERR] swigCPtrCopy is NULL, need to check! me:{me}");
             }
 
@@ -618,8 +613,9 @@ namespace Tizen.NUI
             {
                 Application.Current.XamlResourceChanged -= OnResourcesChanged;
             }
-            
-            NUILog.Debug($"[Dispose] BaseHandle.Dispose({type}) END");
+            DebugFileLogging.Instance.WriteLog($"BaseHandle.Dispose({type}) END");
+            DebugFileLogging.Instance.WriteLog($"=============================");
+            NUILog.Debug($"BaseHandle.Dispose({type}) END");
             NUILog.Debug($"=============================");
         }
 
index ccd2101..67b11b9 100755 (executable)
@@ -22,6 +22,8 @@ using Tizen.NUI.BaseComponents;
 using System.Threading;
 using System.Diagnostics;
 using System.Threading.Tasks;
+using NUnit.Framework.TUnit;
+using NUnit.Framework.Interfaces;
 
 namespace Tizen.NUI.Devel.Tests
 {
@@ -44,6 +46,10 @@ namespace Tizen.NUI.Devel.Tests
         public static int mainPid;
         public static int mainTid;
         Timer timer;
+        private EventThreadCallback eventThreadCallback;
+        private NUnitLite.TUnit.TRunner trunner;
+        private ManualResetEvent methodExecutionResetEvent;
+        private TAsyncThreadMgr asyncThreadMgr;
 
         protected override void OnCreate()
         {
@@ -82,25 +88,47 @@ namespace Tizen.NUI.Devel.Tests
             };
             root.Add(mainTitle);
 
-            tlog.Debug(tag, "OnCreate() END!");
+            Thread.CurrentThread.Name = "main";
+            trunner = new NUnitLite.TUnit.TRunner();
+            trunner.LoadTestsuite();
 
-            timer = new Timer(1000);
-            timer.Tick += OnTick;
-            timer.Start();
+            asyncThreadMgr = TAsyncThreadMgr.GetInstance();
+            methodExecutionResetEvent = asyncThreadMgr.GetMethodExecutionResetEvent();
+            methodExecutionResetEvent.Reset();
 
+            Task t = Task.Run(() =>
+                {
+                    Thread.CurrentThread.Name = "textRunner";
+                    trunner._textRunner.Execute(trunner.args);
+                    asyncThreadMgr.SetData(null, null, null, null, false);
+                    methodExecutionResetEvent.Set();
+                });
+
+            eventThreadCallback = new EventThreadCallback(new EventThreadCallback.CallbackDelegate(ProcessTest));
+            eventThreadCallback.Trigger();
         }
 
-        private bool OnTick(object obj, EventArgs e)
+        private void ProcessTest()
         {
-            TRunner t = new TRunner();
-            t.LoadTestsuite();
-            t.Execute();
+            methodExecutionResetEvent.WaitOne();
 
-            App.MainTitleChangeText("Finished!");
-            return false;
+            if (asyncThreadMgr.RunTestMethod() == false)
+            {
+                mainTitle.Text = title + "Finished!\nWill be terminated after 5 seconds";
+                timer = new Timer(300);
+                timer.Tick += OnTick;
+                timer.Start();
+                return;
+            }
+            eventThreadCallback.Trigger();
         }
 
-
+        private bool OnTick(object obj, EventArgs e)
+        {
+            Thread.Sleep(5000);
+            Exit();
+            return false;
+        }
 
         static public async Task MainTitleChangeBackgroundColor(Color color)
         {
@@ -135,13 +163,7 @@ namespace Tizen.NUI.Devel.Tests
         {
             base.OnResume();
 
-            tlog.Debug(tag, $"### OnResume() START!");
-
-            // TRunner t = new TRunner();
-            // t.LoadTestsuite();
-            // t.Execute();
-
-            tlog.Debug(tag, $"OnResume() END!");
+            tlog.Debug(tag, $"OnResume()");
         }
 
         protected override void OnPause()
@@ -151,12 +173,9 @@ namespace Tizen.NUI.Devel.Tests
 
         protected override void OnTerminate()
         {
-            timer.Tick -= OnTick;
-            mainTitle.GetParent().Remove(mainTitle);
-            mainTitle = null;
-            root.GetParent().Remove(root);
-            root = null;
-
+            timer.Dispose();
+            mainTitle.Unparent();
+            root.Unparent();
             base.OnTerminate();
             Exit();
         }
diff --git a/test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/etc/DisposeTest.cs b/test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/etc/DisposeTest.cs
new file mode 100644 (file)
index 0000000..dcce0a8
--- /dev/null
@@ -0,0 +1,542 @@
+using NUnit.Framework;
+using NUnit.Framework.TUnit;
+using Tizen.NUI.Components;
+using Tizen.NUI.BaseComponents;
+using System.Collections.Generic;
+using System.IO;
+using global::System;
+using System.Threading;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+namespace Tizen.NUI.Devel.Tests
+{
+    using tlog = Tizen.Log;
+
+    [TestFixture]
+    [Description("DisposeTest")]
+    public class DisposeTest
+    {
+        private const string tag = "NUITEST";
+        private const int testSize = 100;
+        private const int testPosition = 100;
+        private const int RefCountWhenNew = 2;
+        private const int RefCountWhenAdd = 1;
+        private const int RefCountWhenRemoveOrUnparent = -1;
+        private const int RefCountWhenAddedInList = 0;
+        private const int RefCountWhenRemovedInList = 0;
+        private const int RefCountWhenCurrentFocusSet = 1;
+        private const int RefCountWhenFocusCleared = -1;
+        private const int RefCountWhenAnimationSet = 0;
+        private const int RefCountWhenAnimationPlayed = 0;
+        private const int RefCountWhenAnimationFinished = 0;
+        private string path;
+
+        [SetUp]
+        public void Init()
+        {
+            tlog.Info(tag, $"Init() is called! process={Process.GetCurrentProcess().Id}, thread={Thread.CurrentThread.ManagedThreadId}\n");
+        }
+
+        [TearDown]
+        public void Destroy()
+        {
+            tlog.Info(tag, $"Destroy() is called! process={Process.GetCurrentProcess().Id}, thread={Thread.CurrentThread.ManagedThreadId}\n");
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_NEW()
+        {
+            /* TEST CODE */
+            View testView = new View();
+
+            var expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_NEW_WITH_SETTINGS()
+        {
+            /* TEST CODE */
+            View testView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+            };
+
+            var expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_ADD()
+        {
+            /* TEST CODE */
+            View testView = new View();
+            NUIApplication.GetDefaultWindow().Add(testView);
+
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Unparent();
+
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenRemoveOrUnparent;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_ADD_WITH_SETTING()
+        {
+            /* TEST CODE */
+            View testView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+            };
+
+            NUIApplication.GetDefaultWindow().Add(testView);
+
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Unparent();
+
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenRemoveOrUnparent;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_ADD_MULTIPLE_WITH_SETTING()
+        {
+            /* TEST CODE */
+            View parentView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+            };
+
+            Layer defaultLayer = NUIApplication.GetDefaultWindow().GetDefaultLayer();
+            //check defaultLayer
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, defaultLayer.RefCnt(), $"reference count should be {expectedValue}");
+
+            NUIApplication.GetDefaultWindow().Add(parentView);
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            View childView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Blue,
+            };
+            parentView.Add(childView);
+
+            //check defaultLayer
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, defaultLayer.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            parentView.Unparent();
+
+            //check defaultLayer
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, defaultLayer.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenRemoveOrUnparent;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            parentView.Dispose();
+
+            //check defaultLayer
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, defaultLayer.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenRemoveOrUnparent;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            childView.Dispose();
+
+            //check defaultLayer
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, defaultLayer.RefCnt(), $"reference count should be {expectedValue}");
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_ADD_WITH_SETTING_IN_CSHARP_LIST()
+        {
+            /* TEST CODE */
+            View parentView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+            };
+
+            NUIApplication.GetDefaultWindow().Add(parentView);
+
+            //check parentView
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            View childView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Blue,
+            };
+            //check childView
+            expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            parentView.Add(childView);
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            List<View> list = new List<View>();
+            list.Add(parentView);
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAddedInList;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            list.Add(childView);
+
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAddedInList;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            //check list
+            expectedValue = 2;
+            Assert.AreEqual(expectedValue, list.Count, $"list count should be {expectedValue}");
+
+            list.Remove(parentView);
+
+            //check parentView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAddedInList + RefCountWhenRemovedInList;
+            Assert.AreEqual(expectedValue, parentView.RefCnt(), $"reference count should be {expectedValue}");
+
+            list.Remove(childView);
+            //check childView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAddedInList + RefCountWhenRemovedInList;
+            Assert.AreEqual(expectedValue, childView.RefCnt(), $"reference count should be {expectedValue}");
+
+            parentView.Unparent();
+            childView.Unparent();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_SET_FOCUSMANAGER()
+        {
+            /* TEST CODE */
+            View testView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+                Focusable = true,
+            };
+
+            NUIApplication.GetDefaultWindow().Add(testView);
+
+            //check testView
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            FocusManager.Instance.SetCurrentFocusView(testView);
+
+            //check testView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenCurrentFocusSet;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            FocusManager.Instance.ClearFocus();
+
+            //check testView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenCurrentFocusSet + RefCountWhenFocusCleared;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_ANIMATION()
+        {
+            /* TEST CODE */
+            View testView = new View()
+            {
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundColor = Color.Red,
+            };
+
+            NUIApplication.GetDefaultWindow().Add(testView);
+
+            //check testView
+            var expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            var ani = new Animation(300);
+            ani.AnimateTo(testView, "Size", new Size(testSize * 2, testSize * 2, 0));
+            ani.Finished += (sender, e) =>
+            {
+                //check testView
+                expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAnimationSet +
+                    RefCountWhenAnimationPlayed + RefCountWhenAnimationFinished;
+                Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+                testView.Dispose();
+            };
+
+            //check testView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAnimationSet;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            ani.Play();
+
+            //check testView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd + RefCountWhenAnimationSet + RefCountWhenAnimationPlayed;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+        }
+
+        private ImageUrl imageUrl;
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_IMAGEURL_CLASS()
+        {
+            /* TEST CODE */
+            path = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "picture.png";
+
+            Stream stream = File.OpenRead(path);
+            EncodedImageBuffer buffer = new EncodedImageBuffer(stream);
+            imageUrl = buffer.GenerateUrl();
+
+            //check imagUrl
+            var expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+
+            View testView = new View
+            {
+                Name = "testImageUrl",
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition, testPosition, 0),
+                BackgroundImage = imageUrl.ToString(),
+            };
+
+            // new EventThreadCallback( new EventThreadCallback.CallbackDelegate
+            //     (
+            //         ()=>
+            //         {
+            //             NUIApplication.GetDefaultWindow().Add(testView);
+            //         }
+            //     )
+            // ).Trigger();
+
+            // test1(testView);
+            // await Task.Delay(300);
+
+            //check imagUrl
+            expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+
+            NUIApplication.GetDefaultWindow().Add(testView);
+
+            //await Task.Delay(300);
+
+            //check imagUrl
+            expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+
+            //imageUrl.Dispose();
+
+            //check testView
+            expectedValue = RefCountWhenNew + RefCountWhenAdd;
+            Assert.AreEqual(expectedValue, testView.RefCnt(), $"reference count should be {expectedValue}");
+
+            View sameImageUrlView = new View
+            {
+                Name = "testImageUrl2",
+                Size = new Size(testSize, testSize, 0),
+                Position = new Position(testPosition * 2, testPosition * 2, 0),
+                BackgroundImage = imageUrl.ToString(),
+            };
+
+            //check imagUrl
+            expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+
+            NUIApplication.GetDefaultWindow().Add(sameImageUrlView);
+
+            //check imagUrl
+            expectedValue = RefCountWhenNew;
+            Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+
+        }
+        // void test1(View view)
+        // {
+        //     NUIApplication.GetDefaultWindow().Add(view);
+        // }
+
+        [Test]
+        [Category("P1")]
+        [Description("DisposeTest")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MMB")]
+        [Property("AUTHOR", "dongsug.song@samsung.com")]
+        public void Dispose_CHECK_REFERENCE_COUNT_WHEN_IMAGEURL_CLASS_DISPOSE_IMAGEURL()
+        {
+            /* TEST CODE */
+            var win = NUIApplication.GetDefaultWindow();
+            View testView = win.GetDefaultLayer().FindChildByName("testImageUrl");
+            var expectedValue = 0;
+            if (testView)
+            {
+                if (imageUrl)
+                {
+                    //check imagUrl
+                    expectedValue = RefCountWhenNew;
+                    Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+                }
+                testView.Dispose();
+
+                //check imagUrl
+                expectedValue = RefCountWhenNew;
+                Assert.AreEqual(expectedValue, imageUrl.RefCnt(), $"reference count should be {expectedValue}");
+            }
+        }
+
+
+    }
+
+    public static class BaseHandleExtension
+    {
+        public static int RefCnt(this BaseHandle baseHandle)
+        {
+            if (baseHandle)
+            {
+                BaseObject tmp = new BaseObject(Interop.BaseHandle.GetBaseObject(baseHandle.GetBaseHandleCPtrHandleRef), false);
+                var refCnt = tmp.ReferenceCount();
+                tmp.Dispose();
+                return refCnt;
+            }
+            return -1;
+        }
+    }
+
+    // public static class ViewExtension
+    // {
+    //     public static int RefCnt(this View view)
+    //     {
+    //         if (view)
+    //         {
+    //             BaseObject tmp = new BaseObject(Interop.BaseHandle.GetBaseObject(view.GetBaseHandleCPtrHandleRef), false);
+    //             var refCnt = tmp.ReferenceCount();
+    //             tmp.Dispose();
+    //             return refCnt;
+    //         }
+    //         return -1;
+    //     }
+    // }
+
+    // public static class LayerExtension
+    // {
+    //     public static int RefCnt(this Layer layer)
+    //     {
+    //         if (layer)
+    //         {
+    //             BaseObject tmp = new BaseObject(Interop.BaseHandle.GetBaseObject(layer.GetBaseHandleCPtrHandleRef), false);
+    //             var refCnt = tmp.ReferenceCount();
+    //             tmp.Dispose();
+    //             return refCnt;
+    //         }
+    //         return -1;
+    //     }
+    // }
+
+}
index dcb11b8..58eb76c 100755 (executable)
@@ -87,17 +87,19 @@ namespace NUnit.Framework.TUnit
         }
 
         /* Invoke async test method in main thread*/
-        public void RunTestMethod()
+        public bool RunTestMethod()
         {
             if (testCommand == null || testMethod == null || context == null)
             {
-                return;
+                return false;
             }
             TLogger.Write("##### RunTestMethod in TAsyncThreadMgr class #####");
             if (IsAsyncOperation)
                 RunAsyncTestMethod();
             else
                 RunNonAsyncTestMethod();
+
+            return true;
         }
 
         public void RunAsyncTestMethod()
@@ -148,7 +150,7 @@ namespace NUnit.Framework.TUnit
 
         public void RunNonAsyncTestMethod()
         {
-            TLogger.Write("##### RunNonAsyncTestMethod in TAsyncThreadMgr class #####");
+            TLogger.Write("##### RunNonAsyncTestMethod in TAsyncThreadMgr class #####\n");
             try
             {
                 runSetup();
@@ -160,12 +162,10 @@ namespace NUnit.Framework.TUnit
             }
             #region nguyen.vtan add TearDown
             runTearDown();
-            Thread.Sleep(50);
             #endregion
             testCommand._testMethodRunComplete.Set();
             _methodExecutionResetEvent.Reset();
             _methodExecutionResetEvent.WaitOne();
-            RunTestMethod();
         }
 
         public object GetResult()
index 38d8963..45750ea 100755 (executable)
@@ -29,8 +29,7 @@ namespace NUnit.Framework.TUnit
 
         public static void Write(string logTag, string message)
         {
-            Tizen.Log.Info(TUnitTag, message);
-            Console.WriteLine(logTag + message);
+            Tizen.Log.Debug(logTag, message + "\n");
         }
 
         public static void Write(string message)
@@ -40,11 +39,11 @@ namespace NUnit.Framework.TUnit
 
         public static void WriteError(string message)
         {
-            Tizen.Log.Error(TUnitTag, message);
+            Tizen.Log.Error(TUnitTag, message + "\n");
         }
         public static void WriteError(string tag, string message)
         {
-            Tizen.Log.Error(tag, message);
+            Tizen.Log.Error(tag, message + "\n");
         }
     }
 
@@ -57,30 +56,26 @@ namespace NUnit.Framework.TUnit
 
         static public void Write(string level, string tag, string msg)
         {
-            foreach (string line in msg.Split('\n'))
-            {
-                Console.WriteLine(tag + "[" + level + "] | " + line);
-                WriteDlog(level, tag, line);
-           }
+            WriteDlog(level, tag, msg);
         }
 
         static private void WriteDlog(string level, string tag, string msg)
         {
             if (level.Equals(DEBUG))
             {
-                Tizen.Log.Debug(tag, msg);
+                Tizen.Log.Debug(tag, msg + "\n");
             }
             else if (level.Equals(INFO))
             {
-                Tizen.Log.Info(tag, msg);
+                Tizen.Log.Info(tag, msg + "\n");
             }
             else if (level.Equals(ERROR))
             {
-                Tizen.Log.Error(tag, msg);
+                Tizen.Log.Error(tag, msg + "\n");
             }
             else
             {
-                Tizen.Log.Info(tag, msg);
+                Tizen.Log.Info(tag, msg + "\n");
             }
         }
     }
index 0ef4cd3..ae763ea 100755 (executable)
@@ -29,8 +29,8 @@ namespace NUnitLite.TUnit
     public class TRunner
     {
         private Assembly _testAssembly;
-        private TextRunner _textRunner;
-        private string[] args;
+        public TextRunner _textRunner;
+        public string[] args;
         public static string TESTCASE_XML_NAME = "test";
         private string pkgName = "";
 
@@ -128,7 +128,7 @@ namespace NUnitLite.TUnit
             //TLogger.Write("Executing the application: " + pkgName + "...");
             Tizen.Log.Fatal("NUITEST", $"Executing the application: {pkgName}");
             string exeFilePathName = "";
-            if(dllPath.Contains("netcoreapp"))
+            if (dllPath.Contains("netcoreapp"))
             {
                 exeFilePathName = string.Format(dllPath + "Tizen.{0}Tests.dll", pkgName);
             }
@@ -150,12 +150,12 @@ namespace NUnitLite.TUnit
             }
 
             string outputFilePathName = string.Format("{0}/{1}.xml", pkgShareDir, TESTCASE_XML_NAME);
-            
+
             TSettings.GetInstance().SetOutputFilePathName(outputFilePathName);
             string[] s = new string[1] { exeFilePathName };
 
             Tizen.Log.Fatal("NUITEST", $"outputFilePathName : {outputFilePathName}");
-            
+
             //new TextRunner(_testAssembly).Execute(s);
             LoadTestsuite(s, outputFilePathName);
         }
@@ -208,6 +208,8 @@ namespace NUnitLite.TUnit
 
             Task t = Task.Run(() =>
                 {
+                    Thread.CurrentThread.Name = "tRunner";
+
                     _textRunner.Execute(args);
                     asyncThreadMgr.SetData(null, null, null, null, false);
                     methodExecutionResetEvent.Set();
@@ -259,7 +261,7 @@ namespace NUnitLite.TUnit
             }
             catch (Exception e)
             {
-                TLogger.WriteError(TLogger.ExceptionTag , e.Message + e.ToString() + ". Please edit packageId as per guideline");
+                TLogger.WriteError(TLogger.ExceptionTag, e.Message + e.ToString() + ". Please edit packageId as per guideline");
             }
 
             return returnValue;