or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconcurrency.mdcore-dsl.mddatetime.mdfilesystem.mdindex.mdnondeterministic.mdprimitives.mdreflection.mdresult.mdstrings.mdthrowable.mdtuples.mdtypes.md

concurrency.mddocs/

0

# Concurrency Matchers

1

2

JVM concurrency testing support for futures, atomic types, channels, thread-safe collections, and synchronization primitives with comprehensive assertions for concurrent operations and thread safety validation.

3

4

## Capabilities

5

6

### CompletableFuture Matchers

7

8

Matchers for validating CompletableFuture behavior including completion, timing, and result validation.

9

10

```kotlin { .api }

11

/**

12

* Assert that CompletableFuture completes within specified duration

13

* @param duration Maximum time to wait for completion

14

* @return The original CompletableFuture for chaining

15

*/

16

fun <T> CompletableFuture<T>.shouldCompleteWithin(duration: Duration): CompletableFuture<T>

17

18

/**

19

* Assert that CompletableFuture does not complete within specified duration

20

* @param duration Time to wait before asserting non-completion

21

* @return The original CompletableFuture for chaining

22

*/

23

fun <T> CompletableFuture<T>.shouldNotCompleteWithin(duration: Duration): CompletableFuture<T>

24

25

/**

26

* Assert that CompletableFuture completes successfully (not exceptionally)

27

* @return The original CompletableFuture for chaining

28

*/

29

fun <T> CompletableFuture<T>.shouldCompleteSuccessfully(): CompletableFuture<T>

30

31

/**

32

* Assert that CompletableFuture completes exceptionally

33

* @return The original CompletableFuture for chaining

34

*/

35

fun <T> CompletableFuture<T>.shouldCompleteExceptionally(): CompletableFuture<T>

36

37

/**

38

* Assert that CompletableFuture completes with specific value

39

* @param expectedValue The value the future should complete with

40

* @return The original CompletableFuture for chaining

41

*/

42

infix fun <T> CompletableFuture<T>.shouldCompleteWith(expectedValue: T): CompletableFuture<T>

43

44

/**

45

* Assert that CompletableFuture completes with exception of specific type

46

* @param T The exception type expected

47

* @return The original CompletableFuture for chaining

48

*/

49

inline fun <reified T : Throwable> CompletableFuture<*>.shouldCompleteWithException(): CompletableFuture<*>

50

51

/**

52

* Assert that CompletableFuture is already done (completed or failed)

53

* @return The original CompletableFuture for chaining

54

*/

55

fun <T> CompletableFuture<T>.shouldBeDone(): CompletableFuture<T>

56

57

/**

58

* Assert that CompletableFuture is not yet done

59

* @return The original CompletableFuture for chaining

60

*/

61

fun <T> CompletableFuture<T>.shouldNotBeDone(): CompletableFuture<T>

62

63

/**

64

* Assert that CompletableFuture is cancelled

65

* @return The original CompletableFuture for chaining

66

*/

67

fun <T> CompletableFuture<T>.shouldBeCancelled(): CompletableFuture<T>

68

69

/**

70

* Create matcher for future completion within duration

71

* @param duration Maximum time to wait for completion

72

* @return Matcher that passes when future completes within time

73

*/

74

fun <T> completeWithin(duration: Duration): Matcher<CompletableFuture<T>>

75

76

/**

77

* Create matcher for successful completion

78

* @return Matcher that passes when future completes successfully

79

*/

80

fun <T> completeSuccessfully(): Matcher<CompletableFuture<T>>

81

82

/**

83

* Create matcher for exceptional completion

84

* @return Matcher that passes when future completes exceptionally

85

*/

86

fun <T> completeExceptionally(): Matcher<CompletableFuture<T>>

87

88

/**

89

* Create matcher for completion with specific value

90

* @param expectedValue The expected completion value

91

* @return Matcher that passes when future completes with expected value

92

*/

93

fun <T> completeWith(expectedValue: T): Matcher<CompletableFuture<T>>

94

95

/**

96

* Create matcher for completion with exception type

97

* @param T The expected exception type

98

* @return Matcher that passes when future completes with specified exception

99

*/

100

inline fun <reified T : Throwable> completeWithException(): Matcher<CompletableFuture<*>>

101

```

