[squeak-dev] The Inbox: KernelTests-jar.428.mcz

commits at source.squeak.org commits at source.squeak.org
Sat Jun 4 19:41:36 UTC 2022


A new version of KernelTests was added to project The Inbox:
http://source.squeak.org/inbox/KernelTests-jar.428.mcz

==================== Summary ====================

Name: KernelTests-jar.428
Author: jar
Time: 4 June 2022, 9:41:34.150893 pm
UUID: d1cbb552-07ab-1b41-a4e1-058eccf13b97
Ancestors: KernelTests-jar.427

More Process and Semaphore tests. These explore boundary scenarios like termination of process with suspendedContext = nil, or with just a single ensure context, or with two ensure contexts directly on top of each other, or a process running at the highest priority etc. These scenarios bit me when working on #terminate so let's share them.

One of the tests: 'testTerminateWithDelayInUnwind' will require a small update of #terminate I'll be sending later today. A process that invokes termination of another process is expected to wait until the terminating process finishes unwinding itself. A delay or yield inside unwind blocks may cause control be handed over to the original process which may be assuming the termination has finished. This scenario will have been fixed in the above mentioned #terminate update.

=============== Diff against KernelTests-jar.427 ===============

Item was added:
+ ----- Method: ProcessTest>>testTerminateByHighestPriorityProcess (in category 'tests') -----
+ testTerminateByHighestPriorityProcess
+ 	"Test temination by a highest priority process."
+ 	
+ 	"Note: #terminate elevates the priority of the terminating process 
+ 	and has to make sure it doesn't exceed the highest priority.
+ 	Workspace example:
+ 		q := [Semaphore new wait] fork.
+ 		p := [q terminate] forkAt: Processor highestPriority.
+ 		q isTerminated
+ 
+ 	We have to catch the 'Invalid priority' error via the 'error' variable
+ 	because #shouldnt:raise: doesn't work between two processes."
+ 
+ 	| p q error |
+ 	p := [Semaphore new wait] fork.
+ 	Processor yield.
+ 	self assert: p isBlocked.
+ 	error := false.
+ 	q := [[p terminate] on: Error do: [error := true]] newProcess.
+ 	q priority: Processor highestPriority.
+ 	q resume.
+ 	self deny: error.
+ 	self assert: p isTerminated.
+ 	self assert: q isTerminated!

Item was added:
+ ----- Method: ProcessTest>>testTerminateEnsureOnTopOfEnsure (in category 'tests') -----
+ testTerminateEnsureOnTopOfEnsure
+ 	"Test two ensure contexts on top of each other unwind correctly,
+ 	that both their unwind blocks get executed."
+ 	
+ 	| beenHere beenHereToo bottom p top |
+ 	beenHere := beenHereToo := false.
+ 	bottom := Context contextEnsure: [beenHereToo := true].
+ 	top := Context contextEnsure: [Processor activeProcess suspend. beenHere := true].
+ 	top privSender: bottom.
+ 	p := Process forContext: top priority: Processor activeProcess priority.
+ 	p resume.
+ 	Processor yield.
+ 	self assert: p isSuspended. 
+ 	p terminate.
+ 	self assert: beenHere & beenHereToo.
+ 	self assert: p isTerminated
+ 
+ !

Item was added:
+ ----- Method: ProcessTest>>testTerminateHighestPriorityProcess (in category 'tests') -----
+ testTerminateHighestPriorityProcess
+ 	"Test termination of a highest priority process."
+ 	
+ 	| p |
+ 	p := [Semaphore new wait] forkAt: Processor highestPriority.
+ 	Processor yield.
+ 	self assert: p isBlocked.
+ 	p terminate.
+ 	self assert: p isTerminated!

Item was added:
+ ----- Method: ProcessTest>>testTerminateNiledSuspendedContextProcess (in category 'tests') -----
+ testTerminateNiledSuspendedContextProcess
+ 	"Test a process with niled suspendedContext terminates correctly."
+ 	
+ 	| p |
+ 	p := [] newProcess.
+ 	self assert: p isSuspended.
+ 	p suspendedContext: nil.
+ 	p terminate.
+ 	self assert: p isTerminated!

Item was added:
+ ----- Method: ProcessTest>>testTerminateSingleEnsure (in category 'tests') -----
+ testTerminateSingleEnsure
+ 	"Test a stack consisting of a single ensure context unwinds correctly."
+ 	
+ 	| beenHere p singleton |
+ 	beenHere := false.
+ 	singleton := Context contextEnsure: [beenHere := true].
+ 	p := Process forContext: singleton priority: Processor activeProcess priority.
+ 	self assert: p isSuspended. 
+ 	self assert: p suspendedContext sender isNil. 
+ 	p terminate.
+ 	self assert: beenHere.
+ 	self assert: p isTerminated!

Item was added:
+ ----- Method: ProcessTest>>testTerminateWithDelayInUnwind (in category 'tests') -----
+ testTerminateWithDelayInUnwind
+ 	"Test the process that invoked the termination of another process waits
+ 	for the other process to finish unwinding."
+ 	
+ 	"Insert delay into the unwind block to force rescheduling; alternatively,
+ 	'Processor yield' could be used instead of 'delay wait'."
+ 	
+ 	| delay p |
+ 	delay := Delay forMilliseconds: 10.
+ 	p := [[Processor activeProcess suspend] ensure: [delay wait]] fork.
+ 	Processor yield.
+ 	self assert: p isSuspended.
+ 	p terminate.
+ 	self assert: p isTerminated!

Item was added:
+ ----- Method: SemaphoreTest>>testSemaAfterCriticalWaitSuspended (in category 'tests') -----
+ testSemaAfterCriticalWaitSuspended	"self run: #testSemaAfterCriticalWaitSuspended"
+ 	"This tests whether a semaphore that has just left the wait in Semaphore>>critical: but
+ 	has been suspended before termination, leaves it with signaling the associated semaphore."
+ 	| s p |
+ 	s := Semaphore new.
+ 	p := [s critical:[]] forkAt: Processor activePriority-1.
+ 	"wait until p entered the critical section"
+ 	[p suspendingList == s] whileFalse:[(Delay forMilliseconds: 10) wait].
+ 	"Now that p entered it, signal the semaphore. p now 'owns' the semaphore
+ 	but since we are running at higher priority than p it will not get to do
+ 	anything."
+ 	s signal.
+ 	self assert: p suspendingList class == LinkedList.
+ 	p suspend.
+ 	self assert: p suspendingList == nil.
+ 	p terminate.
+ 	self assert: 1 equals: s excessSignals!



More information about the Squeak-dev mailing list