1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
|
'
' Visual Basic.Net Compiler
' Copyright (C) 2004 - 2010 Rolf Bjarne Kvinge, RKvinge@novell.com
'
' This library is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
'
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
' Lesser General Public License for more details.
'
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
'
Friend Class TestExecutor
Implements IDisposable
Private m_Thread As Threading.Thread
Private m_Queue As New Generic.LinkedList(Of Test)
Private m_PausedQueue As New Generic.List(Of Test)
Private m_RunningTest As Test
''' <summary>
''' Raised when a test is about to be run.
''' </summary>
''' <param name="Test"></param>
''' <remarks></remarks>
Public Shared Event BeforeExecute As BeforeExecuteDelegate
Public Delegate Sub BeforeExecuteDelegate(ByVal Test As Test)
''' <summary>
''' Raised when a test has been run.
''' </summary>
''' <param name="Test"></param>
''' <remarks></remarks>
Public Shared Event AfterExecute As AfterExecuteDelegate
Public Delegate Sub AfterExecuteDelegate(ByVal Test As Test)
''' <summary>
''' Raised when all pending tests have been run.
''' </summary>
''' <remarks></remarks>
Public Shared Event Finished As FinishedDelegate
Public Delegate Sub FinishedDelegate()
''' <summary>
''' Specifies whether tests should be run in-process or in an external process.
''' </summary>
''' <remarks></remarks>
Private m_RunTestsHosted As Boolean
ReadOnly Property Queue() As Generic.IEnumerable(Of Test)
Get
Return m_Queue
End Get
End Property
''' <summary>
''' Returns the number of tests left in the queue.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property QueueCount() As Integer
Get
Return m_Queue.Count
End Get
End Property
''' <summary>
''' Specifies whether tests should be run in-process or in an external process.
''' </summary>
''' <remarks></remarks>
Property RunTestsHosted() As Boolean
Get
Return m_RunTestsHosted
End Get
Set(ByVal value As Boolean)
m_RunTestsHosted = value
If m_RunTestsHosted Then
Throw New NotImplementedException("Hosted testing is not implemented yet.")
End If
End Set
End Property
''' <summary>
''' This sub should be run async.
''' </summary>
''' <remarks></remarks>
Private Sub Runner()
While disposedValue = False
Try
Dim test As Test
SyncLock m_Queue
If m_Queue.Count > 0 Then
Dim theFirst As Generic.LinkedListNode(Of Test)
theFirst = m_Queue.First
test = theFirst.Value
m_Queue.RemoveFirst()
Else
test = Nothing
End If
End SyncLock
If test IsNot Nothing Then
m_RunningTest = test
RaiseEvent BeforeExecute(test)
Run(test)
RaiseEvent AfterExecute(test)
m_RunningTest = Nothing
If m_Queue.Count = 0 Then
RaiseEvent Finished()
End If
Else
Threading.Thread.Sleep(100)
End If
Catch ex As Exception
Debug.WriteLine("Exception while executing test: " & ex.Message & vbNewLine & ex.StackTrace)
End Try
End While
End Sub
Private Sub StartThread()
SyncLock m_Queue
If m_Thread Is Nothing Then
m_Thread = New Threading.Thread(New Threading.ThreadStart(AddressOf Runner))
m_Thread.IsBackground = True
m_Thread.Start()
End If
End SyncLock
End Sub
''' <summary>
''' Run the specified test, optionally putting it first in the queue.
''' If the test is already in the queue and it is given a priority, it
''' is moved to the start of the queue.
''' </summary>
''' <param name="Test"></param>
''' <remarks></remarks>
Sub RunAsync(ByVal Test As Test, Optional ByVal Priority As Boolean = False)
SyncLock m_Queue
If m_Queue.Contains(Test) Then
If Priority Then
m_Queue.Remove(Test)
m_Queue.AddFirst(Test)
End If
Else
If Priority Then
m_Queue.AddFirst(Test)
Else
m_Queue.AddLast(Test)
End If
End If
End SyncLock
StartThread()
End Sub
''' <summary>
''' Runs the specified test.
''' </summary>
''' <param name="Test"></param>
''' <remarks></remarks>
Sub Run(ByVal Test As Test)
Test.DoTest()
End Sub
''' <summary>
''' Run all tests async
''' </summary>
''' <remarks></remarks>
Sub RunAsync(ByVal Tests As Generic.IEnumerable(Of Test), Optional ByVal Priority As Boolean = False)
SyncLock m_Queue
For Each Test As Test In Tests
If m_Queue.Contains(Test) Then
If Priority Then
m_Queue.Remove(Test)
m_Queue.AddFirst(Test)
End If
Else
If Priority Then
m_Queue.AddFirst(Test)
Else
m_Queue.AddLast(Test)
End If
End If
Next
End SyncLock
StartThread()
End Sub
''' <summary>
''' Run all tests async as well as all contained tests.
''' </summary>
''' <remarks></remarks>
Sub RunAsyncTree(ByVal Tests As Tests)
RunAsync(Tests.Values)
End Sub
''' <summary>
''' Returns true if a test is running.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property IsExecuting() As Boolean
Get
Return m_RunningTest IsNot Nothing
End Get
End Property
''' <summary>
''' Resumes all the paused tests.
''' </summary>
''' <remarks></remarks>
Public Sub [Resume]()
SyncLock m_Queue
For Each test As Test In m_PausedQueue
m_Queue.AddLast(test)
Next
m_PausedQueue.Clear()
End SyncLock
End Sub
''' <summary>
''' Pauses all the tests (but not the running test if a test is beeing run).
''' </summary>
''' <remarks></remarks>
Public Sub Pause()
SyncLock m_Queue
m_PausedQueue.AddRange(m_Queue)
m_Queue.Clear()
End SyncLock
End Sub
''' <summary>
''' Clears the queue.
''' </summary>
''' <remarks></remarks>
Public Sub Clear()
SyncLock m_Queue
m_Queue.Clear()
End SyncLock
End Sub
''' <summary>
''' Clears the queue and blocks until no more tests are running.
''' </summary>
''' <remarks></remarks>
Public Sub [Stop]()
Clear()
If m_Thread IsNot Nothing Then
If Threading.Thread.CurrentThread.Equals(m_Thread) = False Then
Do Until m_Thread.ThreadState <> Threading.ThreadState.Running
Threading.Thread.Sleep(100)
Loop
End If
End If
End Sub
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free unmanaged resources when explicitly called
End If
If m_Thread IsNot Nothing Then
Me.disposedValue = True
If m_Thread.Join(60000) = False Then
m_Thread.Abort()
End If
m_Thread = Nothing
End If
' TODO: free shared unmanaged resources
End If
Me.disposedValue = True
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
|