102

103

**Usage Examples:**

104

105

```kotlin

106

import io.kotest.matchers.concurrent.*

107

import java.util.concurrent.CompletableFuture

108

import java.time.Duration

109

110

val quickTask = CompletableFuture.supplyAsync { "result" }

111

val slowTask = CompletableFuture.supplyAsync {

112

Thread.sleep(1000)

113

"slow result"

114

}

115

val failingTask = CompletableFuture.supplyAsync<String> {

116

throw RuntimeException("Task failed")

117

}

118

119

// Completion timing

120

quickTask.shouldCompleteWithin(Duration.ofSeconds(1))

121

slowTask.shouldNotCompleteWithin(Duration.ofMillis(100))

122

123

// Completion outcomes

124

quickTask.shouldCompleteSuccessfully()

125

failingTask.shouldCompleteExceptionally()

126

quickTask shouldCompleteWith "result"

127

failingTask.shouldCompleteWithException<RuntimeException>()

128

129

// State validation

130

quickTask.shouldBeDone() // after completion

131

val pendingTask = CompletableFuture<String>()

132

pendingTask.shouldNotBeDone()

133

134

// Using matcher syntax

135

quickTask should completeSuccessfully()

136

failingTask should completeExceptionally()

137

slowTask should completeWithin(Duration.ofSeconds(2))

138

```

139

140

### Atomic Reference Matchers

141

142

Matchers for validating atomic reference types and their thread-safe operations.

143

144

```kotlin { .api }

145

/**

146

* Assert that AtomicReference has specific value

147

* @param expected The expected value

148

* @return The original AtomicReference for chaining

149

*/

150

fun <T> AtomicReference<T>.shouldHaveValue(expected: T): AtomicReference<T>

151

152

/**

153

* Assert that AtomicReference does not have specific value

154

* @param unexpected The value that should not be present

155

* @return The original AtomicReference for chaining

156

*/

157

fun <T> AtomicReference<T>.shouldNotHaveValue(unexpected: T): AtomicReference<T>

158

159

/**

160

* Assert that AtomicInteger has specific value

161

* @param expected The expected integer value

162

* @return The original AtomicInteger for chaining

163

*/

164

infix fun AtomicInteger.shouldHaveValue(expected: Int): AtomicInteger

165

166

/**

167

* Assert that AtomicLong has specific value

168

* @param expected The expected long value

169

* @return The original AtomicLong for chaining

170

*/

171

infix fun AtomicLong.shouldHaveValue(expected: Long): AtomicLong

172

173

/**

174

* Assert that AtomicBoolean has specific value

175

* @param expected The expected boolean value

176

* @return The original AtomicBoolean for chaining

177

*/

178

infix fun AtomicBoolean.shouldHaveValue(expected: Boolean): AtomicBoolean

179

180

/**

181

* Assert that AtomicInteger is greater than specified value

182

* @param value The minimum value (exclusive)

183

* @return The original AtomicInteger for chaining

184

*/

185

infix fun AtomicInteger.shouldBeGreaterThan(value: Int): AtomicInteger

186

187

/**

188

* Assert that AtomicInteger is less than specified value

189

* @param value The maximum value (exclusive)

190

* @return The original AtomicInteger for chaining

191

*/

192

infix fun AtomicInteger.shouldBeLessThan(value: Int): AtomicInteger

193

194

/**

195

* Create matcher for atomic reference value validation

196

* @param expected The expected value

197

* @return Matcher that passes when atomic reference has expected value

198

*/

199

fun <T> haveValue(expected: T): Matcher<AtomicReference<T>>

200

201

/**

202

* Create matcher for atomic integer comparison (greater than)

203

* @param value The minimum value (exclusive)

204

* @return Matcher that passes when atomic integer is greater

205

*/

206

fun beGreaterThan(value: Int): Matcher<AtomicInteger>

207

208

/**

209

* Create matcher for atomic boolean validation

210

* @param expected The expected boolean value

211

* @return Matcher that passes when atomic boolean has expected value

212

*/

213

fun haveValue(expected: Boolean): Matcher<AtomicBoolean>

214

```

215

216

