From 69e22961c3ec7e64d7d56316998949820e0b3fb8 Mon Sep 17 00:00:00 2001 From: Yannick Chevalier Date: Mon, 25 Aug 2025 09:48:09 +0200 Subject: [PATCH 1/4] Addition of a add: anElement unless: aPresentelementSatisties adds a new element unless the block evaluates to true on an existing element. A principal motivation is the addition of an element unless it is already present in the queue. --- .../CTQueueTest.class.st | 72 ++++++++++++------- src/Containers-Queue-Tests/package.st | 2 +- src/Containers-Queue/CTQueue.class.st | 56 +++++++++++---- src/Containers-Queue/CTQueueNode.class.st | 17 ++--- src/Containers-Queue/package.st | 2 +- 5 files changed, 99 insertions(+), 50 deletions(-) diff --git a/src/Containers-Queue-Tests/CTQueueTest.class.st b/src/Containers-Queue-Tests/CTQueueTest.class.st index 6d1149e..aa8a6bd 100644 --- a/src/Containers-Queue-Tests/CTQueueTest.class.st +++ b/src/Containers-Queue-Tests/CTQueueTest.class.st @@ -3,17 +3,18 @@ I'm a simple queue i.e., first in first out structure. I support basic collection protocol and in addition enqueue and dequeue as in Scala. " Class { - #name : #CTQueueTest, - #superclass : #TestCase, - #category : #'Containers-Queue-Tests' + #name : 'CTQueueTest', + #superclass : 'TestCase', + #category : 'Containers-Queue-Tests', + #package : 'Containers-Queue-Tests' } -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> queueClass [ ^ CTQueue ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testAdd [ | queue | queue := self queueClass new. @@ -23,7 +24,7 @@ CTQueueTest >> testAdd [ self assert: (queue includes: 2) ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testAddAll [ "Ensure queueAll adds multiple elements at once." | queue | @@ -35,7 +36,7 @@ CTQueueTest >> testAddAll [ self assert: queue remove equals: 40. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testAddAllLargeCollection [ "Test adding a large collection via addAll." | queue collection size | @@ -48,7 +49,7 @@ CTQueueTest >> testAddAllLargeCollection [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testAddGarantyFIFOOrder [ "Ensure elements are dequeued in FIFO order." | queue | @@ -62,7 +63,7 @@ CTQueueTest >> testAddGarantyFIFOOrder [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testAddNilElement [ "Test adding a nil element to the queue." | queue | @@ -74,7 +75,28 @@ CTQueueTest >> testAddNilElement [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } +CTQueueTest >> testAddUnless [ + | queue | + queue := self queueClass new. + queue add: 1 unless: [ :v | (v rem: 2) = 0]. + self assert: (queue includes: 1). + self assert: queue size equals: 1 . + queue add: 2 unless: [ :v | (v rem: 2) = 0]. + self assert: (queue includes: 1). + self assert: (queue includes: 2) . + self assert: queue size equals: 2 . + queue add: 4 unless: [ :v | (v rem: 2) = 0]. + self assert: (queue includes: 1). + self assert: (queue includes: 2) . + self assert: queue size equals: 2 . + queue add: 3 unless: [ :v | (v rem: 2) = 0]. + self assert: (queue includes: 1). + self assert: (queue includes: 2) . + self assert: queue size equals: 2 +] + +{ #category : 'tests' } CTQueueTest >> testDoIteration [ "Test iterating over the queue with do: in FIFO order." | queue collected | @@ -86,19 +108,19 @@ CTQueueTest >> testDoIteration [ self assert: queue size equals: 4. "Iteration should not modify the queue" ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testEmptyQueue [ self assert: self queueClass new isEmpty ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testEmptyQueueRemove [ | queue | queue := self queueClass new. self assert: queue remove isNil. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testIncludes [ "Test the includes: method for existing and non-existing elements." | queue | @@ -109,7 +131,7 @@ CTQueueTest >> testIncludes [ self assert: queue size equals: 3. "includes: should not modify the queue" ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testInterleavedAddRemove [ "Test interleaved add and remove operations to ensure FIFO order and correctness." | queue | @@ -125,7 +147,7 @@ CTQueueTest >> testInterleavedAddRemove [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testIsEmpty [ "Ensure isEmpty works correctly." | queue | @@ -137,7 +159,7 @@ CTQueueTest >> testIsEmpty [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testLargeQueuePerformance [ "Verify FIFO behavior and performance with a large queue." | queue size startTime endTime duration maxDuration | @@ -162,7 +184,7 @@ CTQueueTest >> testLargeQueuePerformance [ self assert: queue isEmpty. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testPeek [ "Ensure peek returns the first element without removing it." | queue | @@ -173,7 +195,7 @@ CTQueueTest >> testPeek [ self assert: queue size equals: 2. "Peek should not remove elements" ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testPoll [ "Ensure poll behaves correctly, returning nil when empty." | queue | @@ -185,17 +207,17 @@ CTQueueTest >> testPoll [ self assert: queue poll isNil. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testQueue [ self assert: self queueClass new isEmpty ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testQueueGarantyFIFOOrder [ self assert: self queueClass new isEmpty ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testRemove [ "Ensure remove behaves correctly, returning nil when empty." | queue | @@ -207,7 +229,7 @@ CTQueueTest >> testRemove [ self assert: queue remove equals: 2 ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testRemoveIfNone [ "Ensure removeIfNone works correctly." | queue result | @@ -216,7 +238,7 @@ CTQueueTest >> testRemoveIfNone [ self assert: result equals: 'fallback'. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testSizeAccuracy [ "Test that the size method accurately reflects the number of elements." | queue | @@ -232,7 +254,7 @@ CTQueueTest >> testSizeAccuracy [ self assert: queue size equals: 2. ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testStressAddRemove [ "Stress test with many add and remove operations." | queue iterations | @@ -248,4 +270,4 @@ CTQueueTest >> testStressAddRemove [ queue addAll: (1 to: 1000). 1 to: 1000 do: [ :i | self assert: queue remove equals: i ]. self assert: queue isEmpty. -] \ No newline at end of file +] diff --git a/src/Containers-Queue-Tests/package.st b/src/Containers-Queue-Tests/package.st index ccf49f0..c9e25b5 100644 --- a/src/Containers-Queue-Tests/package.st +++ b/src/Containers-Queue-Tests/package.st @@ -1 +1 @@ -Package { #name : #'Containers-Queue-Tests' } +Package { #name : 'Containers-Queue-Tests' } diff --git a/src/Containers-Queue/CTQueue.class.st b/src/Containers-Queue/CTQueue.class.st index 2baf9bb..7f213fa 100644 --- a/src/Containers-Queue/CTQueue.class.st +++ b/src/Containers-Queue/CTQueue.class.st @@ -2,17 +2,18 @@ I'm a simple FIFO queue i.e., first in first out structure. I support basic collection protocol with efficient O(1) add and remove operations using a singly linked list. " Class { - #name : #CTQueue, - #superclass : #Object, + #name : 'CTQueue', + #superclass : 'Object', #instVars : [ 'head', 'tail', 'size' ], - #category : #'Containers-Queue' + #category : 'Containers-Queue', + #package : 'Containers-Queue' } -{ #category : #adding } +{ #category : 'adding' } CTQueue >> add: anElement [ "Add an element to the end of the queue (FIFO order)." | newNode | @@ -28,14 +29,39 @@ CTQueue >> add: anElement [ ^ anElement ] -{ #category : #adding } +{ #category : 'adding' } +CTQueue >> add: anElement unless: aTestIsTrue [ + "Add an element to the end of the queue (FIFO order)." + | newNode | + + head ifNil: [ + newNode := CTQueueNode new value: anElement. + head := newNode. + tail := newNode. + ] ifNotNil: [ + |current| + current := head . + [ current = tail ] whileFalse: [ + (aTestIsTrue value: current value) ifTrue: [ ^ current value ] . + current := current next + ] . + (aTestIsTrue value: tail value) ifTrue: [ ^ tail value ] . + newNode := CTQueueNode new value: anElement. + tail next: newNode. + tail := newNode. + ]. + size := size + 1. + ^ anElement +] + +{ #category : 'adding' } CTQueue >> addAll: aCollection [ "Add all elements from aCollection to the end of the queue." aCollection do: [ :each | self add: each ]. ^ aCollection ] -{ #category : #iterating } +{ #category : 'iterating' } CTQueue >> do: aBlock [ "Iterate over elements in FIFO order." | current | @@ -46,7 +72,7 @@ CTQueue >> do: aBlock [ ] ] -{ #category : #testing } +{ #category : 'testing' } CTQueue >> includes: anElement [ "Check if anElement exists in the queue." | current | @@ -58,7 +84,7 @@ CTQueue >> includes: anElement [ ^ false ] -{ #category : #initialization } +{ #category : 'initialization' } CTQueue >> initialize [ "Initialize an empty queue." super initialize. @@ -67,25 +93,25 @@ CTQueue >> initialize [ size := 0. ] -{ #category : #testing } +{ #category : 'testing' } CTQueue >> isEmpty [ "Return true if the queue is empty." ^ head isNil ] -{ #category : #accessing } +{ #category : 'accessing' } CTQueue >> peek [ "Return the front element without removing it, or nil if empty." ^ head ifNil: [ nil ] ifNotNil: [ head value ] ] -{ #category : #removing } +{ #category : 'removing' } CTQueue >> poll [ "Return and remove the front element, or nil if empty." ^ self remove ] -{ #category : #removing } +{ #category : 'removing' } CTQueue >> remove [ "Return and remove the oldest element, or nil if empty." | value | @@ -97,15 +123,15 @@ CTQueue >> remove [ ^ value ] -{ #category : #removing } +{ #category : 'removing' } CTQueue >> removeIfNone: aBlock [ "Return and remove the oldest element, or evaluate aBlock if empty." head ifNil: [ ^ aBlock value ]. ^ self remove ] -{ #category : #accessing } +{ #category : 'accessing' } CTQueue >> size [ "Return the number of elements in the queue." ^ size -] \ No newline at end of file +] diff --git a/src/Containers-Queue/CTQueueNode.class.st b/src/Containers-Queue/CTQueueNode.class.st index 430c3b2..f72eaeb 100644 --- a/src/Containers-Queue/CTQueueNode.class.st +++ b/src/Containers-Queue/CTQueueNode.class.st @@ -1,29 +1,30 @@ Class { - #name : #CTQueueNode, - #superclass : #Object, + #name : 'CTQueueNode', + #superclass : 'Object', #instVars : [ 'value', 'next' ], - #category : #'Containers-Queue' + #category : 'Containers-Queue', + #package : 'Containers-Queue' } -{ #category : #accessing } +{ #category : 'accessing' } CTQueueNode >> next [ ^ next ] -{ #category : #accessing } +{ #category : 'accessing' } CTQueueNode >> next: aNode [ next := aNode ] -{ #category : #accessing } +{ #category : 'accessing' } CTQueueNode >> value [ ^ value ] -{ #category : #accessing } +{ #category : 'accessing' } CTQueueNode >> value: anObject [ value := anObject -] \ No newline at end of file +] diff --git a/src/Containers-Queue/package.st b/src/Containers-Queue/package.st index 500d4dd..bee4046 100644 --- a/src/Containers-Queue/package.st +++ b/src/Containers-Queue/package.st @@ -1 +1 @@ -Package { #name : #'Containers-Queue' } +Package { #name : 'Containers-Queue' } From b3cceab6635489b9cd37119e6824100db64c5265 Mon Sep 17 00:00:00 2001 From: Alokzh Date: Thu, 2 Oct 2025 15:08:25 +0530 Subject: [PATCH 2/4] Added complete fix for Queue DS Implementation --- .../BaselineOfContainersQueue.class.st | 14 +- src/BaselineOfContainersQueue/package.st | 2 +- .../CTQueueTest.class.st | 592 +++++++++++------- src/Containers-Queue-Tests/package.st | 2 +- src/Containers-Queue/CTQueue.class.st | 256 +++++--- src/Containers-Queue/CTQueueNode.class.st | 29 - src/Containers-Queue/package.st | 2 +- 7 files changed, 576 insertions(+), 321 deletions(-) delete mode 100644 src/Containers-Queue/CTQueueNode.class.st diff --git a/src/BaselineOfContainersQueue/BaselineOfContainersQueue.class.st b/src/BaselineOfContainersQueue/BaselineOfContainersQueue.class.st index 33a4bd4..a2737c1 100644 --- a/src/BaselineOfContainersQueue/BaselineOfContainersQueue.class.st +++ b/src/BaselineOfContainersQueue/BaselineOfContainersQueue.class.st @@ -1,15 +1,19 @@ +" +I represent the baseline for Queue DS Implementation +" Class { - #name : #BaselineOfContainersQueue, - #superclass : #BaselineOf, - #category : #BaselineOfContainersQueue + #name : 'BaselineOfContainersQueue', + #superclass : 'BaselineOf', + #category : 'BaselineOfContainersQueue', + #package : 'BaselineOfContainersQueue' } -{ #category : #baselines } +{ #category : 'baselines' } BaselineOfContainersQueue >> baseline: spec [ spec for: #pharo do: [ spec package: 'Containers-Queue'. - spec package: 'Containers-Queue-Tests' with: [ spec requires: #('Containers-Queue')] + spec package: 'Containers-Queue-Tests' with: [ spec requires: #('Containers-Queue') ] ] ] diff --git a/src/BaselineOfContainersQueue/package.st b/src/BaselineOfContainersQueue/package.st index c54be5f..6076cfe 100644 --- a/src/BaselineOfContainersQueue/package.st +++ b/src/BaselineOfContainersQueue/package.st @@ -1 +1 @@ -Package { #name : #BaselineOfContainersQueue } +Package { #name : 'BaselineOfContainersQueue' } diff --git a/src/Containers-Queue-Tests/CTQueueTest.class.st b/src/Containers-Queue-Tests/CTQueueTest.class.st index 6d1149e..48ef019 100644 --- a/src/Containers-Queue-Tests/CTQueueTest.class.st +++ b/src/Containers-Queue-Tests/CTQueueTest.class.st @@ -1,251 +1,423 @@ " -I'm a simple queue i.e., first in first out structure. -I support basic collection protocol and in addition enqueue and dequeue as in Scala. +I provide a comprehensive suite of unit tests for the CTQueue class. +My tests cover basic operations, FIFO behavior, error handling, state management, +capacity growth, constructors, bulk operations, and various edge cases to ensure +the implementation is robust, correct, and performant. " Class { - #name : #CTQueueTest, - #superclass : #TestCase, - #category : #'Containers-Queue-Tests' + #name : 'CTQueueTest', + #superclass : 'TestCase', + #instVars : [ + 'queue' + ], + #category : 'Containers-Queue-Tests', + #package : 'Containers-Queue-Tests' } -{ #category : #tests } -CTQueueTest >> queueClass [ - ^ CTQueue -] - -{ #category : #tests } -CTQueueTest >> testAdd [ - | queue | - queue := self queueClass new. - queue add: 1. - queue add: 2. - self assert: (queue includes: 1). - self assert: (queue includes: 2) -] - -{ #category : #tests } -CTQueueTest >> testAddAll [ - "Ensure queueAll adds multiple elements at once." - | queue | - queue := self queueClass new. - queue addAll: #(10 20 30 40). - self assert: queue remove equals: 10. - self assert: queue remove equals: 20. - self assert: queue remove equals: 30. - self assert: queue remove equals: 40. -] - -{ #category : #tests } -CTQueueTest >> testAddAllLargeCollection [ - "Test adding a large collection via addAll." - | queue collection size | - queue := self queueClass new. +{ #category : 'running' } +CTQueueTest >> setUp [ + super setUp. + + queue := CTQueue new: 5 +] + +{ #category : 'tests' } +CTQueueTest >> testAlternatingEnqueueDequeue [ + + queue enqueue: 'a'. + self assert: queue dequeue equals: 'a'. + + queue enqueue: 'b'; enqueue: 'c'. + self assert: queue dequeue equals: 'b'. + + queue enqueue: 'd'. + self assert: queue front equals: 'c'. + self assert: queue size equals: 2 +] + +{ #category : 'tests' } +CTQueueTest >> testAsArray [ + + | result | + queue enqueue: 'first'; enqueue: 'second'; enqueue: 'third'. + result := queue asArray. + + self assert: result equals: #('first' 'second' 'third'). + "Elements from front to rear" +] + +{ #category : 'tests' } +CTQueueTest >> testAsOrderedCollection [ + + | result | + queue enqueue: 'a'; enqueue: 'b'; enqueue: 'c'. + result := queue asOrderedCollection. + + self assert: result class equals: OrderedCollection. + self assert: result asArray equals: #('a' 'b' 'c') +] + +{ #category : 'tests' } +CTQueueTest >> testCapacityGrowth [ + + | originalCapacity | + originalCapacity := queue capacity. + + 1 to: originalCapacity do: [ :i | queue enqueue: i ]. + self assert: queue capacity equals: originalCapacity. + + queue enqueue: 'overflow'. + self assert: queue capacity equals: originalCapacity * 2. + self assert: queue size equals: originalCapacity + 1 +] + +{ #category : 'tests' } +CTQueueTest >> testCircularArrayWrapping [ + + | testQueue | + testQueue := CTQueue new: 3. + + "Fill the queue" + testQueue enqueue: 1; enqueue: 2; enqueue: 3. + + "Remove front elements" + testQueue dequeue; dequeue. + + "Add more elements to test wraparound" + testQueue enqueue: 4; enqueue: 5. + + self assert: testQueue front equals: 3. + self assert: testQueue size equals: 3 +] + +{ #category : 'tests' } +CTQueueTest >> testCopyCreatesNewObject [ + + | copy | + queue + enqueue: 'a'; + enqueue: 'b'. + copy := queue copy. + self deny: queue identicalTo: copy +] + +{ #category : 'tests' } +CTQueueTest >> testCopyHasSameContents [ + + | copy | + queue + enqueue: 'first'; + enqueue: 'second'; + enqueue: 'third'. + copy := queue copy. + self assert: copy size equals: queue size. + self assert: copy front equals: queue front +] + +{ #category : 'tests' } +CTQueueTest >> testCopyIsIndependent [ + + | copy | + queue enqueue: 'a'; enqueue: 'b'. + copy := queue copy. + "Now, modify the original queue" + queue dequeue. + queue enqueue: 'c'. + + self assert: copy size equals: 2. + self assert: copy front equals: 'a'. + self deny: copy front equals: queue front +] + +{ #category : 'tests' } +CTQueueTest >> testDefaultQueueCreation [ + + | defaultQueue | + defaultQueue := CTQueue new. + self assert: defaultQueue capacity equals: 10. + self assert: defaultQueue isEmpty. + self assert: defaultQueue size equals: 0 +] + +{ #category : 'tests' } +CTQueueTest >> testDequeueAllElements [ + + queue + enqueue: 'a'; + enqueue: 'b'; + enqueue: 'c'. + queue + dequeue; + dequeue; + dequeue. + self assert: queue isEmpty. + self assert: queue size equals: 0 +] + +{ #category : 'tests' } +CTQueueTest >> testDequeueMultipleElements [ + + queue enqueue: 'first'; enqueue: 'second'; enqueue: 'third'. + + self assert: queue dequeue equals: 'first'. + self assert: queue dequeue equals: 'second'. + self assert: queue size equals: 1. + self assert: queue front equals: 'third' +] + +{ #category : 'tests' } +CTQueueTest >> testDequeueSingleElement [ + + | element | + queue enqueue: 'test'. + element := queue dequeue. + self assert: element equals: 'test'. + self assert: queue isEmpty. + self assert: queue size equals: 0 +] + +{ #category : 'tests' } +CTQueueTest >> testDoIteration [ + + | elements | + queue enqueue: 'first'; enqueue: 'second'; enqueue: 'third'. + elements := OrderedCollection new. + + queue do: [ :each | elements add: each ]. + + self assert: elements asArray equals: #('first' 'second' 'third'). + self assert: queue size equals: 3. "Iteration should not modify the queue" +] + +{ #category : 'tests' } +CTQueueTest >> testDynamicQueue [ + + | testQueue | + testQueue := CTQueue new: 2. + testQueue + enqueue: 'a'; + enqueue: 'b'. + self assert: testQueue capacity equals: 2. + "Enqueue one more - should double capacity" + testQueue enqueue: 'c'. + self assert: testQueue capacity equals: 4. + self assert: testQueue size equals: 3. + self assert: testQueue front equals: 'a' +] + +{ #category : 'tests' } +CTQueueTest >> testEnqueueAll [ + + | result | + result := queue enqueueAll: #('a' 'b' 'c'). + + self assert: queue size equals: 3. + self assert: queue front equals: 'a'. + self assert: result identicalTo: queue +] + +{ #category : 'tests' } +CTQueueTest >> testEnqueueAllLargeCollection [ + + | collection size | size := 50000. collection := (1 to: size) asArray. - queue addAll: collection. + queue enqueueAll: collection. self assert: queue size equals: size. - 1 to: size do: [ :i | self assert: queue remove equals: i ]. - self assert: queue isEmpty. + 1 to: size do: [ :i | self assert: queue dequeue equals: i ]. + self assert: queue isEmpty ] -{ #category : #tests } -CTQueueTest >> testAddGarantyFIFOOrder [ - "Ensure elements are dequeued in FIFO order." - | queue | - queue := self queueClass new. - queue add: 'first'. - queue add: 'second'. - queue add: 'third'. - self assert: queue remove equals: 'first'. - self assert: queue remove equals: 'second'. - self assert: queue remove equals: 'third'. +{ #category : 'tests' } +CTQueueTest >> testEnqueueAllWithEmptyCollection [ + + | result | + result := queue enqueueAll: #(). self assert: queue isEmpty. + self assert: result identicalTo: queue +] + +{ #category : 'tests' } +CTQueueTest >> testEnqueueMultipleElements [ + + queue + enqueue: 'first'; + enqueue: 'second'; + enqueue: 'third'. + self assert: queue size equals: 3. + self assert: queue front equals: 'first'. + self deny: queue isEmpty ] -{ #category : #tests } -CTQueueTest >> testAddNilElement [ - "Test adding a nil element to the queue." - | queue | - queue := self queueClass new. - queue add: nil. +{ #category : 'tests' } +CTQueueTest >> testEnqueueNilElement [ + + queue enqueue: nil. self assert: queue size equals: 1. - self assert: queue peek isNil. - self assert: queue remove isNil. - self assert: queue isEmpty. + self assert: queue front isNil. + self assert: queue dequeue isNil. + self assert: queue isEmpty ] -{ #category : #tests } -CTQueueTest >> testDoIteration [ - "Test iterating over the queue with do: in FIFO order." - | queue collected | - queue := self queueClass new. - queue addAll: #(10 20 30 40). - collected := OrderedCollection new. - queue do: [ :each | collected add: each ]. - self assert: collected asArray equals: #(10 20 30 40). - self assert: queue size equals: 4. "Iteration should not modify the queue" +{ #category : 'tests' } +CTQueueTest >> testEnqueueSingleElement [ + + queue enqueue: 'first'. + self assert: queue size equals: 1. + self deny: queue isEmpty. + self assert: queue front equals: 'first' +] + +{ #category : 'tests' } +CTQueueTest >> testErrorHandling [ + + self should: [ queue dequeue ] raise: Error. + self should: [ queue front ] raise: Error. + + queue enqueue: 'test'. + queue dequeue. + + self should: [ queue dequeue ] raise: Error. + self should: [ queue front ] raise: Error ] -{ #category : #tests } -CTQueueTest >> testEmptyQueue [ - self assert: self queueClass new isEmpty +{ #category : 'tests' } +CTQueueTest >> testFIFOOrdering [ + + queue enqueue: 'first'; enqueue: 'second'; enqueue: 'third'; enqueue: 'fourth'. + + self assert: queue dequeue equals: 'first'. + self assert: queue dequeue equals: 'second'. + self assert: queue dequeue equals: 'third'. + self assert: queue dequeue equals: 'fourth' ] -{ #category : #tests } -CTQueueTest >> testEmptyQueueRemove [ - | queue | - queue := self queueClass new. - self assert: queue remove isNil. +{ #category : 'tests' } +CTQueueTest >> testFrontWithoutRemoving [ + + queue enqueue: 'first'; enqueue: 'second'. + + self assert: queue front equals: 'first'. + self assert: queue size equals: 2. + self assert: queue front equals: 'first'. "Still there" ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testIncludes [ - "Test the includes: method for existing and non-existing elements." - | queue | - queue := self queueClass new. - queue addAll: #(5 10 15). + + queue enqueueAll: #(5 10 15). self assert: (queue includes: 10). self deny: (queue includes: 20). - self assert: queue size equals: 3. "includes: should not modify the queue" -] - -{ #category : #tests } -CTQueueTest >> testInterleavedAddRemove [ - "Test interleaved add and remove operations to ensure FIFO order and correctness." - | queue | - queue := self queueClass new. - queue add: 1. - queue add: 2. - self assert: queue remove equals: 1. - queue add: 3. - self assert: queue remove equals: 2. - queue add: 4. - self assert: queue remove equals: 3. - self assert: queue remove equals: 4. - self assert: queue isEmpty. + self assert: queue size equals: 3. +] + +{ #category : 'tests' } +CTQueueTest >> testInterleavedEnqueueDequeue [ + + queue enqueue: 1. + queue enqueue: 2. + self assert: queue dequeue equals: 1. + queue enqueue: 3. + self assert: queue dequeue equals: 2. + queue enqueue: 4. + self assert: queue dequeue equals: 3. + self assert: queue dequeue equals: 4. + self assert: queue isEmpty ] -{ #category : #tests } +{ #category : 'tests' } CTQueueTest >> testIsEmpty [ - "Ensure isEmpty works correctly." - | queue | - queue := self queueClass new. + self assert: queue isEmpty. - queue add: 1. + queue enqueue: 'test'. self deny: queue isEmpty. - queue remove. + queue dequeue. + self assert: queue isEmpty +] + +{ #category : 'tests' } +CTQueueTest >> testQueueCreationWithCapacity [ + + | testQueue | + testQueue := CTQueue new: 3. + self assert: testQueue capacity equals: 3. + self assert: testQueue isEmpty. + self assert: testQueue size equals: 0 +] + +{ #category : 'tests' } +CTQueueTest >> testQueueCreationWithInvalidCapacity [ + + self should: [ CTQueue new: -1 ] raise: Error. + self should: [ CTQueue new: -10 ] raise: Error +] + +{ #category : 'tests' } +CTQueueTest >> testQueueCreationWithZeroCapacity [ + + | zeroQueue | + zeroQueue := CTQueue new: 0. + + self assert: zeroQueue capacity equals: 0. + self assert: zeroQueue isEmpty. + self assert: zeroQueue size equals: 0. + + zeroQueue enqueue: 'first'. + self assert: zeroQueue capacity equals: 10. + self assert: zeroQueue size equals: 1 +] + +{ #category : 'tests' } +CTQueueTest >> testRemoveAll [ + + queue + enqueue: 'a'; + enqueue: 'b'; + enqueue: 'c'. + queue removeAll. self assert: queue isEmpty. + self assert: queue size equals: 0. + queue enqueue: 'd'. + self deny: queue isEmpty. + self assert: queue size equals: 1. + self assert: queue front equals: 'd' ] -{ #category : #tests } -CTQueueTest >> testLargeQueuePerformance [ - "Verify FIFO behavior and performance with a large queue." - | queue size startTime endTime duration maxDuration | - queue := self queueClass new. - size := 100000. - - "Measure time to add elements" - startTime := DateAndTime now. - 1 to: size do: [ :i | queue add: i ]. - endTime := DateAndTime now. - duration := endTime - startTime. - maxDuration := 5 seconds. "Expect adding 100,000 elements to take less than 5 seconds" - self assert: duration < maxDuration description: 'Adding elements took too long'. - - "Measure time to remove elements and verify FIFO order" - startTime := DateAndTime now. - 1 to: size do: [ :i | self assert: queue remove equals: i ]. - endTime := DateAndTime now. - duration := endTime - startTime. - self assert: duration < maxDuration description: 'Removing elements took too long'. +{ #category : 'tests' } +CTQueueTest >> testRemoveAllOnEmptyQueue [ + queue removeAll. + self assert: queue isEmpty. + self assert: queue size equals: 0 +] + +{ #category : 'tests' } +CTQueueTest >> testSearchExistingElement [ + + queue enqueue: 'a'; enqueue: 'b'; enqueue: 'c'; enqueue: 'b'. + + self assert: (queue search: 'a') equals: 1. "Front element" + self assert: (queue search: 'b') equals: 2. "First occurrence" + self assert: (queue search: 'c') equals: 3 ] -{ #category : #tests } -CTQueueTest >> testPeek [ - "Ensure peek returns the first element without removing it." - | queue | - queue := self queueClass new. - queue add: 42. - queue add: 99. - self assert: queue peek equals: 42. - self assert: queue size equals: 2. "Peek should not remove elements" -] - -{ #category : #tests } -CTQueueTest >> testPoll [ - "Ensure poll behaves correctly, returning nil when empty." - | queue | - queue := self queueClass new. - queue add: 'A'. - queue add: 'B'. - self assert: queue poll equals: 'A'. - self assert: queue poll equals: 'B'. - self assert: queue poll isNil. -] - -{ #category : #tests } -CTQueueTest >> testQueue [ - self assert: self queueClass new isEmpty -] - -{ #category : #tests } -CTQueueTest >> testQueueGarantyFIFOOrder [ - self assert: self queueClass new isEmpty -] - -{ #category : #tests } -CTQueueTest >> testRemove [ - "Ensure remove behaves correctly, returning nil when empty." - | queue | - queue := self queueClass new. - queue add: 1. - queue add: 2. - queue add: 3. - self assert: queue remove equals: 1. - self assert: queue remove equals: 2 -] - -{ #category : #tests } -CTQueueTest >> testRemoveIfNone [ - "Ensure removeIfNone works correctly." - | queue result | - queue := self queueClass new. - result := queue removeIfNone: [ 'fallback' ]. - self assert: result equals: 'fallback'. -] - -{ #category : #tests } -CTQueueTest >> testSizeAccuracy [ - "Test that the size method accurately reflects the number of elements." - | queue | - queue := self queueClass new. +{ #category : 'tests' } +CTQueueTest >> testSearchNonExistentElement [ + + queue enqueue: 'a'; enqueue: 'b'; enqueue: 'c'. + + self assert: (queue search: 'x') equals: -1 +] + +{ #category : 'tests' } +CTQueueTest >> testSize [ + self assert: queue size equals: 0. - queue add: 1. + queue enqueue: 'a'. self assert: queue size equals: 1. - queue addAll: #(2 3 4). - self assert: queue size equals: 4. - queue remove. + queue enqueue: 'b'; enqueue: 'c'. self assert: queue size equals: 3. - queue removeIfNone: [ nil ]. - self assert: queue size equals: 2. + queue dequeue. + self assert: queue size equals: 2 ] - -{ #category : #tests } -CTQueueTest >> testStressAddRemove [ - "Stress test with many add and remove operations." - | queue iterations | - queue := self queueClass new. - iterations := 10000. - 1 to: iterations do: [ :i | - queue add: i. - self assert: queue size equals: 1. - self assert: queue remove equals: i. - self assert: queue isEmpty. - ]. - "Add multiple elements and remove them" - queue addAll: (1 to: 1000). - 1 to: 1000 do: [ :i | self assert: queue remove equals: i ]. - self assert: queue isEmpty. -] \ No newline at end of file diff --git a/src/Containers-Queue-Tests/package.st b/src/Containers-Queue-Tests/package.st index ccf49f0..c9e25b5 100644 --- a/src/Containers-Queue-Tests/package.st +++ b/src/Containers-Queue-Tests/package.st @@ -1 +1 @@ -Package { #name : #'Containers-Queue-Tests' } +Package { #name : 'Containers-Queue-Tests' } diff --git a/src/Containers-Queue/CTQueue.class.st b/src/Containers-Queue/CTQueue.class.st index 2baf9bb..1d4eb2e 100644 --- a/src/Containers-Queue/CTQueue.class.st +++ b/src/Containers-Queue/CTQueue.class.st @@ -1,111 +1,219 @@ " -I'm a simple FIFO queue i.e., first in first out structure. I support basic collection protocol with efficient O(1) add and remove operations using a singly linked list. +I implement a simple Queue (FIFO - First In, First Out) that grows dynamically as needed. +- #enqueue: adds a new object to the rear of the queue. +- #dequeue returns and removes the front element from the queue. +- #front answers the front element of the queue without removing it. " Class { - #name : #CTQueue, - #superclass : #Object, + #name : 'CTQueue', + #superclass : 'Object', #instVars : [ - 'head', - 'tail', + 'elements', + 'frontIndex', + 'rearIndex', 'size' ], - #category : #'Containers-Queue' + #category : 'Containers-Queue', + #package : 'Containers-Queue' } -{ #category : #adding } -CTQueue >> add: anElement [ - "Add an element to the end of the queue (FIFO order)." - | newNode | - newNode := CTQueueNode new value: anElement. - head ifNil: [ - head := newNode. - tail := newNode. - ] ifNotNil: [ - tail next: newNode. - tail := newNode. +{ #category : 'instance creation' } +CTQueue class >> new [ + + "Create a new queue with default capacity of 10" + + ^ self new: 10 +] + +{ #category : 'instance creation' } +CTQueue class >> new: anInteger [ + + anInteger < 0 ifTrue: [ self error: 'Initial capacity cannot be negative' ]. + ^ self basicNew + initializeWithCapacity: anInteger; + yourself +] + +{ #category : 'converting' } +CTQueue >> asArray [ + + | result | + self isEmpty ifTrue: [ ^ #() ]. + + result := Array new: self size. + 1 to: self size do: [ :i | + result at: i put: (elements at: (self indexAt: i - 1)) ]. - size := size + 1. - ^ anElement + ^ result ] -{ #category : #adding } -CTQueue >> addAll: aCollection [ - "Add all elements from aCollection to the end of the queue." - aCollection do: [ :each | self add: each ]. - ^ aCollection +{ #category : 'converting' } +CTQueue >> asOrderedCollection [ + + | result | + result := OrderedCollection new: self size. + self do: [ :each | result add: each ]. + ^ result ] -{ #category : #iterating } +{ #category : 'accessing' } +CTQueue >> capacity [ + + ^ elements size +] + +{ #category : 'copying' } +CTQueue >> copy [ + + | newQueue | + newQueue := self class new: self capacity. + self do: [ :each | newQueue enqueue: each ]. + ^ newQueue +] + +{ #category : 'removing' } +CTQueue >> dequeue [ + + | element | + self isEmpty ifTrue: [ self error: 'Queue is empty' ]. + + element := elements at: frontIndex. + elements at: frontIndex put: nil. + frontIndex := self nextIndex: frontIndex. + size := size - 1. + + ^ element +] + +{ #category : 'enumerating' } CTQueue >> do: aBlock [ - "Iterate over elements in FIFO order." - | current | - current := head. - [ current notNil ] whileTrue: [ - aBlock value: current value. - current := current next. + + self isEmpty ifTrue: [ ^ self ]. + + 0 to: size - 1 do: [ :offset | + aBlock value: (elements at: (self indexAt: offset)) ] ] -{ #category : #testing } +{ #category : 'adding' } +CTQueue >> enqueue: anObject [ + + self isFull ifTrue: [ self grow ]. + + elements at: rearIndex put: anObject. + rearIndex := self nextIndex: rearIndex. + size := size + 1. + ^ self +] + +{ #category : 'adding' } +CTQueue >> enqueueAll: aCollection [ + + aCollection do: [ :each | self enqueue: each ]. + ^ self +] + +{ #category : 'accessing' } +CTQueue >> front [ + + self isEmpty ifTrue: [ self error: 'Queue is empty' ]. + ^ elements at: frontIndex +] + +{ #category : 'private' } +CTQueue >> grow [ + + | newElements newCapacity | + newCapacity := (self capacity = 0 ifTrue: [ 10 ] ifFalse: [ self capacity * 2 ]). + newElements := Array new: newCapacity. + + 1 to: size do: [ :i | + newElements at: i put: (elements at: (self indexAt: i - 1)) + ]. + + elements := newElements. + frontIndex := 1. + rearIndex := size + 1 +] + +{ #category : 'testing' } CTQueue >> includes: anElement [ - "Check if anElement exists in the queue." - | current | - current := head. - [ current notNil ] whileTrue: [ - current value = anElement ifTrue: [ ^ true ]. - current := current next. + + self isEmpty ifTrue: [ ^ false ]. + + 0 to: size - 1 do: [ :offset | + (elements at: (self indexAt: offset)) = anElement ifTrue: [ ^ true ] ]. ^ false ] -{ #category : #initialization } -CTQueue >> initialize [ - "Initialize an empty queue." - super initialize. - head := nil. - tail := nil. - size := 0. +{ #category : 'accessing' } +CTQueue >> indexAt: offset [ + + ^ ((frontIndex - 1 + offset) rem: self capacity) + 1 +] + +{ #category : 'initialization' } +CTQueue >> initializeWithCapacity: anInteger [ + + elements := Array new: anInteger. + frontIndex := 1. + rearIndex := 1. + size := 0 ] -{ #category : #testing } +{ #category : 'testing' } CTQueue >> isEmpty [ - "Return true if the queue is empty." - ^ head isNil + + ^ size = 0 ] -{ #category : #accessing } -CTQueue >> peek [ - "Return the front element without removing it, or nil if empty." - ^ head ifNil: [ nil ] ifNotNil: [ head value ] +{ #category : 'testing' } +CTQueue >> isFull [ + + ^ size = self capacity ] -{ #category : #removing } -CTQueue >> poll [ - "Return and remove the front element, or nil if empty." - ^ self remove +{ #category : 'private' } +CTQueue >> nextIndex: currentIndex [ + + ^ currentIndex = self capacity + ifTrue: [ 1 ] + ifFalse: [ currentIndex + 1 ] ] -{ #category : #removing } -CTQueue >> remove [ - "Return and remove the oldest element, or nil if empty." - | value | - head ifNil: [ ^ nil ]. - value := head value. - head := head next. - head ifNil: [ tail := nil ]. - size := size - 1. - ^ value +{ #category : 'accessing' } +CTQueue >> peek [ + + "Answer the front element, or nil if empty." + self isEmpty ifTrue: [ ^ nil ]. + ^ self front ] -{ #category : #removing } -CTQueue >> removeIfNone: aBlock [ - "Return and remove the oldest element, or evaluate aBlock if empty." - head ifNil: [ ^ aBlock value ]. - ^ self remove +{ #category : 'removing' } +CTQueue >> removeAll [ + + elements := Array new: self capacity. + frontIndex := 1. + rearIndex := 1. + size := 0 ] -{ #category : #accessing } +{ #category : 'accessing' } +CTQueue >> search: anObject [ + + self isEmpty ifTrue: [ ^ -1 ]. + + 0 to: size - 1 do: [ :offset | + (elements at: (self indexAt: offset)) = anObject ifTrue: [ + ^ offset + 1 + ] + ]. + ^ -1 +] + +{ #category : 'accessing' } CTQueue >> size [ - "Return the number of elements in the queue." + ^ size -] \ No newline at end of file +] diff --git a/src/Containers-Queue/CTQueueNode.class.st b/src/Containers-Queue/CTQueueNode.class.st deleted file mode 100644 index 430c3b2..0000000 --- a/src/Containers-Queue/CTQueueNode.class.st +++ /dev/null @@ -1,29 +0,0 @@ -Class { - #name : #CTQueueNode, - #superclass : #Object, - #instVars : [ - 'value', - 'next' - ], - #category : #'Containers-Queue' -} - -{ #category : #accessing } -CTQueueNode >> next [ - ^ next -] - -{ #category : #accessing } -CTQueueNode >> next: aNode [ - next := aNode -] - -{ #category : #accessing } -CTQueueNode >> value [ - ^ value -] - -{ #category : #accessing } -CTQueueNode >> value: anObject [ - value := anObject -] \ No newline at end of file diff --git a/src/Containers-Queue/package.st b/src/Containers-Queue/package.st index 500d4dd..bee4046 100644 --- a/src/Containers-Queue/package.st +++ b/src/Containers-Queue/package.st @@ -1 +1 @@ -Package { #name : #'Containers-Queue' } +Package { #name : 'Containers-Queue' } From 07cfc676c98aa6acd0fc6ebf0c5559c9d8da1d7e Mon Sep 17 00:00:00 2001 From: Alokzh Date: Thu, 2 Oct 2025 17:05:38 +0530 Subject: [PATCH 3/4] Replace Travis CI with GitHub CI & update README.md file --- .github/workflows/CI.yml | 32 +++++++++++++++ .github/workflows/matrix.yml | 31 --------------- .travis.yml | 13 ------- README.md | 75 +++++++++++++++++++++--------------- 4 files changed, 77 insertions(+), 74 deletions(-) create mode 100644 .github/workflows/CI.yml delete mode 100644 .github/workflows/matrix.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..c9d3368 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,32 @@ +name: CI + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +on: + push: + branches: [master] + pull_request: + branches: [master] + workflow_dispatch: + +jobs: + build: + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + smalltalk: [Pharo64-14, Pharo64-13, Pharo64-12, Pharo64-11, Pharo64-10] + + runs-on: ${{ matrix.os }} + name: ${{ matrix.smalltalk }} on ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: Setup SmalltalkCI + uses: hpi-swa/setup-smalltalkCI@v1 + with: + smalltalk-version: ${{ matrix.smalltalk }} + - name: Load and Test + run: smalltalkci -s ${{ matrix.smalltalk }} + shell: bash + timeout-minutes: 15 \ No newline at end of file diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml deleted file mode 100644 index 4884745..0000000 --- a/.github/workflows/matrix.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: matrix - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - build: - strategy: - matrix: - os: [ macos-latest, ubuntu-latest ] - smalltalk: [ Pharo64-8.0, Pharo64-7.0 ] - runs-on: ${{ matrix.os }} - name: ${{ matrix.smalltalk }} on ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - - name: Setup smalltalkCI - uses: hpi-swa/setup-smalltalkCI@v1 - with: - smalltalk-version: ${{ matrix.smalltalk }} - - name: Load Image and Run Tests - run: smalltalkci -s ${{ matrix.smalltalk }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - timeout-minutes: 15 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index be200f0..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: smalltalk -sudo: false - -# Select operating system(s) -os: - - linux - - osx - -# Select compatible Smalltalk image(s) -smalltalk: - - Pharo-7.0 - - Pharo64-8.0 - - Pharo64-7.0 diff --git a/README.md b/README.md index 5990133..bd18553 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,33 @@ # Containers-Queue +A High-performance, Circular Array based Queue implementation providing efficient FIFO (First In, First Out) operations with dynamic capacity and proper error handling. -[![Build Status](https://travis-ci.com/pharo-containers/Containers-Queue.svg?branch=master)](https://travis-ci.com/pharo-containers/Containers-Queue) -[![License](https://img.shields.io/badge/license-MIT-blue.svg)]() -[![Pharo version](https://img.shields.io/badge/Pharo-7.0-%23aac9ff.svg)](https://pharo.org/download) -[![Pharo version](https://img.shields.io/badge/Pharo-8.0-%23aac9ff.svg)](https://pharo.org/download) +![Pharo Version](https://img.shields.io/badge/Pharo-10+-blue) +[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) -A queue support FIFO (first in first out) behavior. Now it is a bit limited so feel free to enhance it. +## What is a Queue? -This package is part of the Containers project: This project is to collect, clean, -test and document alternate collection datastructures. Each package is modular so that users -can only load the collection they need without 100 of related collections. +A Queue is a linear data structure that follows the FIFO (First In, First Out) principle. Elements are added at the rear (enqueue) and removed from the front (dequeue). Think of it like a line at a store - the first person in line is the first person served. -## Example +### Key Benefits +- **O(1) Performance**: Constant time enqueue, dequeue, and front operations +- **Dynamic Growth**: Circular array implementation that doubles capacity when needed +- **Memory Safe**: Automatic cleanup prevents memory leaks +- **Simple API**: Clean, intuitive interface following standard queue conventions +- **Robust Error Handling**: Proper empty queue protection with clear error messages -```smalltalk -CTEnvironmentTest >> testDequeue [ - - | queue | - queue := CTQueue new. - queue queue: 1. - queue queue: 2. - queue queue: 3. - self assert: queue dequeue equals: 1. - self assert: queue dequeue equals: 2. -] -``` - -## Loading +## Loading +The following script installs Containers-Queue in Pharo. ```smalltalk Metacello new - baseline: 'ContainersQueue'; - repository: 'github://pharo-containers/Containers-Queue/'; - load. + baseline: 'ContainersQueue'; + repository: 'github://pharo-containers/Containers-Queue/src'; + load. ``` -## If you want to depend on it +## If you want to depend on it + +Add the following code to your Metacello baseline or configuration ```smalltalk spec @@ -43,7 +35,30 @@ spec with: [ spec repository: 'github://pharo-containers/Containers-Queue/src' ]. ``` +## Quick Start + +```smalltalk +"Create a queue with default capacity of 10" +queue := CTQueue new. + +"Enqueue elements" +queue enqueue: 'first'. +queue enqueue: 'second'. +queue enqueue: 'third'. + +"Check front element without removing" +queue front. "Returns 'first'" +queue size. "Returns 3" + +"Dequeue elements (FIFO order)" +queue dequeue. "Returns 'first'" +queue dequeue. "Returns 'second'" +queue dequeue. "Returns 'third'" + +"Queue is now empty" +queue isEmpty. "Returns true" +``` + +## Contributing ----- -The best way to predict the future is to do it! -Less talking more doing. stephane.ducasse@inria.fr +This is part of the Pharo Containers project. Feel free to contribute by implementing additional methods, improving tests, or enhancing documentation. \ No newline at end of file From bf333d8a63395225a03ae3a270b3e814e7c96ff2 Mon Sep 17 00:00:00 2001 From: Yannick Chevalier Date: Wed, 14 Jan 2026 18:09:54 +0100 Subject: [PATCH 4/4] corrected index reference --- src/Containers-Queue/CTQueue.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Containers-Queue/CTQueue.class.st b/src/Containers-Queue/CTQueue.class.st index 36f04b0..d618aab 100644 --- a/src/Containers-Queue/CTQueue.class.st +++ b/src/Containers-Queue/CTQueue.class.st @@ -107,8 +107,8 @@ CTQueue >> enqueue: anObject [ ] { #category : 'adding' } CTQueue >> enqueue: anObject unless: thisTestIsTrue [ - 1 to: rearIndex - 1 do: [ :i | - ( thisTestIsTrue value: (elements at: i) ) ifTrue: [ ^ self ] + 1 to: self size do: [ :i | + ( thisTestIsTrue value: (elements at: (self indexAt: i - 1 ) ) ) ifTrue: [ ^ self ] ]. self isFull ifTrue: [ self grow ].