### Channel Matchers

217

218

Matchers for Kotlin coroutines channels including send/receive operations and channel states.

219

220

```kotlin { .api }

221

/**

222

* Assert that channel receives element within specified duration

223

* @param duration Maximum time to wait for receive

224

* @return The received element

225

*/

226

suspend fun <T> Channel<T>.shouldReceiveWithin(duration: Duration): T

227

228

/**

229

* Assert that channel does not receive element within specified duration

230

* @param duration Time to wait before asserting no receive

231

* @return The original Channel for chaining

232

*/

233

suspend fun <T> Channel<T>.shouldNotReceiveWithin(duration: Duration): Channel<T>

234

235

/**

236

* Assert that channel receives specific element within duration

237

* @param expected The expected element

238

* @param duration Maximum time to wait for receive

239

* @return The original Channel for chaining

240

*/

241

suspend fun <T> Channel<T>.shouldReceive(expected: T, duration: Duration): Channel<T>

242

243

/**

244

* Assert that channel is closed

245

* @return The original Channel for chaining

246

*/

247

fun <T> Channel<T>.shouldBeClosed(): Channel<T>

248

249

/**

250

* Assert that channel is not closed

251

* @return The original Channel for chaining

252

*/

253

fun <T> Channel<T>.shouldNotBeClosed(): Channel<T>

254

255

/**

256

* Assert that channel is empty (no elements available)

257

* @return The original Channel for chaining

258

*/

259

fun <T> Channel<T>.shouldBeEmpty(): Channel<T>

260

261

/**

262

* Assert that channel is not empty (has elements available)

263

* @return The original Channel for chaining

264

*/

265

fun <T> Channel<T>.shouldNotBeEmpty(): Channel<T>

266

267

/**

268

* Assert that channel send operation completes within duration

269

* @param element The element to send

270

* @param duration Maximum time to wait for send completion

271

* @return The original Channel for chaining

272

*/

273

suspend fun <T> Channel<T>.shouldSendWithin(element: T, duration: Duration): Channel<T>

274

275

/**

276

* Create matcher for channel receive within duration

277

* @param duration Maximum time to wait

278

* @return Matcher that passes when channel receives within time

279

*/

280

fun <T> receiveWithin(duration: Duration): Matcher<Channel<T>>

281

282

/**

283

* Create matcher for closed channel validation

284

* @return Matcher that passes for closed channels

285

*/

286

fun <T> beClosed(): Matcher<Channel<T>>

287

288

/**

289

* Create matcher for empty channel validation

290

* @return Matcher that passes for empty channels

291

*/

292

fun <T> beEmpty(): Matcher<Channel<T>>

293

```

294

295

**Usage Examples:**

296

297

```kotlin

298

import io.kotest.matchers.concurrent.*

299

import kotlinx.coroutines.*

300

import kotlinx.coroutines.channels.*

301

import java.util.concurrent.atomic.*

302

import java.time.Duration

303

304

// Atomic reference validation

305

val atomicRef = AtomicReference("initial")

306

val atomicInt = AtomicInteger(42)

307

val atomicBool = AtomicBoolean(true)

308

309

atomicRef.shouldHaveValue("initial")

310

atomicInt shouldHaveValue 42

311

atomicBool shouldHaveValue true

312

atomicInt shouldBeGreaterThan 40

313

314

// Channel operations

315

runBlocking {

316

val channel = Channel<String>(Channel.UNLIMITED)

317

318

// Send and receive operations

319

channel.send("message")

320

channel.shouldReceiveWithin(Duration.ofSeconds(1)) shouldBe "message"

321

322

// Channel state validation

323

channel.shouldNotBeClosed()

324

channel.close()

325

channel.shouldBeClosed()

326

327

// Empty channel validation

328

val emptyChannel = Channel<Int>()

329

emptyChannel.shouldBeEmpty()

330

}

331

332

// Using matcher syntax

333

atomicRef should haveValue("initial")

334

atomicInt should beGreaterThan(30)

335

```

336

337

### Thread and Executor Matchers

338

339

Matchers for validating thread states and executor service operations.

340

341

```kotlin { .api }

342

/**

343

* Assert that thread is alive (not terminated)

344

* @return The original Thread for chaining

345

*/

346

fun Thread.shouldBeAlive(): Thread

347

348

/**

349

* Assert that thread is not alive (terminated)

350

* @return The original Thread for chaining

351

*/

352

fun Thread.shouldNotBeAlive(): Thread

353

354

/**

355

* Assert that thread is in specific state

356

* @param state The expected thread state

357

* @return The original Thread for chaining

358

*/

359

infix fun Thread.shouldBeInState(state: Thread.State): Thread

360

361

/**

362

* Assert that thread should not be in specific state

363

* @param state The thread state that should not match

364

* @return The original Thread for chaining

365

*/

366

infix fun Thread.shouldNotBeInState(state: Thread.State): Thread

367

368

/**

369

* Assert that thread is daemon thread

370

* @return The original Thread for chaining

371

*/

372

fun Thread.shouldBeDaemon(): Thread

373

374

/**

375

* Assert that thread is not daemon thread

376

* @return The original Thread for chaining

377

*/

378

fun Thread.shouldNotBeDaemon(): Thread

379

380

/**

381

* Assert that ExecutorService is shutdown

382

* @return The original ExecutorService for chaining

383

*/

384

fun ExecutorService.shouldBeShutdown(): ExecutorService

385

386

/**

387

* Assert that ExecutorService is not shutdown

388

* @return The original ExecutorService for chaining

389

*/

390

fun ExecutorService.shouldNotBeShutdown(): ExecutorService

391

392

/**

393

* Assert that ExecutorService is terminated

394

* @return The original ExecutorService for chaining

395

*/

396

fun ExecutorService.shouldBeTerminated(): ExecutorService

397

398

/**

399

* Assert that ExecutorService terminates within specified duration

400

* @param duration Maximum time to wait for termination

401

* @return The original ExecutorService for chaining

402

*/

403

fun ExecutorService.shouldTerminateWithin(duration: Duration): ExecutorService

404

405

/**

406

* Create matcher for thread state validation

407

* @param state The expected thread state

408

* @return Matcher that passes when thread is in specified state

409

*/

410

fun beInState(state: Thread.State): Matcher<Thread>

411

412

/**

413

* Create matcher for alive thread validation

414

* @return Matcher that passes for alive threads

415

*/

416

fun beAlive(): Matcher<Thread>

417

418

/**

419

* Create matcher for daemon thread validation

420

* @return Matcher that passes for daemon threads

421

*/

422

fun beDaemon(): Matcher<Thread>

423

424

/**

425

* Create matcher for shutdown executor validation

426

* @return Matcher that passes for shutdown executors

427

*/

428

fun beShutdown(): Matcher<ExecutorService>

429

430

/**

431

* Create matcher for executor termination validation

432

* @param duration Maximum time to wait for termination

433

* @return Matcher that passes when executor terminates within duration

434

*/

435

fun terminateWithin(duration: Duration): Matcher<ExecutorService>

436

```

437

438

### Lock and Synchronization Matchers

439

440

Matchers for validating locks, semaphores, and other synchronization primitives.

441

442

```kotlin { .api }

443

/**

444

* Assert that ReentrantLock is locked

445

* @return The original ReentrantLock for chaining

446

*/

447

fun ReentrantLock.shouldBeLocked(): ReentrantLock

448

449

/**

450

* Assert that ReentrantLock is not locked (unlocked)

451

* @return The original ReentrantLock for chaining

452

*/

453

fun ReentrantLock.shouldNotBeLocked(): ReentrantLock

454

455

/**

456

* Assert that ReentrantLock is held by current thread

457

* @return The original ReentrantLock for chaining

458

*/

459

fun ReentrantLock.shouldBeHeldByCurrentThread(): ReentrantLock

460

461

/**

462

* Assert that ReentrantLock is not held by current thread

463

* @return The original ReentrantLock for chaining

464

*/

465

fun ReentrantLock.shouldNotBeHeldByCurrentThread(): ReentrantLock

466

467

/**

468

* Assert that ReentrantLock has specific hold count

469

* @param count Expected number of times lock is held by current thread

470

* @return The original ReentrantLock for chaining

471

*/

472

infix fun ReentrantLock.shouldHaveHoldCount(count: Int): ReentrantLock

473

474

/**

475

* Assert that Semaphore has specific number of available permits

476

* @param permits Expected number of available permits

477

* @return The original Semaphore for chaining

478

*/

479

infix fun Semaphore.shouldHaveAvailablePermits(permits: Int): Semaphore

480

481

/**

482

* Assert that Semaphore has no available permits

483

* @return The original Semaphore for chaining

484

*/

485

fun Semaphore.shouldHaveNoAvailablePermits(): Semaphore

486

487

/**

488

* Assert that CountDownLatch count is zero (released)

489

* @return The original CountDownLatch for chaining

490

*/

491

fun CountDownLatch.shouldBeReleased(): CountDownLatch

492

493

/**

494

* Assert that CountDownLatch count is not zero (not released)

495

* @return The original CountDownLatch for chaining

496

*/

497

fun CountDownLatch.shouldNotBeReleased(): CountDownLatch

498

499

/**

500

* Assert that CountDownLatch has specific count

501

* @param count Expected latch count

502

* @return The original CountDownLatch for chaining

503

*/

504

infix fun CountDownLatch.shouldHaveCount(count: Long): CountDownLatch

505

506

/**

507

* Create matcher for locked state validation

508

* @return Matcher that passes for locked locks

509

*/

510

fun beLocked(): Matcher<ReentrantLock>

511

512

/**

513

* Create matcher for current thread lock ownership

514

* @return Matcher that passes when current thread holds lock

515

*/

516

fun beHeldByCurrentThread(): Matcher<ReentrantLock>

517

518

/**

519

* Create matcher for lock hold count validation

520

* @param count Expected hold count

521

* @return Matcher that passes when lock has expected hold count

522

*/

523

fun haveHoldCount(count: Int): Matcher<ReentrantLock>

524

525

/**

526

* Create matcher for semaphore permits validation

527

* @param permits Expected available permits

528

* @return Matcher that passes when semaphore has expected permits

529

*/

530

fun haveAvailablePermits(permits: Int): Matcher<Semaphore>

531

532

/**

533

* Create matcher for latch release validation

534

* @return Matcher that passes for released latches

535

*/

536

fun beReleased(): Matcher<CountDownLatch>

537

```

538

539

**Usage Examples:**

540

541

```kotlin

542

import io.kotest.matchers.concurrent.*

543

import java.util.concurrent.*

544

import java.util.concurrent.locks.ReentrantLock

545

import java.time.Duration

546

547

// Thread validation

548

val thread = Thread {

549

Thread.sleep(1000)

550

}

551

thread.start()

552

553

thread.shouldBeAlive()

554

thread shouldBeInState Thread.State.RUNNABLE

555

thread.shouldNotBeDaemon()

556

557

// Executor service validation

558

val executor = Executors.newFixedThreadPool(2)

559

executor.shouldNotBeShutdown()

560

561

executor.shutdown()

562

executor.shouldBeShutdown()

563

executor.shouldTerminateWithin(Duration.ofSeconds(5))

564

565

// Lock validation

566

val lock = ReentrantLock()

567

lock.shouldNotBeLocked()

568

569

lock.lock()

570

try {

571

lock.shouldBeLocked()

572

lock.shouldBeHeldByCurrentThread()

573

lock shouldHaveHoldCount 1

574

} finally {

575

lock.unlock()

576

}

577

578

// Semaphore validation

579

val semaphore = Semaphore(3)

580

semaphore shouldHaveAvailablePermits 3

581

582

semaphore.acquire()

583

semaphore shouldHaveAvailablePermits 2

584

585

// CountDownLatch validation

586

val latch = CountDownLatch(2)

587

latch.shouldNotBeReleased()

588

latch shouldHaveCount 2L

589

590

latch.countDown()

591

latch shouldHaveCount 1L

592

593

latch.countDown()

594

latch.shouldBeReleased()

595

596

// Using matcher syntax

597

thread should beAlive()

598

lock should beLocked()

599

semaphore should haveAvailablePermits(2)

600

latch should beReleased()

601

```

602

603

### Concurrent Collection Matchers

604

605

Matchers for thread-safe collections and their concurrent properties.

606

607

```kotlin { .api }

608

/**

609

* Assert that ConcurrentMap contains key-value pair atomically

610

* @param key The expected key

611

* @param value The expected value

612

* @return The original ConcurrentMap for chaining

613

*/

614

fun <K, V> ConcurrentMap<K, V>.shouldContainAtomically(key: K, value: V): ConcurrentMap<K, V>

615

616

/**

617

* Assert that ConcurrentHashMap is empty atomically

618

* @return The original ConcurrentHashMap for chaining

619

*/

620

fun <K, V> ConcurrentHashMap<K, V>.shouldBeEmptyAtomically(): ConcurrentHashMap<K, V>

621

622

/**

623

* Assert that BlockingQueue contains specific element

624

* @param element The element that should be present

625

* @return The original BlockingQueue for chaining

626

*/

627

fun <T> BlockingQueue<T>.shouldContain(element: T): BlockingQueue<T>

628

629

/**

630

* Assert that BlockingQueue is empty

631

* @return The original BlockingQueue for chaining

632

*/

633

fun <T> BlockingQueue<T>.shouldBeEmpty(): BlockingQueue<T>

634

635

/**

636

* Assert that BlockingQueue has specific size

637

* @param size Expected queue size

638

* @return The original BlockingQueue for chaining

639

*/

640

infix fun <T> BlockingQueue<T>.shouldHaveSize(size: Int): BlockingQueue<T>

641

642

/**

643

* Assert that BlockingQueue offers element within duration

644

* @param element The element to offer

645

* @param duration Maximum time to wait for offer

646

* @return The original BlockingQueue for chaining

647

*/

648

suspend fun <T> BlockingQueue<T>.shouldOfferWithin(element: T, duration: Duration): BlockingQueue<T>

649

650

/**

651

* Create matcher for concurrent map containment

652

* @param key Expected key

653

* @param value Expected value

654

* @return Matcher that passes when map contains key-value pair

655

*/

656

fun <K, V> containAtomically(key: K, value: V): Matcher<ConcurrentMap<K, V>>

657

658

/**

659

* Create matcher for blocking queue element validation

660

* @param element Expected element

661

* @return Matcher that passes when queue contains element

662

*/

663

fun <T> contain(element: T): Matcher<BlockingQueue<T>>

664

665

/**

666

* Create matcher for queue size validation

667

* @param size Expected size

668

* @return Matcher that passes when queue has expected size

669

*/

670

fun <T> haveSize(size: Int): Matcher<BlockingQueue<T>>

671

```

672

673

**Usage Examples:**

674

675

```kotlin

676

import io.kotest.matchers.concurrent.*

677

import java.util.concurrent.*

678

679

// Concurrent collections

680

val concurrentMap = ConcurrentHashMap<String, Int>()

681

val blockingQueue = LinkedBlockingQueue<String>()

682

683

// Map operations

684

concurrentMap["key"] = 42

685

concurrentMap.shouldContainAtomically("key", 42)

686

687

// Queue operations

688

blockingQueue.offer("item1")

689

blockingQueue.offer("item2")

690

691

blockingQueue.shouldContain("item1")

692

blockingQueue shouldHaveSize 2

693

blockingQueue.shouldNotBeEmpty()

694

695

// Clear and verify

696

blockingQueue.clear()

697

blockingQueue.shouldBeEmpty()

698

699

// Using matcher syntax

700

concurrentMap should containAtomically("key", 42)

701

blockingQueue should haveSize(0)

702

```

703

704

## Error Handling

705

706

Concurrency matchers provide detailed error information for assertion failures:

707

708

- **Timing failures**: Show actual vs expected durations with precise timing measurements

709

- **State failures**: Indicate expected vs actual thread/executor states with transition information

710

- **Completion failures**: Details about future completion status and any exceptions thrown

711

- **Atomic operation failures**: Show expected vs actual atomic values with concurrent access context

712

- **Channel failures**: Information about channel capacity, buffering, and element availability

713

- **Lock failures**: Details about lock ownership, hold counts, and contention information

714

715

All concurrency matchers handle race conditions appropriately and provide thread-safe assertions with meaningful error messages that help debug concurrent code issues.